From 02039379f4cad690ac507c377cd818430f540c49 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 12 Mar 2006 18:39:56 +0000 Subject: [PATCH 001/455] == 1.3alpha - 2003/03/12=== * compatible with 1.6dev only, use previous version for 1.5.x * unicode upgrade supported - not much tested * backup fixes - from Penny Leach, thanks! * all languages converted to utf-8 * moved to contrib/book_16 directory * added proper content encoding conversion during import --- README.txt | 114 +++ backuplib.php | 157 ++++ book_print.css | 159 ++++ book_theme.css | 94 ++ config.html | 30 + coursefiles.php | 842 ++++++++++++++++++ db/migrate2utf8.php | 161 ++++ db/migrate2utf8.xml | 33 + db/mysql.php | 36 + db/mysql.sql | 41 + db/postgres7.php | 65 ++ db/postgres7.sql | 39 + delete.php | 68 ++ edit.html | 64 ++ edit.php | 156 ++++ icon.gif | Bin 0 -> 111 bytes icon_chapter.gif | Bin 0 -> 112 bytes import.php | 188 ++++ index.php | 118 +++ lang/be_utf8/book.php | 42 + lang/be_utf8/help/book/customtitles.html | 3 + lang/be_utf8/help/book/disableprinting.html | 3 + lang/be_utf8/help/book/edit.html | 7 + lang/be_utf8/help/book/faq.html | 39 + lang/be_utf8/help/book/import.html | 5 + lang/be_utf8/help/book/index.html | 10 + lang/be_utf8/help/book/mods.html | 4 + lang/be_utf8/help/book/numberingtype.html | 12 + lang/be_utf8/help/book/summary.html | 5 + lang/ca_utf8/book.php | 49 + lang/ca_utf8/help/book/customtitles.html | 3 + lang/ca_utf8/help/book/disableprinting.html | 3 + lang/ca_utf8/help/book/edit.html | 7 + lang/ca_utf8/help/book/faq.html | 39 + lang/ca_utf8/help/book/import.html | 5 + lang/ca_utf8/help/book/index.html | 11 + lang/ca_utf8/help/book/mods.html | 4 + lang/ca_utf8/help/book/numberingtype.html | 12 + lang/ca_utf8/help/book/summary.html | 5 + lang/cs_utf8/book.php | 42 + lang/cs_utf8/help/book/customtitles.html | 3 + lang/cs_utf8/help/book/disableprinting.html | 3 + lang/cs_utf8/help/book/edit.html | 8 + lang/cs_utf8/help/book/faq.html | 41 + lang/cs_utf8/help/book/import.html | 5 + lang/cs_utf8/help/book/index.html | 11 + lang/cs_utf8/help/book/mods.html | 4 + lang/cs_utf8/help/book/numberingtype.html | 14 + lang/cs_utf8/help/book/summary.html | 5 + lang/de_utf8/book.php | 48 + lang/de_utf8/help/book/customtitles.html | 3 + lang/de_utf8/help/book/disableprinting.html | 3 + lang/de_utf8/help/book/edit.html | 7 + lang/de_utf8/help/book/faq.html | 34 + lang/de_utf8/help/book/import.html | 5 + lang/de_utf8/help/book/index.html | 11 + lang/de_utf8/help/book/mods.html | 4 + lang/de_utf8/help/book/numberingtype.html | 14 + lang/de_utf8/help/book/summary.html | 5 + lang/en_utf8/book.php | 49 + lang/en_utf8/help/book/customtitles.html | 3 + lang/en_utf8/help/book/disableprinting.html | 3 + lang/en_utf8/help/book/edit.html | 7 + lang/en_utf8/help/book/faq.html | 51 ++ lang/en_utf8/help/book/import.html | 5 + lang/en_utf8/help/book/index.html | 11 + lang/en_utf8/help/book/mods.html | 4 + lang/en_utf8/help/book/numberingtype.html | 14 + lang/en_utf8/help/book/summary.html | 5 + lang/es_utf8/book.php | 32 + lang/fi_utf8/book.php | 43 + lang/fi_utf8/help/book/customtitles.html | 3 + lang/fi_utf8/help/book/disableprinting.html | 3 + lang/fi_utf8/help/book/edit.html | 7 + lang/fi_utf8/help/book/faq.html | 56 ++ lang/fi_utf8/help/book/import.html | 5 + lang/fi_utf8/help/book/index.html | 11 + lang/fi_utf8/help/book/mods.html | 4 + lang/fi_utf8/help/book/numberingtype.html | 16 + lang/fi_utf8/help/book/summary.html | 5 + lang/fr_utf8/book.php | 46 + lang/id_utf8/book.php | 49 + lang/id_utf8/help/book/faq.html | 37 + lang/id_utf8/help/book/index.html | 7 + lang/id_utf8/help/book/mods.html | 5 + lang/id_utf8/help/book/numberingtype.html | 15 + lang/id_utf8/help/book/summary.html | 5 + lang/it_utf8/book.php | 49 + lang/ja_utf8/book.php | 48 + lang/ja_utf8/help/book/customtitles.html | 3 + lang/ja_utf8/help/book/disableprinting.html | 3 + lang/ja_utf8/help/book/edit.html | 7 + lang/ja_utf8/help/book/faq.html | 22 + lang/ja_utf8/help/book/import.html | 5 + lang/ja_utf8/help/book/index.html | 11 + lang/ja_utf8/help/book/mods.html | 4 + lang/ja_utf8/help/book/numberingtype.html | 14 + lang/ja_utf8/help/book/summary.html | 5 + lang/nl_utf8/book.php | 41 + lang/nl_utf8/help/book/customtitles.html | 1 + lang/nl_utf8/help/book/disableprinting.html | 1 + lang/nl_utf8/help/book/edit.html | 13 + lang/nl_utf8/help/book/faq.html | 21 + lang/nl_utf8/help/book/import.html | 1 + lang/nl_utf8/help/book/index.html | 11 + lang/nl_utf8/help/book/mods.html | 1 + lang/nl_utf8/help/book/numberingtype.html | 1 + lang/nl_utf8/help/book/summary.html | 9 + lang/pl_utf8/book.php | 42 + lang/pl_utf8/help/book/customtitles.html | 3 + lang/pl_utf8/help/book/disableprinting.html | 3 + lang/pl_utf8/help/book/edit.html | 7 + lang/pl_utf8/help/book/faq.html | 47 + lang/pl_utf8/help/book/import.html | 5 + lang/pl_utf8/help/book/index.html | 10 + lang/pl_utf8/help/book/mods.html | 4 + lang/pl_utf8/help/book/numberingtype.html | 15 + lang/pl_utf8/help/book/summary.html | 5 + lang/pt_br_utf8/book.php | 48 + lang/pt_br_utf8/help/book/customtitles.html | 3 + .../pt_br_utf8/help/book/disableprinting.html | 3 + lang/pt_br_utf8/help/book/edit.html | 7 + lang/pt_br_utf8/help/book/faq.html | 52 ++ lang/pt_br_utf8/help/book/import.html | 6 + lang/pt_br_utf8/help/book/index.html | 11 + lang/pt_br_utf8/help/book/mods.html | 4 + lang/pt_br_utf8/help/book/numberingtype.html | 15 + lang/pt_br_utf8/help/book/summary.html | 5 + lang/sk_utf8/book.php | 42 + lang/sk_utf8/help/book/customtitles.html | 3 + lang/sk_utf8/help/book/disableprinting.html | 3 + lang/sk_utf8/help/book/edit.html | 8 + lang/sk_utf8/help/book/faq.html | 41 + lang/sk_utf8/help/book/import.html | 6 + lang/sk_utf8/help/book/index.html | 11 + lang/sk_utf8/help/book/mods.html | 4 + lang/sk_utf8/help/book/numberingtype.html | 14 + lang/sk_utf8/help/book/summary.html | 5 + lang/sv_utf8/book.php | 42 + lang/sv_utf8/help/book/customtitles.html | 2 + lang/sv_utf8/help/book/disableprinting.html | 2 + lang/sv_utf8/help/book/edit.html | 6 + lang/sv_utf8/help/book/faq.html | 42 + lang/sv_utf8/help/book/import.html | 3 + lang/sv_utf8/help/book/index.html | 11 + lang/sv_utf8/help/book/mods.html | 4 + lang/sv_utf8/help/book/numberingtype.html | 9 + lang/sv_utf8/help/book/summary.html | 3 + lib.php | 419 +++++++++ mod.html | 116 +++ move.php | 148 +++ pix/add.gif | Bin 0 -> 68 bytes pix/nav_exit.gif | Bin 0 -> 248 bytes pix/nav_next.gif | Bin 0 -> 246 bytes pix/nav_prev.gif | Bin 0 -> 247 bytes pix/nav_prev_dis.gif | Bin 0 -> 209 bytes pix/nav_sep.gif | Bin 0 -> 41 bytes pix/print_book.gif | Bin 0 -> 204 bytes pix/print_chapter.gif | Bin 0 -> 158 bytes print.php | 180 ++++ restorelib.php | 380 ++++++++ show.php | 38 + teacheraccess.php | 46 + toc.php | 193 ++++ version.php | 13 + view.php | 252 ++++++ 166 files changed, 6016 insertions(+) create mode 100644 README.txt create mode 100644 backuplib.php create mode 100644 book_print.css create mode 100644 book_theme.css create mode 100644 config.html create mode 100644 coursefiles.php create mode 100755 db/migrate2utf8.php create mode 100755 db/migrate2utf8.xml create mode 100644 db/mysql.php create mode 100644 db/mysql.sql create mode 100644 db/postgres7.php create mode 100644 db/postgres7.sql create mode 100644 delete.php create mode 100644 edit.html create mode 100644 edit.php create mode 100644 icon.gif create mode 100644 icon_chapter.gif create mode 100644 import.php create mode 100644 index.php create mode 100644 lang/be_utf8/book.php create mode 100644 lang/be_utf8/help/book/customtitles.html create mode 100644 lang/be_utf8/help/book/disableprinting.html create mode 100644 lang/be_utf8/help/book/edit.html create mode 100644 lang/be_utf8/help/book/faq.html create mode 100644 lang/be_utf8/help/book/import.html create mode 100644 lang/be_utf8/help/book/index.html create mode 100644 lang/be_utf8/help/book/mods.html create mode 100644 lang/be_utf8/help/book/numberingtype.html create mode 100644 lang/be_utf8/help/book/summary.html create mode 100644 lang/ca_utf8/book.php create mode 100644 lang/ca_utf8/help/book/customtitles.html create mode 100644 lang/ca_utf8/help/book/disableprinting.html create mode 100644 lang/ca_utf8/help/book/edit.html create mode 100644 lang/ca_utf8/help/book/faq.html create mode 100644 lang/ca_utf8/help/book/import.html create mode 100644 lang/ca_utf8/help/book/index.html create mode 100644 lang/ca_utf8/help/book/mods.html create mode 100644 lang/ca_utf8/help/book/numberingtype.html create mode 100644 lang/ca_utf8/help/book/summary.html create mode 100644 lang/cs_utf8/book.php create mode 100644 lang/cs_utf8/help/book/customtitles.html create mode 100644 lang/cs_utf8/help/book/disableprinting.html create mode 100644 lang/cs_utf8/help/book/edit.html create mode 100644 lang/cs_utf8/help/book/faq.html create mode 100644 lang/cs_utf8/help/book/import.html create mode 100644 lang/cs_utf8/help/book/index.html create mode 100644 lang/cs_utf8/help/book/mods.html create mode 100644 lang/cs_utf8/help/book/numberingtype.html create mode 100644 lang/cs_utf8/help/book/summary.html create mode 100644 lang/de_utf8/book.php create mode 100644 lang/de_utf8/help/book/customtitles.html create mode 100644 lang/de_utf8/help/book/disableprinting.html create mode 100644 lang/de_utf8/help/book/edit.html create mode 100644 lang/de_utf8/help/book/faq.html create mode 100644 lang/de_utf8/help/book/import.html create mode 100644 lang/de_utf8/help/book/index.html create mode 100644 lang/de_utf8/help/book/mods.html create mode 100644 lang/de_utf8/help/book/numberingtype.html create mode 100644 lang/de_utf8/help/book/summary.html create mode 100644 lang/en_utf8/book.php create mode 100644 lang/en_utf8/help/book/customtitles.html create mode 100644 lang/en_utf8/help/book/disableprinting.html create mode 100644 lang/en_utf8/help/book/edit.html create mode 100644 lang/en_utf8/help/book/faq.html create mode 100644 lang/en_utf8/help/book/import.html create mode 100644 lang/en_utf8/help/book/index.html create mode 100644 lang/en_utf8/help/book/mods.html create mode 100644 lang/en_utf8/help/book/numberingtype.html create mode 100644 lang/en_utf8/help/book/summary.html create mode 100644 lang/es_utf8/book.php create mode 100644 lang/fi_utf8/book.php create mode 100644 lang/fi_utf8/help/book/customtitles.html create mode 100644 lang/fi_utf8/help/book/disableprinting.html create mode 100644 lang/fi_utf8/help/book/edit.html create mode 100644 lang/fi_utf8/help/book/faq.html create mode 100644 lang/fi_utf8/help/book/import.html create mode 100644 lang/fi_utf8/help/book/index.html create mode 100644 lang/fi_utf8/help/book/mods.html create mode 100644 lang/fi_utf8/help/book/numberingtype.html create mode 100644 lang/fi_utf8/help/book/summary.html create mode 100644 lang/fr_utf8/book.php create mode 100644 lang/id_utf8/book.php create mode 100644 lang/id_utf8/help/book/faq.html create mode 100644 lang/id_utf8/help/book/index.html create mode 100644 lang/id_utf8/help/book/mods.html create mode 100644 lang/id_utf8/help/book/numberingtype.html create mode 100644 lang/id_utf8/help/book/summary.html create mode 100644 lang/it_utf8/book.php create mode 100644 lang/ja_utf8/book.php create mode 100644 lang/ja_utf8/help/book/customtitles.html create mode 100644 lang/ja_utf8/help/book/disableprinting.html create mode 100644 lang/ja_utf8/help/book/edit.html create mode 100644 lang/ja_utf8/help/book/faq.html create mode 100644 lang/ja_utf8/help/book/import.html create mode 100644 lang/ja_utf8/help/book/index.html create mode 100644 lang/ja_utf8/help/book/mods.html create mode 100644 lang/ja_utf8/help/book/numberingtype.html create mode 100644 lang/ja_utf8/help/book/summary.html create mode 100644 lang/nl_utf8/book.php create mode 100644 lang/nl_utf8/help/book/customtitles.html create mode 100644 lang/nl_utf8/help/book/disableprinting.html create mode 100644 lang/nl_utf8/help/book/edit.html create mode 100644 lang/nl_utf8/help/book/faq.html create mode 100644 lang/nl_utf8/help/book/import.html create mode 100644 lang/nl_utf8/help/book/index.html create mode 100644 lang/nl_utf8/help/book/mods.html create mode 100644 lang/nl_utf8/help/book/numberingtype.html create mode 100644 lang/nl_utf8/help/book/summary.html create mode 100644 lang/pl_utf8/book.php create mode 100644 lang/pl_utf8/help/book/customtitles.html create mode 100644 lang/pl_utf8/help/book/disableprinting.html create mode 100644 lang/pl_utf8/help/book/edit.html create mode 100644 lang/pl_utf8/help/book/faq.html create mode 100644 lang/pl_utf8/help/book/import.html create mode 100644 lang/pl_utf8/help/book/index.html create mode 100644 lang/pl_utf8/help/book/mods.html create mode 100644 lang/pl_utf8/help/book/numberingtype.html create mode 100644 lang/pl_utf8/help/book/summary.html create mode 100644 lang/pt_br_utf8/book.php create mode 100644 lang/pt_br_utf8/help/book/customtitles.html create mode 100644 lang/pt_br_utf8/help/book/disableprinting.html create mode 100644 lang/pt_br_utf8/help/book/edit.html create mode 100644 lang/pt_br_utf8/help/book/faq.html create mode 100644 lang/pt_br_utf8/help/book/import.html create mode 100644 lang/pt_br_utf8/help/book/index.html create mode 100644 lang/pt_br_utf8/help/book/mods.html create mode 100644 lang/pt_br_utf8/help/book/numberingtype.html create mode 100644 lang/pt_br_utf8/help/book/summary.html create mode 100644 lang/sk_utf8/book.php create mode 100644 lang/sk_utf8/help/book/customtitles.html create mode 100644 lang/sk_utf8/help/book/disableprinting.html create mode 100644 lang/sk_utf8/help/book/edit.html create mode 100644 lang/sk_utf8/help/book/faq.html create mode 100644 lang/sk_utf8/help/book/import.html create mode 100644 lang/sk_utf8/help/book/index.html create mode 100644 lang/sk_utf8/help/book/mods.html create mode 100644 lang/sk_utf8/help/book/numberingtype.html create mode 100644 lang/sk_utf8/help/book/summary.html create mode 100644 lang/sv_utf8/book.php create mode 100644 lang/sv_utf8/help/book/customtitles.html create mode 100644 lang/sv_utf8/help/book/disableprinting.html create mode 100644 lang/sv_utf8/help/book/edit.html create mode 100644 lang/sv_utf8/help/book/faq.html create mode 100644 lang/sv_utf8/help/book/import.html create mode 100644 lang/sv_utf8/help/book/index.html create mode 100644 lang/sv_utf8/help/book/mods.html create mode 100644 lang/sv_utf8/help/book/numberingtype.html create mode 100644 lang/sv_utf8/help/book/summary.html create mode 100644 lib.php create mode 100644 mod.html create mode 100644 move.php create mode 100644 pix/add.gif create mode 100644 pix/nav_exit.gif create mode 100644 pix/nav_next.gif create mode 100644 pix/nav_prev.gif create mode 100644 pix/nav_prev_dis.gif create mode 100644 pix/nav_sep.gif create mode 100644 pix/print_book.gif create mode 100644 pix/print_chapter.gif create mode 100644 print.php create mode 100644 restorelib.php create mode 100644 show.php create mode 100644 teacheraccess.php create mode 100644 toc.php create mode 100644 version.php create mode 100644 view.php diff --git a/README.txt b/README.txt new file mode 100644 index 00000000000..3cd0ccb0bb6 --- /dev/null +++ b/README.txt @@ -0,0 +1,114 @@ +$Id: README.txt,v 1.1 2006/03/12 18:39:59 skodak Exp $ + +/////////////////////////////////////////////////////////////////////////// +// // +// NOTICE OF COPYRIGHT // +// // +// Moodle - Modular Object-Oriented Dynamic Learning Environment // +// http://moodle.org // +// // +// Copyright (C) 1999-2004 Martin Dougiamas http://dougiamas.com // +// // +/////////////////////////////////////////////////////////////////////////// +// // +// Book module original code // +// Copyright (C) 2004 Petr Skoda (petr.skoda@vslib.cz) // +// // +/////////////////////////////////////////////////////////////////////////// +// // +// This program 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 2 of the License, or // +// (at your option) any later version. // +// // +// This program 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: // +// // +// http://www.gnu.org/copyleft/gpl.html // +// // +/////////////////////////////////////////////////////////////////////////// + +Book module for Moodle - version 1.1 (stable release) +=============================================================================== +Created by: + Petr Skoda (skodak) - most of the coding & design + Mojmir Volf - CSS formatted printer friendly format + +Developed for Technical University of Liberec (Czech Republic). +Many ideas and code were taken from other Moodle modules and Moodle itself;-) + +Installation: + 1/ upgrade your Moodle installation to version 1.5.1 or later + (you are advised to install latest official stable 1.5.2+ branch) + 2/ download book.zip to your moodle/mod directory and unzip it there + 3/ go to http://yoursite.com/admin - all necessary tables will be created + + +List of features - version 1.2: + + * easy to use - new teachers can quickly create multipage study materials + * two levels - only chapters and subchapters + * possible automatic chapter numbering + * chapters authored in build-in HTML editor (html stored in database, + images in course data) + * printing support - all chapters can be displayed on one CSS formatted page + * backup/restore with internal link preservation + * support for global searching in study materials (see contrib/search) + * import from html files (relinking of images, flash, Java applets and + relative links) + * works with MySQL and PostgreSQL databases + * no need to move language packs any more + + +Intentionally omitted features: + + * more chapter levels - it would encourage teachers to write too much + complex and long books, better use standard standalone HTML editor and + import it as Resource. DocBook format is another suitable solution. + * TOC hiding in normal view - instead use printer friendly view + * PDF export - there is no elegant way AFAIK to convert HTML to PDF, + use virtual PDF printer or better use DocBook format for authoring + * detailed student tracking (postponed till officially supported) + * export as zipped set of HTML pages - instead use browser command + Save page as... in print view + +Future: + * I like eXe editor, I would like to improve Book in this direction ... ;-) + +CHANGELOG: +== 1.1 - 2005/01/01 ======================================================= + * compatible ONLY with 1.4.3 and later! + * removed some unused searching stuff + * fixed headers in print.php +== 1.1RC1 - 2004/11/15 ======================================================= + * compatible ONLY with 1.4.2 and later !!! + * added sesskey for enhanced security + * navigation links do not enter hidden chapters + * import - correct linking when slasharguments are off + * removed coursefiles.php +== 1.2RC - 2005/07/13 ========================================================== + * compatible with 1.5.1 + only + * improved restore + * fixed selection of directories for import + * html editor for summary + * fixed postgresql upgrade + * no need to move language packs +== 1.2 - 2003/03/11 ========================================================== + * removed 64kB page content limit in mysql + * exit button now goes to course section anchor + * chater title now in browser title bar + * added translations be and sv + * during import chapters with names "*_sub.htm?" are imported as subchapters + * deleting in import selection windows now works + * last version before transition to 1.6 +== 1.3alpha - 2003/03/12 ====================================================== + * compatible with 1.6dev only, use previous version for 1.5.x + * unicode upgrade supported - not much tested + * backup fixes - from Penny Leach, thanks! + * all languages converted to utf-8 + * moved to contrib/book_16 directory + * added proper content encoding conversion during import + +skodak diff --git a/backuplib.php b/backuplib.php new file mode 100644 index 00000000000..85fc7d77a4e --- /dev/null +++ b/backuplib.php @@ -0,0 +1,157 @@ +id) + // | + // | + // | + // book_chapters + // (CL,pk->id, fk->bookid) + // + // Meaning: pk->primary key field of the table + // fk->foreign key to link with parent + // nt->nested field (recursive data) + // CL->course level info + // UL->user level info + // files->table may have files) + // + //----------------------------------------------------------- + + //This function executes all the backup procedure about this mod + function book_backup_mods($bf,$preferences) { + global $CFG; + + $status = true; + + ////Iterate over book table + if ($books = get_records ('book', 'course', $preferences->backup_course, 'id')) { + foreach ($books as $book) { + if (backup_mod_selected($preferences,'book',$book->id)) { + $status = book_backup_one_mod($bf,$preferences,$book); + } + } + } + return $status; + } + + function book_backup_one_mod($bf,$preferences,$book) { + + global $CFG; + + if (is_numeric($book)) { + $book = get_record('book','id',$book); + } + + $status = true; + + //Start mod + fwrite ($bf,start_tag('MOD',3,true)); + //Print book data + fwrite ($bf,full_tag('ID',4,false,$book->id)); + fwrite ($bf,full_tag('MODTYPE',4,false,'book')); + fwrite ($bf,full_tag('NAME',4,false,$book->name)); + fwrite ($bf,full_tag('SUMMARY',4,false,$book->summary)); + fwrite ($bf,full_tag('NUMBERING',4,false,$book->numbering)); + fwrite ($bf,full_tag('DISABLEPRINTING',4,false,$book->disableprinting)); + fwrite ($bf,full_tag('CUSTOMTITLES',4,false,$book->customtitles)); + fwrite ($bf,full_tag('TIMECREATED',4,false,$book->timecreated)); + fwrite ($bf,full_tag('TIMEMODIFIED',4,false,$book->timemodified)); + //back up the chapters + $status = backup_book_chapters($bf,$preferences,$book); + //End mod + $status = fwrite($bf,end_tag('MOD',3,true)); + + return $status; + } + + //Backup book_chapters contents (executed from book_backup_mods) + function backup_book_chapters($bf,$preferences,$book) { + + global $CFG; + + $status = true; + //Print book's chapters + if ($chapters = get_records('book_chapters', 'bookid', $book->id, 'id')) { + //Write start tag + $status =fwrite ($bf,start_tag('CHAPTERS',4,true)); + foreach ($chapters as $ch) { + //Start chapter + fwrite ($bf,start_tag('CHAPTER',5,true)); + //Print chapter data + fwrite ($bf,full_tag('ID',6,false,$ch->id)); + fwrite ($bf,full_tag('PAGENUM',6,false,$ch->pagenum)); + fwrite ($bf,full_tag('SUBCHAPTER',6,false,$ch->subchapter)); + fwrite ($bf,full_tag('TITLE',6,false,$ch->title)); + fwrite ($bf,full_tag('CONTENT',6,false,$ch->content)); + fwrite ($bf,full_tag('HIDDEN',6,false,$ch->hidden)); + fwrite ($bf,full_tag('TIMECREATED',6,false,$ch->timecreated)); + fwrite ($bf,full_tag('TIMEMODIFIED',6,false,$ch->timemodified)); + fwrite ($bf,full_tag('IMPORTSRC',6,false,$ch->importsrc)); + //End chapter + $status = fwrite ($bf,end_tag('CHAPTER',5,true)); + } + //Write end tag + $status = fwrite ($bf,end_tag('CHAPTERS',4,true)); + } + return $status; + } + + //Return a content encoded to support interactivities linking. Every module + //should have its own. They are called automatically from the backup procedure. + function book_encode_content_links ($content,$preferences) { + + global $CFG; + + $base = preg_quote($CFG->wwwroot,"/"); + + $result = $content; + + //Link to the list of books + $buscar="/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/"; + $result= preg_replace($buscar,'$@BOOKINDEX*$2@$',$result); + + //Link to book's specific chapter + $buscar="/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)\&chapterid\=([0-9]+)/"; + $result= preg_replace($buscar,'$@BOOKCHAPTER*$2*$3@$',$result); + + //Link to book's first chapter + $buscar="/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/"; + $result= preg_replace($buscar,'$@BOOKSTART*$2@$',$result); + + return $result; + } + + + ////Return an array of info (name,value) + function book_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) { + + if (!empty($instances) && is_array($instances) && count($instances)) { + $info = array(); + foreach ($instances as $id => $instance) { + $info += book_check_backup_mods_instances($instance,$backup_unique_code); + } + return $info; + } + + //First the course data + $info[0][0] = get_string('modulenameplural','book'); + $info[0][1] = count_records('book', 'course', $course); + + //No user data for books ;-) + + return $info; + } + + ////Return an array of info (name,value) + function book_check_backup_mods_instances($instance,$backup_unique_code) { + $info[$instance->id.'0'][0] = ''.$instance->name.''; + $info[$instance->id.'0'][1] = ''; + + return $info; + } + +?> diff --git a/book_print.css b/book_print.css new file mode 100644 index 00000000000..6fe10d6d6a0 --- /dev/null +++ b/book_print.css @@ -0,0 +1,159 @@ +/* $Id: book_print.css,v 1.1 2006/03/12 18:39:59 skodak Exp $ */ + +h1, h2, h3, h4, h5, h6 { + margin-left: 0px; + font-family: "Times New Roman", Times, serif; + page-break-after: avoid; + page-break-inside: avoid; +} + +.book_title { + margin-left: -40px; + font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; + font-size: 3em; + font-weight: bold; + margin-top: 120px; + margin-bottom: 30px; + text-align: center; +} + +.book_summary { + margin-left: -40px; + text-align: center; + margin-bottom: 120px; +} + +.book_chapter_title { + font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; + text-align: left; + font-size: 1.7em; + font-weight: bold; + + border-style: solid; + border-top-width: 0px; + border-right-width: 0px; + border-bottom-width: 1px; + border-left-width: 0px; + + margin-left: -40px; + margin-left: 0px; + margin-bottom: 20px; +} + +.book_chapter { + page-break-before: always; +} + +body { + margin-left: 50px; + margin-right: 10px; + color: #000000; + background-color: #FFFFFF; + font-family: "Times New Roman", Times, serif; + font-size: 1em; + font-weight: normal; + text-decoration: none; +} + +/* link rewriting for mozilla - collides with filters :-( */ +/* +a[href^="http://"]:after, a[href^="ftp://"]:after { + content: " ["attr(href)"]"; +} +*/ + +/* just some hack - ignore user defined */ +font { + color: #000000; + background-color: #EEEEEE; + font-family: "Times New Roman", Times, serif; + font-size: 1em; + font-weight: normal; + text-decoration: none; +} + +/* ===== TOC numbering styles ===== */ + +/* numbering == NONE */ +.book_toc_none { + page-break-before: always; +} +.book_toc_none ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_none ul ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_none li { + margin-top: 10px; + list-style: none; +} +.book_toc_none li li { + margin-top: 0px; + list-style: none; +} + +/* numbering == NUMBERED */ +.book_toc_numbered { + page-break-before: always; +} +.book_toc_numbered ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_numbered ul ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_numbered li { + margin-top: 10px; + list-style: none; +} +.book_toc_numbered li li { + margin-top: 0px; + list-style: none; +} + +/* numbering == BULLETS */ +.book_toc_bullets { + page-break-before: always; +} +.book_toc_bullets ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_bullets ul ul { + margin-left: 20px; + padding-left: 0px; +} +.book_toc_bullets li { + margin-top: 10px; + list-style: none; +} +.book_toc_bullets li li { + margin-top: 0px; + list-style: circle; +} + +/* numbering == INDENTED */ +.book_toc_indented { + page-break-before: always; +} +.book_toc_indented ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_indented ul ul { + margin-left: 20px; + padding-left: 0px; +} +.book_toc_indented li { + margin-top: 10px; + list-style: none; +} +.book_toc_indented li li { + margin-top: 0px; + list-style: none; +} diff --git a/book_theme.css b/book_theme.css new file mode 100644 index 00000000000..84005bf955f --- /dev/null +++ b/book_theme.css @@ -0,0 +1,94 @@ +/* $Id: book_theme.css,v 1.1 2006/03/12 18:39:59 skodak Exp $*/ +/* later should be defined in themes*/ + + +.book_chapter_title { + font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; + text-align: left; + font-size: large; + font-weight: bold; + + margin-left: 0px; + margin-bottom: 20px; +} + +.book_content { + text-align: left; +} + +/* == TOC styles == */ + +/* toc style NONE */ +.book_toc_none ul { + margin-left: 5px; + padding-left: 0px; +} +.book_toc_none ul ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_none li { + margin-top: 5px; + list-style: none; +} +.book_toc_none li li { + margin-top: 0px; + list-style: none; +} + + +/* toc style NUMBERED */ +.book_toc_numbered ul { + margin-left: 5px; + padding-left: 0px; +} +.book_toc_numbered ul ul { + margin-left: 0px; + padding-left: 0px; +} +.book_toc_numbered li { + margin-top: 5px; + list-style: none; +} +.book_toc_numbered li li { + margin-top: 0px; + list-style: none; +} + + +/*toc style BULLETS */ +.book_toc_bullets ul { + margin-left: 5px; + padding-left: 0px; +} +.book_toc_bullets ul ul { + margin-left: 20px; + padding-left: 0px; +} +.book_toc_bullets li { + margin-top: 5px; + list-style: none; +} +.book_toc_bullets li li { + margin-top: 0px; + list-style: circle; +} + + +/* toc style INDENTED*/ +.book_toc_indented ul { + margin-left: 5px; + padding-left: 0px; +} +.book_toc_indented ul ul { + margin-left: 15px; + padding-left: 0px; +} +.book_toc_indented li { + margin-top: 5px; + list-style: none; +} +.book_toc_indented li li { + margin-top: 0px; + list-style: none; +} diff --git a/config.html b/config.html new file mode 100644 index 00000000000..8769eb9b38c --- /dev/null +++ b/config.html @@ -0,0 +1,30 @@ + + +
+ + + + + + + + + + + + +
+

book_tocwidth:

+
+ '140', '160'=>'160', '180'=>'180', '200'=>'200', + '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); + choose_from_menu ($choices, 'book_tocwidth', $CFG->book_tocwidth, ''); + ?> + + +
+ +
+ +
diff --git a/coursefiles.php b/coursefiles.php new file mode 100644 index 00000000000..fc2e85afa1f --- /dev/null +++ b/coursefiles.php @@ -0,0 +1,842 @@ +libdir.'/filelib.php'); + + $id = required_param('id', PARAM_INT); + $file = optional_param('file', '', PARAM_PATH); + $wdir = optional_param('wdir', '', PARAM_PATH); + $action = optional_param('action', '', PARAM_ACTION); + $name = optional_param('name', '', PARAM_FILE); + $oldname = optional_param('oldname', '', PARAM_FILE); + $choose = required_param('choose', PARAM_CLEAN); + + if ($choose) { + if (count(explode('.', $choose)) != 2) { + error('Incorrect format for choose parameter'); + } + } + + + if (! $course = get_record("course", "id", $id) ) { + error("That's an invalid course id"); + } + + require_login($course->id); + + if (! isteacheredit($course->id) ) { + error("You need to be a teacher with editing privileges"); + } + + function html_footer() { + + global $course, $choose; + + if ($choose) { + echo ""; + } else { + echo ""; + print_footer($course); + } + } + + function html_header($course, $wdir, $formfield=""){ + global $CFG, $ME, $choose; + + if (! $site = get_site()) { + error("Invalid site!"); + } + + if ($course->id == $site->id) { + $strfiles = get_string("sitefiles"); + } else { + $strfiles = get_string("files"); + } + + if ($wdir == "/") { + $fullnav = "$strfiles"; + } else { + $dirs = explode("/", $wdir); + $numdirs = count($dirs); + $link = ""; + $navigation = ""; + for ($i=1; $i<$numdirs-1; $i++) { + $navigation .= " -> "; + $link .= "/".urlencode($dirs[$i]); + $navigation .= "id&wdir=$link&choose=$choose\">".$dirs[$i].""; + } + $fullnav = "id&wdir=/&choose=$choose\">$strfiles $navigation -> ".$dirs[$numdirs-1]; + } + + + if ($choose) { + print_header(); + + $chooseparts = explode('.', $choose); + + ?> + + + ', '»', "$course->shortname -> $fullnav"); + echo ''; + + if ($course->id == $site->id) { + print_heading(get_string("publicsitefileswarning"), "center", 2); + } + + } else { + + if ($course->id == $site->id) { + print_header("$course->shortname: $strfiles", "$course->fullname", + "admin/index.php\">".get_string("administration"). + " -> $fullnav", $formfield); + + print_heading(get_string("publicsitefileswarning"), "center", 2); + + } else { + print_header("$course->shortname: $strfiles", "$course->fullname", + "id\">$course->shortname". + " -> $fullnav", $formfield); + } + } + + + echo ""; + echo ""; + echo "'; +} + +function displaydir ($wdir) { +// $wdir == / or /a or /a/b/c/d etc + + global $basedir; + global $id; + global $USER, $CFG; + global $choose; + + $fullpath = $basedir.$wdir; + + $directory = opendir($fullpath); // Find all files + while (false !== ($file = readdir($directory))) { + if ($file == "." || $file == "..") { + continue; + } + + if (is_dir($fullpath."/".$file)) { + $dirlist[] = $file; + } else { + $filelist[] = $file; + } + } + closedir($directory); + + $strname = get_string("name"); + $strsize = get_string("size"); + $strmodified = get_string("modified"); + $straction = get_string("action"); + $strmakeafolder = get_string("makeafolder"); + $struploadafile = get_string("uploadafile"); + $strwithchosenfiles = get_string("withchosenfiles"); + $strmovetoanotherfolder = get_string("movetoanotherfolder"); + $strmovefilestohere = get_string("movefilestohere"); + $strdeletecompletely = get_string("deletecompletely"); + $strcreateziparchive = get_string("createziparchive"); + $strrename = get_string("rename"); + $stredit = get_string("edit"); + $strunzip = get_string("unzip"); + $strlist = get_string("list"); + $strrestore= get_string("restore"); + $strchoose = get_string("choose"); + + + echo ""; + echo ''; + echo "
"; + echo "
"; + + } + + + if (! $basedir = make_upload_directory("$course->id")) { + error("The site administrator needs to fix the file permissions"); + } + + $baseweb = $CFG->wwwroot; + +// End of configuration and access control + + + if (!$wdir) { + $wdir="/"; + } + + if (($wdir != '/' and detect_munged_arguments($wdir, 0)) + or ($file != '' and detect_munged_arguments($file, 0))) { + $message = "Error: Directories can not contain \"..\""; + $wdir = "/"; + $action = ""; + } + + if ($wdir == "/backupdata") { + if (! make_upload_directory("$course->id/backupdata")) { // Backup folder + error("Could not create backupdata folder. The site administrator needs to fix the file permissions"); + } + } + + switch ($action) { + + case "upload": + html_header($course, $wdir); + require_once($CFG->dirroot.'/lib/uploadlib.php'); + + if (!empty($save) and confirm_sesskey()) { + $course->maxbytes = 0; // We are ignoring course limits + $um = new upload_manager('userfile',false,false,$course,false,0); + $dir = "$basedir$wdir"; + if ($um->process_file_uploads($dir)) { + notify(get_string('uploadedfile')); + } + // um will take care of error reporting. + displaydir($wdir); + } else { + $upload_max_filesize = get_max_upload_file_size($CFG->maxbytes); + $filesize = display_size($upload_max_filesize); + + $struploadafile = get_string("uploadafile"); + $struploadthisfile = get_string("uploadthisfile"); + $strmaxsize = get_string("maxsize", "", $filesize); + $strcancel = get_string("cancel"); + + echo "

$struploadafile ($strmaxsize) --> $wdir"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " sesskey\" />"; + upload_print_form_fragment(1,array('userfile'),null,false,null,$upload_max_filesize,0,false); + echo "
"; + echo " "; + echo ""; + echo ""; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + } + html_footer(); + break; + + case "delete": + if (!empty($confirm) and confirm_sesskey()) { + html_header($course, $wdir); + foreach ($USER->filelist as $file) { + $fullfile = $basedir.$file; + if (! fulldelete($fullfile)) { + echo "
Error: Could not delete: $fullfile"; + } + } + clearfilelist(); + displaydir($wdir); + html_footer(); + + } else { + html_header($course, $wdir); + if (setfilelist($_POST)) { + echo "

".get_string("deletecheckwarning").":

"; + print_simple_box_start("center"); + printfilelist($USER->filelist); + print_simple_box_end(); + echo "
"; + notice_yesno (get_string("deletecheckfiles"), + "coursefiles.php?id=$id&wdir=$wdir&action=delete&confirm=1&sesskey=$USER->sesskey&choose=$choose", + "coursefiles.php?id=$id&wdir=$wdir&action=cancel&choose=$choose"); + } else { + displaydir($wdir); + } + html_footer(); + } + break; + + case "move": + html_header($course, $wdir); + if (($count = setfilelist($_POST)) and confirm_sesskey()) { + $USER->fileop = $action; + $USER->filesource = $wdir; + echo "

"; + print_string("selectednowmove", "moodle", $count); + echo "

"; + } + displaydir($wdir); + html_footer(); + break; + + case "paste": + html_header($course, $wdir); + if (isset($USER->fileop) and ($USER->fileop == "move") and confirm_sesskey()) { + foreach ($USER->filelist as $file) { + $shortfile = basename($file); + $oldfile = $basedir.$file; + $newfile = $basedir.$wdir."/".$shortfile; + if (!rename($oldfile, $newfile)) { + echo "

Error: $shortfile not moved"; + } + } + } + clearfilelist(); + displaydir($wdir); + html_footer(); + break; + + case "rename": + if (!empty($name) and confirm_sesskey()) { + html_header($course, $wdir); + $name = clean_filename($name); + if (file_exists($basedir.$wdir."/".$name)) { + echo "Error: $name already exists!"; + } else if (!rename($basedir.$wdir."/".$oldname, $basedir.$wdir."/".$name)) { + echo "Error: could not rename $oldname to $name"; + } + displaydir($wdir); + + } else { + $strrename = get_string("rename"); + $strcancel = get_string("cancel"); + $strrenamefileto = get_string("renamefileto", "moodle", $file); + html_header($course, $wdir, "form.name"); + echo "

$strrenamefileto:"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo " sesskey\" />"; + echo " "; + echo " "; + echo "
"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + } + html_footer(); + break; + + case "mkdir": + if (!empty($name) and confirm_sesskey()) { + html_header($course, $wdir); + $name = clean_filename($name); + if (file_exists("$basedir$wdir/$name")) { + echo "Error: $name already exists!"; + } else if (! make_upload_directory("$course->id/$wdir/$name")) { + echo "Error: could not create $name"; + } + displaydir($wdir); + + } else { + $strcreate = get_string("create"); + $strcancel = get_string("cancel"); + $strcreatefolder = get_string("createfolder", "moodle", $wdir); + html_header($course, $wdir, "form.name"); + echo "

$strcreatefolder:"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo " sesskey\" />"; + echo " "; + echo "
"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + } + html_footer(); + break; + + case "edit": + html_header($course, $wdir); + if (isset($text) and confirm_sesskey()) { + $fileptr = fopen($basedir.$file,"w"); + fputs($fileptr, stripslashes($text)); + fclose($fileptr); + displaydir($wdir); + + } else { + $streditfile = get_string("edit", "", "$file"); + $fileptr = fopen($basedir.$file, "r"); + $contents = fread($fileptr, filesize($basedir.$file)); + fclose($fileptr); + + if (mimeinfo("type", $file) == "text/html") { + $usehtmleditor = can_use_html_editor(); + } else { + $usehtmleditor = false; + } + $usehtmleditor = false; // Always keep it off for now + + print_heading("$streditfile"); + + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo " sesskey\" />"; + print_textarea($usehtmleditor, 25, 80, 680, 400, "text", $contents); + echo "
"; + echo " "; + echo ""; + echo ""; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + + if ($usehtmleditor) { + use_html_editor(); + } + + + } + html_footer(); + break; + + case "zip": + if (!empty($name) and confirm_sesskey()) { + html_header($course, $wdir); + $name = clean_filename($name); + + $files = array(); + foreach ($USER->filelist as $file) { + $files[] = "$basedir/$file"; + } + + if (!zip_files($files,"$basedir/$wdir/$name")) { + error(get_string("zipfileserror","error")); + } + + clearfilelist(); + displaydir($wdir); + + } else { + html_header($course, $wdir, "form.name"); + + if (setfilelist($_POST)) { + echo "

".get_string("youareabouttocreatezip").":

"; + print_simple_box_start("center"); + printfilelist($USER->filelist); + print_simple_box_end(); + echo "
"; + echo "

".get_string("whattocallzip"); + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo " sesskey\" />"; + echo " "; + echo "
"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + } else { + displaydir($wdir); + clearfilelist(); + } + } + html_footer(); + break; + + case "unzip": + html_header($course, $wdir); + if (!empty($file) and confirm_sesskey()) { + $strok = get_string("ok"); + $strunpacking = get_string("unpacking", "", $file); + + echo "

$strunpacking:

"; + + $file = basename($file); + + if (!unzip_file("$basedir/$wdir/$file")) { + error(get_string("unzipfileserror","error")); + } + + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + } else { + displaydir($wdir); + } + html_footer(); + break; + + case "listzip": + html_header($course, $wdir); + if (!empty($file) and confirm_sesskey()) { + $strname = get_string("name"); + $strsize = get_string("size"); + $strmodified = get_string("modified"); + $strok = get_string("ok"); + $strlistfiles = get_string("listfiles", "", $file); + + echo "

$strlistfiles:

"; + $file = basename($file); + + include_once("$CFG->libdir/pclzip/pclzip.lib.php"); + $archive = new PclZip(cleardoubleslashes("$basedir/$wdir/$file")); + if (!$list = $archive->listContent(cleardoubleslashes("$basedir/$wdir"))) { + notify($archive->errorInfo(true)); + + } else { + echo ""; + echo ""; + foreach ($list as $item) { + echo ""; + print_cell("left", $item['filename'], 'name'); + if (! $item['folder']) { + print_cell("right", display_size($item['size']), 'size'); + } else { + echo ""; + } + $filedate = userdate($item['mtime'], get_string("strftimedatetime")); + print_cell("right", $filedate, 'date'); + echo ""; + } + echo "
$strname$strsize$strmodified
 
"; + } + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + } else { + displaydir($wdir); + } + html_footer(); + break; + + case "restore": + html_header($course, $wdir); + if (!empty($file) and confirm_sesskey()) { + echo "

".get_string("youaregoingtorestorefrom").":

"; + print_simple_box_start("center"); + echo $file; + print_simple_box_end(); + echo "
"; + echo "

".get_string("areyousuretorestorethisinfo")."

"; + $restore_path = "$CFG->wwwroot/backup/restore.php"; + notice_yesno (get_string("areyousuretorestorethis"), + $restore_path."?id=".$id."&file=".cleardoubleslashes($id.$wdir."/".$file), + "coursefiles.php?id=$id&wdir=$wdir&action=cancel"); + } else { + displaydir($wdir); + } + html_footer(); + break; + + case "cancel": + clearfilelist(); + + default: + html_header($course, $wdir); + displaydir($wdir); + html_footer(); + break; +} + + +/// FILE FUNCTIONS /////////////////////////////////////////////////////////// + + +function setfilelist($VARS) { + global $USER; + + $USER->filelist = array (); + $USER->fileop = ""; + + $count = 0; + foreach ($VARS as $key => $val) { + if (substr($key,0,4) == "file") { + $count++; + $val = rawurldecode($val); + if (!detect_munged_arguments($val, 0)) { + $USER->filelist[] = $val; + } + } + } + return $count; +} + +function clearfilelist() { + global $USER; + + $USER->filelist = array (); + $USER->fileop = ""; +} + + +function printfilelist($filelist) { + global $CFG, $basedir; + + foreach ($filelist as $file) { + if (is_dir($basedir.$file)) { + echo "pixpath/f/folder.gif\" height=\"16\" width=\"16\" alt=\"\" /> $file
"; + $subfilelist = array(); + $currdir = opendir($basedir.$file); + while (false !== ($subfile = readdir($currdir))) { + if ($subfile <> ".." && $subfile <> ".") { + $subfilelist[] = $file."/".$subfile; + } + } + printfilelist($subfilelist); + + } else { + $icon = mimeinfo("icon", $file); + echo "pixpath/f/$icon\" height=\"16\" width=\"16\" alt=\"\" /> $file
"; + } + } +} + + +function print_cell($alignment='center', $text=' ', $class='') { + if ($class) { + $class = ' class="'.$class.'"'; + } + echo '
'.$text.'
"; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo "\n"; + + if ($wdir == "/") { + $wdir = ""; + } + if (!empty($wdir)) { + $dirlist[] = '..'; + } + + $count = 0; + + if (!empty($dirlist)) { + asort($dirlist); + foreach ($dirlist as $dir) { + echo ""; + + $dirurl = "$wdir/$dir"; + if (substr($dirurl,0,1) == '/') { + $selectdir = substr($dirurl,1); + } else { + $selectdir = $dirurl; + } + + if ($dir == '..') { + $fileurl = rawurlencode(dirname($wdir)); + print_cell(); + print_cell('left', ''.get_string('parentfolder').''.get_string('parentfolder').'', 'name'); + print_cell(); + print_cell(); + print_cell(); + + } else { + $count++; + $filename = $fullpath."/".$dir; + $fileurl = rawurlencode($wdir."/".$dir); + $filesafe = rawurlencode($dir); + $filesize = display_size(get_directory_size("$fullpath/$dir")); + $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p"); + print_cell("center", "", 'checkbox'); + print_cell("left", "pixpath/f/folder.gif\" height=\"16\" width=\"16\" border=\"0\" alt=\"Folder\" />".htmlspecialchars($dir)."", 'name'); + print_cell("right", $filesize, 'size'); + print_cell("right", $filedate, 'date'); + if ($choose) { + $edittext = "$strchoose "; + } else { + $edittext = ''; + } + print_cell("right", "$edittext $strrename", 'commands'); + } + + echo ""; + } + } + + + if (!empty($filelist)) { + asort($filelist); + foreach ($filelist as $file) { + + $icon = mimeinfo("icon", $file); + + $count++; + $filename = $fullpath."/".$file; + $fileurl = "$wdir/$file"; + $filesafe = rawurlencode($file); + $fileurlsafe = rawurlencode($fileurl); + $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p"); + + if (substr($fileurl,0,1) == '/') { + $selectfile = substr($fileurl,1); + } else { + $selectfile = $fileurl; + } + + echo ""; + + print_cell("center", "", 'checkbox'); + echo ""; + + $file_size = filesize($filename); + print_cell("right", display_size($file_size), 'size'); + print_cell("right", $filedate, 'date'); + + if ($choose && $icon == "html.gif") { + $edittext = "$strchoose "; + } else { + $edittext = ''; + } + + + if ($icon == "text.gif" || $icon == "html.gif") { + $edittext .= "$stredit"; + } else if ($icon == "zip.gif") { + $edittext .= "sesskey&choose=$choose\">$strunzip "; + $edittext .= "sesskey&choose=$choose\">$strlist "; + } + + print_cell("right", "$edittext $strrename", 'commands'); + + echo ""; + } + } + echo "
$strname$strsize$strmodified$straction
"; + if ($CFG->slasharguments) { + $ffurl = "/file.php/$id$fileurl"; + } else { + $ffurl = "/file.php?file=/$id$fileurl"; + } + link_to_popup_window ($ffurl, "display", + "pixpath/f/$icon\" height=\"16\" width=\"16\" border=\"0\" alt=\"File\" />", + 480, 640); + echo ' '; + link_to_popup_window ($ffurl, "display", + htmlspecialchars($file), + 480, 640); + echo "
"; + echo "
"; + + if (empty($wdir)) { + $wdir = "/"; + } + + echo ""; + echo ""; + echo ""; + echo "
"; + echo ""; + echo ''; + echo " "; + echo "sesskey\" />"; + $options = array ( + "move" => "$strmovetoanotherfolder", + "delete" => "$strdeletecompletely", + "zip" => "$strcreateziparchive" + ); + if (!empty($count)) { + choose_from_menu ($options, "action", "", "$strwithchosenfiles...", "javascript:document.dirform.submit()"); + } + + echo ""; + echo ""; + if (!empty($USER->fileop) and ($USER->fileop == "move") and ($USER->filesource <> $wdir)) { + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " sesskey\" />"; + echo " "; + echo "
"; + } + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + echo "
"; + echo ' '; + echo " "; + echo " "; + echo " "; + echo " "; + echo "
"; + echo "
"; + echo "
"; + +} + +?> diff --git a/db/migrate2utf8.php b/db/migrate2utf8.php new file mode 100755 index 00000000000..9f14e2e6ab3 --- /dev/null +++ b/db/migrate2utf8.php @@ -0,0 +1,161 @@ +lang; + $courselang = get_course_lang($book->course); //Non existing! + $userlang = get_main_teacher_lang($book->course); //N.E.!! + + $fromenc = get_original_encoding($sitelang, $courselang, $userlang); + } + +/// We are going to use textlib facilities + if (($fromenc != 'utf-8') && ($fromenc != 'UTF-8')) { +/// Convert the text + $result = utfconvert($book->name, $fromenc); + + $newbook = new object; + $newbook->id = $recordid; + $newbook->name = $result; + migrate2utf8_update_record('book',$newbook); + } +/// And finally, just return the converted field + return $result; +} + +function migrate2utf8_book_summary($recordid){ + global $CFG, $globallang; + +/// Some trivial checks + if (empty($recordid)) { + log_the_problem_somewhere(); + return false; + } + + if (!$book = get_record('book','id',$recordid)) { + log_the_problem_somewhere(); + return false; + } + + if ($globallang) { + $fromenc = $globallang; + } else { + $sitelang = $CFG->lang; + $courselang = get_course_lang($book->course); //Non existing! + $userlang = get_main_teacher_lang($book->course); //N.E.!! + + $fromenc = get_original_encoding($sitelang, $courselang, $userlang); + } +/// We are going to use textlib facilities + +/// Convert the text + if (($fromenc != 'utf-8') && ($fromenc != 'UTF-8')) { + $result = utfconvert($book->summary, $fromenc); + $newbook = new object; + $newbook->id = $recordid; + $newbook->summary = $result; + migrate2utf8_update_record('book',$newbook); + } +/// And finally, just return the converted field + return $result; +} + +function migrate2utf8_book_chapters_title($recordid){ + global $CFG, $globallang; + +/// Some trivial checks + if (empty($recordid)) { + log_the_problem_somewhere(); + return false; + } + + if (!$chapter = get_record('book_chapters','id',$recordid)) { + log_the_problem_somewhere(); + return false; + } + + if (!$book = get_record('book','id',$chapter->bookid)) { + log_the_problem_somewhere(); + return false; + } + + if ($globallang) { + $fromenc = $globallang; + } else { + $sitelang = $CFG->lang; + $courselang = get_course_lang($book->course); //Non existing! + $userlang = get_main_teacher_lang($book->course); //N.E.!! + + $fromenc = get_original_encoding($sitelang, $courselang, $userlang); + } +/// We are going to use textlib facilities + +/// Convert the text + if (($fromenc != 'utf-8') && ($fromenc != 'UTF-8')) { + $result = utfconvert($chapter->title, $fromenc); + $newchapter = new object; + $newchapter->id = $recordid; + $newchapter->title = $result; + migrate2utf8_update_record('book_chapters',$newchapter); + } +/// And finally, just return the converted field + return $result; +} + +function migrate2utf8_book_chapters_content($recordid){ + global $CFG, $globallang; + +/// Some trivial checks + if (empty($recordid)) { + log_the_problem_somewhere(); + return false; + } + + if (!$chapter = get_record('book_chapters','id',$recordid)) { + log_the_problem_somewhere(); + return false; + } + + if (!$book = get_record('book','id',$chapter->bookid)) { + log_the_problem_somewhere(); + return false; + } + + if ($globallang) { + $fromenc = $globallang; + } else { + $sitelang = $CFG->lang; + $courselang = get_course_lang($book->course); //Non existing! + $userlang = get_main_teacher_lang($book->course); //N.E.!! + + $fromenc = get_original_encoding($sitelang, $courselang, $userlang); + } +/// We are going to use textlib facilities + +/// Convert the text + if (($fromenc != 'utf-8') && ($fromenc != 'UTF-8')) { + $result = utfconvert($chapter->content, $fromenc); + $newchapter = new object; + $newchapter->id = $recordid; + $newchapter->content = $result; + migrate2utf8_update_record('book_chapters',$newchapter); + } +/// And finally, just return the converted field + return $result; +} + +?> diff --git a/db/migrate2utf8.xml b/db/migrate2utf8.xml new file mode 100755 index 00000000000..01881957676 --- /dev/null +++ b/db/migrate2utf8.xml @@ -0,0 +1,33 @@ + + + + + + + migrate2utf8_book_name(RECORDID) + + + + + migrate2utf8_book_summary(RECORDID) + + + +
+ + + + + migrate2utf8_book_chapters_title(RECORDID) + + + + + migrate2utf8_book_chapters_content(RECORDID) + + + + +
+
+
diff --git a/db/mysql.php b/db/mysql.php new file mode 100644 index 00000000000..f426543c73f --- /dev/null +++ b/db/mysql.php @@ -0,0 +1,36 @@ +prefix}book + CHANGE intro summary TEXT NOT NULL; + "); + } + if ($oldversion < 2004071100) { + execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters + ADD importsrc VARCHAR(255) NOT NULL DEFAULT '' AFTER timemodified; + "); + } + if ($oldversion < 2004071201) { + execute_sql ("UPDATE {$CFG->prefix}log_display + SET action = 'print' + WHERE action = 'prINT'; + "); + } + if ($oldversion < 2004072400) { + execute_sql ("ALTER TABLE {$CFG->prefix}book + ADD disableprinting TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER numbering; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book + ADD customtitles TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER disableprinting; + "); + } + return true; +} + +?> diff --git a/db/mysql.sql b/db/mysql.sql new file mode 100644 index 00000000000..9cf93e54024 --- /dev/null +++ b/db/mysql.sql @@ -0,0 +1,41 @@ +# $Id: mysql.sql,v 1.1 2006/03/12 18:40:01 skodak Exp $ + +# This file contains a complete database schema for all the +# tables used by the book module, written in SQL + +# It may also contain INSERT statements for particular data +# that may be used, especially new entries in the table log_display + +CREATE TABLE prefix_book ( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + course INT(10) UNSIGNED NOT NULL DEFAULT '0', + name VARCHAR(255) NOT NULL DEFAULT '', + summary TEXT NOT NULL DEFAULT '', + numbering TINYINT(4) UNSIGNED NOT NULL DEFAULT '0', + disableprinting TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + customtitles TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + timecreated INT(10) UNSIGNED NOT NULL DEFAULT '0', + timemodified INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (id) +) COMMENT='Defines book'; +# -------------------------------------------------------- + +CREATE TABLE prefix_book_chapters ( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + bookid INT(10) UNSIGNED NOT NULL DEFAULT '0', + pagenum INT(10) UNSIGNED NOT NULL DEFAULT '0', + subchapter TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + title VARCHAR(255) NOT NULL DEFAULT '', + content LONGTEXT NOT NULL DEFAULT '', + hidden TINYINT(2) UNSIGNED NOT NULL DEFAULT '0', + timecreated INT(10) UNSIGNED NOT NULL DEFAULT '0', + timemodified INT(10) UNSIGNED NOT NULL DEFAULT '0', + importsrc VARCHAR(255) NOT NULL DEFAULT '', + PRIMARY KEY (id) +) COMMENT='Defines book_chapters'; +# -------------------------------------------------------- + +INSERT INTO prefix_log_display VALUES ('book', 'update', 'book', 'name'); +INSERT INTO prefix_log_display VALUES ('book', 'view', 'book', 'name'); +INSERT INTO prefix_log_display VALUES ('book', 'view all', 'book', 'name'); +INSERT INTO prefix_log_display VALUES ('book', 'print', 'book', 'name'); diff --git a/db/postgres7.php b/db/postgres7.php new file mode 100644 index 00000000000..ef34d1e1bf9 --- /dev/null +++ b/db/postgres7.php @@ -0,0 +1,65 @@ +prefix}book + CHANGE intro summary TEXT NOT NULL; + "); + } + if ($oldversion < 2004071100) { + + execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters + ADD importsrc VARCHAR(255); + "); + execute_sql ("UPDATE {$CFG->prefix}book_chapters + SET importsrc = ''; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters + ALTER importsrc SET NOT NULL; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters + ALTER importsrc SET DEFAULT ''; + "); + } + if ($oldversion < 2004071201) { + execute_sql ("UPDATE {$CFG->prefix}log_display + SET action = 'print' + WHERE action = 'prINT'; + "); + } + if ($oldversion < 2004081100) { + execute_sql ("ALTER TABLE {$CFG->prefix}book + ADD disableprinting INT2; + "); + execute_sql ("UPDATE {$CFG->prefix}book + SET disableprinting = '0'; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book + ALTER disableprinting SET NOT NULL; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book + ALTER disableprinting SET DEFAULT '0'; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book + ADD customtitles INT2; + "); + execute_sql ("UPDATE {$CFG->prefix}book + SET customtitles = '0'; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book + ALTER customtitles SET NOT NULL; + "); + execute_sql ("ALTER TABLE {$CFG->prefix}book + ALTER customtitles SET DEFAULT '0'; + "); + } + + return true; +} + +?> diff --git a/db/postgres7.sql b/db/postgres7.sql new file mode 100644 index 00000000000..2d6a4ec77b2 --- /dev/null +++ b/db/postgres7.sql @@ -0,0 +1,39 @@ +# $Id: postgres7.sql,v 1.1 2006/03/12 18:40:01 skodak Exp $ + +# This file contains a complete database schema for all the +# tables used by the book module, written in SQL + +# It may also contain INSERT statements for particular data +# that may be used, especially new entries in the table log_display + +CREATE TABLE prefix_book ( + id SERIAL PRIMARY KEY, + course INT4 NOT NULL DEFAULT '0', + name VARCHAR(255) NOT NULL DEFAULT '', + summary TEXT NOT NULL DEFAULT '', + numbering INT4 NOT NULL DEFAULT '0', + disableprinting INT2 NOT NULL DEFAULT '0', + customtitles INT2 NOT NULL DEFAULT '0', + timecreated INT4 NOT NULL DEFAULT '0', + timemodified INT4 NOT NULL DEFAULT '0' +); +# -------------------------------------------------------- + +CREATE TABLE prefix_book_chapters ( + id SERIAL PRIMARY KEY, + bookid INT4 NOT NULL DEFAULT '0', + pagenum INT4 NOT NULL DEFAULT '0', + subchapter INT2 NOT NULL DEFAULT '0', + title VARCHAR(255) NOT NULL DEFAULT '', + content TEXT NOT NULL DEFAULT '', + hidden INT2 NOT NULL DEFAULT '0', + timecreated INT4 NOT NULL DEFAULT '0', + timemodified INT4 NOT NULL DEFAULT '0', + importsrc VARCHAR(255) NOT NULL DEFAULT '' +); +# -------------------------------------------------------- + +INSERT INTO prefix_log_display VALUES ('book', 'update', 'book', 'name'); +INSERT INTO prefix_log_display VALUES ('book', 'view', 'book', 'name'); +INSERT INTO prefix_log_display VALUES ('book', 'view all', 'book', 'name'); +INSERT INTO prefix_log_display VALUES ('book', 'print', 'book', 'name'); diff --git a/delete.php b/delete.php new file mode 100644 index 00000000000..429112597a2 --- /dev/null +++ b/delete.php @@ -0,0 +1,68 @@ +category) { + $navigation = ''.$course->shortname.' ->'; +} else { + $navigation = ''; +} + +print_header( "$course->shortname: $book->name", + $course->fullname, + "$navigation id>$strbooks -> $book->name", + '', + '', + true, + '', + '' + ); + +///form processing +if ($confirm) { // the operation was confirmed. + if (!$chapter->subchapter) { //delete all its subchapters if any + $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, subchapter'); + $found = false; + foreach($chapters as $ch) { + if ($ch->id === $chapter->id) { + $found = true; + } else if ($found and $ch->subchapter) { + if (!delete_records('book_chapters', 'id', $ch->id)) { + error('Could not update your book'); + } + } else if ($found) { + break; + } + } + } + if (!delete_records('book_chapters', 'id', $chapter->id)) { + error('Could not update your book'); + } + + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); + add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); + book_check_structure($book->id); + redirect('view.php?id='.$cm->id); + die; +} else { + // the operation has not been confirmed yet so ask the user to do so + if ($chapter->subchapter) { + $strconfirm = get_string('confchapterdelete','book'); + } else { + $strconfirm = get_string('confchapterdeleteall','book'); + } + echo '
'; + notice_yesno("$chapter->title

$strconfirm

", + "delete.php?id=$cm->id&chapterid=$chapter->id&confirm=1&sesskey=$USER->sesskey", + "view.php?id=$cm->id&chapterid=$chapter->id"); +} + +print_footer($course); + +?> diff --git a/edit.html b/edit.html new file mode 100644 index 00000000000..db4f2f33950 --- /dev/null +++ b/edit.html @@ -0,0 +1,64 @@ + + +
+ + + + + + + + + + + + + + + + +
+ : + + +
+ : + + subchapter) { + $selected = ' checked="checked"'; + } else { + $selected = ''; + } + echo ''; + ?> +
+

:

+ + '; + if ($usehtmleditor) { + helpbutton('richtext', get_string('helprichtext'), 'moodle', true, true); + } else { + emoticonhelpbutton('theform', 'text'); + } + ?>
+
+
+ content); ?> +
+
+ + + id == -1) { + echo ' ('.get_string('doimport', 'book').')'; + } + ?> +
+ + + + +
diff --git a/edit.php b/edit.php new file mode 100644 index 00000000000..ba74f755d2a --- /dev/null +++ b/edit.php @@ -0,0 +1,156 @@ +course)) { + error('Course is misconfigured'); +} + +if (!isteacheredit($course->id)) { + error('Only editing teachers can edit books!', $_SERVER['HTTP_REFERER']); +} + +if (!$book = get_record('book', 'id', $cm->instance)) { + error('Course module is incorrect'); +} + +$chapter = get_record('book_chapters', 'id', $chapterid); + +//check all variables +unset($id); +unset($chapterid); +if ($chapter) { + if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! + error('Chapter not part of this book!'); + } + $pagenum = $chapter->pagenum; +} else { + $pagenum = (integer)$pagenum; +} + +// ========================================================================= +// security checks END +// ========================================================================= + + +/// If data submitted, then process and store. +if (($form = data_submitted()) && (confirm_sesskey())) { + //TODO: skip it for now + //prepare data - security checks + //$form->title = clean_text($form->title, FORMAT_HTML); + //$form->content = clean_text($form->content, FORMAT_HTML); + + if (isset($form->subchapter) ) { + $form->subchapter = 1; + } else { + $form->subchapter = 0; + } + if ($chapter) { + /// editing existing chapter + $chapter->content = $form->content; + $chapter->title = $form->title; + $chapter->subchapter = $form->subchapter; + $chapter->timemodified = time(); + $chapter->importsrc = addslashes($chapter->importsrc); //use already stored importsrc + if (!update_record('book_chapters', $chapter)) { + error('Could not update your book'); + } + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); + add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + } else { + /// adding new chapter + $chapter->bookid = $book->id; + $chapter->pagenum = $form->pagenum + 1; //place after given pagenum, lets hope it is a number + $chapter->subchapter = $form->subchapter; + $chapter->title = $form->title; + $chapter->content = $form->content; + $chapter->hidden = 0; + $chapter->timecreated = time(); + $chapter->timemodified = $chapter->timecreated; + $chapter->importsrc = ''; + + $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, pagenum'); + if ($chapters) { + foreach($chapters as $ch) { + if ($ch->pagenum > $pagenum) { + $ch->pagenum = $ch->pagenum + 1; + if (!update_record('book_chapters', $ch)) { + error('Could not update your book'); + } + } + } + } + if (!$chapter->id = insert_record('book_chapters', $chapter)) { + error('Could not insert a new chapter'); + } + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); + add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + } + + book_check_structure($book->id); + redirect("view.php?id=$cm->id&chapterid=$chapter->id"); + die; +} + +/// Otherwise fill and print the form. +$strbook = get_string('modulename', 'book'); +$strbooks = get_string('modulenameplural', 'book'); +$stredit = get_string('edit'); +$pageheading = get_string('editingchapter', 'book'); + +$usehtmleditor = can_use_html_editor(); + +if (!$chapter) { + $chapter->id = -1; + $chapter->title = ''; + $chapter->content = ''; + $chapter->subchapter = $subchapter; + $chapter->pagenum = $pagenum; +} + +///prepare the page header +if ($course->category) { + $navigation = ''.$course->shortname.' ->'; +} else { + $navigation = ''; +} + +print_header( "$course->shortname: $book->name", + $course->fullname, + "$navigation id\">$strbooks -> id\">$book->name -> $stredit", + '', + '', + true, + '', + '' + ); + + +$icon = ' '; +print_heading_with_help($pageheading, 'edit', 'book', $icon); +print_simple_box_start('center', ''); +include('edit.html'); +print_simple_box_end(); + +if ($usehtmleditor ) { + use_html_editor(); +} + +print_footer($course); + +?> diff --git a/icon.gif b/icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..bcdde5ac1dcbc217ca7282abe6e0b1771177862d GIT binary patch literal 111 zcmZ?wbhEHb6krfwSj7MW4Gs+d|Nn1jXaMt|gyK&YMg|5J1|1L|q?Uo%#ADZ;bqoi# zKa!X@NyB9d|8qvh7d3$aK`ATOExdJT`JY+7){lGYHk(OaQ0)<{w3Xh}UZujoU=08) CEg|Lr literal 0 HcmV?d00001 diff --git a/icon_chapter.gif b/icon_chapter.gif new file mode 100644 index 0000000000000000000000000000000000000000..3e02109f135ba5000ef02967bb441874c6147c4c GIT binary patch literal 112 zcmZ?wbhEHb6krfwSjE85;J^R`|Ns9#aNq!l1p|sdSr{1@SQvCb0wA>v%%&c@?yOU^ z5kI&8OIkO)y%0KR9@LcNnYMQtAt~XYf4USyW+VR-zruK=`nRQDzE*e{EN^>$; F0|2NBBmMvY literal 0 HcmV?d00001 diff --git a/import.php b/import.php new file mode 100644 index 00000000000..0cbed029c54 --- /dev/null +++ b/import.php @@ -0,0 +1,188 @@ +course)) { + error('Course is misconfigured'); +} + +if (!isteacheredit($course->id)) { + error('Only editing teachers can edit books!'); +} + +if (!$book = get_record('book', 'id', $cm->instance)) { + error('Course module is incorrect'); +} + +//check all variables +unset($id); + +// ========================================================================= +// security checks END +// ========================================================================= + +///cancel pressed, go back to book +if ($cancel) { + redirect('view.php?id='.$cm->id); + die; +} + +///prepare the page header +$strbook = get_string('modulename', 'book'); +$strbooks = get_string('modulenameplural', 'book'); +$strimport = get_string('import', 'book'); + +if ($course->category) { + $navigation = ''.$course->shortname.' ->'; +} else { + $navigation = ''; +} + +print_header( "$course->shortname: $book->name", + $course->fullname, + "$navigation id\">$strbooks -> id\">$book->name -> $strimport", + '', + '', + true, + '', + '' + ); + +/// If data submitted, then process, store and relink. +if (($form = data_submitted()) && (confirm_sesskey())) { + $form->reference = stripslashes($form->reference); + if ($form->reference != '') { //null path is root + $form->reference = book_prepare_link($form->reference); + if ($form->reference == '') { //evil characters in $ref! + error('Invalid character detected in given path!'); + } + } + $coursebase = $CFG->dataroot.'/'.$book->course; + if ($form->reference == '') { + $base = $coursebase; + } else { + $base = $coursebase.'/'.$form->reference; + } + + //prepare list of html files in $refs + $refs = array(); + $htmlpat = '/\.html$|\.htm$/i'; + if (is_dir($base)) { //import whole directory + $basedir = opendir($base); + while ($file = readdir($basedir)) { + $path = $base.'/'.$file; + if (filetype($path) === 'file' and preg_match($htmlpat, $file)) { + $refs[] = str_replace($coursebase, '', $path); + } + } + asort($refs); + } else if (is_file($base)) { //import single file + $refs[] = '/'.$form->reference; + } else { //what is it??? + error('Incorrect file/directory specified!'); + } + + //import files + echo '
'; + echo ''.get_string('importing', 'book').':'; + echo ''; + book_check_structure($book->id); + foreach($refs as $ref) { + $chapter = book_read_chapter($coursebase, $ref); + if ($chapter) { + $chapter->title = addslashes($chapter->title); + $chapter->content = addslashes($chapter->content); + $chapter->importsrc = addslashes($chapter->importsrc); + $chapter->bookid = $book->id; + $chapter->pagenum = count_records('book_chapters', 'bookid', $book->id)+1; + $chapter->timecreated = time(); + $chapter->timemodified = time(); + echo "imsrc:".$chapter->importsrc; + if (($subchapter) || preg_match('/_sub\.htm/i', $chapter->importsrc)) { //if filename or directory starts with sub_* treat as subdirecotories + $chapter->subchapter = 1; + } else { + $chapter->subchapter = 0; + } + if (!$chapter->id = insert_record('book_chapters', $chapter)) { + error('Could not update your book'); + } + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); + add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + } + } + echo '

'; + echo ''.get_string('relinking', 'book').':'; + echo ''; + //relink whole book = all chapters + book_relink($cm->id, $book->id, $course->id); + echo '

'; + echo ''.get_string('continue').''; + echo '
'; +} else { +/// Otherwise fill and print the form. + $strdoimport = get_string('doimport', 'book'); + $strchoose = get_string('choose'); + $pageheading = get_string('importingchapters', 'book'); + + $icon = ' '; + print_heading_with_help($pageheading, 'import', 'book', $icon); + print_simple_box_start('center', ''); + ?> +
+ + + + + + + + + + + + + +
+ : + +  '; + button_to_popup_window ('/mod/book/coursefiles.php?choose=theform.reference&id='.$course->id, + 'coursefiles', $strchoose, 500, 750, $strchoose); + ?> +
+ : + + '; + ?> +
 

+
+ + " /> +
+ + +
+ + diff --git a/index.php b/index.php new file mode 100644 index 00000000000..7f315062077 --- /dev/null +++ b/index.php @@ -0,0 +1,118 @@ +forcelogin) { + require_login(); +} + +if (!$course = get_record('course', 'id', $id)) { + error('Course ID is incorrect'); +} + +if ($course->category) { + require_login($course->id); +} + +//check all variables +unset($id); + +// ========================================================================= +// security checks END +// ========================================================================= + +/// Get all required strings +$strbooks = get_string('modulenameplural', 'book'); +$strbook = get_string('modulename', 'book'); + +/// Print the header +if ($course->category) { + $navigation = ''.$course->shortname.' ->'; +} else { + $navigation = ''; +} + +print_header( "$course->shortname: $strbooks", + $course->fullname, + "$navigation $strbooks", + '', + '', + true, + '', + navmenu($course) + ); + +add_to_log($course->id, 'book', 'view all', 'index.php?id='.$course->id, ''); + +/// Get all the appropriate data +if (!$books = get_all_instances_in_course('book', $course)) { + notice('There are no books', '../../course/view.php?id='.$course->id); + die; +} + +/// Print the list of instances +$strname = get_string('name'); +$strweek = get_string('week'); +$strtopic = get_string('topic'); +$strsummary = get_string('summary'); +$strchapters = get_string('chapterscount', 'book'); + +if ($course->format == 'weeks') { + $table->head = array ($strweek, $strname, $strsummary, $strchapters); + $table->align = array ('center', 'left', 'left', 'center'); +} else if ($course->format == 'topics') { + $table->head = array ($strtopic, $strname, $strsummary, $strchapters); + $table->align = array ('center', 'left', 'left', 'center'); +} else { + $table->head = array ($strname, $strsummary, $strchapters); + $table->align = array ('left', 'left', 'left'); +} + +$currentsection = ''; +foreach ($books as $book) { + $nocleanoption = new object(); + $nocleanoption->noclean = true; + $book->summary = format_text($book->summary, FORMAT_HTML, $nocleanoption, $course->id); + $book->summary = ''.$book->summary.''; + + if (!$book->visible) { + //Show dimmed if the mod is hidden + $link = ''.$book->name.''; + } else { + //Show normal if the mod is visible + $link = ''.$book->name.''; + } + + $count = count_records('book_chapters', 'bookid', $book->id, 'hidden', '0'); + + if ($course->format == 'weeks' or $course->format == 'topics') { + $printsection = ''; + if ($book->section !== $currentsection) { + if ($book->section) { + $printsection = $book->section; + } + if ($currentsection !== '') { + $table->data[] = 'hr'; + } + $currentsection = $book->section; + } + $table->data[] = array ($printsection, $link, $book->summary, $count); + } else { + $table->data[] = array ($link, $book->summary, $count); + } +} + +echo '
'; +print_table($table); + +print_footer($course); + +?> diff --git a/lang/be_utf8/book.php b/lang/be_utf8/book.php new file mode 100644 index 00000000000..7b1ce6b17d6 --- /dev/null +++ b/lang/be_utf8/book.php @@ -0,0 +1,42 @@ + Раздзелы адсартуюцца па алфавіту па назве файлаў.'; +$string['importing'] = 'Імпартаванне'; +$string['importingchapters'] = 'Імпартаванне радзелаў у кнігу'; +$string['maindirectory'] = 'Галоўная тэчка'; +$string['modulename'] = 'Падручнік'; +$string['modulenameplural'] = 'Падручнікі'; +$string['navexit'] = 'Выйсці з падручніка'; +$string['navnext'] = 'Далей'; +$string['navprev'] = 'Назад'; +$string['numbering'] = 'Нумарацыя раздзела'; +$string['numbering0'] = 'Няма'; +$string['numbering1'] = 'Нумары'; +$string['numbering2'] = 'Маркеры'; +$string['numbering3'] = 'Павялічыць водступ'; +$string['printbook'] = 'Друкаваць увесь падручнік'; +$string['printchapter'] = 'Друкаваць раздзел'; +$string['printdate'] = 'Дата'; +$string['printedby'] = 'Надрукаваны'; +$string['relinking'] = 'Перакампанаваць'; +$string['subchapter'] = 'Параграф'; +$string['toc'] = 'Змест'; +$string['tocwidth'] = 'Вызначыць шырыню зместу для ўсіх падручнікаў'; +$string['top'] = 'наверх'; + +?> diff --git a/lang/be_utf8/help/book/customtitles.html b/lang/be_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..a79febf4125 --- /dev/null +++ b/lang/be_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Прыватныя загалоўкі

+ +

Загалоўкі раздзелаў аўтаматычны адлюстроўваюцца толькі ў змесце падручніка.

\ No newline at end of file diff --git a/lang/be_utf8/help/book/disableprinting.html b/lang/be_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..a9b457fe03b --- /dev/null +++ b/lang/be_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Забараніць друкаванне

+ +

Схаваць цэтлік друку.

\ No newline at end of file diff --git a/lang/be_utf8/help/book/edit.html b/lang/be_utf8/help/book/edit.html new file mode 100644 index 00000000000..8c6efd366a8 --- /dev/null +++ b/lang/be_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Рэдагаванне раздзела

+ +

Калі ласка, прызначайце кароткі (па колькасці сімвалаў) загаловак раздзелу.

+ +

Максімальная глыбіня падраздзелаў - два.

+ +

Калі Вы маеце праблемы пры выкарыстанні HTML-рэдактара, лепей абярыце новы браўзэр, напрыклад Mozilla Firefox, або ў наладах уліковага запісу пазначце выкарыстанне Web-форм замест рэдактара ў полі "Падчас рэдагавання тэксту".

\ No newline at end of file diff --git a/lang/be_utf8/help/book/faq.html b/lang/be_utf8/help/book/faq.html new file mode 100644 index 00000000000..129c7c63981 --- /dev/null +++ b/lang/be_utf8/help/book/faq.html @@ -0,0 +1,39 @@ +

+ Часта задаваемыя пытанні аб падручніку +

+
+
+ Чаму толькі два ўзроўня (раздзел і параграф)? +
+
+ Два ўзроўня звычайна дастаткова для ўсіх кніг, трэці ўзровень будзе весці да дрэнна структураваных дакументаў. Модуль "Падручнік" спраектаваны для стварэння невялічкіх шматстаронкавых навучальных матэрыялаў. Звычайна для вялікіх дакументаў лепей выкарыстоўваць файлы фармата PDF. Лёгкі шлях да стварэння PDF-файла - выкарыстанне віртуальнага прынтэра (гл. + PDFCreator, + + PDFFactory, + Adobe Acrobat, + і г.д..). +
+
+
+
+ Студэнты могуць рэдагаваць падручнік? +
+
+ Толькі настаўнікі могуць ствараць і рэдагваць падручнікі. Пакуль няма планаў, каб дадаць првы студэнтаў на рэдагаванне падручніка, але кожны можа стварыць нешта вельмі падобнае для студэнтаў, напрыклад, партфоліо. Галоўная прычына гэтага - пакінуць модуль "Падручнік" як мага простым. +
+
+
+ Як праводзіць пошук падручнікаў і ў іх? +
+
+ На бюягучы момант для пошуку ў падручніку лепей выкарыстоўваць сродкі пошука браўзэра і шукаць дадзеныя на старонцы, якая падрыхтавана для друку. Глабальны пошук магчымы толькі ў форумах Moodle. Было б зручна, калі б быў глабальны пошук па ўсіх рэсурсах, ўключаючы падручнікі. Ці ёсць валанцёры для напісання такога скрыпта? +
+
+
+ Мой загаловак не змяшчаецца ў адзін радок. +
+
+ Калі магчыма, дык скараціце загалоўкі або звяртайцеся да адміністратара сайта, каб змяніў шырыню радка загалоўка. Яна вызначаецца ў наладах модуля для ўсіх падручнікаў на сайце. +
+
+
\ No newline at end of file diff --git a/lang/be_utf8/help/book/import.html b/lang/be_utf8/help/book/import.html new file mode 100644 index 00000000000..e96dfe74d63 --- /dev/null +++ b/lang/be_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Імпарт

+ +

Вы можаце імпартаваць адзін HTML-файл або ўсе HTML-файлы, якія знаходзяцца ў тэчцы.

+ +

Адносныя спасылкі паміж файламі пераўтвараюцца ў абсалютныя спасылкі паміж раздзеламі. Малюнкі, flash і Java таксама правільна імпартуюцца.

\ No newline at end of file diff --git a/lang/be_utf8/help/book/index.html b/lang/be_utf8/help/book/index.html new file mode 100644 index 00000000000..f6a03549276 --- /dev/null +++ b/lang/be_utf8/help/book/index.html @@ -0,0 +1,10 @@ +

Book module

+ \ No newline at end of file diff --git a/lang/be_utf8/help/book/mods.html b/lang/be_utf8/help/book/mods.html new file mode 100644 index 00000000000..be59a96e831 --- /dev/null +++ b/lang/be_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

Падручнікі

+
    +

    Падручнік - гэта просты шматстаронкавы навучальны матэрыял.

    +
\ No newline at end of file diff --git a/lang/be_utf8/help/book/numberingtype.html b/lang/be_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..f46d9451c5a --- /dev/null +++ b/lang/be_utf8/help/book/numberingtype.html @@ -0,0 +1,12 @@ +

Нумарацыя раздзелаў

+ +

Існуе неклаькі вызначаных шляхоў нумарацыі: + +

Няма - усе загалоўкі раздзелаў і параграфаў не фарматуюцца. Калі жадаеца, то ў дадзеным выпадку можаце скарыстаць спецыяльныя стылі для нумарацыі. Напрыклад, выкарыстоўваць літары пры нумарацыі загалоўкаў: "А. Першы раздзел", "А.1. Першы параграф перашага раздзела", ...

+ +

Лічбы - раздзелы і параграфы нумаруюцца (1, 1.1, 1.2, 2, +...)

+ +

Маркеры - параграфы паказваюцца з водступам і пазначаюцца маркерамі.

+ +

З водступам - параграфы паказваюцца з водступам.

\ No newline at end of file diff --git a/lang/be_utf8/help/book/summary.html b/lang/be_utf8/help/book/summary.html new file mode 100644 index 00000000000..9d46653b1ec --- /dev/null +++ b/lang/be_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Абагульненне

+ +

Абагульненне - гэта кароткія звесткі аб падручніку.

+ +

Калі ласка, не спрабуйце пісаць вялізнае абагульненне!

\ No newline at end of file diff --git a/lang/ca_utf8/book.php b/lang/ca_utf8/book.php new file mode 100644 index 00000000000..794fec852ec --- /dev/null +++ b/lang/ca_utf8/book.php @@ -0,0 +1,49 @@ +Els capítols estan ordenats alfabèticament pel nom del fitxer.'; +$string['maindirectory'] = 'Directori principal'; +$string['fileordir'] = 'Fitxer o directori'; + +?> diff --git a/lang/ca_utf8/help/book/customtitles.html b/lang/ca_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..6d0ed70bf68 --- /dev/null +++ b/lang/ca_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Títols personalitzats

+ +

Els títols de capítols es mostren automàticament només a l'índex.

diff --git a/lang/ca_utf8/help/book/disableprinting.html b/lang/ca_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..78c66b0dbf3 --- /dev/null +++ b/lang/ca_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Deshabilita la impressió

+ +

Oculta les icones d'imprimir.

diff --git a/lang/ca_utf8/help/book/edit.html b/lang/ca_utf8/help/book/edit.html new file mode 100644 index 00000000000..2ae442a2a22 --- /dev/null +++ b/lang/ca_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Edició de capítol

+ +

Procureu mantenir curt el títol del capítol.

+ +

El nivell màxim de subcapítols és de dos.

+ +

Si teniu problemes emprant l'editor HTML integrat, proveu d'usar un altre navegador (com ara el Mozilla Firefox) o bé desactivar completament l'editor en el vostre perfil.

diff --git a/lang/ca_utf8/help/book/faq.html b/lang/ca_utf8/help/book/faq.html new file mode 100644 index 00000000000..2731dcc2e0f --- /dev/null +++ b/lang/ca_utf8/help/book/faq.html @@ -0,0 +1,39 @@ +

+ Preguntes Més Freqüents sobre els Llibres +

+
+
+ Per què només dos nivells? +
+
+ Dos nivells acostuma a ser suficient per la majoria de llibres; tres nivells conduirien a documents amb una estructura pobra. El mòdul de llibres està dissenyat per a crear materials d'estudi multipàgina curts. Per a documents més llargs és preferible emprar el format PDF. La manera més simple de crear PDF són les impressores virtuals (vegeu + PDFCreator, + + PDFFactory, + Adobe Acrobat, + etc.). [N. del T.: A banda del mètode de les impressores virtuals, molts programes lliures (p.ex. OpenOffice) permeten exportar els documents directament a format PDF] +
+
+
+
+ Els estudiants poden editar els llibres? +
+
+ Només els professors poden crear i modificar els llibres. No tenim previst implementar la modificació de llibres per part d'estudiants, però algú podria crear quelcom semblant per a estudiants (portafoli?). La raó principal és la de mantenir el mòdul de Llibres el més senzill possible. +
+
+
+ Com puc fer cerques dins dels llibres? +
+
+ De moment només hi ha una manera: emprar les facilitats de cerca del navegador en una pàgina d'impressió. Les cerques globals només són possibles actualment als fòrums de Moodle. Estaria bé poder fer cerques globals en tots els recursos, llibres inclosos; algun voluntari? +
+
+
+ Els meus títols no caben en una línia. +
+
+ Mireu de reescriure els vostres títols o bé demaneu a l'administrador del lloc que un canvïi l'amplada de l'índex. Aquesta amplada és definida de forma global per a tots els llibres a la pàgina de configuració del mòdul. +
+
+
diff --git a/lang/ca_utf8/help/book/import.html b/lang/ca_utf8/help/book/import.html new file mode 100644 index 00000000000..a0d42aeb946 --- /dev/null +++ b/lang/ca_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Importació

+ +

Podeu importar un únic fitxer HTML o bé tots els fitxers HTML d'un directori.

+ +

Els enllaços relatius seran convertits a enllaços absoluts a capítols. Les imatges i els arxius flash o java també es reenllaçaran.

diff --git a/lang/ca_utf8/help/book/index.html b/lang/ca_utf8/help/book/index.html new file mode 100644 index 00000000000..725a957f9c2 --- /dev/null +++ b/lang/ca_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Mòdul de Llibres

+ + diff --git a/lang/ca_utf8/help/book/mods.html b/lang/ca_utf8/help/book/mods.html new file mode 100644 index 00000000000..697a995d3fa --- /dev/null +++ b/lang/ca_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Llibres

+
    +

    Un llibre és un material d\'estudi multipàgina senzill

    +
diff --git a/lang/ca_utf8/help/book/numberingtype.html b/lang/ca_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..28ecf7973aa --- /dev/null +++ b/lang/ca_utf8/help/book/numberingtype.html @@ -0,0 +1,12 @@ +

Numeració de capítols

+ +

Hi ha uns quants tipus de numeració predefinits: + +

Cap - als títols de capítols i subcapítols no se'ls aplica format; useu-lo si voleu definir estils de numeració especials, com ara lletres: en aquest cas, en el títol del capítol escriviu: "A. Primer capítol", "A.1. Un subcapítol",...

+ +

Nombres - els capítols i subcapítols es numeren (1, 1.1, 1.2, 2, +...)

+ +

Pics - els subcapítols s'indenten i es mostren amb pics.

+ +

Indentats - els subcapítols s'indenten.

diff --git a/lang/ca_utf8/help/book/summary.html b/lang/ca_utf8/help/book/summary.html new file mode 100644 index 00000000000..1beb8a5f9fc --- /dev/null +++ b/lang/ca_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Resum

+ +

El resum és una descripció molt curta del llibre.

+ +

No estigueu temptats d'escriure massa coses aquí!

diff --git a/lang/cs_utf8/book.php b/lang/cs_utf8/book.php new file mode 100644 index 00000000000..01a57ba54b1 --- /dev/null +++ b/lang/cs_utf8/book.php @@ -0,0 +1,42 @@ +Kapitoly budou seřazeny abecedně podle názvů souborů.
Soubory s názvem ve tvaru \'sub_*.*\' jsou vždy importovány jako podkapitoly.'; +$string['importing'] = 'Importuji'; +$string['importingchapters'] = 'Importování kapitol'; +$string['maindirectory'] = 'Hlavní složka'; +$string['modulename'] = 'Kniha'; +$string['modulenameplural'] = 'Knihy'; +$string['navnext'] = 'Následující'; +$string['navprev'] = 'Předchozí'; +$string['navexit'] = 'Zpět na přehled'; +$string['numbering'] = 'Číslování kapitol'; +$string['numbering0'] = 'Žádné'; +$string['numbering1'] = 'Čísla'; +$string['numbering2'] = 'Puntíky'; +$string['numbering3'] = 'Odsazené'; +$string['printbook'] = 'Vytisknout celou knihu'; +$string['printchapter'] = 'Vytisknout jednu kapitolu'; +$string['printdate'] = 'Datum'; +$string['printedby'] = 'Vytiskl(a)'; +$string['relinking'] = 'Relinkuji'; +$string['subchapter'] = 'Podkapitola'; +$string['toc'] = 'Obsah'; +$string['tocwidth'] = 'Vyberte šířku obsahu pro všechny knihy.'; +$string['top'] = 'začátek'; + +?> diff --git a/lang/cs_utf8/help/book/customtitles.html b/lang/cs_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..70879bab8be --- /dev/null +++ b/lang/cs_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Uživatelské nadpisy

+ +

Nadpisy jsou zobrazeny pouze v obsahu knihy.

diff --git a/lang/cs_utf8/help/book/disableprinting.html b/lang/cs_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..42c9cb6cad1 --- /dev/null +++ b/lang/cs_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Zakázat tisknutí

+ +

Skrýt ikony pro tisk.

diff --git a/lang/cs_utf8/help/book/edit.html b/lang/cs_utf8/help/book/edit.html new file mode 100644 index 00000000000..51eb694344b --- /dev/null +++ b/lang/cs_utf8/help/book/edit.html @@ -0,0 +1,8 @@ +

Úprava kapitol

+ +

Snažte se psát pouze krátké kapitoly.

+ +

Knika může mít pouze dvě úrovně nadpisů.

+ +

jestliže máte problémy s HTML editorem, můžete si zkusit nainstalovat jiný prohlížeč +(napřiklad Mozilla Firefox).

\ No newline at end of file diff --git a/lang/cs_utf8/help/book/faq.html b/lang/cs_utf8/help/book/faq.html new file mode 100644 index 00000000000..68d1caacfb4 --- /dev/null +++ b/lang/cs_utf8/help/book/faq.html @@ -0,0 +1,41 @@ +

+ Často kladené otázky +

+
+
+ Proč pouze dvě úrovně? +
+
+ Dvě úrovně nadpisu stačí, vždy se snažte psát krátce a srozumitelně. + Jestliže si myslíte, že potřebuje víc úrovní, rozdělte text do několika knih. + Pro delší texty je většinou vhodnější PDF formát. PDF soubory můžete + vytvořit pomocí následujících programů: + PDFCreator, + + PDFFactory, + Adobe Acrobat. +
+
+
+
+ Mohou studenti upravovat knihy? +
+
+ Knihy mohou vytvářet a upravovat pouze učitelé. +
+
+
+ Mohu vyhledávat v knihách? +
+
+ Použijte vyhledávání ve vašem prohlížeči. +
+
+
+ Nadpisy se mi nevejdou na jeden řádek. +
+
+ Buďto zkraťte nadpis, nebo požádejte vašeho správce, aby změnil šířku obsahu. +
+
+
diff --git a/lang/cs_utf8/help/book/import.html b/lang/cs_utf8/help/book/import.html new file mode 100644 index 00000000000..9f4d433f97d --- /dev/null +++ b/lang/cs_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Import

+ +

Můžete importovat jeden HTML soubor nebo všechny soubory ve složce.

+ +

Relativní odkazy jsou převedeny na odkazy na kapitoly. Odkazy na obrázky, flash a Javu jsou rovněž upraveny.

diff --git a/lang/cs_utf8/help/book/index.html b/lang/cs_utf8/help/book/index.html new file mode 100644 index 00000000000..b867e3397c9 --- /dev/null +++ b/lang/cs_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Modul Kniha

+ + diff --git a/lang/cs_utf8/help/book/mods.html b/lang/cs_utf8/help/book/mods.html new file mode 100644 index 00000000000..6cbac92e3e2 --- /dev/null +++ b/lang/cs_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Knihy

+
    +

    Kniha je jednoduchý vícestránkový studijní materiál.

    +
diff --git a/lang/cs_utf8/help/book/numberingtype.html b/lang/cs_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..aa9f93e4e24 --- /dev/null +++ b/lang/cs_utf8/help/book/numberingtype.html @@ -0,0 +1,14 @@ +

Číslování kapitol

+ +

Existuje několik předdefinovaných typů číslování: + +

Žádné - kapitoly a podkapitoly nejsou formátované, používejte v přípaže, +když chcete zadat vaše vlastní číslování. Například: do pole nadpis kapitoly zadejte +"A Úvod", "A.1 Nějaké Povídání", ...

+ +

Čísla - kapitoly a podkapitoly jsou číslované (1, 1.1, 1.2, 2, ...)

+ +

Puntíky - podkapitoly jsou odsazené a zvýrazněné puntíky.

+ +

Odsazené - podkapitoly jsou odsazené.

+ diff --git a/lang/cs_utf8/help/book/summary.html b/lang/cs_utf8/help/book/summary.html new file mode 100644 index 00000000000..b0b86f379ba --- /dev/null +++ b/lang/cs_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Souhrn

+ +

Stručný obsah knihy.

+ +

Snažte se o opravdu krátký a výstižný popis.

\ No newline at end of file diff --git a/lang/de_utf8/book.php b/lang/de_utf8/book.php new file mode 100644 index 00000000000..dd6c77866d8 --- /dev/null +++ b/lang/de_utf8/book.php @@ -0,0 +1,48 @@ +Kapitel sind alphabetisch nach den Dateinamen sortiert.'; +$string['maindirectory'] = 'Hauptordner'; +$string['fileordir'] = 'Datei oder Ordner'; + +?> diff --git a/lang/de_utf8/help/book/customtitles.html b/lang/de_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..7aa14ab8432 --- /dev/null +++ b/lang/de_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Eigene Titel

+ +

Kapiteltitel werden automatisch nur in der TOC angezeigt.

diff --git a/lang/de_utf8/help/book/disableprinting.html b/lang/de_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..d5b2b196244 --- /dev/null +++ b/lang/de_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Drucken ausgeschaltet

+ +

Verstecken der Druck Icons.

diff --git a/lang/de_utf8/help/book/edit.html b/lang/de_utf8/help/book/edit.html new file mode 100644 index 00000000000..60a50dc336e --- /dev/null +++ b/lang/de_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Kapiteländerung

+ +

Versuchen Sie Titel der Kapitel kurz zu halten.

+ +

Maximal zwei Stufe können die Unterkapitel haben.

+ +

Wenn SIe Probleme mit dem WYSIWYG HTML Editor haben, versuchen Sie einen anderen Browser z.B. Mozilla Firefox zu benutzen oder schlaten Sie den Editor im Profil ab.

\ No newline at end of file diff --git a/lang/de_utf8/help/book/faq.html b/lang/de_utf8/help/book/faq.html new file mode 100644 index 00000000000..608e9430739 --- /dev/null +++ b/lang/de_utf8/help/book/faq.html @@ -0,0 +1,34 @@ +

Frequently Asked Questions über Bücher

+ +
+
Warum nur zwei Stufen?
+
Zwei Stufen sind genug für alle Bücher, drei Stufen würden zu einem +schlecht strukturierte Dokumnt führen. Das Buch Modul wurde für die Erstellung +von kurzen Inhalten entwickelt. Für größere und komplexere Dokumente macht es +mehr Sinn das PDF Format zu benutzen. Am einfachsten können Sie PDF Dateien mit +den folgenden Programmen erzeugen + (see PDFCreator, PDF +Factory, Adobe Acrobat, +etc.).
+

+
Können Lerner Bücher editieren?
+
Nur Lehrer können Bücher erstellen und ändern. Es ist nicht geplant +auch für Lerner zu ermöglichen. Aber vielleicht findet sich ja jemand +diese Funktion auch für Lerner erstellt. Der Hauptgrund ist jedoch, daß das +Buch Modul so simpel wie möglich bleiben sollt.

+
Wie kann ich in Büchern suchen?
+
Zur Zeit gibt es nur die Möglichkeit mit der Browsersuchfunktion +in einem Buch zu suchen. Eine globale Suche ist nur in Moodle Foren möglich. +Es wäre toll wenn es eine Art globale Suche für alle Resourcen auch Bücher +in moddle geben würde. Gibt es evtl. jemanden der dies Umsetzen könnte?

+
Mei Titel passt nicht in eine Zeile.
+
Ändern SIe Ihren Titel oder bitten Sie Ihren Administrator der Webseite darum, +daß er die Breite des TOC vergrößert. Dies ist global für alle Bücher in der Modul +Konfigurationsseite einstellbar.

+
diff --git a/lang/de_utf8/help/book/import.html b/lang/de_utf8/help/book/import.html new file mode 100644 index 00000000000..201e8c24e29 --- /dev/null +++ b/lang/de_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Import

+ +

Sie können eine einzelnes HTML Datei importieren oder jede HTML Datei in einem Ordner.

+ +

Relative Datei Verknüpfungen werden zu absoluten Kapitelverlinkungen konvertiert. Bilder, Flash und Java Inhalte werden ebenfalls verlinkt.

diff --git a/lang/de_utf8/help/book/index.html b/lang/de_utf8/help/book/index.html new file mode 100644 index 00000000000..e99b390fd16 --- /dev/null +++ b/lang/de_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Book module

+ + diff --git a/lang/de_utf8/help/book/mods.html b/lang/de_utf8/help/book/mods.html new file mode 100644 index 00000000000..0cbf5aae0f1 --- /dev/null +++ b/lang/de_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Books

+
    +

    Das Buch ist ein simples mehrseitiges Studienmaterial.

    +
diff --git a/lang/de_utf8/help/book/numberingtype.html b/lang/de_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..e79717c0513 --- /dev/null +++ b/lang/de_utf8/help/book/numberingtype.html @@ -0,0 +1,14 @@ +

Nummerierung von Kapiteln

+ +

Es gibt verschiedene vordefinierte Nummerierungstypen: + +

Keine - Kapitel und die Titel der Unterkapitel sind nicht formatiert, Sie können +selber eigene Styles zur Nummerierung benutzen. Zum Beispiel Buchstaben: Im Kapitel Titel +geben Sie dann folgendes ein "A Erstes Kapitel", "A.1 ein Unterkapitel",...

+ +

Nummern - Kapitel und Unterkapitel sind nummeriert (1, 1.1, 1.2, 2, +...)

+ +

Kugeln - Unterkapitel sind eingerückt und werden mit führenden Kugeln angezeigt.

+ +

Eingerückt - Unterkapitel sind eingerückt.

diff --git a/lang/de_utf8/help/book/summary.html b/lang/de_utf8/help/book/summary.html new file mode 100644 index 00000000000..6ffdf0f6d80 --- /dev/null +++ b/lang/de_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Reading Summary

+ +

Diese Einführung ist eine sehr kurze Beschreibung des Buches.

+ +

Schreiben Sie hier nicht zu viel hinein!

\ No newline at end of file diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php new file mode 100644 index 00000000000..19113cd9a5e --- /dev/null +++ b/lang/en_utf8/book.php @@ -0,0 +1,49 @@ +Chapters are sorted alphabetically using file names.
Files named \'sub_*.*\' are always imported as subchapters.'; +$string['maindirectory'] = 'Main directory'; +$string['fileordir'] = 'File or directory'; + +?> diff --git a/lang/en_utf8/help/book/customtitles.html b/lang/en_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..0e5b330b453 --- /dev/null +++ b/lang/en_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Custom Titles

+ +

Chapter titles are displayed automatically only in TOC.

diff --git a/lang/en_utf8/help/book/disableprinting.html b/lang/en_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..2f3635725a0 --- /dev/null +++ b/lang/en_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Disable Printing

+ +

Hide print icons.

diff --git a/lang/en_utf8/help/book/edit.html b/lang/en_utf8/help/book/edit.html new file mode 100644 index 00000000000..9c51f792f24 --- /dev/null +++ b/lang/en_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Chapter editing

+ +

Try to keep the chapter title short.

+ +

Maximum level of subchapters is two.

+ +

If you have encounter problems when using WYSIWYG html editor, try switching to another browser (such as Mozilla Firefox) or turn off the editor completely in your profile.

\ No newline at end of file diff --git a/lang/en_utf8/help/book/faq.html b/lang/en_utf8/help/book/faq.html new file mode 100644 index 00000000000..6f42283cf43 --- /dev/null +++ b/lang/en_utf8/help/book/faq.html @@ -0,0 +1,51 @@ +

+ Frequently Asked Questions about Books +

+
+
+ Why only two levels? +
+
+ Two levels are generally enough for all books, three levels would + lead to poorly structured documents. Book module is designed for + creation of short multipage study materials. It is usually better to + use PDF format for longer documents. The easiest way to create PDFs are + virtual printers (see + PDFCreator, + + PDFFactory, + Adobe Acrobat, + etc.). +
+
+
+
+ Can students edit books? +
+
+ Only teachers can create and edit books. There are no plans to + implement student editing for books, but somebody may create something + similar for students (Portfolio?). The main reason is to keep Book + module as simple as possible. +
+
+
+ How do I search the books? +
+
+ At present there is only one way, use browser's search capability + in print page. Global searching is now possible only in Moodle forums. + It would be nice to have global searching for all resources including + books, any volunteers? +
+
+
+ My titles do not fit on one line. +
+
+ Either rephrase your titles or ask your site admin to change TOC + width. It is defined globally for all books in module configuration + page. +
+
+
diff --git a/lang/en_utf8/help/book/import.html b/lang/en_utf8/help/book/import.html new file mode 100644 index 00000000000..7a62bebea17 --- /dev/null +++ b/lang/en_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Import

+ +

You can import a single HTML file or every HTML file in a direcory.

+ +

Relative file links are converted to absolute chapter links. Images, flash and Java are relinked too.

diff --git a/lang/en_utf8/help/book/index.html b/lang/en_utf8/help/book/index.html new file mode 100644 index 00000000000..752692e009b --- /dev/null +++ b/lang/en_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Book module

+ + diff --git a/lang/en_utf8/help/book/mods.html b/lang/en_utf8/help/book/mods.html new file mode 100644 index 00000000000..a29ff575cdf --- /dev/null +++ b/lang/en_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Books

+
    +

    Book is a simple multipage study material

    +
diff --git a/lang/en_utf8/help/book/numberingtype.html b/lang/en_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..d2f94764a94 --- /dev/null +++ b/lang/en_utf8/help/book/numberingtype.html @@ -0,0 +1,14 @@ +

Numbering of Chapters

+ +

There are several predefined numbering types: + +

None - chapter and subchapter titles are not formatted at all, use +if you want to define special numbering styles. For example letters: in chapter +title type "A First Chapter", "A.1 Some Subchapter",...

+ +

Numbers - chapters and subchapters are numbered (1, 1.1, 1.2, 2, +...)

+ +

Bullets - subchapters are indented and displayed with bullets.

+ +

Indented - subchapters are indented.

diff --git a/lang/en_utf8/help/book/summary.html b/lang/en_utf8/help/book/summary.html new file mode 100644 index 00000000000..5f04a706af8 --- /dev/null +++ b/lang/en_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Reading Summary

+ +

The summary is a very short description of the book.

+ +

Do not be tempted to write too much here!

\ No newline at end of file diff --git a/lang/es_utf8/book.php b/lang/es_utf8/book.php new file mode 100644 index 00000000000..fe5e4b43162 --- /dev/null +++ b/lang/es_utf8/book.php @@ -0,0 +1,32 @@ + diff --git a/lang/fi_utf8/book.php b/lang/fi_utf8/book.php new file mode 100644 index 00000000000..70678bec509 --- /dev/null +++ b/lang/fi_utf8/book.php @@ -0,0 +1,43 @@ +Luvut aakkostetaan tiedostonimien mukaan.'; +$string['importing'] = 'Tuodaan'; +$string['importingchapters'] = 'Tuodaan kirjan lukuja'; +$string['maindirectory'] = 'Päävalikko'; +$string['modulename'] = 'Kirja'; +$string['modulenameplural'] = 'Kirjat'; +$string['navnext'] = 'Seuraava'; +$string['navprev'] = 'Edellinen'; +$string['numbering'] = 'Lukujen numerointi'; +$string['numbering0'] = 'Ei mitään'; +$string['numbering1'] = 'Numerot'; +$string['numbering2'] = 'Luettelomerkit'; +$string['numbering3'] = 'Sisennys'; +$string['printbook'] = 'Tulosta koko kirja'; +$string['printchapter'] = 'Tulosta tämä luku'; +$string['printdate'] = 'Tulostettu'; +$string['printedby'] = 'Tulostanut'; +$string['relinking'] = 'Uudelleenlinkitys'; +$string['subchapter'] = 'Alaluku'; +$string['thisdirection'] = 'ltr'; +$string['thislanguage'] = 'Suomi'; +$string['toc'] = 'Sisällysluettelo'; +$string['tocwidth'] = 'Valitse kaikkien kirjojen sisällysluetteloiden leveys.'; +$string['top'] = 'Alkuun'; + +?> diff --git a/lang/fi_utf8/help/book/customtitles.html b/lang/fi_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..536cdd76e0b --- /dev/null +++ b/lang/fi_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Mukautetut otsikot

+ +

Mukautetut otsikot näytetään automaattisesti vain sisällysluettelossa.

diff --git a/lang/fi_utf8/help/book/disableprinting.html b/lang/fi_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..3bade0237a9 --- /dev/null +++ b/lang/fi_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Estä tulostus

+ +

Piilottaa tulostuspainikkeet.

diff --git a/lang/fi_utf8/help/book/edit.html b/lang/fi_utf8/help/book/edit.html new file mode 100644 index 00000000000..3cda15308f8 --- /dev/null +++ b/lang/fi_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Lukujen muokkaus

+ +

Pidä lukujen otsikot mahdollisimman lyhyenä.

+ +

Lukuja voi olla korkeintaan kahta eri tasoa.

+ +

Jos sinulla on ongelmia visuaalisen muokkaustyökalun kanssa, kokeile selaimen vaihtamista esimerkiksi Mozilla Firefoxiin, tai poista visuaalinen muokkaustyökalu (Richtext HTML -editori) käytöstä profiilin asetuksistasi.

\ No newline at end of file diff --git a/lang/fi_utf8/help/book/faq.html b/lang/fi_utf8/help/book/faq.html new file mode 100644 index 00000000000..bb2d71e0668 --- /dev/null +++ b/lang/fi_utf8/help/book/faq.html @@ -0,0 +1,56 @@ +

+ Usein kysyttyjä kysymyksiä Kirja-moduulista +

+
+
+ Miksi tasoja on vain kaksi? +
+
+ Kaksi tasoa riittää yleensä kaikille kirjoille, kolme + tasoa johtaisi huonompiin asiakirjojen rakenteisiin. Kirja-moduuli on + suunniteltu lyhyiden monisivuisten oppimateriaalien luomiseen. Pidemmät + asiakirjat kannattaa yleensä tallentaa PDF-muodossa. Helpoin tapa luoda + PDF-tiedostoja on käyttää virtuaalitulostimia (katso + PDFCreator, + + PDFFactory, + Adobe Acrobat, + ja niin edelleen). +
+
+
+
+ Voivatko oppilaat muokata kirjoja? +
+
+ Vain opettajat voivan luoda ja muokata kirjoja. Oppilaiden muokattavissa + olevien kirjojen toteuttaminen ei ole suunnitelmissa. On kuitenkin mahdollista, + että joku toteuttaa vastaavan toiminnallisuuden myös oppilaille, + kuten esimerkiksi oppilasportfolion. Tämä päätös on + tehty Kirja-moduulin pitämiseksi mahdollisimman yksinkertaisena. +
+
+
+ Kuinka voin etsiä tekstiä kirjoista? +
+
+ Toistaiseksi tekstiä kirjoista voi etsiä vain yhdellä tavalla: + selaimen tekstinhakutoiminnolla. Jos tulostustoiminto on käytössä, + voit valita koko kirjan tulostettavaksi ja etsiä tekstiä tältä + sivulta (älä kuitenkaan tarpeettomasti tulosta kirjaa). + Vapaa sanahaku on käytössä lähinnä vain Moodlen keskustelupalstoilla. + Muistakin Moodlen resursseista olisi mukava voida etsiä tekstiä, löytyykö + toiminnallisuuden toteuttajiksi vapaaehtoisia? +
+
+
+ Otsikkoni eivät mahdu yhdelle riville. +
+
+ Muotoile otsikkotekstit uudelleen tai levennä sisällysluettelolle + varattua tilaa. Sisällysluettelon tilaa voi leventää + moduulin asetusten määrittämissivulla. (Tämä toiminto + on vain ylläpitäjien käytettävissä). +
+
+
diff --git a/lang/fi_utf8/help/book/import.html b/lang/fi_utf8/help/book/import.html new file mode 100644 index 00000000000..be15342d057 --- /dev/null +++ b/lang/fi_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Tuo

+ +

Voit tuoda moduuliin yksittäisen HTML-tiedoston tai kaikki tietyn kansion HTML-tiedostot.

+ +

Suhteelliset linkit muutetaan absoluuttisiksi linkeiksi. Kuvat, Flash-, ja Java-tiedostot linkitetään myös uudelleen.

diff --git a/lang/fi_utf8/help/book/index.html b/lang/fi_utf8/help/book/index.html new file mode 100644 index 00000000000..752692e009b --- /dev/null +++ b/lang/fi_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Book module

+ + diff --git a/lang/fi_utf8/help/book/mods.html b/lang/fi_utf8/help/book/mods.html new file mode 100644 index 00000000000..650bfd96588 --- /dev/null +++ b/lang/fi_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Kirjat

+
    +

    Kirja on yksinkertainen monisivuinen oppimateriaalikokonaisuus

    +
diff --git a/lang/fi_utf8/help/book/numberingtype.html b/lang/fi_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..40150a9bede --- /dev/null +++ b/lang/fi_utf8/help/book/numberingtype.html @@ -0,0 +1,16 @@ +

Lukujen numerointi

+ +

Lukujen numerointiin on useita tapoja: + +

Ei mitään - lukujen ja alalukujen otsikoita ei muotoilla mitenkään. +Käytä tätä vaihtoehtoa, jos haluat määritellä oman, erikoisemman +numerointitapasi. Voit numeroida luvut esimerkiksi kirjaimia käyttäen: kirjoita +luvun otsikoksi "A Ensimmäinen luku", "A.1 Alaluku" ja niin edelleen. +

+ +

Numerot - luvut ja alaluvut merkitään numeroin (1, 1.1, 1.2, 2 ja niin edelleen). +

+ +

Luettelomerkit - alalukujen otsikot sisennetään ja niiden edessä näkyy luettelomerkki.

+ +

Sisennys - alalukujen otsikot sisennetään.

diff --git a/lang/fi_utf8/help/book/summary.html b/lang/fi_utf8/help/book/summary.html new file mode 100644 index 00000000000..31778fce486 --- /dev/null +++ b/lang/fi_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Yhteenveto

+ +

Yhteenveto on hyvin lyhyt kuvaus kirjasta.

+ +

Älä tee kuvauksesta liian pitkää!

\ No newline at end of file diff --git a/lang/fr_utf8/book.php b/lang/fr_utf8/book.php new file mode 100644 index 00000000000..c4ce5eefa53 --- /dev/null +++ b/lang/fr_utf8/book.php @@ -0,0 +1,46 @@ +les chapitres ont triés alphabétiquement sur la base des noms de fichiers. +

CETTE FONCTIONNALITÉ EST EXPÉRIMENTALE ;-)

'; +$string['maindirectory'] = 'Dossier principal'; +$string['selectdir'] = 'Choisir le dossier du cours'; + +$string['relinking'] = 'Mise à jour des liens'; + +?> \ No newline at end of file diff --git a/lang/id_utf8/book.php b/lang/id_utf8/book.php new file mode 100644 index 00000000000..a858d9c70d9 --- /dev/null +++ b/lang/id_utf8/book.php @@ -0,0 +1,49 @@ +bab diurutkan secara alfabetis berdasarkan nama file. +

Ini adalah FEATURE UJICOBA ;-)

'; +$string['maindirectory'] = 'Direktori utama'; +$string['chooseafileordir'] = 'Pilih sebuah file atau direktori'; + +$string['relinking'] = 'Relinking'; + + + +?> diff --git a/lang/id_utf8/help/book/faq.html b/lang/id_utf8/help/book/faq.html new file mode 100644 index 00000000000..6bd35fbce3d --- /dev/null +++ b/lang/id_utf8/help/book/faq.html @@ -0,0 +1,37 @@ +

FAQ tentang Buku

+ +
+
Kenapa hanya dua level?
+
Dua level secara umum sudah cukup untuk seluruh buku, + tiga level jusru akan menyebabkan struktur dokumen tidak terlalu bagus. + Module buku di desain untuk membuat materi multi halaman yang pendek . + Biasanya lebih baik menggunakan format PDF untuk dokumen yang lebih panjang. + Cara termudah untuk membuat PDF adalah dengan menggunakan printer virtual + (lihat PDFCreator, PDF +Factory, Adobe Acrobat, +etc.).
+

+
Bisakah Mahasiswa meng-edit buku ?
+
Hanya Dosen yang dapat mebuat dan mengedit buku.Tidak ada rencana +untuk memngimplementasikan hak edit pada mahasiswa pada buku,seseorang +mungkin dapat membuat sesuatu yang persis untuk mahasiawa (Portfolio?). +Ini adalah alasan utma membuat modul buku sesederhana mungkin.

+
Bagaimana saya mencari buku?
+
Untuk sekarang hanya ada satu cara, gunakan kemampuan browser + untuk mencari pada halaman cetak.Pencarian Global sekarang memungkinkan + di forum Moodle. + Akan sangat menyenangkan memiliki kemampuan pencarian global + untuk semua resource termasuk buku, ada voluneteer ? +

+
Judul saya cukup satu baris. ?
+
Buat singkatan untuk judul anda atau tanyakan admin situs untuk + mengubah lebar daftar isi. +Ini didefinisikan secara global untuk semua buku pada kalaman konfogurasi modul. +

+
diff --git a/lang/id_utf8/help/book/index.html b/lang/id_utf8/help/book/index.html new file mode 100644 index 00000000000..238da9a1323 --- /dev/null +++ b/lang/id_utf8/help/book/index.html @@ -0,0 +1,7 @@ +

Modul buku

+ + diff --git a/lang/id_utf8/help/book/mods.html b/lang/id_utf8/help/book/mods.html new file mode 100644 index 00000000000..c91bb2f6270 --- /dev/null +++ b/lang/id_utf8/help/book/mods.html @@ -0,0 +1,5 @@ +

 Buku

+
    +

    Buku adalah materi pelajaran multi-halaman sederhana

    +
diff --git a/lang/id_utf8/help/book/numberingtype.html b/lang/id_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..f0eef883eb4 --- /dev/null +++ b/lang/id_utf8/help/book/numberingtype.html @@ -0,0 +1,15 @@ +

Penomoran Bab

+ +

Ada beberapa tipe penomoran yang telah ditentukan : + +

None - Jusul bab and subbab tidak diformat sama sekali, gunakan +ini jika anda ingin mendefinisikan style penomoran sendiri. +Sebagai contoh huruf: pada judul bab tulis " +tipe judul "Bab Pertama", "B.1 beberapa subbab",...

+ +

Numbered - bab dan subbab diberi nomor (1, 1.1, 1.2, 2, +...)

+ +

Bullets - subbab di beri indentasi dan ditampilkan dengan bullet.

+ +

Indented - subbab diindent.

diff --git a/lang/id_utf8/help/book/summary.html b/lang/id_utf8/help/book/summary.html new file mode 100644 index 00000000000..e9f998e0bee --- /dev/null +++ b/lang/id_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Membaca Ringkasan

+ +

Ringkasan adalah dekripsi singkat tentang buku. + +

Jangan terlalu banyak menulis disini! diff --git a/lang/it_utf8/book.php b/lang/it_utf8/book.php new file mode 100644 index 00000000000..0d24a5d320b --- /dev/null +++ b/lang/it_utf8/book.php @@ -0,0 +1,49 @@ +I capitoli saranno ordinati alfabeticamante utilizzando i nomi dei file.'; +$string['maindirectory'] = 'Folder principale'; +$string['fileordir'] = 'Scegli un file oppure un folder'; + +?> diff --git a/lang/ja_utf8/book.php b/lang/ja_utf8/book.php new file mode 100644 index 00000000000..68bd61e077c --- /dev/null +++ b/lang/ja_utf8/book.php @@ -0,0 +1,48 @@ +各章はファイル名順にソートされます。'; +$string['maindirectory'] = 'メインディレクトリ'; +$string['fileordir'] = 'ファイルもしくはディレクトリ'; + +?> diff --git a/lang/ja_utf8/help/book/customtitles.html b/lang/ja_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..92203bd2de8 --- /dev/null +++ b/lang/ja_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

カスタムタイトル

+ +

章の題名はTOCの中だけで自動的に表示されます。

diff --git a/lang/ja_utf8/help/book/disableprinting.html b/lang/ja_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..99f9b80b783 --- /dev/null +++ b/lang/ja_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

印刷不可

+ +

印刷アイコンを隠します。

diff --git a/lang/ja_utf8/help/book/edit.html b/lang/ja_utf8/help/book/edit.html new file mode 100644 index 00000000000..4be77c2e10d --- /dev/null +++ b/lang/ja_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

章の編集

+ +

章の題名はなるべく短くしてください

+ +

各章の下にある節は2レベルまで作成できます

+ +

WYSIWYG htmlエディターを利用していて何か問題があった際には、(Mozilla Firefoxのような)別のブラウザで試してみて、あなたのプロファイルで、そのエディターを使用するのを取りやめる設定にしてください。

\ No newline at end of file diff --git a/lang/ja_utf8/help/book/faq.html b/lang/ja_utf8/help/book/faq.html new file mode 100644 index 00000000000..662afca5c2c --- /dev/null +++ b/lang/ja_utf8/help/book/faq.html @@ -0,0 +1,22 @@ +

ブックに関してよく聞かれる質問

+ +
+
なぜ2レベルしか階層がないのですか?
+
ほとんどの場合、2レベルで十分だからです。3レベルになると、構造的にあまりよくない文書になってしまいます。 ブックモジュールは、複数の短い教材の作成のためにデザインされたものです。通常、長い文書にはPDFのほうが向いております。PDFを作成する簡単な方法は仮想プリンタを利用することです。(次のリンクをご覧ください。 PDFCreator, PDF +Factory, Adobe Acrobat, +etc.).
+

+
生徒はブックを編集できるのですか?
+
教員だけがブックを作成、もしくは編集できます。いまのところ生徒が編集できるようにする機能を実装する予定はありませんが、どなたかが似たような機能をもったもの(ポートフォリオのようなものになるでしょうか)を作成するかもしれません。先生しか編集できない理由は、ブックをできるだけシンプルなものにしておくためです。

+
どうすればブックを検索できますか?
+
いまのところ、各ページに対してブラウザの検索機能を利用するしかありません。文書全体を検索するのはフォーラムだけしかできません。全てのリソースを横断的に検索できる検索ツールがあればいいですね。ボランティアはおられませんでしょうか? +

+
題名が1行におさまらないのですが。
+
題名を変更するか、管理者に目次(TOC)の幅を変更してもらってください。目次(TOC)は、モジュールの設定によって、全てのブックに定義されています。

+
diff --git a/lang/ja_utf8/help/book/import.html b/lang/ja_utf8/help/book/import.html new file mode 100644 index 00000000000..12ca49349a6 --- /dev/null +++ b/lang/ja_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

インポート

+ +

HTMLファイルもしくは複数のHTMLファイルを含んだディレクトリをインポートできます。

+ +

相対リンクは、チャプター間の絶対リンクに変換されます。イメージファイルやフラッシュもリンクが修正されます。

diff --git a/lang/ja_utf8/help/book/index.html b/lang/ja_utf8/help/book/index.html new file mode 100644 index 00000000000..ab97206904c --- /dev/null +++ b/lang/ja_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Book module

+ + diff --git a/lang/ja_utf8/help/book/mods.html b/lang/ja_utf8/help/book/mods.html new file mode 100644 index 00000000000..6b99692c851 --- /dev/null +++ b/lang/ja_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 ブック

+
    +

    ブックとは、複数のページからなる教材です。

    +
diff --git a/lang/ja_utf8/help/book/numberingtype.html b/lang/ja_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..87309d9be16 --- /dev/null +++ b/lang/ja_utf8/help/book/numberingtype.html @@ -0,0 +1,14 @@ +

Numbering of Chapters

+ +

There are several predefined numbering types: + +

None - chapter and subchapter titles are not formatted at all, use +if you want to define special numbering styles. For example letters: in chapter +title type "A First Chapter", "A.1 Some Subchapter",...

+ +

Numbers - chapters and subchapters are numbered (1, 1.1, 1.2, 2, +...)

+ +

Bullets - subchapters are indented and displayed with bullets.

+ +

Indented - subchapters are indented.

diff --git a/lang/ja_utf8/help/book/summary.html b/lang/ja_utf8/help/book/summary.html new file mode 100644 index 00000000000..148ba8dfa8f --- /dev/null +++ b/lang/ja_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

概要を読む

+ +

概要とは、ブックの非常に短い説明です。

+ +

ここにあまり多くの量を書きすぎないように!

\ No newline at end of file diff --git a/lang/nl_utf8/book.php b/lang/nl_utf8/book.php new file mode 100644 index 00000000000..481f4b961db --- /dev/null +++ b/lang/nl_utf8/book.php @@ -0,0 +1,41 @@ +De hoofdstukken worden alfabetisch gerangschikt op bestandsnaam.'; +$string['importing'] = 'Importeren'; +$string['importingchapters'] = 'Importeren van hoofdstukken in het boek'; +$string['maindirectory'] = 'Hoofdmap'; +$string['modulename'] = 'Boek'; +$string['modulenameplural'] = 'Boeken'; +$string['navnext'] = 'Volgende'; +$string['navprev'] = 'Vorige'; +$string['numbering'] = 'Hoofdstuknummering'; +$string['numbering0'] = 'Geen'; +$string['numbering1'] = 'Nummering'; +$string['numbering2'] = 'Bolletjes'; +$string['numbering3'] = 'Inspringen'; +$string['printbook'] = 'Druk het hele boek af'; +$string['printchapter'] = 'Druk dit hoofdstuk af'; +$string['printdate'] = 'Datum'; +$string['printedby'] = 'Afgedrukt door'; +$string['relinking'] = 'Opnieuw linken'; +$string['subchapter'] = 'Paragraaf'; +$string['toc'] = 'Inhoudstafel'; +$string['tocwidth'] = 'Kies de breedte van de inhoudstafel voor alle boeken.'; +$string['top'] = 'boven'; + +?> diff --git a/lang/nl_utf8/help/book/customtitles.html b/lang/nl_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..1ddb5f33268 --- /dev/null +++ b/lang/nl_utf8/help/book/customtitles.html @@ -0,0 +1 @@ +

Titels alleen in inhoudstafel

Indien ja worden de titels van de hoofdstukken automatisch alleen in de inhoudstafel getoond.

\ No newline at end of file diff --git a/lang/nl_utf8/help/book/disableprinting.html b/lang/nl_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..8308e4e8d4b --- /dev/null +++ b/lang/nl_utf8/help/book/disableprinting.html @@ -0,0 +1 @@ +

Schakel afdrukken uit

Verberg alle icoontjes om af te drukken.

\ No newline at end of file diff --git a/lang/nl_utf8/help/book/edit.html b/lang/nl_utf8/help/book/edit.html new file mode 100644 index 00000000000..02c8097a417 --- /dev/null +++ b/lang/nl_utf8/help/book/edit.html @@ -0,0 +1,13 @@ +

Hoofdstuk bewerken

+ + + +

Probeer de titel van een hoofdstuk kort te houden.

+ + + +

Paragrafen maximum twee niveaus diep.

+ + + +

Als je problemen ondervindt met de WYSIWYG HTML-editor, probeer dan een andere browser (zoals Mozilla Firefox) of zet de editor af in je gebruikersprofiel.

\ No newline at end of file diff --git a/lang/nl_utf8/help/book/faq.html b/lang/nl_utf8/help/book/faq.html new file mode 100644 index 00000000000..9ba3c3458e5 --- /dev/null +++ b/lang/nl_utf8/help/book/faq.html @@ -0,0 +1,21 @@ +

Frequently Asked Questions over boeken

+ +
+
Waarom slechts twee niveaus diep?
+
Twee niveaus zijn genoeg voor de meeste boeken, drie niveaus zou tot slecht gestructureerde documenten leiden. De boekmodule is ontworpen voor kort, uit meerdere pagina's bestaand studiemateriaal. Het is beter PDF te gebruiken voor grotere documenten. De gemakkelijkste manier om PDF's te maken is met virtuele printers (zie PDFCreator, PDF +Factory, Adobe Acrobat, +enz.).
+

+
Kunnen leerlingen boeken bewerken?
+
Alleen leraren kunnen boeken maken en bewerken. Er zijn geen plannen voor het implementeren van bewerken voor leerlingen, maar misschien maakt iemand anders iets gelijkaardigs voor leerlingen (Portfolio?). De belangrijkste reden is om de boekmodule zo eenvoudig mogelijk te houden.

+
Hoe kan ik de boeken doorzoeken?
+
Op dit ogenblik is er maar één manier, namelijk de zoekfunctie van de browser op de afdrukpagina. Zoeken is op dit ogenblik enkel mogelijk in de Moodle forums.

+
Mijn titels passen niet op deze lijn.
+
Probeer je titel anders te verwoorden of vraag je sitebeheerder om de breedte van de inhoudstafel aan te passen. Deze wordt voor alle boeken gedefinieerd op de configuratiepagina van de module.

+
diff --git a/lang/nl_utf8/help/book/import.html b/lang/nl_utf8/help/book/import.html new file mode 100644 index 00000000000..b859c2a5b72 --- /dev/null +++ b/lang/nl_utf8/help/book/import.html @@ -0,0 +1 @@ +

Importeren

Je kunt een enkel HTML-bestand of alle HTML-bestanden van een map importeren.

Relatieve links naar bestanden worden geconverteerd in absolute hoofdstuklinks. De links naar bestanden, flash en java worden ook herwerkt.

\ No newline at end of file diff --git a/lang/nl_utf8/help/book/index.html b/lang/nl_utf8/help/book/index.html new file mode 100644 index 00000000000..1afd2ebd7c1 --- /dev/null +++ b/lang/nl_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Boekmodule

+ + diff --git a/lang/nl_utf8/help/book/mods.html b/lang/nl_utf8/help/book/mods.html new file mode 100644 index 00000000000..7ef7cc75c8d --- /dev/null +++ b/lang/nl_utf8/help/book/mods.html @@ -0,0 +1 @@ +

 Boeken

    Met de boekmodule maak je eenvoudig studiemateriaal op meerdere pagina's.

\ No newline at end of file diff --git a/lang/nl_utf8/help/book/numberingtype.html b/lang/nl_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..114de5a92cc --- /dev/null +++ b/lang/nl_utf8/help/book/numberingtype.html @@ -0,0 +1 @@ +

Hoofdstuknummering

Er zijn verschillende voorgedefinieerde nummeringstypes:

Geen - hoofdstukken en ondertitels krijgen geen opmaak. Gebruik deze instelling als je speciale nummeringsstijlen, zoals letters, wil gebruiken. Bijvoorbeeld: "A Eerste hoofdstuk", "A.1 Eerste paragraaf", ....

Getallen - hoofdstukken en paragrafen worden genummerd(1, 1.1, 1.2, 2, ...)

Bolletjes - paragrafen springen in en worden met bolletjes getoond.

Indented - paragrafen springen in.

\ No newline at end of file diff --git a/lang/nl_utf8/help/book/summary.html b/lang/nl_utf8/help/book/summary.html new file mode 100644 index 00000000000..61de4ebc709 --- /dev/null +++ b/lang/nl_utf8/help/book/summary.html @@ -0,0 +1,9 @@ +

Samenvatting

+ + + +

De samenvatting is een heel korte beschrijving van het boek.

+ + + +

Kom niet in de verleiding hier teveel te schrijven!

\ No newline at end of file diff --git a/lang/pl_utf8/book.php b/lang/pl_utf8/book.php new file mode 100644 index 00000000000..9c05949c53d --- /dev/null +++ b/lang/pl_utf8/book.php @@ -0,0 +1,42 @@ +Rozdziały są sortowane alfabetycznie wg. nazw plików.'; +$string['importing'] = 'Importowanie'; +$string['importingchapters'] = 'Importowanie rozdziałów do książki'; +$string['maindirectory'] = 'Główny katalog'; +$string['modulename'] = 'Książka'; +$string['modulenameplural'] = 'Książki'; +$string['navexit'] = 'Zamknij książkę'; +$string['navnext'] = 'Następny'; +$string['navprev'] = 'Poprzedni'; +$string['numbering'] = 'Numerowanie rodziałów'; +$string['numbering0'] = 'żaden'; +$string['numbering1'] = 'Liczby'; +$string['numbering2'] = 'Wypunktowanie'; +$string['numbering3'] = 'Wcięte'; +$string['printbook'] = 'Drukuj kopletną książkę'; +$string['printchapter'] = 'Drukuj ten rozdział'; +$string['printdate'] = 'Data'; +$string['printedby'] = 'Wydrukowane przez użytkoniwka'; +$string['relinking'] = 'Ponowne tworzenie linków'; +$string['subchapter'] = 'Podrozdział'; +$string['toc'] = 'Spis treści'; +$string['tocwidth'] = 'Ustaw szrokość spisu treści dla wszystkich książek'; +$string['top'] = 'Góra'; + +?> diff --git a/lang/pl_utf8/help/book/customtitles.html b/lang/pl_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..1f742246943 --- /dev/null +++ b/lang/pl_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Tytuły użytkownika

+ +

Tytuły rozdziałów są automatycznie wyświetlane tylko w Spisie Treści.

\ No newline at end of file diff --git a/lang/pl_utf8/help/book/disableprinting.html b/lang/pl_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..5254fff096c --- /dev/null +++ b/lang/pl_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Wyłącz drukowanie

+ +

Ukryj ikonki wydruku.

\ No newline at end of file diff --git a/lang/pl_utf8/help/book/edit.html b/lang/pl_utf8/help/book/edit.html new file mode 100644 index 00000000000..ef2cd5327d9 --- /dev/null +++ b/lang/pl_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Edycja rozdziału

+ +

Staraj się używać krótkich tytułów rozdziałów

+ +

Maksymalna liczba poziomów podrozdziałów to dwa.

+ +

Jeśli zauważysz problemy używając edytora html WYSIWYG, spróbuj przejść na inną przeglądarkę (taką jak Mozilla Firefox) lub całkowicie wyłącz edytor w swoim profilu.

\ No newline at end of file diff --git a/lang/pl_utf8/help/book/faq.html b/lang/pl_utf8/help/book/faq.html new file mode 100644 index 00000000000..a57dcc62943 --- /dev/null +++ b/lang/pl_utf8/help/book/faq.html @@ -0,0 +1,47 @@ +

+ Często Zadawane Pytania dotyczace książek +

+
+
+ Dlaczego tylko dwa poziomy? +
+
+ Dwa poziomy są zasadniczno wystarczające dla wszystkich książęk, trzy i więcej mogłyby prowadzić do źle ustruturyzowanych dokumentów. Moduł książka jest zaprojektowany do tworzenia krótkich, kilkustronicowych materiałów. Dla długich dokumentów lepiej użyć formtu PDF. Najprostszy sposób tworzenia plików PDF to wykorzystanie wirtualnych drukarek (zobacz + PDFCreator, + + PDFFactory, + Adobe Acrobat, + itp.). +
+
+
+
+ Czy studenci mogą edytowac książki? +
+
+ Tylko nauczyciele mogą tworzyć i edytować książki. Nie ma planów implementacji takiej + funkcjonalności, ale ktoś może stworzyć coś podobnego dla studnetów (Portfolio?). + Główny powód to utrzymanie modułu tak prostym jak to tylko możliwe. +
+
+
+
+ Jak mogę przeszukiwać książki? +
+
+ Obecnie jest tylko jeden sposób, użyj funkcji przeglądarki w widoku wydruku. Globalne + przeszukiwanie jest możliwe tylko w forach Moodla. + Byłoby dobrze posiadać globalne wyszukiwanie we wszystkich zasobach włączając książki, są + chętni? +
+
+
+
+ Moje tytuły nie mieszczą się. +
+
+ Przeformułuj swoje tytuły lub poproś admina, żeby zmienił szerokość spisu treści. Jest ona + definiowalna globalnie dla wszystkich książek na stronie konfiguracji Moodla. +
+
+
\ No newline at end of file diff --git a/lang/pl_utf8/help/book/import.html b/lang/pl_utf8/help/book/import.html new file mode 100644 index 00000000000..ed09f9af7ff --- /dev/null +++ b/lang/pl_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

Import

+ +

Możesz zaimportować plik HTML lub wszystkie pliki HTML z katalogu.

+ +

Względne linki do plików są przekształcane w bezwzględne linki do rozdziałów. Obrazy, Fleshe i Java są również ponownie linkowane.

\ No newline at end of file diff --git a/lang/pl_utf8/help/book/index.html b/lang/pl_utf8/help/book/index.html new file mode 100644 index 00000000000..65e71583d2e --- /dev/null +++ b/lang/pl_utf8/help/book/index.html @@ -0,0 +1,10 @@ +

ModuŁ Książka

+ \ No newline at end of file diff --git a/lang/pl_utf8/help/book/mods.html b/lang/pl_utf8/help/book/mods.html new file mode 100644 index 00000000000..c49b244aa22 --- /dev/null +++ b/lang/pl_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

Książki

+
    +

    Książka jest prostym kilkustronicowym materiałem do studiowania.

    +
\ No newline at end of file diff --git a/lang/pl_utf8/help/book/numberingtype.html b/lang/pl_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..cae0cf1b811 --- /dev/null +++ b/lang/pl_utf8/help/book/numberingtype.html @@ -0,0 +1,15 @@ +

Numerownie rodziałów

+ +

Jest kilka predefiniowanych typów numerowania: + +

żaden - tytuły rodziałów i podrozdziałów nie są w żaden sposób formatwane, użyj go jeśli chcesz zdefiniować specjalny styl numerowania. +
Na przykład litery: w tytule rozdziału typu +
"A Pierwszy rozdział", +
"A.1 Jakiś podrozdział",...

+ +

Liczby - rozdziały i podrozdziały są numerowane (1, 1.1, 1.2, 2, +...)

+ +

Wypunktowanie - podrozdziały sa wcięte i wyświetlane ze znakami wypunktowania.

+ +

Wcięty - podrozdziały są wcięte.

\ No newline at end of file diff --git a/lang/pl_utf8/help/book/summary.html b/lang/pl_utf8/help/book/summary.html new file mode 100644 index 00000000000..0227b5363bc --- /dev/null +++ b/lang/pl_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Streszczenie

+ +

Streszczenie jest bardzo krótkim opisem książki.

+ +

Niech cię nie kusi pisać tu zbyt dużo!

\ No newline at end of file diff --git a/lang/pt_br_utf8/book.php b/lang/pt_br_utf8/book.php new file mode 100644 index 00000000000..d097dbfbe20 --- /dev/null +++ b/lang/pt_br_utf8/book.php @@ -0,0 +1,48 @@ +Os capítulos são ordenados alfabeticamente usando os nomes dos arquivos.'; +$string['maindirectory'] = 'Diretório principal'; +$string['fileordir'] = 'Arquivo ou diretório'; + +?> diff --git a/lang/pt_br_utf8/help/book/customtitles.html b/lang/pt_br_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..01988d7cd57 --- /dev/null +++ b/lang/pt_br_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Títulos personalizados

+ +

Os títulos dos capítulos são mostrados automaticamente só no sumário.

diff --git a/lang/pt_br_utf8/help/book/disableprinting.html b/lang/pt_br_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..6e93432ea37 --- /dev/null +++ b/lang/pt_br_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Desabilitar Impressão

+ +

Esconde o ícode de impressão.

diff --git a/lang/pt_br_utf8/help/book/edit.html b/lang/pt_br_utf8/help/book/edit.html new file mode 100644 index 00000000000..0ec3298dcd8 --- /dev/null +++ b/lang/pt_br_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

Edução de capítulo

+ +

Tente manter o título do capítulo breve.

+ +

O nível máximo de sub-capítulos é dois.

+ +

Se encontrar problemas com o editor HTML interno, tente mudar para outro navegador (como, por exemplo, Mozilla Firefox) ou desabilite de vez o editor em suas preferências.

diff --git a/lang/pt_br_utf8/help/book/faq.html b/lang/pt_br_utf8/help/book/faq.html new file mode 100644 index 00000000000..0a8250d4688 --- /dev/null +++ b/lang/pt_br_utf8/help/book/faq.html @@ -0,0 +1,52 @@ +

+ Perguntas sobre "Livro" +

+
+
+ Porque só dois níveis? +
+
+ Dois níveis são em geral suficiente para todos os livros. Três níveis + levariam a documentos pobremente estruturados. O módulo Livro foi + desenhado para a criação de materiais de estudo com várias páginas + curtos. Normalmente seria melhor usar o formato PDF para documentos + maiores. A forma mais fácil de criar PDFs é usar as impressoras virtuais + (veja + PDFCreator, + + PDFFactory, + Adobe Acrobat, + etc.). +
+
+
+
+ Os alunos podem editar livros? +
+
+ Só professores podem criar e editar livros. Não há previsão de implementar + edição de livros por estudantes, mas alguém poderia criar algo similar + para estudantes (portfólios?). O principal motivo é para manter o módulo + Livro tão simples quanto possível. +
+
+
+ Como faço uma busca nos livros? +
+
+ Atualmente só há uma forma, use o mecanismo de busca de seu navegador + na página que é mostrada. A busca global só é possível atualmente nos + fóruns do Moodle. Seria ótimo ter uma busca global em todos os recursos, + incluindo os livros. Algum voluntário? +
+
+
+ Meus títulos não cabem numa linha. +
+
+ Veja uma alternativa menor para seus títulos, ou peça para o administrador + do sistema mudar a largura máxima do sumário. Ela é definida globalmente + para todos os livros no módulo de configuração. +
+
+
diff --git a/lang/pt_br_utf8/help/book/import.html b/lang/pt_br_utf8/help/book/import.html new file mode 100644 index 00000000000..5f95e9348e7 --- /dev/null +++ b/lang/pt_br_utf8/help/book/import.html @@ -0,0 +1,6 @@ +

Importação

+ +

Você pode importar um arquivo HTML ou todos os arquivos HTML num diretório.

+ +

As referências relativas (links) são convertidos para referências absolutas de capítulos. Imagens, flash e Java também são + re-referenciados.

diff --git a/lang/pt_br_utf8/help/book/index.html b/lang/pt_br_utf8/help/book/index.html new file mode 100644 index 00000000000..6ca4cd266db --- /dev/null +++ b/lang/pt_br_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Módulo Livro

+ + diff --git a/lang/pt_br_utf8/help/book/mods.html b/lang/pt_br_utf8/help/book/mods.html new file mode 100644 index 00000000000..c256fc8ce2e --- /dev/null +++ b/lang/pt_br_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Livros

+
    +

    Livro é simplesmente um material de estudo com várias páginas

    +
diff --git a/lang/pt_br_utf8/help/book/numberingtype.html b/lang/pt_br_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..a12ceaca2f8 --- /dev/null +++ b/lang/pt_br_utf8/help/book/numberingtype.html @@ -0,0 +1,15 @@ +

Numeração de capítulos

+ +

Há várias maneiras pré-definidas de numerar capítulos:

+ +

Nada - títulos de capítulos e sub-capítulos não são formatados. Use +se quiser definir um estilo especial de numeração. Por exemplo, letras: no +título do capítulo escreva "A Primeiro capítulo", "A.1 Algum sub-capítulo",... +

+ +

Números - capítulos e sub-capítulos são numerados (1, 1.1, 1.2, 2, +...)

+ +

Bolinhas - sub-capítulos são indentados, tendo uma bolinha na frente.

+ +

Indentado - sub-capítulos são indentados.

diff --git a/lang/pt_br_utf8/help/book/summary.html b/lang/pt_br_utf8/help/book/summary.html new file mode 100644 index 00000000000..a193ed5df6a --- /dev/null +++ b/lang/pt_br_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Sumário de Leitura

+ +

Este sumário é uma descrição muito breve do livro.

+ +

Não caia na tentação de escrever demasiado aqui!

diff --git a/lang/sk_utf8/book.php b/lang/sk_utf8/book.php new file mode 100644 index 00000000000..9e23f499d2c --- /dev/null +++ b/lang/sk_utf8/book.php @@ -0,0 +1,42 @@ +Kapitoly budú striedené abecedne podľa názvov súborov.'; +$string['importing'] = 'Importujej'; +$string['importingchapters'] = 'Importovanie kapitol'; +$string['maindirectory'] = 'Hlavná zložka'; +$string['modulename'] = 'Kniha'; +$string['modulenameplural'] = 'Knihy'; +$string['navnext'] = 'Následujúci'; +$string['navprev'] = 'Predchádzajúci'; +$string['navexit'] = 'Späť na prehľad'; +$string['numbering'] = 'Číslovanie kapitol'; +$string['numbering0'] = 'Žiadne'; +$string['numbering1'] = 'Čísla'; +$string['numbering2'] = 'Odrážky'; +$string['numbering3'] = 'Odsadené'; +$string['printbook'] = 'Vytlačiť celú knihu'; +$string['printchapter'] = 'Vytlačiť jednu kapitolu'; +$string['printdate'] = 'Dátum'; +$string['printedby'] = 'Vytlačil(a)'; +$string['relinking'] = 'Relinkujem'; +$string['subchapter'] = 'Podkapitola'; +$string['toc'] = 'Obsah'; +$string['tocwidth'] = 'Vyberte šírku obsahu pre všetky knihy.'; +$string['top'] = 'začiatok'; + +?> diff --git a/lang/sk_utf8/help/book/customtitles.html b/lang/sk_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..6fb24c43556 --- /dev/null +++ b/lang/sk_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +

Užívateľské nadpisy

+ +

Nadpisy sú zobrazené iba v obsahu knihy.

diff --git a/lang/sk_utf8/help/book/disableprinting.html b/lang/sk_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..efe62146baf --- /dev/null +++ b/lang/sk_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

Zakázať tlač

+ +

Skryť ikony pre tlač.

diff --git a/lang/sk_utf8/help/book/edit.html b/lang/sk_utf8/help/book/edit.html new file mode 100644 index 00000000000..3305aeaeda3 --- /dev/null +++ b/lang/sk_utf8/help/book/edit.html @@ -0,0 +1,8 @@ +

Úprava kapitol

+ +

Snažte sa písať iba krátke kapitoly.

+ +

Knika môže mať iba dve úrovne nadpisov.

+ +

ak máte problémy s HTML editorom, môžete si skúsiť nainštalovať iný prohliadač +(napríklad Mozilla Firefox).

\ No newline at end of file diff --git a/lang/sk_utf8/help/book/faq.html b/lang/sk_utf8/help/book/faq.html new file mode 100644 index 00000000000..e1a9dda165b --- /dev/null +++ b/lang/sk_utf8/help/book/faq.html @@ -0,0 +1,41 @@ +

+ Často kladené otázky +

+
+
+ Prečo iba dve úrovne? +
+
+ Dve úrovne nadpisu stačia, vždy se snažte písať krátko a zrozumiteľne. + Ak si myslíte, že potrebujete viac úrovní, rozdeľte text do niekoľkých kníh. + Pre dlhšie texty je väčšinou vhodnejší PDF formát. PDF súbory môžete + vytvoriť pomocou nasledujúcich programov: + PDFCreator, + + PDFFactory, + Adobe Acrobat. +
+
+
+
+ Môžu študenti upravovať knihy? +
+
+ Knihy môžu vytvárať a upravovať iba učitelia. +
+
+
+ Môžem vyhľadávať v knihách? +
+
+ Použite vyhľadávanie vo vašom prehliadači. +
+
+
+ Nadpisy sa mi nevojdu na jeden riadok. +
+
+ Alebo skráťte nadpis, alebo požiadajte vášho správce, aby zmenil šírku obsahu. +
+
+
diff --git a/lang/sk_utf8/help/book/import.html b/lang/sk_utf8/help/book/import.html new file mode 100644 index 00000000000..7440b308cb0 --- /dev/null +++ b/lang/sk_utf8/help/book/import.html @@ -0,0 +1,6 @@ +

Import

+ +

Môžete importovať jeden HTML súbor alebo všetky súbory v zložke.

+ +

Relatívne odkazy sú prevedené na odkazy na kapitoly. Odkazy na +obrázky, flash a Javu sú tiež upravené.

diff --git a/lang/sk_utf8/help/book/index.html b/lang/sk_utf8/help/book/index.html new file mode 100644 index 00000000000..fa79f5a2934 --- /dev/null +++ b/lang/sk_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Modul Kniha

+ + diff --git a/lang/sk_utf8/help/book/mods.html b/lang/sk_utf8/help/book/mods.html new file mode 100644 index 00000000000..5a1c46e41e9 --- /dev/null +++ b/lang/sk_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Knihy

+
    +

    Kniha je jednoduchý viacstránkový študijný materiál.

    +
diff --git a/lang/sk_utf8/help/book/numberingtype.html b/lang/sk_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..5639f4a099a --- /dev/null +++ b/lang/sk_utf8/help/book/numberingtype.html @@ -0,0 +1,14 @@ +

Číslovanie kapitol

+ +

Existuje niekoľko preddefinovaných typov číslovania: + +

Žiadne - kapitoly a podkapitoly nie sú formátované, používajte v prípade, +ak chcete zadať vaše vlastné číslovánie. Napríklad: do poľa nadpis kapitoly zadajte +"A Úvod", "A.1 Nejaké Rozprávanie", ...

+ +

Čísla - kapitoly a podkapitoly sú číslované (1, 1.1, 1.2, 2, ...)

+ +

Odrážky - podkapitoly sú odsadené a zvýraznené odrážkami.

+ +

Odsadené - podkapitoly sú odsadené.

+ diff --git a/lang/sk_utf8/help/book/summary.html b/lang/sk_utf8/help/book/summary.html new file mode 100644 index 00000000000..2f065470f25 --- /dev/null +++ b/lang/sk_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

Súhrn

+ +

Stručný obsah knihy.

+ +

Snažte sa o skutočne krátky a výstižný opis.

\ No newline at end of file diff --git a/lang/sv_utf8/book.php b/lang/sv_utf8/book.php new file mode 100644 index 00000000000..0acd53fe94f --- /dev/null +++ b/lang/sv_utf8/book.php @@ -0,0 +1,42 @@ +Kapitel sorteras alfabetiskt utifrån filnamn.'; +$string['importing'] = 'Importerar'; +$string['importingchapters'] = 'Importerar kapitel till bok'; +$string['maindirectory'] = 'Huvudkatalog'; +$string['modulename'] = 'Bok'; +$string['modulenameplural'] = 'Böcker'; +$string['navexit'] = 'Exit Book'; +$string['navnext'] = 'Nästa'; +$string['navprev'] = 'Föregående'; +$string['numbering'] = 'Numrering av kapitel'; +$string['numbering0'] = 'Ingen'; +$string['numbering1'] = 'Tal'; +$string['numbering2'] = 'Bullets'; +$string['numbering3'] = 'Indragen'; +$string['printbook'] = 'Skriv ut hela boken'; +$string['printchapter'] = 'Skriv ut det här kapitlet'; +$string['printdate'] = 'Datum'; +$string['printedby'] = 'Utskrivet av'; +$string['relinking'] = 'Länkar tillbaka'; +$string['subchapter'] = 'Underavdelning'; +$string['toc'] = 'Innehållsförteckning'; +$string['tocwidth'] = 'Välj en bredd på innehållsförteckningen som gäller alla böcker.'; +$string['top'] = 'Upp'; + +?> diff --git a/lang/sv_utf8/help/book/customtitles.html b/lang/sv_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..9ebe5dfde98 --- /dev/null +++ b/lang/sv_utf8/help/book/customtitles.html @@ -0,0 +1,2 @@ +

Standardiserade titlar

+

Titlar på kapitel visas automatiskt bara i innehållsförteckningen.

\ No newline at end of file diff --git a/lang/sv_utf8/help/book/disableprinting.html b/lang/sv_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..d44f22e1a6d --- /dev/null +++ b/lang/sv_utf8/help/book/disableprinting.html @@ -0,0 +1,2 @@ +

Avaktivera utskrift

+

Dölj ikonen för utskrift.

\ No newline at end of file diff --git a/lang/sv_utf8/help/book/edit.html b/lang/sv_utf8/help/book/edit.html new file mode 100644 index 00000000000..2b626ac5085 --- /dev/null +++ b/lang/sv_utf8/help/book/edit.html @@ -0,0 +1,6 @@ +

Att redigera ett kapitel

+

Försök att använda korta titlar på kapitel.

+

Den maximala nivån på underkapitel är två.

+

Om Du stöter på problem när Du använder WYSIWYG HTML-redigeraren, +så kan Du försöka att byta till en annan webbläsare +(som Mozilla Firefox) eller stänga av redigeraren helt och hållet i Din profil.

\ No newline at end of file diff --git a/lang/sv_utf8/help/book/faq.html b/lang/sv_utf8/help/book/faq.html new file mode 100644 index 00000000000..fe7fc6cf9d2 --- /dev/null +++ b/lang/sv_utf8/help/book/faq.html @@ -0,0 +1,42 @@ +

Vanligt förekommande frågor om Modulen bok

+
+
+ Varför bara två nivåer? +
+
+ Två nivåer räcker vanligtvis för alla böcker, tre nivåer skulle leda till + illa strukturerade dokument. Modulen bok är utformad för att skapa korta + studiematerial som består av ett antal sidor. För längre dokument är det normalt + sett bättre med Pdf-format. Det enklaste sättet att skapa Pdf-filer är + virtuella skrivare (se + PDFCreator, + + PDFFactory, + Adobe Acrobat, + etc.). +

+
+
Kan studenter/elever/deltagare/lärande redigera böcker?
+
Endast lärare kan skapa och redigera böcker. + Det finns inga planer på att utvidga detta, men någon kan kanske + skapa någonting liknande för studenter/elever/deltagare/lärande + (Portfolio?). Den viktigaste orsaken är att den här modulen ska vara så enkel som möjligt.

+
+
+ Hur söker jag i böckerna? +
+
+ F.n. finns det bara ett sätt, nämligen att använda webbläsarens + sökfunktion i "Skriv ut". Global sökning går bara att göra i Moodles forum. + Det vore trevligt med global sökning för alla resurser inklusive böcker, + några frivilliga?

+
+
+ Min titlar passar inte in på raden. +
+
+ Formulera antingen om dina titlar eller be din systemadministratör + att öka vidden på innehållsförteckningen. Den är globalt definierad + på sidan för konfiguration av modulen. +
+
\ No newline at end of file diff --git a/lang/sv_utf8/help/book/import.html b/lang/sv_utf8/help/book/import.html new file mode 100644 index 00000000000..afb75010eac --- /dev/null +++ b/lang/sv_utf8/help/book/import.html @@ -0,0 +1,3 @@ +

Att importera

+

Du kan importera en enskild HTML-fil eller varje HTML-fil i en katalog.

+

Relativa länkar konverteras till absoluta länkar för kapitel. Bilder, Flash och Java länkas också om.

\ No newline at end of file diff --git a/lang/sv_utf8/help/book/index.html b/lang/sv_utf8/help/book/index.html new file mode 100644 index 00000000000..5b411bf5ae9 --- /dev/null +++ b/lang/sv_utf8/help/book/index.html @@ -0,0 +1,11 @@ +

Modulen bok (utvecklingsmodul)

+ \ No newline at end of file diff --git a/lang/sv_utf8/help/book/mods.html b/lang/sv_utf8/help/book/mods.html new file mode 100644 index 00000000000..d3246f505be --- /dev/null +++ b/lang/sv_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

 Böcker

+
    +
  • Bok är ett enkelt studiematerial bestående av ett antal sidor
  • +
\ No newline at end of file diff --git a/lang/sv_utf8/help/book/numberingtype.html b/lang/sv_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..5b4c5ff9675 --- /dev/null +++ b/lang/sv_utf8/help/book/numberingtype.html @@ -0,0 +1,9 @@ +

Att numrera kapitel

+

Det finns ett antal fördefinierade sätt att numrera:

+

Inget - kapitel och undertitlar formatteras inte alls, använd det om Du vill +definiera Dina egna sätt att numrera. T.ex. bokstäver: I titlar på kapitel av typen +"Första kapitlet", "A.1 några underavdelningar",...

+

Siffror - kapitel och undertitlar numreras (1, 1.1, 1.2, 2, +...)

+

Punkter - undertitlar har indrag och visas med punkter.

+

Indrag - undertitlar har indrag.

\ No newline at end of file diff --git a/lang/sv_utf8/help/book/summary.html b/lang/sv_utf8/help/book/summary.html new file mode 100644 index 00000000000..ea4eec17084 --- /dev/null +++ b/lang/sv_utf8/help/book/summary.html @@ -0,0 +1,3 @@ +

Sammanfattning av läsningen

+

Sammanfattningen är en mycket kort beskrivning av boken.

+

Låt Dig inte frestas att skriva för mycket här!

\ No newline at end of file diff --git a/lib.php b/lib.php new file mode 100644 index 00000000000..fc8f8a372cc --- /dev/null +++ b/lib.php @@ -0,0 +1,419 @@ + get_string('numbering0', 'book'), + NUM_NUMBERS => get_string('numbering1', 'book'), + NUM_BULLETS => get_string('numbering2', 'book'), + NUM_INDENTED => get_string('numbering3', 'book') ); + +if (!isset($CFG->book_tocwidth)) { + set_config("book_tocwidth", 180); // default toc width +} + + +/// Library of functions and constants for module 'book' + +function book_add_instance($book) { +/// Given an object containing all the necessary data, +/// (defined by the form in mod.html) this function +/// will create a new instance and return the id number +/// of the new instance. + + $book->timecreated = time(); + $book->timemodified = $book->timecreated; + + return insert_record('book', $book); +} + + +function book_update_instance($book) { +/// Given an object containing all the necessary data, +/// (defined by the form in mod.html) this function +/// will update an existing instance with new data. + + $book->timemodified = time(); + $book->id = $book->instance; + + # May have to add extra stuff in here # + + return update_record('book', $book); +} + + +function book_delete_instance($id) { +/// Given an ID of an instance of this module, +/// this function will permanently delete the instance +/// and any data that depends on it. + + if (! $book = get_record('book', 'id', $id)) { + return false; + } + + $result = true; + + delete_records('book_chapters', 'bookid', $book->id); + + if (! delete_records('book', 'id', $book->id)) { + $result = false; + } + + return $result; +} + +function book_user_outline($course, $user, $mod, $book) { +/// Return a small object with summary information about what a +/// user has done with a given particular instance of this module +/// Used for user activity reports. +/// $return->time = the time they did it +/// $return->info = a short text description + + $return = null; + return $return; +} + +function book_user_complete($course, $user, $mod, $book) { +/// Print a detailed representation of what a user has done with +/// a given particular instance of this module, for user activity reports. + + return true; +} + +function book_print_recent_activity($course, $isteacher, $timestart) { +/// Given a course and a time, this module should find recent activity +/// that has occurred in book activities and print it out. +/// Return true if there was output, or false is there was none. + + global $CFG; + + return false; // True if anything was printed, otherwise false +} + +function book_cron () { +/// Function to be run periodically according to the moodle cron +/// This function searches for things that need to be done, such +/// as sending out mail, toggling flags etc ... + + global $CFG; + + return true; +} + +function book_grades($bookid) { +/// Must return an array of grades for a given instance of this module, +/// indexed by user. It also returns a maximum allowed grade. + + return NULL; +} + +function book_get_participants($bookid) { +//Must return an array of user records (all data) who are participants +//for a given instance of book. Must include every user involved +//in the instance, independient of his role (student, teacher, admin...) +//See other modules as example. + + return false; +} + +function book_scale_used ($bookid,$scaleid) { +//This function returns if a scale is being used by one book +//it it has support for grading and scales. Commented code should be +//modified if necessary. See forum, glossary or journal modules +//as reference. + + $return = false; + + //$rec = get_record('book','id',$bookid,'scale',"-$scaleid"); + // + //if (!empty($rec) && !empty($scaleid)) { + // $return = true; + //} + + return $return; +} + +////////////////////////////////////////////////////////////////////////////////////// +/// Any other book functions go here. Each of them must have a name that +/// starts with book_ + +//check chapter ordering and +//make sure subchapter is not first in book +//hidden chapter must have all subchapters hidden too +function book_check_structure($bookid) { + if ($chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, subchapter, hidden')) { + $first = true; + $hidesub = true; + $i = 1; + foreach($chapters as $ch) { + if ($first and $ch->subchapter) { + $ch->subchapter = 0; + } + $first = false; + if (!$ch->subchapter) { + $hidesub = $ch->hidden; + } else { + $ch->hidden = $hidesub ? true : $ch->hidden; + } + $ch->pagenum = $i; + update_record('book_chapters', $ch); + $i++; + } + } +} + + +/// prepare button to turn chapter editing on - connected with course editing +function book_edit_button($id, $courseid, $chapterid) { + global $CFG, $USER; + + + if (isteacheredit($courseid)) { + if (!empty($USER->editing)) { + $string = get_string("turneditingoff"); + $edit = '0'; + } else { + $string = get_string("turneditingon"); + $edit = '1'; + } + return '
'. + ''. + ''. + ''. + '
'; + } else { + return ''; + } +} + +/// general function for logging to table +function book_log($str1, $str2, $level = 0) { + switch ($level) { + case 1: + echo ''.$str1.''.$str2.''; + break; + case 2: + echo ''.$str1.''.$str2.''; + break; + default: + echo ''.$str1.''.$str2.''; + break; + } +} + +//================================================= +// import functions +//================================================= + +/// normalize relative links (= remove ..) +function book_prepare_link($ref) { + if ($ref == '') { + return ''; + } + $ref = str_replace('\\','/',$ref); //anti MS hack + $cnt = substr_count($ref, '..'); + for($i=0; $i<$cnt; $i++) { + $ref = ereg_replace('[^/]+/\.\./', '', $ref); + } + //still any '..' left?? == error! error! + if (substr_count($ref, '..') > 0) { + return ''; + } + if (ereg('[\|\`]', $ref)) { // check for other bad characters + return ''; + } + return $ref; +} + +/// read chapter content from file +function book_read_chapter($base, $ref) { + $file = $base.'/'.$ref; + if (filesize($file) <= 0 or !is_readable($file)) { + book_log($ref, get_string('error'), 2); + return; + } + //first read data + $handle = fopen($file, "rb"); + $contents = fread($handle, filesize($file)); + fclose($handle); + //extract title + if (preg_match('/([^<]+)<\/title>/i', $contents, $matches)) { + $chapter->title = $matches[1]; + } else { + $chapter->title = $ref; + } + //extract page body + if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { + $chapter->content = $matches[1]; + } else { + book_log($ref, get_string('error'), 2); + return; + } + book_log($ref, get_string('ok')); + $chapter->importsrc = $ref; + //extract page head + if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { + $head = $matches[1]; + if (preg_match('/charset=([^"]+)/is', $head, $matches)) { + $enc = $matches[1]; + $textlib = textlib_get_instance(); + $chapter->content = $textlib->convert($chapter->content, $enc, current_charset()); + $chapter->title = $textlib->convert($chapter->title, $enc, current_charset()); + } + if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css + for($i=0; $i<count($matches[0]); $i++){ + $chapter->content = $matches[0][$i]."\n".$chapter->content; + } + } + } + return $chapter; +} + +///relink images and relative links +function book_relink($id, $bookid, $courseid) { + global $CFG; + if ($CFG->slasharguments) { + $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; + } else { + $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; + } + $chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, title, content, importsrc'); + $originals = array(); + foreach($chapters as $ch) { + $originals[$ch->importsrc] = $ch; + } + foreach($chapters as $ch) { + $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); + $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) + $modified = false; + //image relinking + if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { + for($i = 0; $i<count($images[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link + $link = book_prepare_link($base.$images[2][$i]); + if ($link == '') { + continue; + } + $origtag = $images[0][$i]; + $newtag = $images[1][$i].$link.$images[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $images[2][$i].' --> '.$link); + } + } + } + //css relinking (dlnsk) + if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { + for($i = 0; $i<count($csslinks[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link + $link = book_prepare_link($base.$csslinks[2][$i]); + if ($link == '') { + continue; + } + $origtag = $csslinks[0][$i]; + $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $csslinks[2][$i].' --> '.$link); + } + } + } + //general embed relinking - flash and others?? + if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { + for($i = 0; $i<count($embeds[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link + $link = book_prepare_link($base.$embeds[2][$i]); + if ($link == '') { + continue; + } + $origtag = $embeds[0][$i]; + $newtag = $embeds[1][$i].$link.$embeds[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $embeds[2][$i].' --> '.$link); + } + } + } + //flash in IE <param name=movie value="something" - I do hate IE! + if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { + for($i = 0; $i<count($params[0]); $i++) { + if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { + if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link + $link = book_prepare_link($base.$values[2]); + if ($link == '') { + continue; + } + $newvalue = $values[1].$link.$values[3]; + $newparam = str_replace($values[0], $newvalue, $params[0][$i]); + $ch->content = str_replace($params[0][$i], $newparam, $ch->content); + $modified = true; + book_log($ch->title, $values[2].' --> '.$link); + } + } + } + } + //java applet - add code bases if not present!!!! + if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { + for($i = 0; $i<count($applets[0]); $i++) { + if (!stripos($applets[0][$i], 'codebase')) { + $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); + $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); + $modified = true; + } + } + } + //relink java applet code bases + if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { + for($i = 0; $i<count($codebases[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link + $link = book_prepare_link($base.$codebases[2][$i]); + if ($link == '') { + continue; + } + $origtag = $codebases[0][$i]; + $newtag = $codebases[1][$i].$link.$codebases[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $codebases[2][$i].' --> '.$link); + } + } + } + //relative link conversion + if ($ch->importsrc && preg_match_all('/(<a[^>]+href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { + for($i = 0; $i<count($links[0]); $i++) { + if ($links[2][$i] != '' //check for inner anchor links + && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link + $origtag = $links[0][$i]; + $target = book_prepare_link($rel.$links[2][$i]); //target chapter + if ($target != '' && array_key_exists($target, $originals)) { + $o = $originals[$target]; + $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; + $newtag = preg_replace('/target=[^\s>]/i','', $newtag); + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); + } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links + $target = book_prepare_link($base.$links[2][$i]); + $origtag = $links[0][$i]; + $newtag = $links[1][$i].$target.$links[4][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $links[2][$i].' --> '.$target); + } + } + } + } + if ($modified) { + $ch->title = addslashes($ch->title); + $ch->content = addslashes($ch->content); + $ch->importsrc = addslashes($ch->importsrc); + if (!update_record('book_chapters', $ch)) { + error('Could not update your book'); + } + } + } +} + +?> diff --git a/mod.html b/mod.html new file mode 100644 index 00000000000..d29c4bcb68c --- /dev/null +++ b/mod.html @@ -0,0 +1,116 @@ +<?php // $Id: mod.html,v 1.1 2006/03/12 18:39:59 skodak Exp $ +require($CFG->dirroot.'/mod/book/lib.php'); + +if (empty($form->name)) { + $form->name = ''; +} +if (empty($form->summary)) { + $form->summary = ''; +} +if (empty($form->numbering)) { + $form->numbering = NUM_NONE; +} +if (empty($form->disableprinting)) { + $form->disableprinting = 0; +} +if (empty($form->customtitles)) { + $form->customtitles = 0; +} +?> + +<form name="form" method="post" action="mod.php"> +<table cellpadding="5" align="center"> +<tr valign="top"> + <td align="right"><p><b><?php print_string('name') ?>:</b></p></td> + <td> + <input type="text" name="name" size="30" value="<?php p($form->name) ?>"> + </td> +</tr> + +<tr valign="top"> + <td align="right"><p><b><?php print_string('summary') ?>:</b></p> + <font size="1"> + <?php + helpbutton("writing", get_string("helpwriting"), "moodle", true, true); + echo "<br />"; + helpbutton("questions", get_string("helpquestions"), "moodle", true, true); + echo "<br />"; + if ($usehtmleditor) { + helpbutton("richtext", get_string("helprichtext"), "moodle", true, true); + } else { + emoticonhelpbutton("form", "description"); + } + ?> + <br /> + </font> + </td> + <td> + <?php print_textarea($usehtmleditor, 20, 60, 680, 400, 'summary', $form->summary); ?> + </td> +</tr> + +<tr valign="top"> + <td align="right"><p><b><?php print_string('numbering', 'book') ?>:</b></p></td> + <td> + <?php + choose_from_menu($NUMBERING_TYPE, 'numbering', $form->numbering, ''); + helpbutton('numberingtype', get_string('numbering', 'book'), 'book'); + ?> + </td> +</tr> + +<tr valign="top"> + <td align="right"><p><b><?php print_string('disableprinting', 'book') ?>:</b></p></td> + <td> + <select size="1" name="disableprinting"> + <option value="1" <?php + if ( $form->disableprinting ) { + echo 'selected="selected"'; + } + ?>><?php echo get_string('yes') ?> + </option> + <option value="0" <?php + if ( !$form->disableprinting ) { + echo 'selected="selected"'; + } + ?>><?php echo get_string('no') ?> + </option> + </select> <?php helpbutton('disableprinting', get_string('disableprinting', 'book'), 'book') ?> + </td> +</tr> + +<tr valign="top"> + <td align="right"><p><b><?php print_string('customtitles', 'book') ?>:</b></p></td> + <td> + <select size="1" name="customtitles"> + <option value="1" <?php + if ( $form->customtitles ) { + echo 'selected="selected"'; + } + ?>><?php echo get_string('yes') ?> + </option> + <option value="0" <?php + if ( !$form->customtitles ) { + echo 'selected="selected"'; + } + ?>><?php echo get_string('no') ?> + </option> + </select> <?php helpbutton('customtitles', get_string('customtitles', 'book'), 'book') ?> + </td> +</tr> + + +</table> +<center> + <input type="submit" value="<?php print_string('savechanges') ?>" /> +</center> + <input type="hidden" name="course" value="<?php p($form->course) ?>" /> + <input type="hidden" name="sesskey" value="<?php p($form->sesskey) ?>" /> + <input type="hidden" name="coursemodule" value="<?php p($form->coursemodule) ?>" /> + <input type="hidden" name="section" value="<?php p($form->section) ?>" /> + <input type="hidden" name="module" value="<?php p($form->module) ?>" /> + <input type="hidden" name="modulename" value="<?php p($form->modulename) ?>" /> + <input type="hidden" name="instance" value="<?php p($form->instance) ?>" /> + <input type="hidden" name="mode" value="<?php p($form->mode) ?>" /> +</form> + diff --git a/move.php b/move.php new file mode 100644 index 00000000000..21fde8692d1 --- /dev/null +++ b/move.php @@ -0,0 +1,148 @@ +<?PHP // $Id: move.php,v 1.1 2006/03/12 18:39:59 skodak Exp $ + +require('teacheraccess.php'); //page only for teachers +$up = optional_param('up', 0, PARAM_BOOL); + + +$oldchapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, pagenum, subchapter'); + +$nothing = 0; + +$chapters = array(); +$chs = 0; +$che = 0; +$ts = 0; +$te = 0; +// create new ordered array and find chapters to be moved +$i = 1; +$found = 0; +foreach ($oldchapters as $ch) { + $chapters[$i] = $ch; + if ($chapter->id === $ch->id) { + $chs = $i; + $che = $chs; + if ($ch->subchapter) { + $found = 1;//subchapter moves alone + } + } else if ($chs) { + if ($found) { + //nothing + } else if ($ch->subchapter) { + $che = $i; // chapter with subchapter(s) + } else { + $found = 1; + } + } + $i++; +} + +// find target chapter(s) +if ($chapters[$chs]->subchapter) { //moving single subchapter up or down + if ($up) { + if ($chs === 1) { + $nothing = 1; //already first + } else { + $ts = $chs - 1; + $te = $ts; + } + } else { //down + if ($che === count($chapters)) { + $nothing = 1; //already last + } else { + $ts = $che + 1; + $te = $ts; + } + } +} else { // moving chapter and looking for next/previous chapter + if ($up) { //up + if ($chs === 1) { + $nothing = 1; //already first + } else { + $te = $chs - 1; + for($i = $chs-1; $i >= 1; $i--) { + if ($chapters[$i]->subchapter) { + $ts = $i; + } else { + $ts = $i; + break; + } + } + } + } else { //down + if ($che === count($chapters)) { + $nothing = 1; //already last + } else { + $ts = $che + 1; + $found = 0; + for($i = $che+1; $i <= count($chapters); $i++) { + if ($chapters[$i]->subchapter) { + $te = $i; + } else { + if ($found) { + break; + } else { + $te = $i; + $found = 1; + } + } + } + } + } +} + +//recreated newly sorted list of chapters +if (!$nothing) { + $newchapters = array(); + + if ($up) { + if ($ts > 1) { + for ($i=1; $i<$ts; $i++) { + $newchapters[] = $chapters[$i]; + } + } + for ($i=$chs; $i<=$che; $i++) { + $newchapters[$i] = $chapters[$i]; + } + for ($i=$ts; $i<=$te; $i++) { + $newchapters[$i] = $chapters[$i]; + } + if ($che<count($chapters)) { + for ($i=$che; $i<=count($chapters); $i++) { + $newchapters[$i] = $chapters[$i]; + } + } + } else { + if ($chs > 1) { + for ($i=1; $i<$chs; $i++) { + $newchapters[] = $chapters[$i]; + } + } + for ($i=$ts; $i<=$te; $i++) { + $newchapters[$i] = $chapters[$i]; + } + for ($i=$chs; $i<=$che; $i++) { + $newchapters[$i] = $chapters[$i]; + } + if ($te<count($chapters)) { + for ($i=$te; $i<=count($chapters); $i++) { + $newchapters[$i] = $chapters[$i]; + } + } + } + + //store chapters in the new order + $i = 1; + foreach ($newchapters as $ch) { + $ch->pagenum = $i; + update_record('book_chapters', $ch); + $i++; + } +} + +add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); +add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); +book_check_structure($book->id); +redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); +die; + +?> diff --git a/pix/add.gif b/pix/add.gif new file mode 100644 index 0000000000000000000000000000000000000000..3a0de01034f7619f568f9f6684e225b73a5651b3 GIT binary patch literal 68 zcmZ?wbhEHb<YwSzn90EKAB2n<z(DaQ3nK#q6N3(j2a;!C5}m?Y*?nr-f#$wt0-NvI O=-D^+pP0bPU=0AvsSs%Z literal 0 HcmV?d00001 diff --git a/pix/nav_exit.gif b/pix/nav_exit.gif new file mode 100644 index 0000000000000000000000000000000000000000..6177c8e7c3b95bb151e03f8770ce3075da1a5832 GIT binary patch literal 248 zcmZ?wbhEHblwgox*v$X}|NsAg`t)gGVd3}h-=|NXZf<Vw>+1`a!9pnhWMO1r;9$@J z$$`vZU|A|~va^fPVz%>d9e1-H=Q5FdAxy3h_T@G5W?CNjkzM{tR)8g(jX`^%8pC~m z3zb(4TFbR>oH;N_RBWA9%}Jdgwd-1YG>#^}d?n*Cnfdjd)w847pO#1*)XU!=Uv11( zo@v3tq$=JVl3dl!z!uNc+^Ro0o<nuAL#=)L<Om_p$=#L?OH@T{mpH6lyFy3SY{{0b c)^ggcTbCFu)KpMXQFGUn7x$g0Dac?A071P_G5`Po literal 0 HcmV?d00001 diff --git a/pix/nav_next.gif b/pix/nav_next.gif new file mode 100644 index 0000000000000000000000000000000000000000..17b42333ed7f18f9576ec1ac87b3491c4dceec70 GIT binary patch literal 246 zcmZ?wbhEHblwgox*v-K3|Nnmm28O3kpB5Gte*gY``t<4M=H|Y>zCb~&K=CIFBLf2m zgAPa*WCjDvVu6#LeVi7voqp@MoAo%C70e4^V|}nMuaP&?^1zSm@=tUBt4>jQ@SBl& z@+83tCj|vJO*0fe;HvMfCMv!|q&|cv=PU2*qk2Yfa;}}_&@a2;s&F{=lkNgL;X8AS ztC>{A>saawtJ;}j1DV=le4Cg8IaK>6bcVLG^!qzA&uF*o?pGDDT{LI)3`beB85=iQ c%W1Q2nqf3wQ$a~Z%}G;;RXkBzQ;@+L09sH_^#A|> literal 0 HcmV?d00001 diff --git a/pix/nav_prev.gif b/pix/nav_prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..0a40548aa382a626045e5e719bb6e29ddd5b9703 GIT binary patch literal 247 zcmZ?wbhEHblwgox*v-K3|Nnmm28O3kpB5Gte*gY``t<4M=H|Y>zCb~&K=CIFBLf2m zgAPa*WCjDv5`mMQU7QxPoqy}NoAo%CiQEfeV|}nMuaP&?^1zSm@=tUBt6oug@SBl& zm4jX~i-5LHj9ccE$QA1~zlrY<nR`nuA@s^DLxZAkGS|*>=#@!3C>%amv}LuO@SU@6 zEKI86b@joPEL}{oVN7*}J_g-PVH~RcT?Lb>oBI8QT>9HO=QVrCFPb@P&0<Gcv&EY> dTgz#)ZeDD(KvO|UMa@Z5UObBJkcc3IH2~b)QW^jN literal 0 HcmV?d00001 diff --git a/pix/nav_prev_dis.gif b/pix/nav_prev_dis.gif new file mode 100644 index 0000000000000000000000000000000000000000..6815c16e5f392dd614f2cb4e03af293f9804d480 GIT binary patch literal 209 zcmZ?wbhEHblwgoxSjE8b|NsAK)28+G^c*;F;OWz+-@kun00YIJEQ|~cYz#Ue9!M<% z^R$dzVxK;+x`h{fN-A7E)j^}}Mu_FX6<r#w>kKaF#mHFSUv)DkxPQ9it7DZbnw+E= zj8s_JE~u?JQsvY-OO{(?SJi&z1xqflHoLY8Nha8}UlKZWYp<4o*{7Y`<2HC(uoR^R zXw^3A@-^0`ge$i-+Hy5?W%re}Gx2CNR(5yKF_veXvt;SQS%phyOq3J%ky<aOCn%^U I!pUF_0HG65TL1t6 literal 0 HcmV?d00001 diff --git a/pix/nav_sep.gif b/pix/nav_sep.gif new file mode 100644 index 0000000000000000000000000000000000000000..821ac1eb5613688eb46d9ba0f40e49f765aa604b GIT binary patch literal 41 scmZ?wbh9u|WMVL2=wM(lHa2EpV9)_#29O8?6Guz`%F}Q8leHME0gB!StpET3 literal 0 HcmV?d00001 diff --git a/pix/print_book.gif b/pix/print_book.gif new file mode 100644 index 0000000000000000000000000000000000000000..19311922071ab9833a006fe5b4e8552bbdea4b26 GIT binary patch literal 204 zcmZ?wbhEHblwgox*v$X}4Gs(k4jlOZ|G%-Z@&Df+{{Lr~Hf>r%Ljzb6olyMA!pOkD z$)E$00GYwSQfY9~bM;<}*JpRzyJ+;Wh|4*zTK1G}Pl3%ADS<mbc+bq4``9{4)$I(c ze#0TH&<`&wrpXpQsNqsQnYv2Kf^X#}2?48<S&U3u&UdRGyY$jjQg_Aex39KreN%S* msYyw>L4B2#VrqFQTTgwSbFCpqrfFC66upW1a&yE48LR=|5lLDA literal 0 HcmV?d00001 diff --git a/pix/print_chapter.gif b/pix/print_chapter.gif new file mode 100644 index 0000000000000000000000000000000000000000..b98dde903756da8aa13b333b8375fa03012e7d05 GIT binary patch literal 158 zcmZ?wbhEHblwgoxSj7MW|Ns9#aNxj$2M_-L{_y`lLqkIYP*CwF3nK#qJA)2L1xPIe zb8^M5JO2z$d9L0o_~NW1tD{Dj9BW^)<=l)FR<iB;cpSE{ymm?ue_?%NE$biKDkDkH z8^1Uin8kFDRoX4x+L&<qDbt!8tfp!mdPncRb^Ggc^-@z)jPKfB^R^W%T;Z?7%S|N2 HI2o(~>WDs) literal 0 HcmV?d00001 diff --git a/print.php b/print.php new file mode 100644 index 00000000000..269c9a2c85a --- /dev/null +++ b/print.php @@ -0,0 +1,180 @@ +<?PHP // $Id: print.php,v 1.1 2006/03/12 18:39:59 skodak Exp $ + +require_once('../../config.php'); +require_once('lib.php'); + +$id = required_param('id', PARAM_INT); // Course Module ID +$chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID + +// ========================================================================= +// security checks START - teachers and students view +// ========================================================================= +if ($CFG->forcelogin) { + require_login(); +} + +if (!$cm = get_record('course_modules', 'id', $id)) { + error('Course Module ID was incorrect'); +} + +if (!$course = get_record('course', 'id', $cm->course)) { + error('Course is misconfigured'); +} + +if ($course->category) { + require_login($course->id); +} + +if (!$cm->visible and !isteacher($course->id)) { + notice(get_string('activityiscurrentlyhidden')); +} + +if (!$book = get_record('book', 'id', $cm->instance)) { + error('Course module is incorrect'); +} + +if ($book->disableprinting) { + error('Printing is disabled'); +} + +//check all variables +if ($chapterid) { + //single chapter printing + if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { + error('Incorrect chapter ID'); + } + if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! + error('Chapter not in this book!'); + } + if ($chapter->hidden) { + error('Only visible chapters can be printed'); + } +} else { + //complete book + $chapter = false; +} +unset($id); +unset($chapterid); +// ========================================================================= +// security checks END +// ========================================================================= + +$strbooks = get_string('modulenameplural', 'book'); +$strbook = get_string('modulename', 'book'); +$strtop = get_string('top', 'book'); + +if (!empty($CFG->unicode)) { + $encoding = 'utf-8'; +} else { + $encoding = get_string('thischarset'); +} + +moodle_setlocale(); //workaround for buggy forced course language + +@header('Cache-Control: private, pre-check=0, post-check=0, max-age=0'); +@header('Pragma: no-cache'); +@header('Expires: '); +@header('Accept-Ranges: none'); +@header('Content-type: text/html; charset='.$encoding); + +$formatoptions = new stdClass; +$formatoptions->noclean = true; + +if ($chapter) { + add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + + $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum, title'); + + $print = 0; + $edit = 0; + require('toc.php'); + + /// page header + ?> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + <html> + <head> + <title><?PHP echo str_replace('"', '"', $book->name) ?> + + name) ?>" /> + + + + +
+ customtitles) { + if ($currsubtitle == ' ') { + echo '

'.$currtitle.'

'; + } else { + echo '

'.$currtitle.'
'.$currsubtitle.'

'; + } + } + echo format_text($chapter->content, FORMAT_HTML, $formatoptions, $course->id); + echo '
'; + echo ' '; + +} else { + add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id, $book->id, $cm->id); + $site = get_record('course','id',1); + $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum'); + + /// page header + ?> + + + + <?PHP echo str_replace('"', '"', $book->name) ?> + + name) ?>" /> + + + + +

name) ?>

+

summary) ?>

+
+ + + + + + + + + + + + + + + + +
:fullname) ?>
:fullname) ?>
:name) ?>
:
:
+ + wwwroot.'/mod/book/view.php?id='.$course->id.'&chapterid='; + $link2 = $CFG->wwwroot.'/mod/book/view.php?id='.$course->id; + foreach ($chapters as $ch) { + if (!$ch->hidden) { + echo '
'; + if (!$book->customtitles) { + echo '

'.$titles[$ch->id].'

'; + } + $content = str_replace($link1, '#ch', $ch->content); + $content = str_replace($link2, '#top', $content); + echo format_text($content, FORMAT_HTML, $formatoptions, $course->id); + echo '
'; + //echo ''.$strtop.''; + + } + } + echo ' '; +} + +?> diff --git a/restorelib.php b/restorelib.php new file mode 100644 index 00000000000..739e6af0d65 --- /dev/null +++ b/restorelib.php @@ -0,0 +1,380 @@ +id) + // | + // | + // | + // book_chapters + // (CL,pk->id, fk->bookid) + // + // Meaning: pk->primary key field of the table + // fk->foreign key to link with parent + // nt->nested field (recursive data) + // CL->course level info + // UL->user level info + // files->table may have files) + // + //----------------------------------------------------------- + + + //This function executes all the restore procedure about this mod + function book_restore_mods($mod,$restore) { + + global $CFG; + + $status = true; + + //Get record from backup_ids + $data = backup_getid($restore->backup_unique_code,$mod->modtype,$mod->id); + + if ($data) { + //Now get completed xmlized object + $info = $data->info; + //traverse_xmlize($info); //Debug + //print_object ($GLOBALS['traverse_array']); //Debug + //$GLOBALS['traverse_array']=""; //Debug + + //Now, build the BOOK record structure + $book->course = $restore->course_id; + $book->name = backup_todb($info['MOD']['#']['NAME']['0']['#']); + $book->summary = backup_todb($info['MOD']['#']['SUMMARY']['0']['#']); + $book->numbering = backup_todb($info['MOD']['#']['NUMBERING']['0']['#']); + $book->disableprinting = backup_todb($info['MOD']['#']['DISABLEPRINTING']['0']['#']); + $book->customtitles = backup_todb($info['MOD']['#']['CUSTOMTITLES']['0']['#']); + $book->timecreated = $info['MOD']['#']['TIMECREATED']['0']['#']; + $book->timemodified = $info['MOD']['#']['TIMEMODIFIED']['0']['#']; + + //The structure is equal to the db, so insert the book + $newid = insert_record ('book',$book); + + //Do some output + if (!defined('RESTORE_SILENTLY')) { + echo '
  • '.get_string('modulename','book').' "'.$book->name.'"
    '; + } + backup_flush(300); + + if ($newid) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,$mod->modtype, + $mod->id, $newid); + //now restore chapters + $status = book_chapters_restore($mod->id,$newid,$info,$restore); + + } else { + $status = false; + } + //Finalize ul + if (!defined('RESTORE_SILENTLY')) { + echo "
"; + } + + } else { + $status = false; + } + + return $status; + } + + //This function restores the book_chapters + function book_chapters_restore($old_book_id, $new_book_id,$info,$restore) { + + global $CFG; + + $status = true; + + //Get the chapters array + $chapters = $info['MOD']['#']['CHAPTERS']['0']['#']['CHAPTER']; + + //Iterate over chapters + for($i = 0; $i < sizeof($chapters); $i++) { + $sub_info = $chapters[$i]; + //traverse_xmlize($sub_info); //Debug + //print_object ($GLOBALS['traverse_array']); //Debug + //$GLOBALS['traverse_array']=""; //Debug + + //We'll need this later!! + $old_id = backup_todb($sub_info['#']['ID']['0']['#']); + + //Now, build the ASSIGNMENT_CHAPTERS record structure + $chapter->bookid = $new_book_id; + $chapter->pagenum = backup_todb($sub_info['#']['PAGENUM']['0']['#']); + $chapter->subchapter = backup_todb($sub_info['#']['SUBCHAPTER']['0']['#']); + $chapter->title = backup_todb($sub_info['#']['TITLE']['0']['#']); + $chapter->content = backup_todb($sub_info['#']['CONTENT']['0']['#']); + $chapter->hidden = backup_todb($sub_info['#']['HIDDEN']['0']['#']); + $chapter->timecreated = backup_todb($sub_info['#']['TIMECREATED']['0']['#']); + $chapter->timemodified = backup_todb($sub_info['#']['TIMEMODIFIED']['0']['#']); + $chapter->importsrc = backup_todb($sub_info['#']['IMPORTSRC']['0']['#']); + + //The structure is equal to the db, so insert the book_chapters + $newid = insert_record ('book_chapters',$chapter); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo '.'; + if (($i+1) % 1000 == 0) { + echo '
'; + } + } + backup_flush(300); + } + + if ($newid) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,'book_chapters',$old_id, + $newid); + } else { + $status = false; + } + } + return $status; + } + + //This function returns a log record with all the necessay transformations + //done. It's used by restore_log_module() to restore modules log. + function book_restore_logs($restore,$log) { + + $status = false; + + //Depending of the action, we recode different things + switch ($log->action) { + case "update": + case "view": //TO DO ... verify!!! + if ($log->cmid) { + //Get the new_id of the chapter (to recode the url field) + $ch = backup_getid($restore->backup_unique_code,"book_chapters",$log->info); + if ($pag) { + $log->url = "view.php?id=".$log->cmid."&chapterid=".$ch->new_id; + $log->info = $ch->new_id; + $status = true; + } + } + break; + case "view all": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "view.php?id=".$log->cmid; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "export": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "export.php?id=".$log->cmid; + $log->info = $mod->new_id; + $status = true; + } + } + break; + case "print": + if ($log->cmid) { + //Get the new_id of the module (to recode the info field) + $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); + if ($mod) { + $log->url = "print.php?id=".$log->cmid; + $log->info = $mod->new_id; + $status = true; + } + } + break; + default: + if (!defined('RESTORE_SILENTLY')) { + echo "action (".$log->module."-".$log->action.") unknow. Not restored
"; //Debug + } + break; + } + + if ($status) { + $status = $log; + } + return $status; + } + + //Return a content decoded to support interactivities linking. Every module + //should have its own. They are called automatically from + //book_decode_content_links_caller() function in each module + //in the restore process + function book_decode_content_links ($content,$restore) { + + global $CFG; + + $result = $content; + + //Link to the list of books + + $searchstring='/\$@(BOOKINDEX)\*([0-9]+)@\$/'; + //We look for it + preg_match_all($searchstring,$content,$foundset); + //If found, then we are going to look for its new id (in backup tables) + if ($foundset[0]) { + //print_object($foundset); //Debug + //Iterate over foundset[2]. They are the old_ids + foreach($foundset[2] as $old_id) { + //We get the needed variables here (course id) + $rec = backup_getid($restore->backup_unique_code,"course",$old_id); + //Personalize the searchstring + $searchstring='/\$@(BOOKINDEX)\*('.$old_id.')@\$/'; + //If it is a link to this course, update the link to its new location + if($rec->new_id) { + //Now replace it + $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/book/index.php?id='.$rec->new_id,$result); + } else { + //It's a foreign link so leave it as original + $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/book/index.php?id='.$old_id,$result); + } + } + } + + + //Links to specific chapters of books + + $searchstring='/\$@(BOOKCHAPTER)\*([0-9]+)\*([0-9]+)@\$/'; + //We look for it + preg_match_all($searchstring,$result,$foundset); + //If found, then we are going to look for its new id (in backup tables) + if ($foundset[0]) { + //print_object($foundset); //Debug + //Iterate over foundset[2] and foundset[3]. They are the old_ids + foreach($foundset[2] as $key => $old_id) { + $old_id2 = $foundset[3][$key]; + //We get the needed variables here (discussion id and post id) + $rec = backup_getid($restore->backup_unique_code,'course_modules',$old_id); + $rec2 = backup_getid($restore->backup_unique_code,'book_chapters',$old_id2); + //Personalize the searchstring + $searchstring='/\$@(BOOKCHAPTER)\*('.$old_id.')\*('.$old_id2.')@\$/'; + //If it is a link to this course, update the link to its new location + if($rec->new_id && $rec2->new_id) { + //Now replace it + $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/book/view.php?id='.$rec->new_id.'&chapterid='.$rec2->new_id,$result); + } else { + //It's a foreign link so leave it as original + $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/book/view.php?id='.$old_id.'&chapterid='.$old_id2,$result); + } + } + } + + + //Links to first chapters of books + + $searchstring='/\$@(BOOKSTART)\*([0-9]+)@\$/'; + //We look for it + preg_match_all($searchstring,$result,$foundset); + //If found, then we are going to look for its new id (in backup tables) + if ($foundset[0]) { + //print_object($foundset); //Debug + //Iterate over foundset[2]. They are the old_ids + foreach($foundset[2] as $old_id) { + //We get the needed variables here (course_modules id) + $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id); + //Personalize the searchstring + $searchstring='/\$@(BOOKSTART)\*('.$old_id.')@\$/'; + //If it is a link to this course, update the link to its new location + if($rec->new_id) { + //Now replace it + $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/book/view.php?id='.$rec->new_id,$result); + } else { + //It's a foreign link so leave it as original + $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/book/view.php?id='.$old_id,$result); + } + } + } + + return $result; + } + + //This function makes all the necessary calls to xxxx_decode_content_links() + //function in each module, passing them the desired contents to be decoded + //from backup format to destination site/course in order to mantain inter-activities + //working in the backup/restore process. It's called from restore_decode_content_links() + //function in restore process + function book_decode_content_links_caller($restore) { + global $CFG; + $status = true; + + //Decode every BOOK (summary) in the coure + if ($books = get_records_sql ("SELECT b.id, b.summary + FROM {$CFG->prefix}book b + WHERE b.course = $restore->course_id")) { + //Iterate over each book->summary + $i = 0; //Counter to send some output to the browser to avoid timeouts + foreach ($books as $book) { + //Increment counter + $i++; + $content = $book->summary; + $result = restore_decode_content_links_worker($content,$restore); + if ($result != $content) { + //Update record + $book->summary = addslashes($result); + $status = update_record('book',$book); + if ($CFG->debug>7) { + if (!defined('RESTORE_SILENTLY')) { + echo '

'.htmlentities($content).'
changed to
'.htmlentities($result).'

'; + } + } + } + //Do some output + if (($i+1) % 5 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo '.'; + if (($i+1) % 100 == 0) { + echo '
'; + } + } + backup_flush(300); + } + } + } + + //Decode every CHAPTER in the course + if ($chapters = get_records_sql ("SELECT ch.id, ch.content + FROM {$CFG->prefix}book b, + {$CFG->prefix}book_chapters ch + WHERE b.course = $restore->course_id AND + ch.bookid = b.id")) { + //Iterate over each chapter->content + $i = 0; //Counter to send some output to the browser to avoid timeouts + foreach ($chapters as $chapter) { + //Increment counter + $i++; + $content = $chapter->content; + $result = restore_decode_content_links_worker($content,$restore); + if ($result != $content) { + //Update record + $chapter->content = addslashes($result); + $status = update_record('book_chapters',$chapter); + if ($CFG->debug>7) { + if (!defined('RESTORE_SILENTLY')) { + echo '

'.htmlentities($content).'
changed to
'.htmlentities($result).'

'; + } + } + } + //Do some output + if (($i+1) % 5 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo '.'; + if (($i+1) % 100 == 0) { + echo '
'; + } + } + backup_flush(300); + } + } + } + + return $status; + } + + +?> diff --git a/show.php b/show.php new file mode 100644 index 00000000000..a4104feed4c --- /dev/null +++ b/show.php @@ -0,0 +1,38 @@ +hidden = $chapter->hidden ? 0 : 1; + +///add slashes to all text fields +$chapter->content = addslashes($chapter->content); +$chapter->title = addslashes($chapter->title); +$chapter->importsrc = addslashes($chapter->importsrc); +if (!update_record('book_chapters', $chapter)) { + error('Could not update your book'); +} + +///change visibility of subchapters too +if (!$chapter->subchapter) { + $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, subchapter, hidden'); + $found = 0; + foreach($chapters as $ch) { + if ($ch->id === $chapter->id) { + $found = 1; + } else if ($found and $ch->subchapter) { + $ch->hidden = $chapter->hidden; + update_record('book_chapters', $ch); + } else if ($found) { + break; + } + } +} + +add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); +add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); +book_check_structure($book->id); +redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); +die; + +?> diff --git a/teacheraccess.php b/teacheraccess.php new file mode 100644 index 00000000000..5f2f6e23806 --- /dev/null +++ b/teacheraccess.php @@ -0,0 +1,46 @@ +course)) { + error('Course is misconfigured'); +} + +if (!isteacheredit($course->id)) { + error('Only editing teachers can edit books!'); +} + +if (!$book = get_record('book', 'id', $cm->instance)) { + error('Course module is incorrect'); +} + +if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { + error('Incorrect chapter ID'); +} + +if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! + error('Chapter not in this book!'); +} + +//check all variables +unset($id); +unset($chapterid); + +?> diff --git a/toc.php b/toc.php new file mode 100644 index 00000000000..6b332974bb4 --- /dev/null +++ b/toc.php @@ -0,0 +1,193 @@ +numbering) { + case NUM_NONE: + $toc .= '
'; + break; + case NUM_NUMBERS: + $toc .= '
'; + break; + case NUM_BULLETS: + $toc .= '
'; + break; + case NUM_INDENTED: + $toc .= '
'; + break; +} + + +if ($print) { ///TOC for printing + $toc .= ''; + if ($book->customtitles) { + $toc .= '

'.get_string('toc', 'book').'

'; + } else { + $toc .= '

'.get_string('toc', 'book').'

'; + } + $titles = array(); + $toc .= '
    '; + foreach($chapters as $ch) { + $title = trim(strip_tags($ch->title)); + if (!$ch->hidden) { + if (!$ch->subchapter) { + $nch++; + $ns = 0; + $toc .= ($first) ? '
  • ' : '
  • '; + if ($book->numbering === NUM_NUMBERS) { + $title = "$nch $title"; + } + } else { + $ns++; + $toc .= ($first) ? '
    • ' : '
    • '; + if ($book->numbering === NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } + $titles[$ch->id] = $title; + $toc .= ''.$title.''; + $toc .= (!$ch->subchapter) ? '
        ' : ''; + $first = 0; + } + } + $toc .= '
    '; +} else if ($edit) { ///teacher's TOC + $toc .= '
      '; + $i = 0; + foreach($chapters as $ch) { + $i++; + $title = trim(strip_tags($ch->title)); + if (!$ch->subchapter) { + $toc .= ($first) ? '
    • ' : '
  • '; + if (!$ch->hidden) { + $nch++; + $ns = 0; + if ($book->numbering === NUM_NUMBERS) { + $title = "$nch $title"; + } + } else { + if ($book->numbering === NUM_NUMBERS) { + $title = "x $title"; + } + $title = ''.$title.''; + } + $prevtitle = $title; + } else { + $toc .= ($first) ? '
    • ' : '
    • '; + if (!$ch->hidden) { + $ns++; + if ($book->numbering === NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } else { + if ($book->numbering === NUM_NUMBERS) { + $title = "x.x $title"; + } + $title = ''.$title.''; + } + } + + if ($ch->id === $chapter->id) { + $toc .= ''.$title.''; + if ($ch->subchapter) { + $currtitle = $prevtitle; + $currsubtitle = $title; + } else { + $currtitle = $title; + $currsubtitle = ' '; + } + } else { + $toc .= ''.$title.''; + } + $toc .= '  '; + if ($i != 1) { + $toc .= ' '; + } + if ($i != count($chapters)) { + $toc .= ' '; + } + $toc .= ' '; + $toc .= ' '; + if ($ch->hidden) { + $toc .= ' '; + } else { + $toc .= ' '; + } + $toc .= ' '; + + $toc .= (!$ch->subchapter) ? '
        ' : ''; + $first = 0; + } + $toc .= '
    '; +} else { //normal students view + $toc .= '
      '; + foreach($chapters as $ch) { + $title = trim(strip_tags($ch->title)); + if (!$ch->hidden) { + if (!$ch->subchapter) { + $nch++; + $ns = 0; + $toc .= ($first) ? '
    • ' : '
  • '; + if ($book->numbering === NUM_NUMBERS) { + $title = "$nch $title"; + } + $prevtitle = $title; + } else { + $ns++; + $toc .= ($first) ? '
    • ' : '
    • '; + if ($book->numbering === NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } + if ($ch->id === $chapter->id) { + $toc .= ''.$title.''; + if ($ch->subchapter) { + $currtitle = $prevtitle; + $currsubtitle = $title; + } else { + $currtitle = $title; + $currsubtitle = ' '; + } + } else { + $toc .= ''.$title.''; + } + $toc .= (!$ch->subchapter) ? '
        ' : ''; + $first = 0; + } + } + $toc .= '
    '; +} + +$toc .= '
  • '; + +$toc = str_replace('
      ', '', $toc); //cleanup of invalid structures + +?> diff --git a/version.php b/version.php new file mode 100644 index 00000000000..e5b30774573 --- /dev/null +++ b/version.php @@ -0,0 +1,13 @@ +version = 2006031200; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2006031000; // Requires this Moodle version +$module->cron = 0; // Period for cron to check this module (secs) + +$release = "1.3alpha"; // User-friendly version number + +?> diff --git a/view.php b/view.php new file mode 100644 index 00000000000..6aff971f9e4 --- /dev/null +++ b/view.php @@ -0,0 +1,252 @@ +forcelogin) { + require_login(); +} + +if (!$cm = get_record('course_modules', 'id', $id)) { + error('Course Module ID is incorrect'); +} + +if (!$course = get_record('course', 'id', $cm->course)) { + error('Course is misconfigured'); +} + +if ($course->category) { + require_login($course->id); +} + +if (!$book = get_record('book', 'id', $cm->instance)) { + error('Course module is incorrect'); +} + +$isteacher = isteacheredit($course->id); +if ($isteacher) { + if($edit != -1) { + $USER->editing = $edit; + } else { + if (isset($USER->editing)) { + $edit = $USER->editing; + } else { + $edit = 0; + } + } +} else { + $edit = 0; +} + +if (!$cm->visible and !$isteacher) { + notice(get_string('activityiscurrentlyhidden')); +} + +/// read chapters +$select = $isteacher ? "bookid = $book->id" : "bookid = $book->id AND hidden = 0"; +$chapters = get_records_select('book_chapters', $select, 'pagenum', 'id, pagenum, subchapter, title, hidden'); + +if (!$chapters) { + if ($isteacher) { + redirect('edit.php?id='.$cm->id); //no chapters - add new one + die; + } else { + error('Error reading book chapters.'); + } +} +/// check chapterid and read chapter data +if ($chapterid == '0') { // go to first chapter if no given + foreach($chapters as $ch) { + if ($isteacher) { + $chapterid = $ch->id; + break; + } + if (!$ch->hidden) { + $chapterid = $ch->id; + break; + } + } +} + + +if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { + error('Error reading book chapters.'); +} + +//check all variables +unset($id); +unset($chapterid); + +/// chapter is hidden for students +if (!$isteacher and $chapter->hidden) { + error('Error reading book chapters.'); +} + +/// chapter not part of this book! +if ($chapter->bookid != $book->id) { + error('Chapter not part of this book!'); +} +// ========================================================================= +// security checks END +// ========================================================================= + +add_to_log($course->id, 'book', 'view', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + + +///read standard strings +$strbooks = get_string('modulenameplural', 'book'); +$strbook = get_string('modulename', 'book'); +$strTOC = get_string('TOC', 'book'); + +/// prepare header +if ($course->category) { + $navigation = ''.$course->shortname.' ->'; +} else { + $navigation = ''; +} + +$buttons = $isteacher ? ''. + '
      '.update_module_button($cm->id, $course->id, $strbook).' '.book_edit_button($cm->id, $course->id, $chapter->id).'
      ' + : ' '; + +print_header( "$course->shortname: $book->name ($chapter->title)", + $course->fullname, + "$navigation id\">$strbooks -> $book->name", + '', + '', + true, + $buttons, + navmenu($course, $cm) + ); + + +/// prepare chapter navigation icons +$previd = null; +$nextid = null; +$found = 0; +foreach ($chapters as $ch) { + if ($found) { + $nextid= $ch->id; + break; + } + if ($ch->id == $chapter->id) { + $found = 1; + } + if (!$found) { + $previd = $ch->id; + } +} +if ($ch == current($chapters)) { + $nextid = $ch->id; +} +$chnavigation = ''; +if ($previd) { + $chnavigation .= ''; +} else { + $chnavigation .= ''; +} +$chnavigation .= '    '; +if ($nextid) { + $chnavigation .= ''; +} else { + $sec = ''; + if ($section = get_record('course_sections', 'id', $cm->section)) { + $sec = $section->section; + } + $chnavigation .= ''; +} + +/// prepare print icons +if ($book->disableprinting) { + $printbook = ''; + $printchapter = ''; +} else { + $printbook = ''; + $printchapter = ''; +} + +// prepare $toc and $currtitle, $currsubtitle +require('toc.php'); + +if ($edit) { + $tocwidth = $CFG->book_tocwidth + 80; +} else { + $tocwidth = $CFG->book_tocwidth; +} + +$doimport = ($isteacher and $edit) ? ' ('.get_string('doimport', 'book').')' : ''; + + +// ===================================================== +// Book display HTML code +// ===================================================== + +?> + + + + + + + + + + + + + +
      + + + + + + + +
      +
      +
      '; + helpbutton('faq', get_string('faq','book'), 'book', true, true); + echo ''; + } + ?> +
      + customtitles) { + if ($currsubtitle == ' ') { + $content .= '

      '.$currtitle.'

      '; + } else { + $content .= '

      '.$currtitle.'
      '.$currsubtitle.'

      '; + } + } + $content .= $chapter->content; + + $nocleanoption = new object(); + $nocleanoption->noclean = true; + echo '
      '; + echo format_text($content, FORMAT_HTML, $nocleanoption, $course->id); + echo '
      '; + print_simple_box_end(); + /// lower navigation + echo '

      '.$chnavigation.'

      '; + ?> +

      + + From d9b10a5a91965b0fb19536dc1d1f6172e5460749 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 29 Mar 2006 06:21:56 +0000 Subject: [PATCH 002/455] fixed typo --- restorelib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/restorelib.php b/restorelib.php index 739e6af0d65..724b131cada 100644 --- a/restorelib.php +++ b/restorelib.php @@ -1,4 +1,4 @@ -module."-".$log->action.") unknow. Not restored
      "; //Debug + echo "action (".$log->module."-".$log->action.") unknown. Not restored
      "; //Debug } break; } From e4a0993bdefd962a5212bf2a46d50ce78e9e9ea4 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 24 Apr 2006 19:35:48 +0000 Subject: [PATCH 003/455] fixed log action inserts --- db/mysql.sql | 10 +++++----- db/postgres7.sql | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/db/mysql.sql b/db/mysql.sql index 9cf93e54024..ecb8593b16b 100644 --- a/db/mysql.sql +++ b/db/mysql.sql @@ -1,4 +1,4 @@ -# $Id: mysql.sql,v 1.1 2006/03/12 18:40:01 skodak Exp $ +# $Id: mysql.sql,v 1.2 2006/04/24 19:35:48 skodak Exp $ # This file contains a complete database schema for all the # tables used by the book module, written in SQL @@ -35,7 +35,7 @@ CREATE TABLE prefix_book_chapters ( ) COMMENT='Defines book_chapters'; # -------------------------------------------------------- -INSERT INTO prefix_log_display VALUES ('book', 'update', 'book', 'name'); -INSERT INTO prefix_log_display VALUES ('book', 'view', 'book', 'name'); -INSERT INTO prefix_log_display VALUES ('book', 'view all', 'book', 'name'); -INSERT INTO prefix_log_display VALUES ('book', 'print', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'update', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'view', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'view all', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'print', 'book', 'name'); diff --git a/db/postgres7.sql b/db/postgres7.sql index 2d6a4ec77b2..9c74f3f7d47 100644 --- a/db/postgres7.sql +++ b/db/postgres7.sql @@ -1,4 +1,4 @@ -# $Id: postgres7.sql,v 1.1 2006/03/12 18:40:01 skodak Exp $ +# $Id: postgres7.sql,v 1.2 2006/04/24 19:35:48 skodak Exp $ # This file contains a complete database schema for all the # tables used by the book module, written in SQL @@ -33,7 +33,7 @@ CREATE TABLE prefix_book_chapters ( ); # -------------------------------------------------------- -INSERT INTO prefix_log_display VALUES ('book', 'update', 'book', 'name'); -INSERT INTO prefix_log_display VALUES ('book', 'view', 'book', 'name'); -INSERT INTO prefix_log_display VALUES ('book', 'view all', 'book', 'name'); -INSERT INTO prefix_log_display VALUES ('book', 'print', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'update', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'view', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'view all', 'book', 'name'); +INSERT INTO prefix_log_display (module, action, mtable, field) VALUES ('book', 'print', 'book', 'name'); From d034a70d6f8576ab9c6e0ef32dea058d98c7eab7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 24 Apr 2006 19:41:14 +0000 Subject: [PATCH 004/455] fixed dates of releases --- README.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.txt b/README.txt index 3cd0ccb0bb6..b1ac52d86d6 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -$Id: README.txt,v 1.1 2006/03/12 18:39:59 skodak Exp $ +$Id: README.txt,v 1.2 2006/04/24 19:41:14 skodak Exp $ /////////////////////////////////////////////////////////////////////////// // // @@ -78,16 +78,16 @@ Future: * I like eXe editor, I would like to improve Book in this direction ... ;-) CHANGELOG: -== 1.1 - 2005/01/01 ======================================================= - * compatible ONLY with 1.4.3 and later! - * removed some unused searching stuff - * fixed headers in print.php == 1.1RC1 - 2004/11/15 ======================================================= * compatible ONLY with 1.4.2 and later !!! * added sesskey for enhanced security * navigation links do not enter hidden chapters * import - correct linking when slasharguments are off * removed coursefiles.php +== 1.1 - 2005/01/01 ======================================================= + * compatible ONLY with 1.4.3 and later! + * removed some unused searching stuff + * fixed headers in print.php == 1.2RC - 2005/07/13 ========================================================== * compatible with 1.5.1 + only * improved restore @@ -95,7 +95,7 @@ CHANGELOG: * html editor for summary * fixed postgresql upgrade * no need to move language packs -== 1.2 - 2003/03/11 ========================================================== +== 1.2 - 2006/03/11 ========================================================== * removed 64kB page content limit in mysql * exit button now goes to course section anchor * chater title now in browser title bar @@ -103,7 +103,7 @@ CHANGELOG: * during import chapters with names "*_sub.htm?" are imported as subchapters * deleting in import selection windows now works * last version before transition to 1.6 -== 1.3alpha - 2003/03/12 ====================================================== +== 1.3alpha - 2006/03/12 ====================================================== * compatible with 1.6dev only, use previous version for 1.5.x * unicode upgrade supported - not much tested * backup fixes - from Penny Leach, thanks! From 1f17c197e96470fa00215efe1e4cc47cdff7a2b9 Mon Sep 17 00:00:00 2001 From: Gustav Delius Date: Mon, 16 Oct 2006 08:05:26 +0000 Subject: [PATCH 005/455] Fixed typo, converting

      into

      --- view.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view.php b/view.php index 6aff971f9e4..f16fedd816b 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,4 @@ - ('.$currtitle.'

      '; + $content .= '

      '.$currtitle.'

      '; } else { $content .= '

      '.$currtitle.'
      '.$currsubtitle.'

      '; } From 0d717a52326cb8c2185f0de46aee53b03d40c01d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 7 Nov 2006 18:32:05 +0000 Subject: [PATCH 006/455] fixed incorrect === in Book mod --- toc.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/toc.php b/toc.php index 6b332974bb4..94782fb5204 100644 --- a/toc.php +++ b/toc.php @@ -1,4 +1,4 @@ -' : '
    • '; - if ($book->numbering === NUM_NUMBERS) { + if ($book->numbering == NUM_NUMBERS) { $title = "$nch $title"; } } else { $ns++; $toc .= ($first) ? '
    • "; echo ""; + echo ""; echo ""; echo ""; + echo ""; echo ""; echo "
      "; if (!empty($USER->fileop) and ($USER->fileop == "move") and ($USER->filesource <> $wdir)) { echo "
      "; - echo ' '; + echo "
      "; + echo ' '; echo " "; echo " "; echo " "; echo " sesskey\" />"; echo " "; + echo "
      "; echo "
      "; } + echo "
      "; echo "
      "; - echo ' '; + echo "
      "; + echo ' '; echo " "; echo " "; - echo " "; + echo " "; echo " "; + echo "
      "; + echo "
      "; + echo "
      "; + echo "
      "; //dummy form - alignment only + echo "
      "; + echo " "; + echo " "; + echo "
      "; echo "
      "; echo "
      "; echo "
      "; - echo ' '; + echo "
      "; + echo ' '; echo " "; echo " "; echo " "; echo " "; + echo "
      "; echo "
      "; echo "
      "; - echo "
      "; + echo "
      "; + //echo "
      "; } diff --git a/edit.php b/edit.php index ba74f755d2a..23049f6ede3 100644 --- a/edit.php +++ b/edit.php @@ -1,4 +1,4 @@ -course)) { error('Course is misconfigured'); } -if (!isteacheredit($course->id)) { - error('Only editing teachers can edit books!', $_SERVER['HTTP_REFERER']); -} +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('moodle/course:manageactivities', $context); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); diff --git a/generateimscp.php b/generateimscp.php index 1112dbcde0a..60f5799967c 100644 --- a/generateimscp.php +++ b/generateimscp.php @@ -1,4 +1,4 @@ -dirroot . '/backup/lib.php'); require_once($CFG->dirroot . '/lib/filelib.php'); -$id = required_param('id', PARAM_INT); // Course Module ID +$id = required_param('id', PARAM_INT); // Course Module ID -if ($CFG->forcelogin) { - require_login(); -} +require_login(); -if (!$cm = get_record('course_modules', 'id', $id)) { +if (!$cm = get_coursemodule_from_id('book', $id)) { error('Course Module ID was incorrect'); } @@ -43,22 +41,13 @@ if (!$course = get_record('course', 'id', $cm->course)) { error('Course is misconfigured'); } -if ($course->category) { - require_login($course->id); -} - -if (!$cm->visible and !isteacher($course->id)) { - notice(get_string('activityiscurrentlyhidden')); -} +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('moodle/course:manageactivities', $context); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); } -if (!isteacher($course->id)) { - error('Only teachers are allowed to generate IMS CP packages'); -} - $strbooks = get_string('modulenameplural', 'book'); $strbook = get_string('modulename', 'book'); $strtop = get_string('top', 'book'); @@ -220,6 +209,7 @@ function chapter2html($chapter, $courseid, $bookid) { $content .= '' . "\n"; $content .= '' . "\n"; $content .= '

      ' . $chapter->title . '

      ' ."\n"; + $options = new object(); $options->noclean = true; $content .= format_text($chapter->content, '', $options, $courseid) . "\n"; $content .= '' . "\n"; @@ -255,7 +245,7 @@ function chapter2html($chapter, $courseid, $bookid) { } /// Build the final object needed to have all the info in order to create the manifest - $object = new stdClass; + $object = new object(); $object->content = $content; $object->localfiles = $basefiles; diff --git a/import.php b/import.php index 3f345a59856..f53f09fa3ed 100644 --- a/import.php +++ b/import.php @@ -1,4 +1,4 @@ -course)) { error('Course is misconfigured'); } -if (!isteacheredit($course->id)) { - error('Only editing teachers can edit books!'); -} +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('moodle/course:manageactivities', $context); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); @@ -150,8 +149,8 @@ if (($form = data_submitted()) && (confirm_sesskey())) {  '; - button_to_popup_window ('/mod/book/coursefiles.php?choose=theform.reference&id='.$course->id, + echo ' '; + button_to_popup_window ('/mod/book/coursefiles.php?choose=id_reference&id='.$course->id, 'coursefiles', $strchoose, 500, 750, $strchoose); ?> diff --git a/index.php b/index.php index 7f315062077..445af84addb 100644 --- a/index.php +++ b/index.php @@ -1,4 +1,4 @@ -forcelogin) { - require_login(); -} if (!$course = get_record('course', 'id', $id)) { error('Course ID is incorrect'); } -if ($course->category) { - require_login($course->id); -} +require_course_login($course, true); //check all variables unset($id); diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php index 19113cd9a5e..f6171e170f7 100644 --- a/lang/en_utf8/book.php +++ b/lang/en_utf8/book.php @@ -1,4 +1,4 @@ -Chapters are sorted alphabetically using file names.
      Files named \'sub_*.*\' are always imported as subchapters.'; diff --git a/lib.php b/lib.php index fc8f8a372cc..37d17d3251a 100644 --- a/lib.php +++ b/lib.php @@ -1,19 +1,21 @@ - get_string('numbering0', 'book'), - NUM_NUMBERS => get_string('numbering1', 'book'), - NUM_BULLETS => get_string('numbering2', 'book'), - NUM_INDENTED => get_string('numbering3', 'book') ); if (!isset($CFG->book_tocwidth)) { set_config("book_tocwidth", 180); // default toc width } +function book_get_numbering_types() { + return array (NUM_NONE => get_string('numbering0', 'book'), + NUM_NUMBERS => get_string('numbering1', 'book'), + NUM_BULLETS => get_string('numbering2', 'book'), + NUM_INDENTED => get_string('numbering3', 'book') ); +} /// Library of functions and constants for module 'book' @@ -25,6 +27,12 @@ function book_add_instance($book) { $book->timecreated = time(); $book->timemodified = $book->timecreated; + if (!isset($book->customtitles)) { + $book->customtitles = 0; + } + if (!isset($book->disableprinting)) { + $book->disableprinting = 0; + } return insert_record('book', $book); } @@ -37,6 +45,12 @@ function book_update_instance($book) { $book->timemodified = time(); $book->id = $book->instance; + if (!isset($book->customtitles)) { + $book->customtitles = 0; + } + if (!isset($book->disableprinting)) { + $book->disableprinting = 0; + } # May have to add extra stuff in here # @@ -64,6 +78,20 @@ function book_delete_instance($id) { return $result; } + +function book_get_types() { + global $CFG; + + $types = array(); + + $type = new object(); + $type->modclass = MOD_CLASS_RESOURCE; + $type->type = 'book'; + $type->typestr = get_string('modulename', 'book'); + $types[] = $type; + + return $types; +} function book_user_outline($course, $user, $mod, $book) { /// Return a small object with summary information about what a /// user has done with a given particular instance of this module @@ -178,11 +206,11 @@ function book_edit_button($id, $courseid, $chapterid) { $string = get_string("turneditingon"); $edit = '1'; } - return '
      '. + return '
      '. ''. ''. ''. - ''; + '
      '; } else { return ''; } diff --git a/mod.html b/mod.html deleted file mode 100644 index d29c4bcb68c..00000000000 --- a/mod.html +++ /dev/null @@ -1,116 +0,0 @@ -dirroot.'/mod/book/lib.php'); - -if (empty($form->name)) { - $form->name = ''; -} -if (empty($form->summary)) { - $form->summary = ''; -} -if (empty($form->numbering)) { - $form->numbering = NUM_NONE; -} -if (empty($form->disableprinting)) { - $form->disableprinting = 0; -} -if (empty($form->customtitles)) { - $form->customtitles = 0; -} -?> - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      :

      - -

      :

      - - "; - helpbutton("questions", get_string("helpquestions"), "moodle", true, true); - echo "
      "; - if ($usehtmleditor) { - helpbutton("richtext", get_string("helprichtext"), "moodle", true, true); - } else { - emoticonhelpbutton("form", "description"); - } - ?> -
      -
      -
      - summary); ?> -

      :

      - numbering, ''); - helpbutton('numberingtype', get_string('numbering', 'book'), 'book'); - ?> -

      :

      - -

      :

      - -
      -
      - -
      - - - - - - - - -
      - diff --git a/mod_form.php b/mod_form.php new file mode 100644 index 00000000000..61e613f892a --- /dev/null +++ b/mod_form.php @@ -0,0 +1,44 @@ +dirroot.'/mod/book/lib.php'); +require_once('moodleform_mod.php'); + +class mod_book_mod_form extends moodleform_mod { + + function definition() { + + global $CFG; + $mform =& $this->_form; + +//------------------------------------------------------------------------------- + $mform->addElement('header', 'general', get_string('general', 'form')); + + $mform->addElement('text', 'name', get_string('name'), array('size'=>'64')); + $mform->setType('name', PARAM_TEXT); + $mform->addRule('name', null, 'required', null, 'client'); + + $mform->addElement('htmleditor', 'summary', get_string('summary')); + $mform->setType('summary', PARAM_RAW); + $mform->addRule('summary', null, 'required', null, 'client'); + $mform->setHelpButton('summary', array('writing', 'questions', 'richtext'), false, 'editorhelpbutton'); + + $mform->addElement('select', 'numbering', get_string('numbering', 'book'), book_get_numbering_types()); + $mform->setHelpButton('numbering', array('numberingtype', get_string('numbering', 'book'), 'book')); + + $mform->addElement('checkbox', 'disableprinting', get_string('disableprinting', 'book')); + $mform->setHelpButton('disableprinting', array('disableprinting', get_string('disableprinting', 'book'), 'book')); + $mform->setDefault('disableprinting', 0); + + $mform->addElement('checkbox', 'customtitles', get_string('customtitles', 'book')); + $mform->setHelpButton('customtitles', array('customtitles', get_string('customtitles', 'book'), 'book')); + $mform->setDefault('customtitles', 0); + + $this->standard_coursemodule_elements(); + +//------------------------------------------------------------------------------- + // buttons + $this->add_action_buttons(); + } + + +} +?> \ No newline at end of file diff --git a/print.php b/print.php index 269c9a2c85a..8582d7614c9 100644 --- a/print.php +++ b/print.php @@ -1,4 +1,4 @@ -forcelogin) { - require_login(); -} - -if (!$cm = get_record('course_modules', 'id', $id)) { +if (!$cm = get_coursemodule_from_id('book', $id)) { error('Course Module ID was incorrect'); } @@ -21,13 +17,7 @@ if (!$course = get_record('course', 'id', $cm->course)) { error('Course is misconfigured'); } -if ($course->category) { - require_login($course->id); -} - -if (!$cm->visible and !isteacher($course->id)) { - notice(get_string('activityiscurrentlyhidden')); -} +require_course_login($course, true, $cm); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); @@ -61,23 +51,15 @@ unset($chapterid); $strbooks = get_string('modulenameplural', 'book'); $strbook = get_string('modulename', 'book'); -$strtop = get_string('top', 'book'); - -if (!empty($CFG->unicode)) { - $encoding = 'utf-8'; -} else { - $encoding = get_string('thischarset'); -} - -moodle_setlocale(); //workaround for buggy forced course language +$strtop = get_string('top', 'book'); @header('Cache-Control: private, pre-check=0, post-check=0, max-age=0'); @header('Pragma: no-cache'); @header('Expires: '); @header('Accept-Ranges: none'); -@header('Content-type: text/html; charset='.$encoding); +@header('Content-type: text/html; charset=utf-8'); -$formatoptions = new stdClass; +$formatoptions = new object(); $formatoptions->noclean = true; if ($chapter) { @@ -94,9 +76,9 @@ if ($chapter) { - <?PHP echo str_replace('"', '"', $book->name) ?> - - name) ?>" /> + <?PHP echo format_string($book->name) ?> + + @@ -125,28 +107,28 @@ if ($chapter) { - <?PHP echo str_replace('"', '"', $book->name) ?> + <?PHP echo format_string(name) ?> - name) ?>" /> + -

      name) ?>

      -

      summary) ?>

      +

      name) ?>

      +

      summary) ?>

      - + - + - + - + diff --git a/teacheraccess.php b/teacheraccess.php index 5f2f6e23806..45ecbc7414b 100644 --- a/teacheraccess.php +++ b/teacheraccess.php @@ -1,4 +1,4 @@ -course)) { error('Course is misconfigured'); } -if (!isteacheredit($course->id)) { - error('Only editing teachers can edit books!'); -} +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('moodle/course:manageactivities', $context); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); diff --git a/toc.php b/toc.php index 94782fb5204..090f7f593d6 100644 --- a/toc.php +++ b/toc.php @@ -1,4 +1,4 @@ -id.'&chapterid='.$ch->id.'">'.$title.''; + $toc .= ''.$title.''; } $toc .= '  '; if ($i != 1) { - $toc .= ' '; + $toc .= ' '.get_string('up').''; } if ($i != count($chapters)) { - $toc .= ' '; + $toc .= ' '.get_string('down').''; } - $toc .= ' '; - $toc .= ' '; + $toc .= ' '.get_string('edit').''; + $toc .= ' '.get_string('delete').''; if ($ch->hidden) { - $toc .= ' '; + $toc .= ' '.get_string('show').''; } else { - $toc .= ' '; + $toc .= ' '.get_string('hide').''; } - $toc .= ' '; + $toc .= ' '.get_string('addafter', 'book').''; $toc .= (!$ch->subchapter) ? '
        ' : ''; $first = 0; @@ -177,7 +177,7 @@ if ($print) { ///TOC for printing $currsubtitle = ' '; } } else { - $toc .= ''.$title.''; + $toc .= ''.$title.''; } $toc .= (!$ch->subchapter) ? '
          ' : ''; $first = 0; diff --git a/version.php b/version.php index 465340020f4..160fbe3c781 100644 --- a/version.php +++ b/version.php @@ -1,13 +1,13 @@ -version = 2007040600; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2006101020; // Requires this Moodle version +$module->version = 2007052000; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2007021505; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) -$release = "1.3alpha+"; // User-friendly version number +$release = "1.4alpha"; // User-friendly version number ?> diff --git a/view.php b/view.php index f16fedd816b..fe91db352f8 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,4 @@ -forcelogin) { - require_login(); -} - -if (!$cm = get_record('course_modules', 'id', $id)) { - error('Course Module ID is incorrect'); +if (!$cm = get_coursemodule_from_id('book', $id)) { + error('Course Module ID was incorrect'); } if (!$course = get_record('course', 'id', $cm->course)) { error('Course is misconfigured'); } -if ($course->category) { - require_login($course->id); -} - if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); } -$isteacher = isteacheredit($course->id); -if ($isteacher) { - if($edit != -1) { +require_course_login($course, true, $cm); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +$allowedit = has_capability('moodle/course:manageactivities', $context); + +if ($allowedit) { + if ($edit != -1) { $USER->editing = $edit; } else { if (isset($USER->editing)) { @@ -45,16 +41,12 @@ if ($isteacher) { $edit = 0; } -if (!$cm->visible and !$isteacher) { - notice(get_string('activityiscurrentlyhidden')); -} - /// read chapters -$select = $isteacher ? "bookid = $book->id" : "bookid = $book->id AND hidden = 0"; +$select = $allowedit ? "bookid = $book->id" : "bookid = $book->id AND hidden = 0"; $chapters = get_records_select('book_chapters', $select, 'pagenum', 'id, pagenum, subchapter, title, hidden'); if (!$chapters) { - if ($isteacher) { + if ($allowedit) { redirect('edit.php?id='.$cm->id); //no chapters - add new one die; } else { @@ -64,7 +56,7 @@ if (!$chapters) { /// check chapterid and read chapter data if ($chapterid == '0') { // go to first chapter if no given foreach($chapters as $ch) { - if ($isteacher) { + if ($allowedit) { $chapterid = $ch->id; break; } @@ -85,7 +77,7 @@ unset($id); unset($chapterid); /// chapter is hidden for students -if (!$isteacher and $chapter->hidden) { +if (!$allowedit and $chapter->hidden) { error('Error reading book chapters.'); } @@ -97,7 +89,7 @@ if ($chapter->bookid != $book->id) { // security checks END // ========================================================================= -add_to_log($course->id, 'book', 'view', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); +add_to_log($course->id, 'book', 'view', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); ///read standard strings @@ -112,7 +104,7 @@ if ($course->category) { $navigation = ''; } -$buttons = $isteacher ? '
      :fullname) ?>fullname) ?>
      :fullname) ?>fullname) ?>
      :name) ?>name) ?>
      :
      :
      '. +$buttons = $allowedit ? '
      '.update_module_button($cm->id, $course->id, $strbook).'
      '. '
      '.update_module_button($cm->id, $course->id, $strbook).' '.book_edit_button($cm->id, $course->id, $chapter->id).'
      ' : ' '; @@ -148,19 +140,18 @@ if ($ch == current($chapters)) { } $chnavigation = ''; if ($previd) { - $chnavigation .= ''; + $chnavigation .= ''.get_string('navprev', 'book').''; } else { - $chnavigation .= ''; + $chnavigation .= ''; } -$chnavigation .= '    '; if ($nextid) { - $chnavigation .= ''; + $chnavigation .= ''.get_string('navnext', 'book').''; } else { $sec = ''; if ($section = get_record('course_sections', 'id', $cm->section)) { $sec = $section->section; } - $chnavigation .= ''; + $chnavigation .= ''.get_string('navexit', 'book').''; } /// prepare print icons @@ -168,8 +159,8 @@ if ($book->disableprinting) { $printbook = ''; $printchapter = ''; } else { - $printbook = ''; - $printchapter = ''; + $printbook = ''.get_string('printbook', 'book').''; + $printchapter = ''.get_string('printchapter', 'book').''; } // prepare $toc and $currtitle, $currsubtitle @@ -181,7 +172,8 @@ if ($edit) { $tocwidth = $CFG->book_tocwidth; } -$doimport = ($isteacher and $edit) ? ' ('.get_string('doimport', 'book').')' : ''; +$doimport = ($allowedit and $edit) ? ''.get_string('doimport', 'book').'' : ''; +$doexport = ($allowedit and $edit) ? ''.get_string('doexport', 'book').'' : ''; // ===================================================== @@ -194,12 +186,17 @@ $doimport = ($isteacher and $edit) ? ' (" valign="bottom"> - + ($doimport, $doexport)"; + } + ?> - +
      @@ -210,10 +207,10 @@ $doimport = ($isteacher and $edit) ? ' (
      " valign="top" align="left">
      '; helpbutton('faq', get_string('faq','book'), 'book', true, true); echo '
      '; @@ -222,7 +219,7 @@ $doimport = ($isteacher and $edit) ? ' ( customtitles) { if ($currsubtitle == ' ') { @@ -238,9 +235,9 @@ $doimport = ($isteacher and $edit) ? ' ('; echo format_text($content, FORMAT_HTML, $nocleanoption, $course->id); echo '
      '; - print_simple_box_end(); + print_box_end(); /// lower navigation - echo '

      '.$chnavigation.'

      '; + echo '

      '.$chnavigation.'

      '; ?> From a4e28b9b9a75a7f8b6573cb405ea4819edb76c76 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Sun, 17 Jun 2007 10:41:25 +0000 Subject: [PATCH 013/455] Moving the "Export to IMS CP" option from "export" to a new icon. Some people is having problems locating / understanding it. Merged from MOODLE_18_STABLE --- view.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/view.php b/view.php index fe91db352f8..f0b698f0112 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,4 @@ -id.'">'.get_string('doimport', 'book').'
      ' : ''; -$doexport = ($allowedit and $edit) ? ''.get_string('doexport', 'book').'' : ''; + +/// Enable the IMS CP button +$generateimscp = ($allowedit) ? '' : ''; // ===================================================== @@ -189,15 +191,15 @@ $doexport = ($allowedit and $edit) ? '($doimport, $doexport)"; + echo "
      ($doimport)"; } ?> - - + +
      From 51877fd8898ccd78e31787aa8c2b2cd98be94093 Mon Sep 17 00:00:00 2001 From: Andrea Bicciolo Date: Tue, 3 Jul 2007 11:42:29 +0000 Subject: [PATCH 014/455] Traduzione di Claudio Maggi --- lang/it_utf8/book.php | 2 +- lang/it_utf8/help/book/customtitles.html | 3 ++ lang/it_utf8/help/book/disableprinting.html | 3 ++ lang/it_utf8/help/book/edit.html | 7 ++++ lang/it_utf8/help/book/faq.html | 39 +++++++++++++++++++++ lang/it_utf8/help/book/import.html | 5 +++ lang/it_utf8/help/book/index.html | 10 ++++++ lang/it_utf8/help/book/mods.html | 4 +++ lang/it_utf8/help/book/numberingtype.html | 12 +++++++ lang/it_utf8/help/book/summary.html | 5 +++ 10 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lang/it_utf8/help/book/customtitles.html create mode 100644 lang/it_utf8/help/book/disableprinting.html create mode 100644 lang/it_utf8/help/book/edit.html create mode 100644 lang/it_utf8/help/book/faq.html create mode 100644 lang/it_utf8/help/book/import.html create mode 100644 lang/it_utf8/help/book/index.html create mode 100644 lang/it_utf8/help/book/mods.html create mode 100644 lang/it_utf8/help/book/numberingtype.html create mode 100644 lang/it_utf8/help/book/summary.html diff --git a/lang/it_utf8/book.php b/lang/it_utf8/book.php index 54f4c0451a3..e96d2a84cd7 100644 --- a/lang/it_utf8/book.php +++ b/lang/it_utf8/book.php @@ -1,4 +1,4 @@ -Titoli personalizzati

      + +

      I titoli dei capitoli sono mostrati automaticamente solo nel Sommario.

      \ No newline at end of file diff --git a/lang/it_utf8/help/book/disableprinting.html b/lang/it_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..389d77a0fae --- /dev/null +++ b/lang/it_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +

      Esclusione stampa

      + +

      L'icona per la stampa viene nascosta.

      \ No newline at end of file diff --git a/lang/it_utf8/help/book/edit.html b/lang/it_utf8/help/book/edit.html new file mode 100644 index 00000000000..aa808a033ed --- /dev/null +++ b/lang/it_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +

      Modifica Capitolo

      + +

      Cerca di definire titoli corti per i capitoli.

      + +

      Il massimo numero di sottocapitoli è due.

      + +

      Se si riscontrano problemi nell'uso dell'editor html WYSIWYG, provare a passare a un altro browser (come Mozilla Firefox) o disattivare completamente l'editor nel proprio profilo.

      \ No newline at end of file diff --git a/lang/it_utf8/help/book/faq.html b/lang/it_utf8/help/book/faq.html new file mode 100644 index 00000000000..a716aa24d78 --- /dev/null +++ b/lang/it_utf8/help/book/faq.html @@ -0,0 +1,39 @@ +

      + FAQ (Frequently Asked Questions) sui Libri +

      +
      +
      + Perché solo due livelli? +
      +
      +Due livelli di solito sono sufficienti per tutti i libri, tre livelli porterebbero a documenti mal strutturati. Il modulo Libro è stato progettato per la creazione di brevi documenti di studio a più pagine. Per documenti più lunghi di solito è meglio usare il formato PDF. Un modo per creare PDF è costituito dalle stampanti virtuali (vedi + PDFCreator, + + PDFFactory, + Adobe Acrobat, + etc.). Il più facile è usare OpenOffice salvando direttamente in formato PDF il documento creato. +
      +
      +
      +
      + Gli studenti possono modificare i libri? +
      +
      +Solo i docenti possono creare e modificare i libri. Per ora non è prevista la possibilità di modifica da parte degli studenti, ma qualcuno potrebbe creare qualcosa di simile per gli stessi (Portfolio?). La ragione principale è stata quella di mantenere il modulo Libro più semplice possibile. +
      +
      +
      + Come posso fare una ricerca nei libri? +
      +
      +Al momento c'è solo un modo, quello di usare la funzione di ricerca del proprio browser nella pagina di stampa. La ricerca globale è al momento possibile solo nei forum di Moodle. Sarebbe utile avere una ricerca globale per tutte le risorse inclusi i libri. Qualche volontario? +
      +
      +
      + I miei titoli non entrano su una riga. +
      +
      +O riscrivi i tuoi titoli o chiedi all'amministratore del tuo sito di ridimensionare la larghezza del sommario. Questa è definita globalmente per tutti i libri nella pagina di configurazione del modulo. +
      +
      +
      \ No newline at end of file diff --git a/lang/it_utf8/help/book/import.html b/lang/it_utf8/help/book/import.html new file mode 100644 index 00000000000..61830e01828 --- /dev/null +++ b/lang/it_utf8/help/book/import.html @@ -0,0 +1,5 @@ +

      Importazione

      + +

      Si può importare un singolo file HTML o tutti i files HTML di una cartella.

      + +

      I link di files di tipo relativo sono trasformati in link assoluti a capitoli. Sono anche rilinkati files Immagini, Flash e Java.

      \ No newline at end of file diff --git a/lang/it_utf8/help/book/index.html b/lang/it_utf8/help/book/index.html new file mode 100644 index 00000000000..7890e73dea7 --- /dev/null +++ b/lang/it_utf8/help/book/index.html @@ -0,0 +1,10 @@ +

      Libro

      + \ No newline at end of file diff --git a/lang/it_utf8/help/book/mods.html b/lang/it_utf8/help/book/mods.html new file mode 100644 index 00000000000..b2b212a9c4f --- /dev/null +++ b/lang/it_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +

       Libro

      +
        +

        Il Libro è un semplice oggetto di studio fatto di più pagine

        +
      \ No newline at end of file diff --git a/lang/it_utf8/help/book/numberingtype.html b/lang/it_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..7aea1449c7f --- /dev/null +++ b/lang/it_utf8/help/book/numberingtype.html @@ -0,0 +1,12 @@ +

      Numerazione dei Capitoli

      + +

      Sono predefiniti diversi tipi di numerazione: + +

      Nessuna - i titoli dei capitoli e dei sottocapitoli non sono formattati, da usare se si vogliono definire stili speciali di numerazione. Per esempio lettere: nei titoli dei capitoli, tipo "A Primo Capitolo", "A.1 Qualche Sottocapitolo",...

      + +

      Numeri - capitoli e sottocapitoli sono numerati (1, 1.1, 1.2, 2, +...)

      + +

      Punti - i sottocapitoli sono indentati e mostrati con punti.

      + +

      Indentata - i sottocapitoli sono indentati.

      \ No newline at end of file diff --git a/lang/it_utf8/help/book/summary.html b/lang/it_utf8/help/book/summary.html new file mode 100644 index 00000000000..6bf878a6e61 --- /dev/null +++ b/lang/it_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +

      Sommario

      + +

      Il sommario è una descrizione molto breve del libro.

      + +

      Non essere tentato di scrivere troppo qui dentro!

      \ No newline at end of file From 8d8735e5c6398b3c350e79f53e923a9c628ebd0b Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Mon, 27 Aug 2007 14:13:01 +0000 Subject: [PATCH 015/455] Fixing some lists and ampersands. --- lang/en_utf8/help/book/index.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lang/en_utf8/help/book/index.html b/lang/en_utf8/help/book/index.html index 752692e009b..01f6b96e389 100644 --- a/lang/en_utf8/help/book/index.html +++ b/lang/en_utf8/help/book/index.html @@ -1,11 +1,11 @@

      Book module

      From 727fdf1bc597f5aa081ac3594143fa58f2bcd7f2 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Mon, 27 Aug 2007 14:15:43 +0000 Subject: [PATCH 016/455] And h2-ing it --- lang/en_utf8/help/book/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/en_utf8/help/book/index.html b/lang/en_utf8/help/book/index.html index 01f6b96e389..87397c1e450 100644 --- a/lang/en_utf8/help/book/index.html +++ b/lang/en_utf8/help/book/index.html @@ -1,4 +1,4 @@ -

      Book module

      +

      Book module

      • Chapter Numbering
      • Disable Printing
      • From 7bf645e7e87c79a19058d8f0518cf2bcc9c15ca8 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 24 Sep 2007 08:47:34 +0000 Subject: [PATCH 017/455] incorrect import src fields type fixed --- db/install.xml | 5 ++--- db/upgrade.php | 15 +++++++++++---- version.php | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/db/install.xml b/db/install.xml index 133d7ee224c..b0f3f2b1294 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -31,7 +31,7 @@ - + @@ -48,5 +48,4 @@ - \ No newline at end of file diff --git a/db/upgrade.php b/db/upgrade.php index 901e1a5bbb6..f68a47d41ec 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,4 +1,4 @@ -setAttributes(XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, '', 'timemodified'); + + /// Launch change of type for field importsrc + $result = $result && change_field_type($table, $field); + } return $result; } diff --git a/version.php b/version.php index 160fbe3c781..d343087db57 100644 --- a/version.php +++ b/version.php @@ -1,10 +1,10 @@ -version = 2007052000; // The current module version (Date: YYYYMMDDXX) +$module->version = 2007052001; // The current module version (Date: YYYYMMDDXX) $module->requires = 2007021505; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) From dfb3876a0991ea72a3ba6c7801564a3f066ed644 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Mon, 24 Sep 2007 19:15:38 +0000 Subject: [PATCH 018/455] First pass. Deleting some default comments. MDL-11385 (plus minor change in NOT NULL default, must not be explicit) --- db/install.xml | 10 +++++----- db/upgrade.php | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/db/install.xml b/db/install.xml index b0f3f2b1294..9397d23d4d1 100644 --- a/db/install.xml +++ b/db/install.xml @@ -6,7 +6,7 @@ - + @@ -22,7 +22,7 @@
        - + @@ -31,10 +31,10 @@ - + - +
        @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/db/upgrade.php b/db/upgrade.php index f68a47d41ec..72297260773 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,4 +1,4 @@ -setAttributes(XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, '', 'timemodified'); + $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null, 'timemodified'); /// Launch change of type for field importsrc $result = $result && change_field_type($table, $field); From ee7758e5659a3b702451fae55ca45f953974b544 Mon Sep 17 00:00:00 2001 From: Eloy Lafuente Date: Mon, 24 Sep 2007 22:26:30 +0000 Subject: [PATCH 019/455] Second pass. Contrib. Some more default comments are out. MDL-11385 --- db/install.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/install.xml b/db/install.xml index 9397d23d4d1..dd4ca0be9b2 100644 --- a/db/install.xml +++ b/db/install.xml @@ -17,7 +17,7 @@ - + From 50c53e20493166bee6dbc720452f4315199b979f Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Tue, 25 Mar 2008 20:19:49 +0000 Subject: [PATCH 020/455] CONTRIB-350 - Update book module to use new navigation structure & admin settings in 1.9 --- config.html | 30 ------------------------------ delete.php | 18 +++--------------- edit.php | 19 +++---------------- import.php | 21 ++++++--------------- index.php | 22 ++++++---------------- lang/en_utf8/book.php | 3 ++- settings.php | 11 +++++++++++ view.php | 10 +++------- 8 files changed, 34 insertions(+), 100 deletions(-) delete mode 100644 config.html create mode 100644 settings.php diff --git a/config.html b/config.html deleted file mode 100644 index 8769eb9b38c..00000000000 --- a/config.html +++ /dev/null @@ -1,30 +0,0 @@ - - -
        - - -
        - - - - - - - - - -
        -

        book_tocwidth:

        -
        - '140', '160'=>'160', '180'=>'180', '200'=>'200', - '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); - choose_from_menu ($choices, 'book_tocwidth', $CFG->book_tocwidth, ''); - ?> - - -
        - -
        - - diff --git a/delete.php b/delete.php index 0103a174794..860a5c84fb7 100644 --- a/delete.php +++ b/delete.php @@ -1,4 +1,4 @@ -category) { - $navigation = ''.$course->shortname.' ->'; -} else { - $navigation = ''; -} +$navigation = build_navigation('', $cm); -print_header( "$course->shortname: $book->name", - $course->fullname, - "$navigation id>$strbooks -> $book->name", - '', - '', - true, - '', - '' - ); +print_header("$course->shortname: $book->name", $course->fullname, $navigation); ///form processing if ($confirm) { // the operation was confirmed. diff --git a/edit.php b/edit.php index 23049f6ede3..2b0a5b21416 100644 --- a/edit.php +++ b/edit.php @@ -1,4 +1,4 @@ -category) { - $navigation = ''.$course->shortname.' ->'; -} else { - $navigation = ''; -} - -print_header( "$course->shortname: $book->name", - $course->fullname, - "$navigation id\">$strbooks -> id\">$book->name -> $stredit", - '', - '', - true, - '', - '' - ); +$navigation = build_navigation('', $cm); +print_header("$course->shortname: $book->name", $course->fullname, $navigation); $icon = ' '; print_heading_with_help($pageheading, 'edit', 'book', $icon); diff --git a/import.php b/import.php index f53f09fa3ed..00b050365c3 100644 --- a/import.php +++ b/import.php @@ -1,4 +1,4 @@ -category) { - $navigation = ''.$course->shortname.' ->'; -} else { - $navigation = ''; -} +$navlinks = array(); +$navlinks[] = array('name' => $strimport, 'link' => '', 'type' => 'title'); -print_header( "$course->shortname: $book->name", - $course->fullname, - "$navigation id\">$strbooks -> id\">$book->name -> $strimport", - '', - '', - true, - '', - '' - ); +$navigation = build_navigation($navlinks, $cm); + +print_header("$course->shortname: $book->name", $course->fullname, $navigation); /// If data submitted, then process, store and relink. if (($form = data_submitted()) && (confirm_sesskey())) { diff --git a/index.php b/index.php index 445af84addb..be48a5095c9 100644 --- a/index.php +++ b/index.php @@ -1,4 +1,4 @@ -category) { - $navigation = ''.$course->shortname.' ->'; -} else { - $navigation = ''; -} -print_header( "$course->shortname: $strbooks", - $course->fullname, - "$navigation $strbooks", - '', - '', - true, - '', - navmenu($course) - ); +$navlinks = array(); +$navlinks[] = array('name' => $strbooks, 'link' => '', 'type' => 'activity'); +$navigation = build_navigation($navlinks); + +print_header_simple($strbooks, '', $navigation, '', '', true, '', navmenu($course)); add_to_log($course->id, 'book', 'view all', 'index.php?id='.$course->id, ''); diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php index f6171e170f7..e79a1406d35 100644 --- a/lang/en_utf8/book.php +++ b/lang/en_utf8/book.php @@ -1,10 +1,11 @@ -'140', '160'=>'160', '180'=>'180', '200'=>'200', + '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); + + +$settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'book'), + get_string('tocwidth', 'book'), '180', $choices)); + + +?> diff --git a/view.php b/view.php index f0b698f0112..7dcb8935447 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,4 @@ -category) { - $navigation = ''.$course->shortname.' ->'; -} else { - $navigation = ''; -} +$navigation = build_navigation('', $cm); $buttons = $allowedit ? ''. '
        '.update_module_button($cm->id, $course->id, $strbook).' '.book_edit_button($cm->id, $course->id, $chapter->id).'
        ' @@ -110,7 +106,7 @@ $buttons = $allowedit ? ' - + -
        '.update print_header( "$course->shortname: $book->name ($chapter->title)", $course->fullname, - "$navigation id\">$strbooks -> $book->name", + $navigation, '', '', true, From 71d78d24d55875adc39f87f38753f47b28324ac7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 22 Jul 2008 14:30:07 +0000 Subject: [PATCH 021/455] CONTRIB-417 fixed include problem on some server - credit goes to Andreas Grupp --- mod_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_form.php b/mod_form.php index 61e613f892a..1ba5cfe4b73 100644 --- a/mod_form.php +++ b/mod_form.php @@ -1,6 +1,6 @@ dirroot.'/mod/book/lib.php'); -require_once('moodleform_mod.php'); +require_once ($CFG->dirroot.'/course/moodleform_mod.php'); class mod_book_mod_form extends moodleform_mod { From e472fa764bd4efd228aae3f51e87b00c5f053477 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 22 Jul 2008 14:31:02 +0000 Subject: [PATCH 022/455] CONTRIB-417 fixed include problem on some server - credit goes to Andreas Grupp --- mod_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_form.php b/mod_form.php index 1ba5cfe4b73..44c8da48cb3 100644 --- a/mod_form.php +++ b/mod_form.php @@ -1,6 +1,6 @@ dirroot.'/mod/book/lib.php'); -require_once ($CFG->dirroot.'/course/moodleform_mod.php'); +require_once ($CFG->dirroot.'/course/moodleform_mod.php'); class mod_book_mod_form extends moodleform_mod { From dbdb0676a74d6eacd112f7cb857689a8c11d1e8c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 22 Jul 2008 14:36:37 +0000 Subject: [PATCH 023/455] CONTRIB-601 fix groups on book modedit page --- mod_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod_form.php b/mod_form.php index 44c8da48cb3..ab33c804d25 100644 --- a/mod_form.php +++ b/mod_form.php @@ -32,7 +32,7 @@ class mod_book_mod_form extends moodleform_mod { $mform->setHelpButton('customtitles', array('customtitles', get_string('customtitles', 'book'), 'book')); $mform->setDefault('customtitles', 0); - $this->standard_coursemodule_elements(); + $this->standard_coursemodule_elements(array('groups'=>false, 'groupmembersonly'=>true, 'gradecat'=>false)); //------------------------------------------------------------------------------- // buttons From 4c39c4ae2446cf0ce1afb324687b7c41e478f83f Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 22 Jul 2008 14:40:38 +0000 Subject: [PATCH 024/455] CONTRIB-500 causes scales to go *really* slow, use new API credit goes to Alan Trick --- lib.php | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/lib.php b/lib.php index 37d17d3251a..0352b4a7d45 100644 --- a/lib.php +++ b/lib.php @@ -1,4 +1,4 @@ - Date: Tue, 22 Jul 2008 14:56:49 +0000 Subject: [PATCH 025/455] CONTRIB-22 removed outdated installation instructions --- README.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.txt b/README.txt index 9b2b5782e6c..07c4d8a2adc 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -$Id: README.txt,v 1.3 2007/05/20 06:00:29 skodak Exp $ +$Id: README.txt,v 1.4 2008/07/22 14:56:49 skodak Exp $ /////////////////////////////////////////////////////////////////////////// // // @@ -39,13 +39,6 @@ Created by: Developed for Technical University of Liberec (Czech Republic). Many ideas and code were taken from other Moodle modules and Moodle itself;-) -Installation: - 1/ upgrade your Moodle installation to version 1.5.1 or later - (you are advised to install latest official stable 1.5.2+ branch) - 2/ download book.zip to your moodle/mod directory and unzip it there - 3/ go to http://yoursite.com/admin - all necessary tables will be created - - List of features - version 1.2: * easy to use - new teachers can quickly create multipage study materials From 54cdee377aedd2a28d1de21e1b10fb175d0e6638 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 22 Jul 2008 14:59:13 +0000 Subject: [PATCH 026/455] CONTRIB-22 removed outdated installation instructions --- README.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt index 07c4d8a2adc..a3192615154 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -$Id: README.txt,v 1.4 2008/07/22 14:56:49 skodak Exp $ +$Id: README.txt,v 1.5 2008/07/22 14:59:13 skodak Exp $ /////////////////////////////////////////////////////////////////////////// // // @@ -30,7 +30,7 @@ $Id: README.txt,v 1.4 2008/07/22 14:56:49 skodak Exp $ // // /////////////////////////////////////////////////////////////////////////// -Book module for Moodle - version 1.1 (stable release) +Book module for Moodle - version 1.2 (stable release) =============================================================================== Created by: Petr Skoda (skodak) - most of the coding & design @@ -39,6 +39,9 @@ Created by: Developed for Technical University of Liberec (Czech Republic). Many ideas and code were taken from other Moodle modules and Moodle itself;-) +Installation: + * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins + List of features - version 1.2: * easy to use - new teachers can quickly create multipage study materials From 2006381428ca275567a40c449a978c8e43f0ef29 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 22 Jul 2008 15:13:29 +0000 Subject: [PATCH 027/455] CONTRIB-68 missing lang string for ims packages --- lang/en_utf8/book.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php index e79a1406d35..baa7b074194 100644 --- a/lang/en_utf8/book.php +++ b/lang/en_utf8/book.php @@ -1,4 +1,4 @@ - Date: Tue, 22 Jul 2008 15:16:26 +0000 Subject: [PATCH 028/455] CONTRIB-360 missing lang string for ims packages, credit goes to Ralf Hilgenstock --- lang/de_utf8/book.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lang/de_utf8/book.php b/lang/de_utf8/book.php index dd6c77866d8..249157695a6 100644 --- a/lang/de_utf8/book.php +++ b/lang/de_utf8/book.php @@ -1,4 +1,4 @@ - Date: Wed, 23 Jul 2008 14:03:49 +0000 Subject: [PATCH 029/455] CONTRIB-500 fixed regression --- lib.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib.php b/lib.php index 0352b4a7d45..7d90b06848a 100644 --- a/lib.php +++ b/lib.php @@ -1,4 +1,4 @@ - Date: Sat, 26 Jul 2008 22:58:27 +0000 Subject: [PATCH 030/455] Fix A tag regex searching in book. MDL-15842 ; merged from 19_STABLE --- lib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib.php b/lib.php index 7d90b06848a..aa9b9307c8a 100644 --- a/lib.php +++ b/lib.php @@ -1,4 +1,4 @@ -importsrc && preg_match_all('/(]+href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { + if ($ch->importsrc && preg_match_all('/(]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { for($i = 0; $i Date: Wed, 13 Aug 2008 23:21:13 +0000 Subject: [PATCH 031/455] book v1.5beta compatible with 1.9.1 or later, not 2.0dev --- README.txt | 10 ++- coursefiles.php | 8 +-- db/access.php | 70 +++++++++++++++++++ edit.html | 64 ----------------- edit.php | 129 +++++++++++++++-------------------- edit_form.php | 53 ++++++++++++++ generateimscp.php | 21 +++--- import.php | 124 ++++++++++++--------------------- import_form.php | 63 +++++++++++++++++ lang/en_utf8/book.php | 9 ++- lib.php | 9 +-- print.php | 10 ++- restorelib.php | 6 +- show.php | 3 +- book_theme.css => styles.php | 34 ++++++++- teacheraccess.php | 12 ++-- toc.php | 26 +++---- version.php | 8 +-- view.php | 59 ++++++++-------- 19 files changed, 417 insertions(+), 301 deletions(-) create mode 100644 db/access.php delete mode 100644 edit.html create mode 100644 edit_form.php create mode 100644 import_form.php rename book_theme.css => styles.php (76%) diff --git a/README.txt b/README.txt index a3192615154..6e6909c1a0e 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -$Id: README.txt,v 1.5 2008/07/22 14:59:13 skodak Exp $ +$Id: README.txt,v 1.6 2008/08/13 23:21:14 skodak Exp $ /////////////////////////////////////////////////////////////////////////// // // @@ -42,7 +42,7 @@ Many ideas and code were taken from other Moodle modules and Moodle itself;-) Installation: * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins -List of features - version 1.2: +List of features - version 1.4: * easy to use - new teachers can quickly create multipage study materials * two levels - only chapters and subchapters @@ -110,5 +110,11 @@ CHANGELOG: * compatible with 1.8 * export link enabled - thanks Eloy! * no new features +== 1.5beta - 2008/08/14 ==================================================== + * compatible with 1.9.1 and above + * xhtml strict and css improvements + * formslib conversion + * capabilities implemented + * no new features skodak diff --git a/coursefiles.php b/coursefiles.php index b3537a2006c..5864e6d408b 100644 --- a/coursefiles.php +++ b/coursefiles.php @@ -1,4 +1,4 @@ -$struploadafile ($strmaxsize) --> $wdir

        "; echo "
        "; - echo "
        "; + echo "
        "; echo "
        "; echo ' '; echo " "; @@ -211,7 +211,7 @@ echo ""; echo ""; echo "
        "; - echo "
        "; + echo "
        "; echo ' '; echo " "; echo " "; diff --git a/db/access.php b/db/access.php new file mode 100644 index 00000000000..30dd4840d4d --- /dev/null +++ b/db/access.php @@ -0,0 +1,70 @@ + array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_ALLOW, + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW + ) + ), + + 'mod/book:viewhiddenchapters' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW + ) + ), + + 'mod/book:edit' => array( + 'riskbitmask' => RISK_XSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'editingteacher' => CAP_ALLOW + ) + ), + + 'mod/book:import' => array( + 'riskbitmask' => RISK_XSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'editingteacher' => CAP_ALLOW + ) + ), + + 'mod/book:print' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_ALLOW, + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW + ) + ), + + 'mod/book:exportimscp' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE + ), + +); + +?> diff --git a/edit.html b/edit.html deleted file mode 100644 index a0d5ba57875..00000000000 --- a/edit.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - -
        - : - - -
        - : - - subchapter) { - $selected = ' checked="checked"'; - } else { - $selected = ''; - } - echo ''; - ?> -
        -

        :

        - - '; - if ($usehtmleditor) { - helpbutton('richtext', get_string('helprichtext'), 'moodle', true, true); - } else { - emoticonhelpbutton('theform', 'text'); - } - ?>
        -
        -
        - content, $course->id); ?> -
        -
        - - - id == -1) { - echo ' ('.get_string('doimport', 'book').')'; - } - ?> -
        - - - - - diff --git a/edit.php b/edit.php index 2b0a5b21416..23573fec289 100644 --- a/edit.php +++ b/edit.php @@ -1,19 +1,19 @@ -course)) { error('Course is misconfigured'); } +require_login($course, false, $cm); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); -require_capability('moodle/course:manageactivities', $context); +require_capability('mod/book:edit', $context); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); } -$chapter = get_record('book_chapters', 'id', $chapterid); - -//check all variables -unset($id); -unset($chapterid); -if ($chapter) { +if ($chapterid) { + if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { + error('Incorrect chapter id'); + } if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! error('Chapter not part of this book!'); } - $pagenum = $chapter->pagenum; } else { - $pagenum = (integer)$pagenum; + $chapter = null; } +//check all variables +unset($cmid); +unset($chapterid); + // ========================================================================= // security checks END // ========================================================================= +$mform = new book_chapter_edit_form(null, $cm); + +if ($chapter) { + $chapter->cmid = $cm->id; + $mform->set_data($chapter); +} else { + $mform->set_data(array('cmid'=>$cm->id, 'pagenum'=>($pagenum+1), 'subchapter'=>$subchapter)); +} /// If data submitted, then process and store. -if (($form = data_submitted()) && (confirm_sesskey())) { - //TODO: skip it for now - //prepare data - security checks - //$form->title = clean_text($form->title, FORMAT_HTML); - //$form->content = clean_text($form->content, FORMAT_HTML); - - if (isset($form->subchapter) ) { - $form->subchapter = 1; +if ($mform->is_cancelled()) { + if (empty($chapter->id)) { + redirect("view.php?id=$cm->id"); } else { - $form->subchapter = 0; + redirect("view.php?id=$cm->id&chapterid=$chapter->id"); } - if ($chapter) { - /// editing existing chapter - $chapter->content = $form->content; - $chapter->title = $form->title; - $chapter->subchapter = $form->subchapter; - $chapter->timemodified = time(); - $chapter->importsrc = addslashes($chapter->importsrc); //use already stored importsrc - if (!update_record('book_chapters', $chapter)) { + +} else if ($data = $mform->get_data(false)) { + + if ($data->id) { + if (!update_record('book_chapters', addslashes_recursive($data))) { error('Could not update your book'); } add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); - add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); + } else { /// adding new chapter - $chapter->bookid = $book->id; - $chapter->pagenum = $form->pagenum + 1; //place after given pagenum, lets hope it is a number - $chapter->subchapter = $form->subchapter; - $chapter->title = $form->title; - $chapter->content = $form->content; - $chapter->hidden = 0; - $chapter->timecreated = time(); - $chapter->timemodified = $chapter->timecreated; - $chapter->importsrc = ''; + $data->bookid = $book->id; + $data->hidden = 0; + $data->timecreated = time(); + $data->timemodified = time(); + $data->importsrc = ''; - $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, pagenum'); - if ($chapters) { - foreach($chapters as $ch) { - if ($ch->pagenum > $pagenum) { - $ch->pagenum = $ch->pagenum + 1; - if (!update_record('book_chapters', $ch)) { - error('Could not update your book'); - } - } - } - } - if (!$chapter->id = insert_record('book_chapters', $chapter)) { + // make room for new page + $sql = "UPDATE {$CFG->prefix}book_chapters + SET pagenum = pagenum + 1 + WHERE bookid = $book->id AND pagenum >= $data->pagenum"; + execute_sql($sql, false); + + if (!$data->id = insert_record('book_chapters', addslashes_recursive($data))) { error('Could not insert a new chapter'); } add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); - add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); } book_check_structure($book->id); - redirect("view.php?id=$cm->id&chapterid=$chapter->id"); + redirect("view.php?id=$cm->id&chapterid=$data->id"); die; } @@ -112,30 +107,18 @@ $strbooks = get_string('modulenameplural', 'book'); $stredit = get_string('edit'); $pageheading = get_string('editingchapter', 'book'); -$usehtmleditor = can_use_html_editor(); - -if (!$chapter) { - $chapter->id = -1; - $chapter->title = ''; - $chapter->content = ''; - $chapter->subchapter = $subchapter; - $chapter->pagenum = $pagenum; -} - ///prepare the page header -$navigation = build_navigation('', $cm); +$navlinks = array(); +$navlinks[] = array('name' => $stredit, 'link' => '', 'type' => 'title'); + +$navigation = build_navigation($navlinks, $cm); print_header("$course->shortname: $book->name", $course->fullname, $navigation); -$icon = ' '; +$icon = ' '; print_heading_with_help($pageheading, 'edit', 'book', $icon); -print_simple_box_start('center', ''); -include('edit.html'); -print_simple_box_end(); -if ($usehtmleditor ) { - use_html_editor(); -} +$mform->display(); print_footer($course); diff --git a/edit_form.php b/edit_form.php new file mode 100644 index 00000000000..5562d58199c --- /dev/null +++ b/edit_form.php @@ -0,0 +1,53 @@ +libdir.'/formslib.php'); + +class book_chapter_edit_form extends moodleform { + + function definition() { + global $CFG; + $mform =& $this->_form; + $cm = $this->_customdata; + + $mform->addElement('header', 'general', get_string('edit')); + + $mform->addElement('text', 'title', get_string('chaptertitle', 'book'), array('size'=>'30')); + $mform->setType('title', PARAM_RAW); + $mform->addRule('title', null, 'required', null, 'client'); + + $mform->addElement('advcheckbox', 'subchapter', get_string('subchapter', 'book')); + + $mform->addElement('htmleditor', 'content', get_string('content', 'book'), array('cols'=>50, 'rows'=>30)); + $mform->setType('content', PARAM_RAW); + $mform->setHelpButton('content', array('reading', 'writing', 'questions', 'richtext'), false, 'editorhelpbutton'); + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'cmid'); + $mform->setType('cmid', PARAM_INT); + + $mform->addElement('hidden', 'pagenum'); + $mform->setType('pagenum', PARAM_INT); + + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + if (has_capability('mod/book:import', $context)) { + $mform->addElement('static', 'doimport', get_string('importingchapters', 'book').':', ''.get_string('doimport', 'book').''); + } + + $this->add_action_buttons(true); + } + + function definition_after_data() { + global $CFG; + $mform =& $this->_form; + + if ($mform->getElementValue('id')) { + if ($mform->elementExists('doimport')) { + $mform->removeElement('doimport'); + } + } + } +} + +?> diff --git a/generateimscp.php b/generateimscp.php index 60f5799967c..293eb08f95a 100644 --- a/generateimscp.php +++ b/generateimscp.php @@ -1,4 +1,4 @@ -dirroot . '/backup/lib.php'); -require_once($CFG->dirroot . '/lib/filelib.php'); +require_once($CFG->dirroot.'/backup/lib.php'); +require_once($CFG->libdir.'/filelib.php'); $id = required_param('id', PARAM_INT); // Course Module ID -require_login(); - if (!$cm = get_coursemodule_from_id('book', $id)) { error('Course Module ID was incorrect'); } @@ -41,9 +39,12 @@ if (!$course = get_record('course', 'id', $cm->course)) { error('Course is misconfigured'); } +require_login($course, true, $cm); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); -require_capability('moodle/course:manageactivities', $context); - +require_capability('mod/book:read', $context); +require_capability('mod/book:exportimscp', $context); + if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); } @@ -71,7 +72,7 @@ add_to_log($course->id, 'book', 'generateimscp', 'generateimscp.php?id='.$cm->id /// Now delete all the temp dirs delete_dir_contents($CFG->dataroot . "/$cm->course/moddata/book/$book->id"); /// Now serve the file - send_file($zipfile, clean_filename($book->name) . '.zip', 86400, 0, false, true); + send_temp_file($zipfile, clean_filename($book->name) . '.zip'); /** * This function will create the default imsmanifest plus contents for the book chapters passed as array @@ -192,7 +193,7 @@ $cssresource = ' shortname: $book->name", $course->fullname, $navigation); +$mform = new book_import_form(null, $cm); +$mform->set_data(array('id'=>$cm->id)); -/// If data submitted, then process, store and relink. -if (($form = data_submitted()) && (confirm_sesskey())) { - $form->reference = stripslashes($form->reference); - if ($form->reference != '') { //null path is root - $form->reference = book_prepare_link($form->reference); - if ($form->reference == '') { //evil characters in $ref! - error('Invalid character detected in given path!'); - } +/// If data submitted, then process and store. +if ($mform->is_cancelled()) { + if (empty($chapter->id)) { + redirect("view.php?id=$cm->id"); + } else { + redirect("view.php?id=$cm->id&chapterid=$chapter->id"); } + +} else if ($data = $mform->get_data(false)) { $coursebase = $CFG->dataroot.'/'.$book->course; - if ($form->reference == '') { + + $reference = book_prepare_link($data->reference); + + if ($reference == '') { $base = $coursebase; } else { - $base = $coursebase.'/'.$form->reference; + $base = $coursebase.'/'.$reference; } //prepare list of html files in $refs @@ -81,14 +79,16 @@ if (($form = data_submitted()) && (confirm_sesskey())) { } asort($refs); } else if (is_file($base)) { //import single file - $refs[] = '/'.$form->reference; + $refs[] = '/'.$reference; } else { //what is it??? error('Incorrect file/directory specified!'); } + print_header("$course->shortname: $book->name", $course->fullname, $navigation); + //import files - echo '
        '; - echo ''.get_string('importing', 'book').':'; + print_box_start('generalbox boxaligncenter centerpara'); + echo ''.get_string('importing', 'book').':'; echo ''; book_check_structure($book->id); foreach($refs as $ref) { @@ -102,7 +102,7 @@ if (($form = data_submitted()) && (confirm_sesskey())) { $chapter->timecreated = time(); $chapter->timemodified = time(); echo "imsrc:".$chapter->importsrc; - if (($subchapter) || preg_match('/_sub\.htm/i', $chapter->importsrc)) { //if filename or directory starts with sub_* treat as subdirecotories + if (($data->subchapter) || preg_match('/_sub\.htm/i', $chapter->importsrc)) { //if filename or directory starts with sub_* treat as subdirecotories $chapter->subchapter = 1; } else { $chapter->subchapter = 0; @@ -115,64 +115,28 @@ if (($form = data_submitted()) && (confirm_sesskey())) { } } echo '

        '; - echo ''.get_string('relinking', 'book').':'; + echo ''.get_string('relinking', 'book').':'; echo ''; //relink whole book = all chapters book_relink($cm->id, $book->id, $course->id); echo '

        '; - echo ''.get_string('continue').''; - echo '
        '; -} else { -/// Otherwise fill and print the form. - $strdoimport = get_string('doimport', 'book'); - $strchoose = get_string('choose'); - $pageheading = get_string('importingchapters', 'book'); - - $icon = ' '; - print_heading_with_help($pageheading, 'import', 'book', $icon); - print_simple_box_start('center', ''); - ?> -
        - - - - - - - - - - - - - -
        - : - -  '; - button_to_popup_window ('/mod/book/coursefiles.php?choose=id_reference&id='.$course->id, - 'coursefiles', $strchoose, 500, 750, $strchoose); - ?> -
        - : - - '; - ?> -
         

        -
        - - " /> -
        - - -
        - - id); + print_footer($course); + die; } +print_header("$course->shortname: $book->name", $course->fullname, $navigation); + +$strdoimport = get_string('doimport', 'book'); +$strchoose = get_string('choose'); +$pageheading = get_string('importingchapters', 'book'); + +$icon = ' '; +print_heading_with_help($pageheading, 'import', 'book', $icon); + +$mform->display(); + print_footer($course); ?> diff --git a/import_form.php b/import_form.php new file mode 100644 index 00000000000..aa83c418d4f --- /dev/null +++ b/import_form.php @@ -0,0 +1,63 @@ +libdir.'/formslib.php'); + +class book_import_form extends moodleform { + + function definition() { + global $CFG; + $mform =& $this->_form; + $cm = $this->_customdata; + + $mform->addElement('header', 'general', get_string('import')); + + $group = array(); + $group[0] =& MoodleQuickForm::createElement('text', 'reference', get_string('fileordir', 'book'), array('size'=>'48')); + $group[1] =& MoodleQuickForm::createElement('button', 'popup', get_string('chooseafile', 'resource') .' ...'); + + $options = 'menubar=0,location=0,scrollbars,resizable,width=600,height=400'; + $url = '/mod/book/coursefiles.php?choose=id_reference&id='.$cm->course; + $buttonattributes = array('title'=>get_string('chooseafile', 'resource'), 'onclick'=>"return openpopup('$url', '".$group[1]->getName()."', '$options', 0);"); + $group[1]->updateAttributes($buttonattributes); + + $mform->addGroup($group, 'choosesomething', get_string('fileordir', 'book'), array(''), false); + + $mform->addElement('checkbox', 'subchapter', get_string('subchapter', 'book')); + $mform->addElement('static', 'importfileinfo', get_string('help'), get_string('importinfo', 'book')); + + $mform->addElement('hidden', 'id', $cm->id); + $mform->setType('id', PARAM_INT); + + $this->add_action_buttons(true, get_string('import', 'book')); + } + + function validation($data, $files) { + global $CFG; + $cm = $this->_customdata; + + $errors = parent::validation($data, $files); + $reference = stripslashes($data['reference']); + + if ($reference != '') { //null path is root + $reference = book_prepare_link($reference); + if ($reference == '') { //evil characters in $ref! + $errors['choosesomething'] = get_string('error'); + } else { + $coursebase = $CFG->dataroot.'/'.$cm->course; + + if ($reference == '') { + $base = $coursebase; + } else { + $base = $coursebase.'/'.$reference; + } + if (!is_dir($base) and !is_file($base)) { + $errors['choosesomething'] = get_string('error'); + } + } + } + + return $errors; + } +} + +?> diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php index baa7b074194..3ccc6da1745 100644 --- a/lang/en_utf8/book.php +++ b/lang/en_utf8/book.php @@ -1,4 +1,4 @@ -Chapters a $string['maindirectory'] = 'Main directory'; $string['fileordir'] = 'File or directory'; +$string['book:read'] = 'Read book'; +$string['book:edit'] = 'Edit book chapters'; +$string['book:viewhiddenchapters'] = 'View hidden book chapters'; +$string['book:import'] = 'Import chapters'; +$string['book:print'] = 'Print book'; +$string['book:exportimscp'] = 'Export book as IMS content package'; + ?> diff --git a/lib.php b/lib.php index aa9b9307c8a..187993177c8 100644 --- a/lib.php +++ b/lib.php @@ -1,4 +1,4 @@ -book_tocwidth)) { - set_config("book_tocwidth", 180); // default toc width -} - function book_get_numbering_types() { return array (NUM_NONE => get_string('numbering0', 'book'), NUM_NUMBERS => get_string('numbering1', 'book'), @@ -273,6 +269,7 @@ function book_read_chapter($base, $ref) { $contents = fread($handle, filesize($file)); fclose($handle); //extract title + $chapter = new object(); if (preg_match('/([^<]+)<\/title>/i', $contents, $matches)) { $chapter->title = $matches[1]; } else { @@ -320,7 +317,7 @@ function book_relink($id, $bookid, $courseid) { } foreach($chapters as $ch) { $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); - $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) + $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) $modified = false; //image relinking if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { diff --git a/print.php b/print.php index 8582d7614c9..011acd63bf7 100644 --- a/print.php +++ b/print.php @@ -1,4 +1,4 @@ -<?PHP // $Id: print.php,v 1.2 2007/05/20 06:00:26 skodak Exp $ +<?PHP // $Id: print.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ require_once('../../config.php'); require_once('lib.php'); @@ -18,7 +18,7 @@ if (!$course = get_record('course', 'id', $cm->course)) { } require_course_login($course, true, $cm); - + if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); } @@ -27,6 +27,10 @@ if ($book->disableprinting) { error('Printing is disabled'); } +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/book:read', $context); +require_capability('mod/book:print', $context); + //check all variables if ($chapterid) { //single chapter printing @@ -55,7 +59,7 @@ $strtop = get_string('top', 'book'); @header('Cache-Control: private, pre-check=0, post-check=0, max-age=0'); @header('Pragma: no-cache'); -@header('Expires: '); +@header('Expires: '); @header('Accept-Ranges: none'); @header('Content-type: text/html; charset=utf-8'); diff --git a/restorelib.php b/restorelib.php index 724b131cada..5408ae494ca 100644 --- a/restorelib.php +++ b/restorelib.php @@ -1,4 +1,4 @@ -<?PHP // $Id: restorelib.php,v 1.2 2006/03/29 06:21:56 skodak Exp $ +<?PHP // $Id: restorelib.php,v 1.3 2008/08/13 23:21:13 skodak Exp $ //This php script contains all the stuff to backup/restore //book mods @@ -40,6 +40,7 @@ //$GLOBALS['traverse_array']=""; //Debug //Now, build the BOOK record structure + $book = new object(); $book->course = $restore->course_id; $book->name = backup_todb($info['MOD']['#']['NAME']['0']['#']); $book->summary = backup_todb($info['MOD']['#']['SUMMARY']['0']['#']); @@ -101,6 +102,7 @@ $old_id = backup_todb($sub_info['#']['ID']['0']['#']); //Now, build the ASSIGNMENT_CHAPTERS record structure + $chapter = new object(); $chapter->bookid = $new_book_id; $chapter->pagenum = backup_todb($sub_info['#']['PAGENUM']['0']['#']); $chapter->subchapter = backup_todb($sub_info['#']['SUBCHAPTER']['0']['#']); @@ -149,7 +151,7 @@ if ($log->cmid) { //Get the new_id of the chapter (to recode the url field) $ch = backup_getid($restore->backup_unique_code,"book_chapters",$log->info); - if ($pag) { + if ($ch) { $log->url = "view.php?id=".$log->cmid."&chapterid=".$ch->new_id; $log->info = $ch->new_id; $status = true; diff --git a/show.php b/show.php index 8104067ee27..beae942b2b7 100644 --- a/show.php +++ b/show.php @@ -1,8 +1,9 @@ -<?PHP // $Id: show.php,v 1.2 2006/11/21 19:26:36 skodak Exp $ +<?PHP // $Id: show.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ require('teacheraccess.php'); //page only for teachers ///switch hidden state +$chapter = new object(); $chapter->hidden = $chapter->hidden ? 0 : 1; ///add slashes to all text fields diff --git a/book_theme.css b/styles.php similarity index 76% rename from book_theme.css rename to styles.php index 098b19408f8..8eaa9214a75 100644 --- a/book_theme.css +++ b/styles.php @@ -1,4 +1,4 @@ -/* $Id: book_theme.css,v 1.2 2007/05/20 06:00:30 skodak Exp $*/ +/* $Id: styles.php,v 1.1 2008/08/13 23:21:13 skodak Exp $*/ /* later should be defined in themes*/ @@ -25,9 +25,32 @@ img.bigicon { border:0px; } +#mod-book-view table.booktable { + border:0; +} + +#mod-book-view .bookexport { + float:left; +} + +#mod-book-view .booknav { + float:right; +} + +#mod-book-view table.booktable tr.tocandchapter { + vertical-align:text-top; +} + +#mod-book-view div.faq { + font-size: 0.7em; +} + /* == TOC styles == */ /* toc style NONE */ +.book_toc_none { + font-size: 0.8em; +} .book_toc_none ul { margin-left: 5px; padding-left: 0px; @@ -47,6 +70,9 @@ img.bigicon { /* toc style NUMBERED */ +.book_toc_numbered { + font-size: 0.8em; +} .book_toc_numbered ul { margin-left: 5px; padding-left: 0px; @@ -66,6 +92,9 @@ img.bigicon { /*toc style BULLETS */ +.book_toc_bullets { + font-size: 0.8em; +} .book_toc_bullets ul { margin-left: 5px; padding-left: 0px; @@ -85,6 +114,9 @@ img.bigicon { /* toc style INDENTED*/ +.book_toc_indented { + font-size: 0.8em; +} .book_toc_indented ul { margin-left: 5px; padding-left: 0px; diff --git a/teacheraccess.php b/teacheraccess.php index 45ecbc7414b..4a333bb8f8b 100644 --- a/teacheraccess.php +++ b/teacheraccess.php @@ -1,18 +1,16 @@ -<?PHP // $Id: teacheraccess.php,v 1.2 2007/05/20 06:00:27 skodak Exp $ +<?PHP // $Id: teacheraccess.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ ///standard routine to allow only teachers in ///check of $id and $chapterid parameters -require_once('../../config.php'); +require('../../config.php'); require_once('lib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = required_param('chapterid', PARAM_INT); // Chapter ID -require_login(); - if (!confirm_sesskey()) { - error(get_string('confirmsesskeybad', 'error')); + error(get_string('confirmsesskeybad', 'error')); } if (!$cm = get_coursemodule_from_id('book', $id)) { error('Course Module ID was incorrect'); @@ -22,8 +20,10 @@ if (!$course = get_record('course', 'id', $cm->course)) { error('Course is misconfigured'); } +require_login($course, false, $cm); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); -require_capability('moodle/course:manageactivities', $context); +require_capability('mod/book:edit', $context); if (!$book = get_record('book', 'id', $cm->instance)) { error('Course module is incorrect'); diff --git a/toc.php b/toc.php index 090f7f593d6..a49c2011ebf 100644 --- a/toc.php +++ b/toc.php @@ -1,7 +1,7 @@ -<?PHP // $Id: toc.php,v 1.3 2007/05/20 06:00:30 skodak Exp $ +<?PHP // $Id: toc.php,v 1.4 2008/08/13 23:21:14 skodak Exp $ defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); - + /// included from mod/book/view.php and print.php /// /// uses: @@ -26,10 +26,6 @@ $ns = 0; //subchapter number $title = ''; $first = 1; -if (!isset($print)) { - $print = 0; -} - switch ($book->numbering) { case NUM_NONE: $toc .= '<div class="book_toc_none">'; @@ -73,14 +69,14 @@ if ($print) { ///TOC for printing } } $titles[$ch->id] = $title; - $toc .= '<a title="'.htmlspecialchars($title).'" href="#ch'.$ch->id.'">'.$title.'</a>'; + $toc .= '<a title="'.s($title).'" href="#ch'.$ch->id.'">'.$title.'</a>'; $toc .= (!$ch->subchapter) ? '<ul>' : '</li>'; $first = 0; } } $toc .= '</ul></li></ul>'; } else if ($edit) { ///teacher's TOC - $toc .= '<font size="-1"><ul>'; + $toc .= '<ul>'; $i = 0; foreach($chapters as $ch) { $i++; @@ -125,7 +121,7 @@ if ($print) { ///TOC for printing $currsubtitle = ' '; } } else { - $toc .= '<a title="'.htmlspecialchars($title).'" href="view.php?id='.$cm->id.'&chapterid='.$ch->id.'">'.$title.'</a>'; + $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&chapterid='.$ch->id.'">'.$title.'</a>'; } $toc .= '  '; if ($i != 1) { @@ -134,21 +130,21 @@ if ($print) { ///TOC for printing if ($i != count($chapters)) { $toc .= ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=0&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/down.gif" height="11" class="iconsmall" alt="'.get_string('down').'" /></a>'; } - $toc .= ' <a title="'.get_string('edit').'" href="edit.php?id='.$cm->id.'&chapterid='.$ch->id.'"><img src="'.$CFG->pixpath.'/t/edit.gif" height="11" class="iconsmall" alt="'.get_string('edit').'" /></a>'; + $toc .= ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&id='.$ch->id.'"><img src="'.$CFG->pixpath.'/t/edit.gif" height="11" class="iconsmall" alt="'.get_string('edit').'" /></a>'; $toc .= ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/delete.gif" height="11" class="iconsmall" alt="'.get_string('delete').'" /></a>'; if ($ch->hidden) { $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/show.gif" height="11" class="iconsmall" alt="'.get_string('show').'" /></a>'; } else { $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/hide.gif" height="11" class="iconsmall" alt="'.get_string('hide').'" /></a>'; } - $toc .= ' <a title="'.get_string('addafter', 'book').'" href="edit.php?id='.$cm->id.'&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="pix/add.gif" height="11" class="iconsmall" alt="'.get_string('addafter', 'book').'" /></a>'; + $toc .= ' <a title="'.get_string('addafter', 'book').'" href="edit.php?cmid='.$cm->id.'&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="pix/add.gif" height="11" class="iconsmall" alt="'.get_string('addafter', 'book').'" /></a>'; $toc .= (!$ch->subchapter) ? '<ul>' : '</li>'; $first = 0; } - $toc .= '</ul></li></ul></font>'; + $toc .= '</ul></li></ul>'; } else { //normal students view - $toc .= '<font size="-1"><ul>'; + $toc .= '<ul>'; foreach($chapters as $ch) { $title = trim(strip_tags($ch->title)); if (!$ch->hidden) { @@ -177,13 +173,13 @@ if ($print) { ///TOC for printing $currsubtitle = ' '; } } else { - $toc .= '<a title="'.htmlspecialchars($title).'" href="view.php?id='.$cm->id.'&chapterid='.$ch->id.'">'.$title.'</a>'; + $toc .= '<a title="'.s($title).'" href="view.php?id='.$cm->id.'&chapterid='.$ch->id.'">'.$title.'</a>'; } $toc .= (!$ch->subchapter) ? '<ul>' : '</li>'; $first = 0; } } - $toc .= '</ul></li></ul></font>'; + $toc .= '</ul></li></ul>'; } $toc .= '</div>'; diff --git a/version.php b/version.php index d343087db57..2f91ca0e0d6 100644 --- a/version.php +++ b/version.php @@ -1,13 +1,13 @@ -<?PHP // $Id: version.php,v 1.4 2007/09/24 08:47:36 skodak Exp $ +<?PHP // $Id: version.php,v 1.5 2008/08/13 23:21:13 skodak Exp $ ///////////////////////////////////////////////////////////////////////////////// /// Called by moodle_needs_upgrading() and /admin/index.php ///////////////////////////////////////////////////////////////////////////////// -$module->version = 2007052001; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2007021505; // Requires this Moodle version +$module->version = 2008081402; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2007101512; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) -$release = "1.4alpha"; // User-friendly version number +$release = "1.5beta"; // User-friendly version number ?> diff --git a/view.php b/view.php index 7dcb8935447..1dc7893b359 100644 --- a/view.php +++ b/view.php @@ -1,11 +1,11 @@ -<?PHP // $Id: view.php,v 1.5 2008/03/25 20:19:49 poltawski Exp $ +<?PHP // $Id: view.php,v 1.6 2008/08/13 23:21:14 skodak Exp $ -require_once('../../config.php'); +require('../../config.php'); require_once('lib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID -$edit = optional_param('edit', -1, PARAM_BOOL); // Edit mode +$edit = optional_param('edit', -1, PARAM_BOOL); // Edit mode // ========================================================================= // security checks START - teachers edit; students view @@ -25,7 +25,13 @@ if (!$book = get_record('book', 'id', $cm->instance)) { require_course_login($course, true, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); -$allowedit = has_capability('moodle/course:manageactivities', $context); +require_capability('mod/book:read', $context); + +$allowedit = has_capability('mod/book:edit', $context); +$allowimport = has_capability('mod/book:import', $context); +$allowprint = has_capability('mod/book:print', $context) and !$book->disableprinting; +$allowexport = has_capability('mod/book:exportimscp', $context); +$viewhidden = has_capability('mod/book:viewhiddenchapters', $context); if ($allowedit) { if ($edit != -1) { @@ -42,12 +48,12 @@ if ($allowedit) { } /// read chapters -$select = $allowedit ? "bookid = $book->id" : "bookid = $book->id AND hidden = 0"; +$select = $viewhidden ? "bookid = $book->id" : "bookid = $book->id AND hidden = 0"; $chapters = get_records_select('book_chapters', $select, 'pagenum', 'id, pagenum, subchapter, title, hidden'); if (!$chapters) { if ($allowedit) { - redirect('edit.php?id='.$cm->id); //no chapters - add new one + redirect('edit.php?cmid='.$cm->id); //no chapters - add new one die; } else { error('Error reading book chapters.'); @@ -77,7 +83,7 @@ unset($id); unset($chapterid); /// chapter is hidden for students -if (!$allowedit and $chapter->hidden) { +if (!$viewhidden and $chapter->hidden) { error('Error reading book chapters.'); } @@ -108,7 +114,7 @@ print_header( "$course->shortname: $book->name ($chapter->title)", $course->fullname, $navigation, '', - '<style type="text/css">@import url('.$CFG->wwwroot.'/mod/book/book_theme.css);</style>', + '', true, $buttons, navmenu($course, $cm) @@ -151,7 +157,7 @@ if ($nextid) { } /// prepare print icons -if ($book->disableprinting) { +if (!$allowprint) { $printbook = ''; $printchapter = ''; } else { @@ -160,6 +166,7 @@ if ($book->disableprinting) { } // prepare $toc and $currtitle, $currsubtitle +$print = 0; require('toc.php'); if ($edit) { @@ -168,10 +175,10 @@ if ($edit) { $tocwidth = $CFG->book_tocwidth; } -$doimport = ($allowedit and $edit) ? '<a href="import.php?id='.$cm->id.'">'.get_string('doimport', 'book').'</a>' : ''; +$doimport = ($allowimport and $edit) ? '<div>(<a href="import.php?id='.$cm->id.'">'.get_string('doimport', 'book').'</a>)</div>' : ''; /// Enable the IMS CP button -$generateimscp = ($allowedit) ? '<a title="'.get_string('generateimscp', 'book').'" href="generateimscp.php?id='.$cm->id.'"><img class="bigicon" src="pix/generateimscp.gif" height="24" width="24" border="0"></img></a>' : ''; +$generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book').'" href="generateimscp.php?id='.$cm->id.'"><img class="bigicon" src="pix/generateimscp.gif" alt="'.get_string('generateimscp', 'book').'"></img></a>' : ''; // ===================================================== @@ -179,43 +186,37 @@ $generateimscp = ($allowedit) ? '<a title="'.get_string('generateimscp', 'book') // ===================================================== ?> -<table border="0" cellspacing="0" width="100%" valign="top" cellpadding="2"> +<table class="booktable" width="100%" cellspacing="0" cellpadding="2"> <!-- subchapter title and upper navigation row //--> <tr> - <td width="<?php echo $tocwidth ?>" valign="bottom"> + <td style="width:<?php echo $tocwidth ?>px" valign="bottom"> <?php print_string('toc', 'book'); - if (!empty($doimport)) { - echo "<br/>($doimport)"; - } + echo $doimport; ?> </td> - <td valign="top"> - <table border="0" cellspacing="0" width="100%" valign="top" cellpadding="0"> - <tr> - <td nowrap="nowrap" align="left"><?php echo $printbook.$printchapter.$generateimscp ?></td> - <td nowrap ="nowrap" align="right"><?php echo $chnavigation ?></td> - </tr> - </table> + <td> + <div class="bookexport"><?php echo $printbook.$printchapter.$generateimscp ?></div> + <div class="booknav"><?php echo $chnavigation ?></div> </td> </tr> <!-- toc and chapter row //--> -<tr> - <td width="<?php echo $tocwidth ?>" valign="top" align="left"> +<tr class="tocandchapter"> + <td style="width:<?php echo $tocwidth ?>px" align="left"><div class="clearer"> </div> <?php print_box_start('generalbox'); echo $toc; print_box_end(); if ($allowedit and $edit) { - echo '<font size="1"><br />'; + echo '<div class="faq">'; helpbutton('faq', get_string('faq','book'), 'book', true, true); - echo '</font>'; + echo '</div>'; } ?> </td> - <td valign="top" align="right"> + <td align="right"><div class="clearer"> </div> <?php print_box_start('generalbox'); $content = ''; @@ -235,7 +236,7 @@ $generateimscp = ($allowedit) ? '<a title="'.get_string('generateimscp', 'book') echo '</div>'; print_box_end(); /// lower navigation - echo '<p>'.$chnavigation.'</p>'; + echo '<div class="booknav">'.$chnavigation.'</div>'; ?> </td> </tr> From b58b82c30d8cb14c9adb319597a02d1500879673 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Sun, 17 Aug 2008 13:04:56 +0000 Subject: [PATCH 032/455] fixed regression reported by Miroslav FIkar --- show.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/show.php b/show.php index beae942b2b7..ce99d9c94e2 100644 --- a/show.php +++ b/show.php @@ -1,9 +1,8 @@ -<?PHP // $Id: show.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ +<?PHP // $Id: show.php,v 1.4 2008/08/17 13:04:56 skodak Exp $ require('teacheraccess.php'); //page only for teachers ///switch hidden state -$chapter = new object(); $chapter->hidden = $chapter->hidden ? 0 : 1; ///add slashes to all text fields From 9da8ea22e651ae279c871414e1dd9c65656fcbb2 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Sun, 1 Aug 2010 12:15:46 +0000 Subject: [PATCH 033/455] CONTRIB-2232 preparations for git migration --- backuplib.php | 3 +-- book_print.css | 1 - coursefiles.php | 4 +--- db/access.php | 2 -- db/mysql.php | 4 +--- db/postgres7.php | 4 +--- db/upgrade.php | 10 ++++------ delete.php | 3 +-- edit.php | 6 ++---- edit_form.php | 4 +--- generateimscp.php | 4 +--- import.php | 3 +-- import_form.php | 4 +--- index.php | 4 +--- lang/be_utf8/book.php | 3 +-- lang/ca_utf8/book.php | 4 +--- lang/cs_utf8/book.php | 4 +--- lang/de_utf8/book.php | 3 +-- lang/en_utf8/book.php | 3 +-- lang/es_utf8/book.php | 4 +--- lang/fi_utf8/book.php | 4 +--- lang/fr_utf8/book.php | 4 +--- lang/id_utf8/book.php | 6 +----- lang/it_utf8/book.php | 4 +--- lang/ja_utf8/book.php | 4 +--- lang/nl_utf8/book.php | 3 +-- lang/pl_utf8/book.php | 3 +-- lang/pt_br_utf8/book.php | 4 +--- lang/sk_utf8/book.php | 4 +--- lang/sv_utf8/book.php | 3 +-- lib.php | 4 +--- mod_form.php | 1 - move.php | 3 +-- print.php | 3 +-- restorelib.php | 5 +---- settings.php | 5 +---- show.php | 4 +--- styles.php | 3 +-- teacheraccess.php | 4 +--- toc.php | 3 +-- version.php | 4 +--- view.php | 4 +--- 42 files changed, 43 insertions(+), 116 deletions(-) diff --git a/backuplib.php b/backuplib.php index 85fc7d77a4e..b6da903cdec 100644 --- a/backuplib.php +++ b/backuplib.php @@ -1,4 +1,4 @@ -<?PHP // $Id: backuplib.php,v 1.1 2006/03/12 18:39:59 skodak Exp $ +<?PHP //This php script contains all the stuff to backup/restore //book mods @@ -154,4 +154,3 @@ return $info; } -?> diff --git a/book_print.css b/book_print.css index 6fe10d6d6a0..57574ed20d6 100644 --- a/book_print.css +++ b/book_print.css @@ -1,4 +1,3 @@ -/* $Id: book_print.css,v 1.1 2006/03/12 18:39:59 skodak Exp $ */ h1, h2, h3, h4, h5, h6 { margin-left: 0px; diff --git a/coursefiles.php b/coursefiles.php index 5864e6d408b..8d845218b17 100644 --- a/coursefiles.php +++ b/coursefiles.php @@ -1,4 +1,4 @@ -<?php // $Id: coursefiles.php,v 1.3 2008/08/13 23:21:13 skodak Exp $ +<?php // Manage all uploaded files in a course file area @@ -912,5 +912,3 @@ function displaydir ($wdir) { //echo "<hr width=\"640\" align=\"center\" noshade=\"noshade\" size=\"1\" />"; } - -?> diff --git a/db/access.php b/db/access.php index 30dd4840d4d..be2f89cc7ab 100644 --- a/db/access.php +++ b/db/access.php @@ -66,5 +66,3 @@ $mod_book_capabilities = array( ), ); - -?> diff --git a/db/mysql.php b/db/mysql.php index f426543c73f..ff6c7fc0e24 100644 --- a/db/mysql.php +++ b/db/mysql.php @@ -1,4 +1,4 @@ -<?PHP // $Id: mysql.php,v 1.1 2006/03/12 18:40:01 skodak Exp $ +<?PHP function book_upgrade($oldversion) { /// This function does anything necessary to upgrade @@ -32,5 +32,3 @@ function book_upgrade($oldversion) { } return true; } - -?> diff --git a/db/postgres7.php b/db/postgres7.php index ef34d1e1bf9..e0dc84683a9 100644 --- a/db/postgres7.php +++ b/db/postgres7.php @@ -1,4 +1,4 @@ -<?PHP // $Id: postgres7.php,v 1.1 2006/03/12 18:40:01 skodak Exp $ +<?PHP function book_upgrade($oldversion) { // This function does anything necessary to upgrade @@ -61,5 +61,3 @@ function book_upgrade($oldversion) { return true; } - -?> diff --git a/db/upgrade.php b/db/upgrade.php index 72297260773..a0eea5ebff1 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,6 +1,6 @@ -<?php //$Id: upgrade.php,v 1.4 2007/09/24 19:15:39 stronk7 Exp $ +<?php -// This file keeps track of upgrades to +// This file keeps track of upgrades to // the assignment module // // Sometimes, changes between versions involve @@ -23,8 +23,8 @@ function xmldb_book_upgrade($oldversion=0) { $result = true; -/// And upgrade begins here. For each one, you'll need one -/// block of code similar to the next one. Please, delete +/// And upgrade begins here. For each one, you'll need one +/// block of code similar to the next one. Please, delete /// this comment lines once this file start handling proper /// upgrade code. @@ -41,5 +41,3 @@ function xmldb_book_upgrade($oldversion=0) { return $result; } - -?> diff --git a/delete.php b/delete.php index 860a5c84fb7..74e57c76207 100644 --- a/delete.php +++ b/delete.php @@ -1,4 +1,4 @@ -<?PHP // $Id: delete.php,v 1.3 2008/03/25 20:19:49 poltawski Exp $ +<?PHP require('teacheraccess.php'); //page only for teachers $confirm = optional_param('confirm', 0, PARAM_BOOL); @@ -53,4 +53,3 @@ if ($confirm) { // the operation was confirmed. print_footer($course); -?> diff --git a/edit.php b/edit.php index 23573fec289..2eb36a986c4 100644 --- a/edit.php +++ b/edit.php @@ -1,4 +1,4 @@ -<?PHP // $Id: edit.php,v 1.4 2008/08/13 23:21:14 skodak Exp $ +<?PHP require_once('../../config.php'); require_once('lib.php'); @@ -87,7 +87,7 @@ if ($mform->is_cancelled()) { $sql = "UPDATE {$CFG->prefix}book_chapters SET pagenum = pagenum + 1 WHERE bookid = $book->id AND pagenum >= $data->pagenum"; - execute_sql($sql, false); + execute_sql($sql, false); if (!$data->id = insert_record('book_chapters', addslashes_recursive($data))) { error('Could not insert a new chapter'); @@ -121,5 +121,3 @@ print_heading_with_help($pageheading, 'edit', 'book', $icon); $mform->display(); print_footer($course); - -?> diff --git a/edit_form.php b/edit_form.php index 5562d58199c..0efb8f535bb 100644 --- a/edit_form.php +++ b/edit_form.php @@ -1,4 +1,4 @@ -<?php //$Id: edit_form.php,v 1.1 2008/08/13 23:21:14 skodak Exp $ +<?php require_once($CFG->libdir.'/formslib.php'); @@ -49,5 +49,3 @@ class book_chapter_edit_form extends moodleform { } } } - -?> diff --git a/generateimscp.php b/generateimscp.php index 293eb08f95a..47f0fc23de4 100644 --- a/generateimscp.php +++ b/generateimscp.php @@ -1,4 +1,4 @@ -<?PHP // $Id: generateimscp.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ +<?PHP /////////////////////////////////////////////////////////////////////////// // // @@ -252,5 +252,3 @@ function chapter2html($chapter, $courseid, $bookid) { return $object; } - -?> diff --git a/import.php b/import.php index 2bb800e7f0a..bcc48f8fa92 100644 --- a/import.php +++ b/import.php @@ -1,4 +1,4 @@ -<?PHP // $Id: import.php,v 1.5 2008/08/13 23:21:13 skodak Exp $ +<?PHP require('../../config.php'); require_once('lib.php'); @@ -139,4 +139,3 @@ $mform->display(); print_footer($course); -?> diff --git a/import_form.php b/import_form.php index aa83c418d4f..74f2a3cf838 100644 --- a/import_form.php +++ b/import_form.php @@ -1,4 +1,4 @@ -<?php //$Id: import_form.php,v 1.1 2008/08/13 23:21:14 skodak Exp $ +<?php require_once($CFG->libdir.'/formslib.php'); @@ -59,5 +59,3 @@ class book_import_form extends moodleform { return $errors; } } - -?> diff --git a/index.php b/index.php index be48a5095c9..9bb5925a2c3 100644 --- a/index.php +++ b/index.php @@ -1,4 +1,4 @@ -<?PHP // $Id: index.php,v 1.3 2008/03/25 20:19:49 poltawski Exp $ +<?PHP /// This page lists all the instances of book in a particular course @@ -99,5 +99,3 @@ echo '<br />'; print_table($table); print_footer($course); - -?> diff --git a/lang/be_utf8/book.php b/lang/be_utf8/book.php index 7b1ce6b17d6..47c17741f68 100644 --- a/lang/be_utf8/book.php +++ b/lang/be_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:03 skodak Exp $ +<?PHP // book.php - created with Moodle 1.4.4 (2004083140) @@ -39,4 +39,3 @@ $string['toc'] = 'Змест'; $string['tocwidth'] = 'Вызначыць шырыню зместу для ўсіх падручнікаў'; $string['top'] = 'наверх'; -?> diff --git a/lang/ca_utf8/book.php b/lang/ca_utf8/book.php index 794fec852ec..217b5ad01fe 100644 --- a/lang/ca_utf8/book.php +++ b/lang/ca_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:03 skodak Exp $ +<?PHP $string['modulename'] = 'Llibre'; $string['modulenameplural'] = 'Llibres'; @@ -45,5 +45,3 @@ $string['relinking'] = 'S\'està reenllaçant'; $string['importinfo'] = 'Importa el directori o el fitxer HTML seleccionat.<br />Els capítols estan ordenats alfabèticament pel nom del fitxer.'; $string['maindirectory'] = 'Directori principal'; $string['fileordir'] = 'Fitxer o directori'; - -?> diff --git a/lang/cs_utf8/book.php b/lang/cs_utf8/book.php index 01a57ba54b1..2a428240a4f 100644 --- a/lang/cs_utf8/book.php +++ b/lang/cs_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:03 skodak Exp $ +<?PHP // book.php - created with Moodle 1.3.3 + (2004052503) @@ -38,5 +38,3 @@ $string['subchapter'] = 'Podkapitola'; $string['toc'] = 'Obsah'; $string['tocwidth'] = 'Vyberte šířku obsahu pro všechny knihy.'; $string['top'] = 'začátek'; - -?> diff --git a/lang/de_utf8/book.php b/lang/de_utf8/book.php index 249157695a6..59db5bfea1b 100644 --- a/lang/de_utf8/book.php +++ b/lang/de_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.2 2008/07/22 15:16:26 skodak Exp $ +<?PHP $string['modulename'] = 'Buch'; $string['modulenameplural'] = 'Bücher'; @@ -46,4 +46,3 @@ $string['importinfo'] = 'Importiert die gewählten HTML Dateien oder Ordner.<br $string['maindirectory'] = 'Hauptordner'; $string['fileordir'] = 'Datei oder Ordner'; -?> diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php index 3ccc6da1745..7a4a1dc1645 100644 --- a/lang/en_utf8/book.php +++ b/lang/en_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.5 2008/08/13 23:21:14 skodak Exp $ +<?PHP $string['modulename'] = 'Book'; $string['modulenameplural'] = 'Books'; @@ -56,4 +56,3 @@ $string['book:import'] = 'Import chapters'; $string['book:print'] = 'Print book'; $string['book:exportimscp'] = 'Export book as IMS content package'; -?> diff --git a/lang/es_utf8/book.php b/lang/es_utf8/book.php index fe5e4b43162..c49911354a2 100644 --- a/lang/es_utf8/book.php +++ b/lang/es_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:03 skodak Exp $ +<?PHP // book.php - created with Moodle 1.3 (2004052500) // book.php - Translated to Spanish by Juan Luis Martinez from Dominican Republic (fernluichi@hotmail.com) @@ -28,5 +28,3 @@ $string['subchapter'] = 'Subcápitulo'; $string['toc'] = 'Tabla de Contenido'; $string['tocwidth'] = 'Seleciona el Ancho de la Tabla de Contenidos de Todos los Libros.'; $string['top'] = 'arriba'; - -?> diff --git a/lang/fi_utf8/book.php b/lang/fi_utf8/book.php index 70678bec509..f1e10971ccb 100644 --- a/lang/fi_utf8/book.php +++ b/lang/fi_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:03 skodak Exp $ +<?PHP // book.php - created with Moodle 1.5 unstable development (2004092000) @@ -39,5 +39,3 @@ $string['thislanguage'] = 'Suomi'; $string['toc'] = 'Sisällysluettelo'; $string['tocwidth'] = 'Valitse kaikkien kirjojen sisällysluetteloiden leveys.'; $string['top'] = 'Alkuun'; - -?> diff --git a/lang/fr_utf8/book.php b/lang/fr_utf8/book.php index c4ce5eefa53..54b604ae86d 100644 --- a/lang/fr_utf8/book.php +++ b/lang/fr_utf8/book.php @@ -1,4 +1,4 @@ -<?php // $Id: book.php,v 1.1 2006/03/12 18:40:05 skodak Exp $ +<?php $string['modulename'] = 'Livre'; $string['modulenameplural'] = 'Livre'; @@ -42,5 +42,3 @@ $string['maindirectory'] = 'Dossier principal'; $string['selectdir'] = 'Choisir le dossier du cours'; $string['relinking'] = 'Mise à jour des liens'; - -?> \ No newline at end of file diff --git a/lang/id_utf8/book.php b/lang/id_utf8/book.php index a858d9c70d9..1be9d967818 100644 --- a/lang/id_utf8/book.php +++ b/lang/id_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:05 skodak Exp $ +<?PHP $string['modulename'] = 'Buku'; $string['modulenameplural'] = 'Buku-buku'; @@ -43,7 +43,3 @@ $string['maindirectory'] = 'Direktori utama'; $string['chooseafileordir'] = 'Pilih sebuah file atau direktori'; $string['relinking'] = 'Relinking'; - - - -?> diff --git a/lang/it_utf8/book.php b/lang/it_utf8/book.php index e96d2a84cd7..ead1c748b92 100644 --- a/lang/it_utf8/book.php +++ b/lang/it_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.3 2007/07/03 11:42:29 andreabix Exp $ +<?PHP // book.php - created with Moodle 1.7.1+ (2006101010) @@ -38,5 +38,3 @@ $string['subchapter'] = 'Paragrafo'; $string['toc'] = 'Sommario'; $string['tocwidth'] = 'Larghezza in pixel del Sommario per tutti i Libri.'; $string['top'] = 'Ritorna su'; - -?> diff --git a/lang/ja_utf8/book.php b/lang/ja_utf8/book.php index 68bd61e077c..240c56dd18c 100644 --- a/lang/ja_utf8/book.php +++ b/lang/ja_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:04 skodak Exp $ +<?PHP $string['modulename'] = 'ブック'; $string['modulenameplural'] = 'ブック'; @@ -44,5 +44,3 @@ $string['relinking'] = 'リンクの再作成中'; $string['importinfo'] = '選択したHTMLもしくはディレクトリのインポート<br />各章はファイル名順にソートされます。'; $string['maindirectory'] = 'メインディレクトリ'; $string['fileordir'] = 'ファイルもしくはディレクトリ'; - -?> diff --git a/lang/nl_utf8/book.php b/lang/nl_utf8/book.php index 481f4b961db..d3496fe55e0 100644 --- a/lang/nl_utf8/book.php +++ b/lang/nl_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:04 skodak Exp $ +<?PHP // book.php - created with Moodle 1.5 development (2004082300) @@ -38,4 +38,3 @@ $string['toc'] = 'Inhoudstafel'; $string['tocwidth'] = 'Kies de breedte van de inhoudstafel voor alle boeken.'; $string['top'] = 'boven'; -?> diff --git a/lang/pl_utf8/book.php b/lang/pl_utf8/book.php index 9c05949c53d..d62e1ab076d 100644 --- a/lang/pl_utf8/book.php +++ b/lang/pl_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:04 skodak Exp $ +<?PHP // book.php - created with Moodle 1.5 UNSTABLE DEVELOPMENT (2005031000) @@ -39,4 +39,3 @@ $string['toc'] = 'Spis treści'; $string['tocwidth'] = 'Ustaw szrokość spisu treści dla wszystkich książek'; $string['top'] = 'Góra'; -?> diff --git a/lang/pt_br_utf8/book.php b/lang/pt_br_utf8/book.php index d097dbfbe20..62e89f1ea0f 100644 --- a/lang/pt_br_utf8/book.php +++ b/lang/pt_br_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:02 skodak Exp $ +<?PHP $string['modulename'] = 'Livro'; $string['modulenameplural'] = 'Livros'; @@ -44,5 +44,3 @@ $string['relinking'] = 'Re-linkando'; $string['importinfo'] = 'Importar o arquivo HTML ou diretório selecionados.<br />Os capítulos são ordenados alfabeticamente usando os nomes dos arquivos.'; $string['maindirectory'] = 'Diretório principal'; $string['fileordir'] = 'Arquivo ou diretório'; - -?> diff --git a/lang/sk_utf8/book.php b/lang/sk_utf8/book.php index 9e23f499d2c..cafefc6b038 100644 --- a/lang/sk_utf8/book.php +++ b/lang/sk_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:00 skodak Exp $ +<?PHP // book.php - created with Moodle 1.3.3 + (2004052503) @@ -38,5 +38,3 @@ $string['subchapter'] = 'Podkapitola'; $string['toc'] = 'Obsah'; $string['tocwidth'] = 'Vyberte šírku obsahu pre všetky knihy.'; $string['top'] = 'začiatok'; - -?> diff --git a/lang/sv_utf8/book.php b/lang/sv_utf8/book.php index 0acd53fe94f..8652fd7e74f 100644 --- a/lang/sv_utf8/book.php +++ b/lang/sv_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP // $Id: book.php,v 1.1 2006/03/12 18:40:04 skodak Exp $ +<?PHP // book.php - created with Moodle 1.4 (2004083100) @@ -39,4 +39,3 @@ $string['toc'] = 'Innehållsförteckning'; $string['tocwidth'] = 'Välj en bredd på innehållsförteckningen som gäller alla böcker.'; $string['top'] = 'Upp'; -?> diff --git a/lib.php b/lib.php index 187993177c8..ac378ed0801 100644 --- a/lib.php +++ b/lib.php @@ -1,4 +1,4 @@ -<?PHP // $Id: lib.php,v 1.6 2008/08/13 23:21:14 skodak Exp $ +<?PHP define('NUM_NONE', '0'); define('NUM_NUMBERS', '1'); @@ -446,5 +446,3 @@ function book_relink($id, $bookid, $courseid) { } } } - -?> diff --git a/mod_form.php b/mod_form.php index ab33c804d25..ac5634c5382 100644 --- a/mod_form.php +++ b/mod_form.php @@ -41,4 +41,3 @@ class mod_book_mod_form extends moodleform_mod { } -?> \ No newline at end of file diff --git a/move.php b/move.php index 76e3e9e0ec0..42c6563a7e4 100644 --- a/move.php +++ b/move.php @@ -1,4 +1,4 @@ -<?PHP // $Id: move.php,v 1.2 2006/11/21 19:26:36 skodak Exp $ +<?PHP require('teacheraccess.php'); //page only for teachers $up = optional_param('up', 0, PARAM_BOOL); @@ -145,4 +145,3 @@ book_check_structure($book->id); redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); die; -?> diff --git a/print.php b/print.php index 011acd63bf7..954bf4f7cde 100644 --- a/print.php +++ b/print.php @@ -1,4 +1,4 @@ -<?PHP // $Id: print.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ +<?PHP require_once('../../config.php'); require_once('lib.php'); @@ -163,4 +163,3 @@ if ($chapter) { echo '</body> </html>'; } -?> diff --git a/restorelib.php b/restorelib.php index 5408ae494ca..ad9164cf68f 100644 --- a/restorelib.php +++ b/restorelib.php @@ -1,4 +1,4 @@ -<?PHP // $Id: restorelib.php,v 1.3 2008/08/13 23:21:13 skodak Exp $ +<?PHP //This php script contains all the stuff to backup/restore //book mods @@ -377,6 +377,3 @@ return $status; } - - -?> diff --git a/settings.php b/settings.php index 2686f300563..2e4c8b88a59 100644 --- a/settings.php +++ b/settings.php @@ -1,4 +1,4 @@ -<?php //$Id: settings.php,v 1.2 2008/03/25 20:19:49 poltawski Exp $ +<?php $choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); @@ -6,6 +6,3 @@ $choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', $settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'book'), get_string('tocwidth', 'book'), '180', $choices)); - - -?> diff --git a/show.php b/show.php index ce99d9c94e2..e0ad56c325a 100644 --- a/show.php +++ b/show.php @@ -1,4 +1,4 @@ -<?PHP // $Id: show.php,v 1.4 2008/08/17 13:04:56 skodak Exp $ +<?PHP require('teacheraccess.php'); //page only for teachers @@ -34,5 +34,3 @@ add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm book_check_structure($book->id); redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); die; - -?> diff --git a/styles.php b/styles.php index 8eaa9214a75..9327c878c04 100644 --- a/styles.php +++ b/styles.php @@ -1,4 +1,3 @@ -/* $Id: styles.php,v 1.1 2008/08/13 23:21:13 skodak Exp $*/ /* later should be defined in themes*/ @@ -44,7 +43,7 @@ img.bigicon { #mod-book-view div.faq { font-size: 0.7em; } - + /* == TOC styles == */ /* toc style NONE */ diff --git a/teacheraccess.php b/teacheraccess.php index 4a333bb8f8b..7d6ee536187 100644 --- a/teacheraccess.php +++ b/teacheraccess.php @@ -1,4 +1,4 @@ -<?PHP // $Id: teacheraccess.php,v 1.3 2008/08/13 23:21:14 skodak Exp $ +<?PHP ///standard routine to allow only teachers in ///check of $id and $chapterid parameters @@ -40,5 +40,3 @@ if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! //check all variables unset($id); unset($chapterid); - -?> diff --git a/toc.php b/toc.php index a49c2011ebf..977d74c8854 100644 --- a/toc.php +++ b/toc.php @@ -1,4 +1,4 @@ -<?PHP // $Id: toc.php,v 1.4 2008/08/13 23:21:14 skodak Exp $ +<?PHP defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); @@ -186,4 +186,3 @@ $toc .= '</div>'; $toc = str_replace('<ul></ul>', '', $toc); //cleanup of invalid structures -?> diff --git a/version.php b/version.php index 2f91ca0e0d6..3619421a0ca 100644 --- a/version.php +++ b/version.php @@ -1,4 +1,4 @@ -<?PHP // $Id: version.php,v 1.5 2008/08/13 23:21:13 skodak Exp $ +<?PHP ///////////////////////////////////////////////////////////////////////////////// /// Called by moodle_needs_upgrading() and /admin/index.php @@ -9,5 +9,3 @@ $module->requires = 2007101512; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $release = "1.5beta"; // User-friendly version number - -?> diff --git a/view.php b/view.php index 1dc7893b359..ce4cf375dc9 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,4 @@ -<?PHP // $Id: view.php,v 1.6 2008/08/13 23:21:14 skodak Exp $ +<?PHP require('../../config.php'); require_once('lib.php'); @@ -244,5 +244,3 @@ $generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book <?php print_footer($course); - -?> From 1b7aed36ffaada2ef899c25c0cbba49fccd77c3e Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Sun, 1 Aug 2010 12:50:22 +0000 Subject: [PATCH 034/455] CONTRIB-2232 preparations for git migration - line ending fixes --- lang/nl_utf8/help/book/customtitles.html | 7 +++++- lang/nl_utf8/help/book/disableprinting.html | 7 +++++- lang/nl_utf8/help/book/import.html | 11 ++++++++- lang/nl_utf8/help/book/mods.html | 9 ++++++- lang/nl_utf8/help/book/numberingtype.html | 26 ++++++++++++++++++++- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/lang/nl_utf8/help/book/customtitles.html b/lang/nl_utf8/help/book/customtitles.html index 1ddb5f33268..d40ffbf57d0 100644 --- a/lang/nl_utf8/help/book/customtitles.html +++ b/lang/nl_utf8/help/book/customtitles.html @@ -1 +1,6 @@ -<p align=center><b>Titels alleen in inhoudstafel</b></p> <p>Indien ja worden de titels van de hoofdstukken automatisch alleen in de inhoudstafel getoond.</p> \ No newline at end of file +<p align=center><b>Titels alleen in inhoudstafel</b></p> + + + +<p>Indien ja worden de titels van de hoofdstukken automatisch alleen in de inhoudstafel getoond.</p> + diff --git a/lang/nl_utf8/help/book/disableprinting.html b/lang/nl_utf8/help/book/disableprinting.html index 8308e4e8d4b..3f6827c5dd5 100644 --- a/lang/nl_utf8/help/book/disableprinting.html +++ b/lang/nl_utf8/help/book/disableprinting.html @@ -1 +1,6 @@ -<p align=center><b>Schakel afdrukken uit</b></p> <p>Verberg alle icoontjes om af te drukken.</p> \ No newline at end of file +<p align=center><b>Schakel afdrukken uit</b></p> + + + +<p>Verberg alle icoontjes om af te drukken.</p> + diff --git a/lang/nl_utf8/help/book/import.html b/lang/nl_utf8/help/book/import.html index b859c2a5b72..0a71f9a99c8 100644 --- a/lang/nl_utf8/help/book/import.html +++ b/lang/nl_utf8/help/book/import.html @@ -1 +1,10 @@ -<p align=center><b>Importeren</b></p> <p> Je kunt een enkel HTML-bestand of alle HTML-bestanden van een map importeren.</p> <p> Relatieve links naar bestanden worden geconverteerd in absolute hoofdstuklinks. De links naar bestanden, flash en java worden ook herwerkt.</p> \ No newline at end of file +<p align=center><b>Importeren</b></p> + + + +<p> Je kunt een enkel HTML-bestand of alle HTML-bestanden van een map importeren.</p> + + + +<p> Relatieve links naar bestanden worden geconverteerd in absolute hoofdstuklinks. De links naar bestanden, flash en java worden ook herwerkt.</p> + diff --git a/lang/nl_utf8/help/book/mods.html b/lang/nl_utf8/help/book/mods.html index 7ef7cc75c8d..d69f273b1a3 100644 --- a/lang/nl_utf8/help/book/mods.html +++ b/lang/nl_utf8/help/book/mods.html @@ -1 +1,8 @@ -<p><img valign=absmiddle src="<?php echo $CFG->wwwroot?>/mod/book/icon.gif"> <b>Boeken</b></p> <ul> <p>Met de boekmodule maak je eenvoudig studiemateriaal op meerdere pagina's.</p> </ul> \ No newline at end of file +<p><img valign=absmiddle src="<?php echo $CFG->wwwroot?>/mod/book/icon.gif"> <b>Boeken</b></p> + +<ul> + +<p>Met de boekmodule maak je eenvoudig studiemateriaal op meerdere pagina's.</p> + +</ul> + diff --git a/lang/nl_utf8/help/book/numberingtype.html b/lang/nl_utf8/help/book/numberingtype.html index 114de5a92cc..a982b976b59 100644 --- a/lang/nl_utf8/help/book/numberingtype.html +++ b/lang/nl_utf8/help/book/numberingtype.html @@ -1 +1,25 @@ -<p align=center><b>Hoofdstuknummering</b></p> <p>Er zijn verschillende voorgedefinieerde nummeringstypes: <p><b>Geen</b> - hoofdstukken en ondertitels krijgen geen opmaak. Gebruik deze instelling als je speciale nummeringsstijlen, zoals letters, wil gebruiken. Bijvoorbeeld: "A Eerste hoofdstuk", "A.1 Eerste paragraaf", .... </p> <p><b>Getallen</b> - hoofdstukken en paragrafen worden genummerd(1, 1.1, 1.2, 2, ...)<p> <p><b>Bolletjes</b> - paragrafen springen in en worden met bolletjes getoond.<p> <p><b>Indented</b> - paragrafen springen in.</p> \ No newline at end of file +<p align=center><b>Hoofdstuknummering</b></p> + + + +<p>Er zijn verschillende voorgedefinieerde nummeringstypes: + + + +<p><b>Geen</b> - hoofdstukken en ondertitels krijgen geen opmaak. Gebruik deze instelling als je speciale nummeringsstijlen, zoals letters, wil gebruiken. Bijvoorbeeld: "A Eerste hoofdstuk", "A.1 Eerste paragraaf", .... +</p> + + + +<p><b>Getallen</b> - hoofdstukken en paragrafen worden genummerd(1, 1.1, 1.2, 2, + +...)<p> + + + +<p><b>Bolletjes</b> - paragrafen springen in en worden met bolletjes getoond.<p> + + + +<p><b>Indented</b> - paragrafen springen in.</p> + From 8d623d147bc8b9eea046a02d2cc55b3736f5d034 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Sun, 1 Aug 2010 13:10:36 +0000 Subject: [PATCH 035/455] CONTRIB-2232 oops, merging all changes from 1.9.x first --- README.txt | 12 ++--- backuplib.php | 3 +- coursefiles.php | 1 + db/mysql.php | 2 +- db/postgres7.php | 2 +- db/upgrade.php | 2 +- delete.php | 3 +- edit.php | 3 +- edit_form.php | 4 +- generateimscp.php | 2 +- import.php | 2 +- import_form.php | 2 +- index.php | 3 +- lang/be_utf8/book.php | 3 +- lang/ca_utf8/book.php | 2 +- lang/cs_utf8/book.php | 2 +- lang/de_utf8/book.php | 3 +- lang/de_utf8/help/book/customtitles.html | 4 +- lang/de_utf8/help/book/disableprinting.html | 4 +- lang/de_utf8/help/book/edit.html | 8 +--- lang/de_utf8/help/book/faq.html | 35 +-------------- lang/de_utf8/help/book/import.html | 6 +-- lang/de_utf8/help/book/index.html | 12 +---- lang/de_utf8/help/book/mods.html | 5 +-- lang/de_utf8/help/book/numberingtype.html | 15 +------ lang/de_utf8/help/book/summary.html | 6 +-- lang/en_utf8/book.php | 3 +- lang/es_utf8/book.php | 2 +- lang/fi_utf8/book.php | 2 +- lang/id_utf8/book.php | 2 +- lang/it_utf8/book.php | 39 +++++++++------- lang/ja_utf8/book.php | 2 +- lang/nl_utf8/book.php | 3 +- lang/pl_utf8/book.php | 3 +- lang/pt_br_utf8/book.php | 2 +- lang/sk_utf8/book.php | 2 +- lang/sl_utf8/book.php | 50 +++++++++++++++++++++ lang/sl_utf8/help/book/customtitles.html | 3 ++ lang/sl_utf8/help/book/disableprinting.html | 3 ++ lang/sl_utf8/help/book/edit.html | 7 +++ lang/sl_utf8/help/book/faq.html | 39 ++++++++++++++++ lang/sl_utf8/help/book/import.html | 5 +++ lang/sl_utf8/help/book/index.html | 11 +++++ lang/sl_utf8/help/book/mods.html | 4 ++ lang/sl_utf8/help/book/numberingtype.html | 12 +++++ lang/sl_utf8/help/book/summary.html | 5 +++ lang/sv_utf8/book.php | 3 +- lib.php | 20 ++++++++- move.php | 3 +- print.php | 2 +- restorelib.php | 3 +- settings.php | 1 + show.php | 2 +- teacheraccess.php | 2 +- toc.php | 2 +- version.php | 2 +- view.php | 3 +- 57 files changed, 238 insertions(+), 150 deletions(-) create mode 100644 lang/sl_utf8/book.php create mode 100644 lang/sl_utf8/help/book/customtitles.html create mode 100644 lang/sl_utf8/help/book/disableprinting.html create mode 100644 lang/sl_utf8/help/book/edit.html create mode 100644 lang/sl_utf8/help/book/faq.html create mode 100644 lang/sl_utf8/help/book/import.html create mode 100644 lang/sl_utf8/help/book/index.html create mode 100644 lang/sl_utf8/help/book/mods.html create mode 100644 lang/sl_utf8/help/book/numberingtype.html create mode 100644 lang/sl_utf8/help/book/summary.html diff --git a/README.txt b/README.txt index 6e6909c1a0e..6b1276b92fd 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,3 @@ -$Id: README.txt,v 1.6 2008/08/13 23:21:14 skodak Exp $ - /////////////////////////////////////////////////////////////////////////// // // // NOTICE OF COPYRIGHT // @@ -12,7 +10,7 @@ $Id: README.txt,v 1.6 2008/08/13 23:21:14 skodak Exp $ /////////////////////////////////////////////////////////////////////////// // // // Book module original code // -// Copyright (C) 2004 Petr Skoda (petr.skoda@vslib.cz) // +// Copyright (C) 2004 Petr Skoda (info@skodak.org) // // // /////////////////////////////////////////////////////////////////////////// // // @@ -30,7 +28,7 @@ $Id: README.txt,v 1.6 2008/08/13 23:21:14 skodak Exp $ // // /////////////////////////////////////////////////////////////////////////// -Book module for Moodle - version 1.2 (stable release) +Book module for Moodle - version 1.5 (stable release) =============================================================================== Created by: Petr Skoda (skodak) - most of the coding & design @@ -42,7 +40,7 @@ Many ideas and code were taken from other Moodle modules and Moodle itself;-) Installation: * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins -List of features - version 1.4: +List of features - version 1.5: * easy to use - new teachers can quickly create multipage study materials * two levels - only chapters and subchapters @@ -116,5 +114,9 @@ CHANGELOG: * formslib conversion * capabilities implemented * no new features +== 1.5 2009/11/11 ============================================================ + * minor cleanup + * new Slovenian language pack - thanks Mitja Podreka + * updated German Language pack - thanks Ralf Hilgenstock skodak diff --git a/backuplib.php b/backuplib.php index b6da903cdec..3b9f5df0369 100644 --- a/backuplib.php +++ b/backuplib.php @@ -1,4 +1,4 @@ -<?PHP +<?php //This php script contains all the stuff to backup/restore //book mods @@ -153,4 +153,3 @@ return $info; } - diff --git a/coursefiles.php b/coursefiles.php index 8d845218b17..c5400ce036a 100644 --- a/coursefiles.php +++ b/coursefiles.php @@ -912,3 +912,4 @@ function displaydir ($wdir) { //echo "<hr width=\"640\" align=\"center\" noshade=\"noshade\" size=\"1\" />"; } + diff --git a/db/mysql.php b/db/mysql.php index ff6c7fc0e24..56d367748a8 100644 --- a/db/mysql.php +++ b/db/mysql.php @@ -1,4 +1,4 @@ -<?PHP +<?php function book_upgrade($oldversion) { /// This function does anything necessary to upgrade diff --git a/db/postgres7.php b/db/postgres7.php index e0dc84683a9..a1b6e7a4e3b 100644 --- a/db/postgres7.php +++ b/db/postgres7.php @@ -1,4 +1,4 @@ -<?PHP +<?php function book_upgrade($oldversion) { // This function does anything necessary to upgrade diff --git a/db/upgrade.php b/db/upgrade.php index a0eea5ebff1..a85e9d8e4c3 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,4 +1,4 @@ -<?php +<?php //$Id: upgrade.php,v 1.6 2010/08/01 13:10:36 skodak Exp $ // This file keeps track of upgrades to // the assignment module diff --git a/delete.php b/delete.php index 74e57c76207..e21fe24c98c 100644 --- a/delete.php +++ b/delete.php @@ -1,4 +1,4 @@ -<?PHP +<?php require('teacheraccess.php'); //page only for teachers $confirm = optional_param('confirm', 0, PARAM_BOOL); @@ -52,4 +52,3 @@ if ($confirm) { // the operation was confirmed. } print_footer($course); - diff --git a/edit.php b/edit.php index 2eb36a986c4..393cb6be15a 100644 --- a/edit.php +++ b/edit.php @@ -1,4 +1,4 @@ -<?PHP +<?php require_once('../../config.php'); require_once('lib.php'); @@ -121,3 +121,4 @@ print_heading_with_help($pageheading, 'edit', 'book', $icon); $mform->display(); print_footer($course); + diff --git a/edit_form.php b/edit_form.php index 0efb8f535bb..93b7fa8ecad 100644 --- a/edit_form.php +++ b/edit_form.php @@ -1,4 +1,4 @@ -<?php +<?php //$Id: edit_form.php,v 1.3 2010/08/01 13:10:37 skodak Exp $ require_once($CFG->libdir.'/formslib.php'); @@ -49,3 +49,5 @@ class book_chapter_edit_form extends moodleform { } } } + +?> diff --git a/generateimscp.php b/generateimscp.php index 47f0fc23de4..4068cb1622a 100644 --- a/generateimscp.php +++ b/generateimscp.php @@ -1,4 +1,4 @@ -<?PHP +<?php /////////////////////////////////////////////////////////////////////////// // // diff --git a/import.php b/import.php index bcc48f8fa92..07a4c5ed9f8 100644 --- a/import.php +++ b/import.php @@ -1,4 +1,4 @@ -<?PHP +<?php require('../../config.php'); require_once('lib.php'); diff --git a/import_form.php b/import_form.php index 74f2a3cf838..dbe88bd1cae 100644 --- a/import_form.php +++ b/import_form.php @@ -1,4 +1,4 @@ -<?php +<?php //$Id: import_form.php,v 1.3 2010/08/01 13:10:37 skodak Exp $ require_once($CFG->libdir.'/formslib.php'); diff --git a/index.php b/index.php index 9bb5925a2c3..74e6b5e6032 100644 --- a/index.php +++ b/index.php @@ -1,4 +1,4 @@ -<?PHP +<?php /// This page lists all the instances of book in a particular course @@ -99,3 +99,4 @@ echo '<br />'; print_table($table); print_footer($course); + diff --git a/lang/be_utf8/book.php b/lang/be_utf8/book.php index 47c17741f68..da69c253376 100644 --- a/lang/be_utf8/book.php +++ b/lang/be_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.4.4 (2004083140) @@ -38,4 +38,3 @@ $string['subchapter'] = 'Параграф'; $string['toc'] = 'Змест'; $string['tocwidth'] = 'Вызначыць шырыню зместу для ўсіх падручнікаў'; $string['top'] = 'наверх'; - diff --git a/lang/ca_utf8/book.php b/lang/ca_utf8/book.php index 217b5ad01fe..b89826e6d3b 100644 --- a/lang/ca_utf8/book.php +++ b/lang/ca_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php $string['modulename'] = 'Llibre'; $string['modulenameplural'] = 'Llibres'; diff --git a/lang/cs_utf8/book.php b/lang/cs_utf8/book.php index 2a428240a4f..70e64584504 100644 --- a/lang/cs_utf8/book.php +++ b/lang/cs_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.3.3 + (2004052503) diff --git a/lang/de_utf8/book.php b/lang/de_utf8/book.php index 59db5bfea1b..122ac9aa6e2 100644 --- a/lang/de_utf8/book.php +++ b/lang/de_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php $string['modulename'] = 'Buch'; $string['modulenameplural'] = 'Bücher'; @@ -45,4 +45,3 @@ $string['relinking'] = 'Verlinken'; $string['importinfo'] = 'Importiert die gewählten HTML Dateien oder Ordner.<br />Kapitel sind alphabetisch nach den Dateinamen sortiert.'; $string['maindirectory'] = 'Hauptordner'; $string['fileordir'] = 'Datei oder Ordner'; - diff --git a/lang/de_utf8/help/book/customtitles.html b/lang/de_utf8/help/book/customtitles.html index 7aa14ab8432..94b0b39106d 100644 --- a/lang/de_utf8/help/book/customtitles.html +++ b/lang/de_utf8/help/book/customtitles.html @@ -1,3 +1 @@ -<p align=center><b>Eigene Titel</b></p> - -<p>Kapiteltitel werden automatisch nur in der TOC angezeigt.</p> +<h2>Titel der Kapitel</h2><p>Kapiteltitel werden automatisch im Inhaltsverzeichnis angezeigt.</p> \ No newline at end of file diff --git a/lang/de_utf8/help/book/disableprinting.html b/lang/de_utf8/help/book/disableprinting.html index d5b2b196244..024a7eaed42 100644 --- a/lang/de_utf8/help/book/disableprinting.html +++ b/lang/de_utf8/help/book/disableprinting.html @@ -1,3 +1 @@ -<p align=center><b>Drucken ausgeschaltet</b></p> - -<p>Verstecken der Druck Icons.</p> +<h2>Druckfunktion ausschalten</h2></p><p>Verbirgt die Funktion zum Ausdruck einzelner Seiten oder des gesamten Buches.</p> \ No newline at end of file diff --git a/lang/de_utf8/help/book/edit.html b/lang/de_utf8/help/book/edit.html index 60a50dc336e..e450b74ef32 100644 --- a/lang/de_utf8/help/book/edit.html +++ b/lang/de_utf8/help/book/edit.html @@ -1,7 +1 @@ -<p align=center><b>Kapiteländerung</b></p> - -<p>Versuchen Sie Titel der Kapitel kurz zu halten.</p> - -<p>Maximal zwei Stufe können die Unterkapitel haben.</p> - -<p>Wenn SIe Probleme mit dem WYSIWYG HTML Editor haben, versuchen Sie einen anderen Browser z.B. Mozilla Firefox zu benutzen oder schlaten Sie den Editor im Profil ab.</p> \ No newline at end of file +<h2>Kapitel bearbeiten</h2></p><p>Versuchen Sie die Überschriften der Kapitel knapp zu halten. Sie stehen links im Inhaltsverzeichnis. Lange Titel werden umbrochen und sehen nicht gut aus.</p><p>Neben der Hauptebene kann eine Unterkapitelebene angelegt werden.</p><p>Wenn Sie Probleme mit dem WYSIWYG HTML Editor haben, versuchen Sie einen anderen Browser z.B. Mozilla Firefox zu benutzen oder schalten Sie den Editor im Profil ab.</p> \ No newline at end of file diff --git a/lang/de_utf8/help/book/faq.html b/lang/de_utf8/help/book/faq.html index 608e9430739..602caadeb4a 100644 --- a/lang/de_utf8/help/book/faq.html +++ b/lang/de_utf8/help/book/faq.html @@ -1,34 +1 @@ -<p align=center><b>Frequently Asked Questions über Bücher</b></p> - -<dl> - <dt><b>Warum nur zwei Stufen?</b></dt> - <dd>Zwei Stufen sind genug für alle Bücher, drei Stufen würden zu einem -schlecht strukturierte Dokumnt führen. Das Buch Modul wurde für die Erstellung -von kurzen Inhalten entwickelt. Für größere und komplexere Dokumente macht es -mehr Sinn das PDF Format zu benutzen. Am einfachsten können Sie PDF Dateien mit -den folgenden Programmen erzeugen - (see <a - href="http://sector7g.wurzel6.de/pdfcreator/index_en.htm" - target="_blank">PDFCreator</a>, <a - href="http://fineprint.com/products/pdffactory/index.html" - target="_blank">PDF -Factory</a>, <a - href="http://www.adobe.com/products/acrobatstd/main.html" - target="_blank">Adobe Acrobat</a>, -etc.).<br /> - </dd><br /> - <dt><b>Können Lerner Bücher editieren?</b></dt> - <dd>Nur Lehrer können Bücher erstellen und ändern. Es ist nicht geplant -auch für Lerner zu ermöglichen. Aber vielleicht findet sich ja jemand -diese Funktion auch für Lerner erstellt. Der Hauptgrund ist jedoch, daß das -Buch Modul so simpel wie möglich bleiben sollt.</dd><br /> - <dt><b>Wie kann ich in Büchern suchen?</b></dt> - <dd>Zur Zeit gibt es nur die Möglichkeit mit der Browsersuchfunktion -in einem Buch zu suchen. Eine globale Suche ist nur in Moodle Foren möglich. -Es wäre toll wenn es eine Art globale Suche für alle Resourcen auch Bücher -in moddle geben würde. Gibt es evtl. jemanden der dies Umsetzen könnte?</dd><br /> - <dt><b>Mei Titel passt nicht in eine Zeile.</b></dt> - <dd>Ändern SIe Ihren Titel oder bitten Sie Ihren Administrator der Webseite darum, -daß er die Breite des TOC vergrößert. Dies ist global für alle Bücher in der Modul -Konfigurationsseite einstellbar.</dd><br /> -</dl> +<h2>Frequently Asked Questions über Bücher</h2></p><dl> <dt><b>Warum nur zwei Gliederungsebenen?</b></dt> <dd>Zwei Stufen sind in den meisten Fällen ausreichend. Drei Stufen würden häufig zu einem schlecht strukturierten Dokument führen. Das Buch Modul wurde für die Erstellung von kurzen Inhalten entwickelt. Für größere und komplexere Dokumente macht es mehr Sinn das PDF Format zu benutzen. Am einfachsten können Sie PDF Dateien mit den folgenden Programmen erzeugen (see <a href="http://sector7g.wurzel6.de/pdfcreator/index_en.htm" target="_blank">PDFCreator</a>, <a href="http://fineprint.com/products/pdffactory/index.html" target="_blank">PDFFactory</a>, <a href="http://www.adobe.com/products/acrobatstd/main.html" target="_blank">Adobe Acrobat</a>,etc.).<br /> </dd><br /> <dt><b>Können Teilnehmer/innen Bücher editieren?</b></dt> <dd>Nur Trainer/innen können Bücher erstellen und ändern. Es ist nicht geplant auch für Teilnehmer zu ermöglichen. Der Hauptgrund ist jedoch, daß das Buch Modul so simpel wie möglich bleiben soll. Mit Hilfe der Rollenfunktion kann man dieses dennoch erreichen.</dd><br /> <dt><b>Wie kann ich in Büchern suchen?</b></dt> <dd>Zur Zeit gibt es nur die Möglichkeit mit der Browsersuchfunktionin einem Buch zu suchen. Eine globale Suche ist nur in Moodle Foren möglich.</dd><br /> <dt><b>Mein Titel passt nicht in eine Zeile.</b></dt> <dd>Ändern Sie Ihren Titel oder bitten Sie Ihren Administrator der Webseite darum ,daß er die Breite des Inhaltsverzeichnis vergrößert. Dies ist global für alle Bücher in der Modul Konfigurationsseite einstellbar.</dd><br /></dl> \ No newline at end of file diff --git a/lang/de_utf8/help/book/import.html b/lang/de_utf8/help/book/import.html index 201e8c24e29..2c72d9c0904 100644 --- a/lang/de_utf8/help/book/import.html +++ b/lang/de_utf8/help/book/import.html @@ -1,5 +1 @@ -<p align=center><b>Import</b></p> - -<p> Sie können eine einzelnes HTML Datei importieren oder jede HTML Datei in einem Ordner.</p> - -<p> Relative Datei Verknüpfungen werden zu absoluten Kapitelverlinkungen konvertiert. Bilder, Flash und Java Inhalte werden ebenfalls verlinkt.</p> +<h2>Import</h2></p><p> Sie können Buchseiten als HTML-Dateien importieren. Jede einzelne HTML-Datei wird zu einer neuen Seite des Buches. Die Anordnung erfolgt alphabetisch nach den Titeln der HTML-Dateien.</p><p> Relative Dateiverknüpfungen werden zu absoluten Kapitelverlinkungen konvertiert. Bilder, Flash und Java Inhalte werden ebenfalls verlinkt.</p> \ No newline at end of file diff --git a/lang/de_utf8/help/book/index.html b/lang/de_utf8/help/book/index.html index e99b390fd16..312fb42b9a1 100644 --- a/lang/de_utf8/help/book/index.html +++ b/lang/de_utf8/help/book/index.html @@ -1,11 +1 @@ -<p>Book module</p> -<ul> - <li><a href="help.php?module=book&file=numberingtype.html">Kapitelnummerierung</a> - <li><a href="help.php?module=book&file=disableprinting.html">Drucken ausschalten</a> - <li><a href="help.php?module=book&file=customtitles.html">Eigene Titel</a> - <li><a href="help.php?module=book&file=summary.html">Zusammenfassung lesen</a> - <li><a href="help.php?module=book&file=edit.html">Kapitel ändern</a> - <li><a href="help.php?module=book&file=import.html">Import</a> - <li><a href="help.php?module=book&file=faq.html">Buch FAQ</a> -</ul> - +<h2>Buch-Modul</h2><ul> <li><a href="help.php?module=book&file=numberingtype.html">Kapitelnummerierung</a> <li><a href="help.php?module=book&file=disableprinting.html">Druckfunktion abschalten</a> <li><a href="help.php?module=book&file=customtitles.html">Eigene Titelüberschriften</a> <li><a href="help.php?module=book&file=summary.html">Beschreibung</a> <li><a href="help.php?module=book&file=edit.html">Kapitel ändern</a> <li><a href="help.php?module=book&file=import.html">Import</a> <li><a href="help.php?module=book&file=faq.html">Buch FAQ</a></ul> \ No newline at end of file diff --git a/lang/de_utf8/help/book/mods.html b/lang/de_utf8/help/book/mods.html index 0cbf5aae0f1..433a63fa941 100644 --- a/lang/de_utf8/help/book/mods.html +++ b/lang/de_utf8/help/book/mods.html @@ -1,4 +1 @@ -<p><img valign=absmiddle src="<?php echo $CFG->wwwroot?>/mod/book/icon.gif"> <b>Books</b></p> -<ul> -<p>Das Buch ist ein simples mehrseitiges Studienmaterial.</p> -</ul> +<h2><img valign=absmiddle src="<?php echo $CFG->wwwroot?>/mod/book/icon.gif"> Bücher</h2></p><ul><p>Das Arbeitsmaterial Buch ermöglicht es, Lerninhalte in strukturierter und gegliederter Form zu hinterlegen. Wie in einem Buch findet man ein Inhaltsverzeichnis und kann durch die Seiten blättern.</p></ul> \ No newline at end of file diff --git a/lang/de_utf8/help/book/numberingtype.html b/lang/de_utf8/help/book/numberingtype.html index e79717c0513..c53c97c841a 100644 --- a/lang/de_utf8/help/book/numberingtype.html +++ b/lang/de_utf8/help/book/numberingtype.html @@ -1,14 +1 @@ -<p align=center><b>Nummerierung von Kapiteln</b></p> - -<p>Es gibt verschiedene vordefinierte Nummerierungstypen: - -<p><b>Keine</b> - Kapitel und die Titel der Unterkapitel sind nicht formatiert, Sie können -selber eigene Styles zur Nummerierung benutzen. Zum Beispiel Buchstaben: Im Kapitel Titel -geben Sie dann folgendes ein "A Erstes Kapitel", "A.1 ein Unterkapitel",...</p> - -<p><b>Nummern</b> - Kapitel und Unterkapitel sind nummeriert (1, 1.1, 1.2, 2, -...)<p> - -<p><b>Kugeln</b> - Unterkapitel sind eingerückt und werden mit führenden Kugeln angezeigt.<p> - -<p><b>Eingerückt</b> - Unterkapitel sind eingerückt.</p> +<h2>Nummerierung von Kapiteln</h2><p>Es gibt verschiedene vordefinierte Nummerierungstypen:<p><b>Keine</b> - Kapitel und die Titel der Unterkapitel sind nicht formatiert. Sie könnenselber eigene Styles zur Nummerierung benutzen. Zum Beispiel Buchstaben. Im Kapitel Titelgeben Sie dann folgendes ein "A Erstes Kapitel", "A.1 ein Unterkapitel",...</p><p><b>Nummern</b> - Kapitel und Unterkapitel sind nummeriert (1, 1.1, 1.2, 2,...)<p><p><b>Punkte</b> - Unterkapitel sind eingerückt und werden mit Auszählungspunkten angezeigt.<p><p><b>Eingerückt</b> - Unterkapitel sind eingerückt.</p> \ No newline at end of file diff --git a/lang/de_utf8/help/book/summary.html b/lang/de_utf8/help/book/summary.html index 6ffdf0f6d80..76951e70e40 100644 --- a/lang/de_utf8/help/book/summary.html +++ b/lang/de_utf8/help/book/summary.html @@ -1,5 +1 @@ -<p align=center><b>Reading Summary</b></p> - -<p>Diese Einführung ist eine sehr kurze Beschreibung des Buches.</p> - -<p>Schreiben Sie hier nicht zu viel hinein!</p> \ No newline at end of file +<h2>Beschreibung des Buches</h2></p><p>Diese Einführung ist eine sehr kurze Beschreibung des Buches.</p><p>Schreiben Sie hier nicht zu viel hinein! Diese Beschreibung wird in der Übersicht der Bücher eines Kurses angezeigt. Sie ist mit dem Klappentext eines Buches vergleichbar.</p> \ No newline at end of file diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php index 7a4a1dc1645..5a7e88cc6ab 100644 --- a/lang/en_utf8/book.php +++ b/lang/en_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php $string['modulename'] = 'Book'; $string['modulenameplural'] = 'Books'; @@ -55,4 +55,3 @@ $string['book:viewhiddenchapters'] = 'View hidden book chapters'; $string['book:import'] = 'Import chapters'; $string['book:print'] = 'Print book'; $string['book:exportimscp'] = 'Export book as IMS content package'; - diff --git a/lang/es_utf8/book.php b/lang/es_utf8/book.php index c49911354a2..f0ac4a64879 100644 --- a/lang/es_utf8/book.php +++ b/lang/es_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.3 (2004052500) // book.php - Translated to Spanish by Juan Luis Martinez from Dominican Republic (fernluichi@hotmail.com) diff --git a/lang/fi_utf8/book.php b/lang/fi_utf8/book.php index f1e10971ccb..bf678769a0c 100644 --- a/lang/fi_utf8/book.php +++ b/lang/fi_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.5 unstable development (2004092000) diff --git a/lang/id_utf8/book.php b/lang/id_utf8/book.php index 1be9d967818..73f11047c6c 100644 --- a/lang/id_utf8/book.php +++ b/lang/id_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php $string['modulename'] = 'Buku'; $string['modulenameplural'] = 'Buku-buku'; diff --git a/lang/it_utf8/book.php b/lang/it_utf8/book.php index ead1c748b92..27a5406e79d 100644 --- a/lang/it_utf8/book.php +++ b/lang/it_utf8/book.php @@ -1,19 +1,26 @@ -<?PHP - // book.php - created with Moodle 1.7.1+ (2006101010) +<?php - -$string['addafter'] = 'Aggiungi un nuovo capitolo'; +$string['addafter'] = 'Aggiungi un nuovo capitolo.'; +$string['book:edit'] = 'Modifica capitoli'; +$string['book:exportimscp'] = 'Esportare libro come pacchetto IMS'; +$string['book:import'] = 'Importare capitoli'; +$string['book:print'] = 'Stampare libro'; +$string['book:read'] = 'Leggere libro'; +$string['book:viewhiddenchapters'] = 'Visualizzare capitoli nascosti'; +$string['book_tocwidth'] = 'Larghezza sommario'; $string['chapterscount'] = 'Capitoli'; -$string['chaptertitle'] = 'Titolo del Capitolo'; -$string['confchapterdelete'] = 'Sei sicuro di voler cancellare questo capitolo?'; -$string['confchapterdeleteall'] = 'Sei sicuro di voler cancellare questo capitolo e tutti i suoi paragrafi?'; +$string['chaptertitle'] = 'Titolo del capitolo'; +$string['confchapterdelete'] = 'Sei sicuro di eliminare questo capitolo?'; +$string['confchapterdeleteall'] = 'Sei sicuro di eliminare questo capitolo e tutti i suoi paragrafi?'; $string['content'] = 'Contenuto'; $string['customtitles'] = 'Titoli personalizzati'; -$string['disableprinting'] = 'Escludi la stampa'; +$string['disableprinting'] = 'Disabilita la stampa'; +$string['doexport'] = 'Esporta'; $string['doimport'] = 'Importa'; -$string['editingchapter'] = 'Modifica del capitolo'; -$string['faq'] = 'FAQ Modulo Libro'; -$string['fileordir'] = 'Scegli un file oppure un folder'; +$string['editingchapter'] = 'Modifica capitolo'; +$string['faq'] = 'FAQ Modulo libro'; +$string['fileordir'] = 'Scegli un file o un folder'; +$string['generateimscp'] = 'Genera un pacchetto IMS'; $string['import'] = 'Importa'; $string['importinfo'] = 'Importa un file HTML oppure una cartella.<br />I capitoli saranno ordinati alfabeticamente utilizzando i nomi dei file.'; $string['importing'] = 'Importazione in corso'; @@ -21,20 +28,20 @@ $string['importingchapters'] = 'Importazione dei capitoli'; $string['maindirectory'] = 'Cartella principale'; $string['modulename'] = 'Libro'; $string['modulenameplural'] = 'Libri'; -$string['navexit'] = 'Chiudi'; +$string['navexit'] = 'Esci'; $string['navnext'] = 'Pagina successiva'; $string['navprev'] = 'Pagina precedente'; -$string['numbering'] = 'Numerazione dei capitoli'; -$string['numbering0'] = 'Nessuna numerazione'; +$string['numbering'] = 'Numerazione capitoli'; +$string['numbering0'] = 'Senza numerazione'; $string['numbering1'] = 'Numeri'; $string['numbering2'] = 'Elenco puntato'; $string['numbering3'] = 'Elenco rientrato'; $string['printbook'] = 'Stampa tutto'; -$string['printchapter'] = 'Stampa questo capitolo'; +$string['printchapter'] = 'Stampa capitolo'; $string['printdate'] = 'Data'; $string['printedby'] = 'Stampato da'; $string['relinking'] = 'Elaborazione dei collegamenti'; $string['subchapter'] = 'Paragrafo'; $string['toc'] = 'Sommario'; -$string['tocwidth'] = 'Larghezza in pixel del Sommario per tutti i Libri.'; +$string['tocwidth'] = 'Larghezza in pixel del Sommario per i Libri.'; $string['top'] = 'Ritorna su'; diff --git a/lang/ja_utf8/book.php b/lang/ja_utf8/book.php index 240c56dd18c..00a1964210f 100644 --- a/lang/ja_utf8/book.php +++ b/lang/ja_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php $string['modulename'] = 'ブック'; $string['modulenameplural'] = 'ブック'; diff --git a/lang/nl_utf8/book.php b/lang/nl_utf8/book.php index d3496fe55e0..3806da05367 100644 --- a/lang/nl_utf8/book.php +++ b/lang/nl_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.5 development (2004082300) @@ -37,4 +37,3 @@ $string['subchapter'] = 'Paragraaf'; $string['toc'] = 'Inhoudstafel'; $string['tocwidth'] = 'Kies de breedte van de inhoudstafel voor alle boeken.'; $string['top'] = 'boven'; - diff --git a/lang/pl_utf8/book.php b/lang/pl_utf8/book.php index d62e1ab076d..123d5cb6ecd 100644 --- a/lang/pl_utf8/book.php +++ b/lang/pl_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.5 UNSTABLE DEVELOPMENT (2005031000) @@ -38,4 +38,3 @@ $string['subchapter'] = 'Podrozdział'; $string['toc'] = 'Spis treści'; $string['tocwidth'] = 'Ustaw szrokość spisu treści dla wszystkich książek'; $string['top'] = 'Góra'; - diff --git a/lang/pt_br_utf8/book.php b/lang/pt_br_utf8/book.php index 62e89f1ea0f..4006f9f83cb 100644 --- a/lang/pt_br_utf8/book.php +++ b/lang/pt_br_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php $string['modulename'] = 'Livro'; $string['modulenameplural'] = 'Livros'; diff --git a/lang/sk_utf8/book.php b/lang/sk_utf8/book.php index cafefc6b038..bdff3e4d242 100644 --- a/lang/sk_utf8/book.php +++ b/lang/sk_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.3.3 + (2004052503) diff --git a/lang/sl_utf8/book.php b/lang/sl_utf8/book.php new file mode 100644 index 00000000000..e7153fb44b8 --- /dev/null +++ b/lang/sl_utf8/book.php @@ -0,0 +1,50 @@ +<?php + // Translation for Moodle 1.9.2 + // Translated by Mitja Podreka - Faculty of Arts, University of Ljubljana + +$string['modulename'] = 'Knjiga'; +$string['modulenameplural'] = 'Knjige'; +$string['toc'] = 'Kazalo vsebine'; +$string['tocwidth'] = 'Izberite širino kazala vsebine za vse knjige.'; +$string['faq'] = 'Knjiga - pogosta vprašanja'; +$string['disableprinting'] = 'Onemogoči tiskanje'; +$string['customtitles'] = 'Ločeni naslovi'; +$string['editingchapter'] = 'Urejanje poglavja'; +$string['chaptertitle'] = 'Naslov poglavja'; +$string['content'] = 'Vsebina'; +$string['subchapter'] = 'Podpoglavje'; +$string['numbering'] = 'Označevanje poglavij'; +$string['numbering0'] = 'Brez'; +$string['numbering1'] = 'Številke'; +$string['numbering2'] = 'Vrstične oznake'; +$string['numbering3'] = 'Zamik'; +$string['chapterscount'] = 'Poglavja'; +$string['addafter'] = 'Dodaj novo poglavje'; +$string['confchapterdelete'] = 'Ali zares želite izbrisati to poglavje?'; +$string['confchapterdeleteall'] = 'Ali zares želite izbrisati to poglavje in vsa njegova podpoglavja?'; +$string['printbook'] = 'Natisni celotno knjigo'; +$string['printchapter'] = 'Natisni to poglavje'; +$string['printdate'] = 'Datum'; +$string['printedby'] = 'Natisnil'; +$string['top'] = 'na vrh'; +$string['navprev'] = 'Prejšnje'; +$string['navnext'] = 'Naslednje'; +$string['navexit'] = 'Zapri knjigo'; +$string['importingchapters'] = 'Uvoz poglavij v knjigo'; +$string['import'] = 'Uvozi'; +$string['doimport'] = 'Uvozi'; +$string['doexport'] = 'Izvozi'; +$string['importing'] = 'Uvažam'; +$string['relinking'] = 'Ponastavitev povezav'; +$string['importinfo'] = 'Uvozi izbrane datoteke ali mape.<br />Poglavja bodo razvrščena po abecedi glede na imena datotek.<br />Datoteke imenovane \'sub_*.*\' bodo vedno uvožene kod podpoglavja.'; +$string['maindirectory'] = 'Glavna mapa'; +$string['fileordir'] = 'Datoteka ali mapa'; +$string['book:edit'] = 'Uredi poglavja knjige'; +$string['book:exportimscp'] = 'Izvozi knjigo kot IMS vsebinski paket'; +$string['book:import'] = 'Uvozi poglavja'; +$string['book:print'] = 'Natisni knjigo'; +$string['book:read'] = 'Beri knjigo'; +$string['book:viewhiddenchapters'] = 'Poglej skrita poglavja'; +$string['book_tocwidth'] = 'Širina kazala vsebine'; +$string['generateimscp'] = 'Generiraj IMS vsebinski paket'; +?> diff --git a/lang/sl_utf8/help/book/customtitles.html b/lang/sl_utf8/help/book/customtitles.html new file mode 100644 index 00000000000..fe18c5c0c2c --- /dev/null +++ b/lang/sl_utf8/help/book/customtitles.html @@ -0,0 +1,3 @@ +<p align="center"><b>Ločeni naslovi</b></p> + +<p>Naslov poglavja se običajno izpiše v kazalu vsebine in pri ogledu poglavja. Če odkljukate to možnost se bo naslov poglavja izpisal le v kazalu. Ta možnost je koristna, če hočete ob ogledu poglavja prikazati drugačen naslov oz. ga sploh nočete prikazati.</p> diff --git a/lang/sl_utf8/help/book/disableprinting.html b/lang/sl_utf8/help/book/disableprinting.html new file mode 100644 index 00000000000..59c220637b8 --- /dev/null +++ b/lang/sl_utf8/help/book/disableprinting.html @@ -0,0 +1,3 @@ +<p align="center"><b>Onemogoči tiskanje</b></p> + +<p>Skrije ikone za printanje.</p> diff --git a/lang/sl_utf8/help/book/edit.html b/lang/sl_utf8/help/book/edit.html new file mode 100644 index 00000000000..4704cb1f3b5 --- /dev/null +++ b/lang/sl_utf8/help/book/edit.html @@ -0,0 +1,7 @@ +<p align="center"><b>Urejanje poglavja</b></p> + +<p>Skušajte uporabljati kratke naslove.</p> + +<p>Mogoča sta samo dva (2) nivoja poglavij.</p> + +<p>Če med uporabo html urejevalnika tekstov (WYSIWYG) naletite na težave, skušajte uporabiti drug brskalnik (npr. Mozilla Firefox) ali izključite urejevalnik v vašem profilu.</p> \ No newline at end of file diff --git a/lang/sl_utf8/help/book/faq.html b/lang/sl_utf8/help/book/faq.html new file mode 100644 index 00000000000..93bca047156 --- /dev/null +++ b/lang/sl_utf8/help/book/faq.html @@ -0,0 +1,39 @@ +<p align="center"> + <b>Pogosta vprašanja o modulu Knjiga</b> +</p> +<dl> + <dt> + <b>Zakaj samo dva nivoja?</b> + </dt> + <dd> + Dva nivoja sta običajno dovolj za vse knjige, trije nivoji pa bi že vodili k slabo strukturiranim dokumentom. Modul Knjiga je bil zasnovan za izdelavo kratkih večstranskih študijskih gradiv. Za daljše dokumente pa je ponavadi bolje uporabiti PDF format. Najlažji način za izdelavo PDF formatov je uporaba virtualnega tiskalnika (glej + <a href="http://sector7g.wurzel6.de/pdfcreator/index_en.htm" target="_blank">PDFCreator</a>, + <a href="http://fineprint.com/products/pdffactory/index.html" target="_blank"> + PDFFactory</a>, + <a href="http://www.adobe.com/products/acrobatstd/main.html" target="_blank">Adobe Acrobat</a>, + idr.). + <br /> + </dd> + <br /> + <dt> + <b>Ali lahko študentje urejajo knjigo?</b> + </dt> + <dd> + Knjigo lahko ustvarijo in urejajo samo učitelji. Zaenkrat ni nobenih načrtov za izdelavo tovrstne funkcije, vendar bo lahko izdelal nekaj podobnega tudi za študente (Portfolio?). Glavni razlog za to je, da bi bil modul Knjiga čim bolj enostaven. + </dd> + <br /> + <dt> + <b>Kako naj iščem po knjigah?</b> + </dt> + <dd> + Trenutno je mogoč samo en način in sicer uporaba brskalnikove funkcije "najdi" na strani knjige za tiskanje. Globalno iskanje je trenutno možno le v Moodle forumih. Lepo bi bilo, če bi ta možnost obstajala za vse aktivnosti, vključno s Knjigo. Kak prostovoljec? + </dd> + <br /> + <dt> + <b>Moji naslovi se ne prilegajo v eno vrstico.</b> + </dt> + <dd> + Spremenite naslov ali pa prosite administratorja, da spremeni širino kazala. Ta nastavitev je definirana globalno in velja za vse knjige. + </dd> + <br /> +</dl> diff --git a/lang/sl_utf8/help/book/import.html b/lang/sl_utf8/help/book/import.html new file mode 100644 index 00000000000..434b5e9df59 --- /dev/null +++ b/lang/sl_utf8/help/book/import.html @@ -0,0 +1,5 @@ +<p align="center"><b>Uvoz</b></p> + +<p>Uvozite lahko eno HTML datoteko ali vse HTML datoteke v mapi.</p> + +<p>Relativne povezave na datoteke so spremenjene v absolutne povezave na poglavja. Spremenjene so tudi povezave na grafike, flash animacije in Java skripte.</p> diff --git a/lang/sl_utf8/help/book/index.html b/lang/sl_utf8/help/book/index.html new file mode 100644 index 00000000000..b0de7ee86cd --- /dev/null +++ b/lang/sl_utf8/help/book/index.html @@ -0,0 +1,11 @@ +<p>Modul Knjiga</p> +<ul> + <li><a href="help.php?module=book&file=numberingtype.html">Označevanje poglavij</a> + <li><a href="help.php?module=book&file=disableprinting.html">Onemogoči tiskanje</a> + <li><a href="help.php?module=book&file=customtitles.html">Ločeni naslovi</a> + <li><a href="help.php?module=book&file=summary.html">Povzetek knjige</a> + <li><a href="help.php?module=book&file=edit.html">Urejanje poglavja</a> + <li><a href="help.php?module=book&file=import.html">Uvoz</a> + <li><a href="help.php?module=book&file=faq.html">Pogosta vprašanja</a> +</ul> + diff --git a/lang/sl_utf8/help/book/mods.html b/lang/sl_utf8/help/book/mods.html new file mode 100644 index 00000000000..aad38c64c16 --- /dev/null +++ b/lang/sl_utf8/help/book/mods.html @@ -0,0 +1,4 @@ +<p><img valign="absmiddle" src="<?php echo $CFG->wwwroot?>/mod/book/icon.gif"> <b>Knjiga</b></p> +<ul> +<p>Knjiga je enostavno večstransko študijsko gradivo</p> +</ul> diff --git a/lang/sl_utf8/help/book/numberingtype.html b/lang/sl_utf8/help/book/numberingtype.html new file mode 100644 index 00000000000..950efb3007e --- /dev/null +++ b/lang/sl_utf8/help/book/numberingtype.html @@ -0,0 +1,12 @@ +<p align="center"><b>Označevanje poglavij</b></p> + +<p>Na voljo je več prednastavljenih načinov označevanja: + +<p><b>Brez</b> - naslovi poglavij in podpoglavij niso oblikovani. To možnost izberite, če želite uporabiti poseben način označevanja. Na primer črke: v naslovu poglavja zapišete "A Prvo poglavje!, "A.1 Neko podpoglavje", ...</p> + +<p><b>Številke</b> - naslovi poglavij in podpoglavij bodo oštevilčeni (1, 1.1, 1.2, 2, +...)<p> + +<p><b>Vrstične oznake</b> - naslovi podpoglavij so zamaknjeni in označeni z vrstično oznako (pika, kvadratek,...).<p> + +<p><b>Zamik</b> - naslovi podpoglavij so zamaknjeni.</p> diff --git a/lang/sl_utf8/help/book/summary.html b/lang/sl_utf8/help/book/summary.html new file mode 100644 index 00000000000..fd5ef10ce8c --- /dev/null +++ b/lang/sl_utf8/help/book/summary.html @@ -0,0 +1,5 @@ +<p align="center"><b>Povzetek knjige</b></p> + +<p>Povzetek je zelo kratek opis knjige.</p> + +<p>Naj vas ne premami, da bi napisali preveč!p> \ No newline at end of file diff --git a/lang/sv_utf8/book.php b/lang/sv_utf8/book.php index 8652fd7e74f..6fc026c2375 100644 --- a/lang/sv_utf8/book.php +++ b/lang/sv_utf8/book.php @@ -1,4 +1,4 @@ -<?PHP +<?php // book.php - created with Moodle 1.4 (2004083100) @@ -38,4 +38,3 @@ $string['subchapter'] = 'Underavdelning'; $string['toc'] = 'Innehållsförteckning'; $string['tocwidth'] = 'Välj en bredd på innehållsförteckningen som gäller alla böcker.'; $string['top'] = 'Upp'; - diff --git a/lib.php b/lib.php index ac378ed0801..a3ac84725bd 100644 --- a/lib.php +++ b/lib.php @@ -1,4 +1,4 @@ -<?PHP +<?php define('NUM_NONE', '0'); define('NUM_NUMBERS', '1'); @@ -165,6 +165,15 @@ function book_scale_used ($bookid,$scaleid) { function book_scale_used_anywhere($scaleid) { return false; } + +function book_get_view_actions() { + return array('view', 'view all', 'print'); +} + +function book_get_post_actions() { + return array('update'); +} + ////////////////////////////////////////////////////////////////////////////////////// /// Any other book functions go here. Each of them must have a name that /// starts with book_ @@ -446,3 +455,12 @@ function book_relink($id, $bookid, $courseid) { } } } + +/** + * Tells if files in moddata are trusted and can be served without XSS protection. + * @return bool true if file can be submitted by teacher only (trusted), false otherwise + */ +function book_is_moddata_trusted() { + return true; +} + diff --git a/move.php b/move.php index 42c6563a7e4..ba4ee24ddd3 100644 --- a/move.php +++ b/move.php @@ -1,4 +1,4 @@ -<?PHP +<?php require('teacheraccess.php'); //page only for teachers $up = optional_param('up', 0, PARAM_BOOL); @@ -144,4 +144,3 @@ add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm book_check_structure($book->id); redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); die; - diff --git a/print.php b/print.php index 954bf4f7cde..b09166f0ece 100644 --- a/print.php +++ b/print.php @@ -1,4 +1,4 @@ -<?PHP +<?php require_once('../../config.php'); require_once('lib.php'); diff --git a/restorelib.php b/restorelib.php index ad9164cf68f..b3dcf158bb7 100644 --- a/restorelib.php +++ b/restorelib.php @@ -1,4 +1,4 @@ -<?PHP +<?php //This php script contains all the stuff to backup/restore //book mods @@ -377,3 +377,4 @@ return $status; } + diff --git a/settings.php b/settings.php index 2e4c8b88a59..00fea531d4e 100644 --- a/settings.php +++ b/settings.php @@ -6,3 +6,4 @@ $choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', $settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'book'), get_string('tocwidth', 'book'), '180', $choices)); + diff --git a/show.php b/show.php index e0ad56c325a..c244c652e8b 100644 --- a/show.php +++ b/show.php @@ -1,4 +1,4 @@ -<?PHP +<?php require('teacheraccess.php'); //page only for teachers diff --git a/teacheraccess.php b/teacheraccess.php index 7d6ee536187..a3f6807c3a3 100644 --- a/teacheraccess.php +++ b/teacheraccess.php @@ -1,4 +1,4 @@ -<?PHP +<?php ///standard routine to allow only teachers in ///check of $id and $chapterid parameters diff --git a/toc.php b/toc.php index 977d74c8854..1c51c9a7070 100644 --- a/toc.php +++ b/toc.php @@ -1,4 +1,4 @@ -<?PHP +<?php defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); diff --git a/version.php b/version.php index 3619421a0ca..002cdf99e10 100644 --- a/version.php +++ b/version.php @@ -1,4 +1,4 @@ -<?PHP +<?php ///////////////////////////////////////////////////////////////////////////////// /// Called by moodle_needs_upgrading() and /admin/index.php diff --git a/view.php b/view.php index ce4cf375dc9..2e1ca50a208 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,4 @@ -<?PHP +<?php require('../../config.php'); require_once('lib.php'); @@ -244,3 +244,4 @@ $generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book <?php print_footer($course); + From c008e4aefc92bf5ad5181e945ee124929e54ed24 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Sun, 1 Aug 2010 15:28:51 +0200 Subject: [PATCH 036/455] getting rid of pesky cvs Id mess --- README.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.txt b/README.txt index 6e6909c1a0e..1c87c13a95d 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,3 @@ -$Id: README.txt,v 1.6 2008/08/13 23:21:14 skodak Exp $ - /////////////////////////////////////////////////////////////////////////// // // // NOTICE OF COPYRIGHT // From f6140b075185d27e32bab8995ca3e4697699e7b7 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Sun, 1 Aug 2010 15:29:02 +0200 Subject: [PATCH 037/455] readme for github --- README | 1 + 1 file changed, 1 insertion(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 00000000000..347ef90930c --- /dev/null +++ b/README @@ -0,0 +1 @@ +Book module for Moodle \ No newline at end of file From 31859517a317877572da3ce5ea2c18bb79af7d71 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 1 Sep 2010 12:37:24 +0200 Subject: [PATCH 038/455] renaming lang pack --- lang/en/book.php | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 lang/en/book.php diff --git a/lang/en/book.php b/lang/en/book.php new file mode 100644 index 00000000000..5a7e88cc6ab --- /dev/null +++ b/lang/en/book.php @@ -0,0 +1,57 @@ +<?php + +$string['modulename'] = 'Book'; +$string['modulenameplural'] = 'Books'; + +$string['toc'] = 'Table of Contents'; +$string['tocwidth'] = 'Select width of the Table of Contents for all books.'; +$string['book_tocwidth'] = 'Table of Contents width'; +$string['faq'] = 'Book FAQ'; + +$string['disableprinting'] = 'Disable Printing'; +$string['customtitles'] = 'Custom Titles'; + +$string['editingchapter'] = 'Editing chapter'; +$string['chaptertitle'] = 'Chapter Title'; +$string['content'] = 'Content'; +$string['subchapter'] = 'Subchapter'; + +$string['numbering'] = 'Chapter Numbering'; +$string['numbering0'] = 'None'; +$string['numbering1'] = 'Numbers'; +$string['numbering2'] = 'Bullets'; +$string['numbering3'] = 'Indented'; + +$string['chapterscount'] = 'Chapters'; + +$string['addafter'] = 'Add new chapter'; +$string['confchapterdelete'] = 'Do you really want to delete this chapter?'; +$string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?'; + +$string['generateimscp'] = 'Generate IMS content package'; +$string['printbook'] = 'Print Complete Book'; +$string['printchapter'] = 'Print This Chapter'; +$string['printdate'] = 'Date'; +$string['printedby'] = 'Printed by'; +$string['top'] = 'top'; + +$string['navprev'] = 'Previous'; +$string['navnext'] = 'Next'; +$string['navexit'] = 'Exit Book'; + +$string['importingchapters'] = 'Importing chapters into book'; +$string['import'] = 'Import'; +$string['doimport'] = 'Import'; +$string['doexport'] = 'Export'; +$string['importing'] = 'Importing'; +$string['relinking'] = 'Relinking'; +$string['importinfo'] = 'Import selected HTML file or directory.<br />Chapters are sorted alphabetically using file names.<br />Files named \'sub_*.*\' are always imported as subchapters.'; +$string['maindirectory'] = 'Main directory'; +$string['fileordir'] = 'File or directory'; + +$string['book:read'] = 'Read book'; +$string['book:edit'] = 'Edit book chapters'; +$string['book:viewhiddenchapters'] = 'View hidden book chapters'; +$string['book:import'] = 'Import chapters'; +$string['book:print'] = 'Print book'; +$string['book:exportimscp'] = 'Export book as IMS content package'; From 1148f9d40e703892d99a75e99ca36e15b69b8d5e Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 13:35:08 +0100 Subject: [PATCH 039/455] renaming lang dirs --- lang/{be_utf8 => be}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{be_utf8 => be}/help/book/edit.html | 0 lang/{be_utf8 => be}/help/book/faq.html | 0 lang/{be_utf8 => be}/help/book/import.html | 0 lang/{be_utf8 => be}/help/book/index.html | 0 lang/{be_utf8 => be}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{be_utf8 => be}/help/book/summary.html | 0 lang/{ca_utf8 => ca}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{ca_utf8 => ca}/help/book/edit.html | 0 lang/{ca_utf8 => ca}/help/book/faq.html | 0 lang/{ca_utf8 => ca}/help/book/import.html | 0 lang/{ca_utf8 => ca}/help/book/index.html | 0 lang/{ca_utf8 => ca}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{ca_utf8 => ca}/help/book/summary.html | 0 lang/{cs_utf8 => cs}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{cs_utf8 => cs}/help/book/edit.html | 0 lang/{cs_utf8 => cs}/help/book/faq.html | 0 lang/{cs_utf8 => cs}/help/book/import.html | 0 lang/{cs_utf8 => cs}/help/book/index.html | 0 lang/{cs_utf8 => cs}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{cs_utf8 => cs}/help/book/summary.html | 0 lang/{de_utf8 => de}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{de_utf8 => de}/help/book/edit.html | 0 lang/{de_utf8 => de}/help/book/faq.html | 0 lang/{de_utf8 => de}/help/book/import.html | 0 lang/{de_utf8 => de}/help/book/index.html | 0 lang/{de_utf8 => de}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{de_utf8 => de}/help/book/summary.html | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{en_utf8 => en}/help/book/edit.html | 0 lang/{en_utf8 => en}/help/book/faq.html | 0 lang/{en_utf8 => en}/help/book/import.html | 0 lang/{en_utf8 => en}/help/book/index.html | 0 lang/{en_utf8 => en}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{en_utf8 => en}/help/book/summary.html | 0 lang/en_utf8/book.php | 57 ------------------- lang/{es_utf8 => es}/book.php | 0 lang/{fi_utf8 => fi}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{fi_utf8 => fi}/help/book/edit.html | 0 lang/{fi_utf8 => fi}/help/book/faq.html | 0 lang/{fi_utf8 => fi}/help/book/import.html | 0 lang/{fi_utf8 => fi}/help/book/index.html | 0 lang/{fi_utf8 => fi}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{fi_utf8 => fi}/help/book/summary.html | 0 lang/{fr_utf8 => fr}/book.php | 0 lang/{id_utf8 => id}/book.php | 0 lang/{id_utf8 => id}/help/book/faq.html | 0 lang/{id_utf8 => id}/help/book/index.html | 0 lang/{id_utf8 => id}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{id_utf8 => id}/help/book/summary.html | 0 lang/{it_utf8 => it}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{it_utf8 => it}/help/book/edit.html | 0 lang/{it_utf8 => it}/help/book/faq.html | 0 lang/{it_utf8 => it}/help/book/import.html | 0 lang/{it_utf8 => it}/help/book/index.html | 0 lang/{it_utf8 => it}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{it_utf8 => it}/help/book/summary.html | 0 lang/{ja_utf8 => ja}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{ja_utf8 => ja}/help/book/edit.html | 0 lang/{ja_utf8 => ja}/help/book/faq.html | 0 lang/{ja_utf8 => ja}/help/book/import.html | 0 lang/{ja_utf8 => ja}/help/book/index.html | 0 lang/{ja_utf8 => ja}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{ja_utf8 => ja}/help/book/summary.html | 0 lang/{nl_utf8 => nl}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{nl_utf8 => nl}/help/book/edit.html | 0 lang/{nl_utf8 => nl}/help/book/faq.html | 0 lang/{nl_utf8 => nl}/help/book/import.html | 0 lang/{nl_utf8 => nl}/help/book/index.html | 0 lang/{nl_utf8 => nl}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{nl_utf8 => nl}/help/book/summary.html | 0 lang/{pl_utf8 => pl}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{pl_utf8 => pl}/help/book/edit.html | 0 lang/{pl_utf8 => pl}/help/book/faq.html | 0 lang/{pl_utf8 => pl}/help/book/import.html | 0 lang/{pl_utf8 => pl}/help/book/index.html | 0 lang/{pl_utf8 => pl}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{pl_utf8 => pl}/help/book/summary.html | 0 lang/{pt_br_utf8 => pt_br}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 .../{pt_br_utf8 => pt_br}/help/book/edit.html | 0 lang/{pt_br_utf8 => pt_br}/help/book/faq.html | 0 .../help/book/import.html | 0 .../help/book/index.html | 0 .../{pt_br_utf8 => pt_br}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 .../help/book/summary.html | 0 lang/{sk_utf8 => sk}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{sk_utf8 => sk}/help/book/edit.html | 0 lang/{sk_utf8 => sk}/help/book/faq.html | 0 lang/{sk_utf8 => sk}/help/book/import.html | 0 lang/{sk_utf8 => sk}/help/book/index.html | 0 lang/{sk_utf8 => sk}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{sk_utf8 => sk}/help/book/summary.html | 0 lang/{sl_utf8 => sl}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{sl_utf8 => sl}/help/book/edit.html | 0 lang/{sl_utf8 => sl}/help/book/faq.html | 0 lang/{sl_utf8 => sl}/help/book/import.html | 0 lang/{sl_utf8 => sl}/help/book/index.html | 0 lang/{sl_utf8 => sl}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{sl_utf8 => sl}/help/book/summary.html | 0 lang/{sv_utf8 => sv}/book.php | 0 .../help/book/customtitles.html | 0 .../help/book/disableprinting.html | 0 lang/{sv_utf8 => sv}/help/book/edit.html | 0 lang/{sv_utf8 => sv}/help/book/faq.html | 0 lang/{sv_utf8 => sv}/help/book/import.html | 0 lang/{sv_utf8 => sv}/help/book/index.html | 0 lang/{sv_utf8 => sv}/help/book/mods.html | 0 .../help/book/numberingtype.html | 0 lang/{sv_utf8 => sv}/help/book/summary.html | 0 148 files changed, 57 deletions(-) rename lang/{be_utf8 => be}/book.php (100%) rename lang/{be_utf8 => be}/help/book/customtitles.html (100%) rename lang/{be_utf8 => be}/help/book/disableprinting.html (100%) rename lang/{be_utf8 => be}/help/book/edit.html (100%) rename lang/{be_utf8 => be}/help/book/faq.html (100%) rename lang/{be_utf8 => be}/help/book/import.html (100%) rename lang/{be_utf8 => be}/help/book/index.html (100%) rename lang/{be_utf8 => be}/help/book/mods.html (100%) rename lang/{be_utf8 => be}/help/book/numberingtype.html (100%) rename lang/{be_utf8 => be}/help/book/summary.html (100%) rename lang/{ca_utf8 => ca}/book.php (100%) rename lang/{ca_utf8 => ca}/help/book/customtitles.html (100%) rename lang/{ca_utf8 => ca}/help/book/disableprinting.html (100%) rename lang/{ca_utf8 => ca}/help/book/edit.html (100%) rename lang/{ca_utf8 => ca}/help/book/faq.html (100%) rename lang/{ca_utf8 => ca}/help/book/import.html (100%) rename lang/{ca_utf8 => ca}/help/book/index.html (100%) rename lang/{ca_utf8 => ca}/help/book/mods.html (100%) rename lang/{ca_utf8 => ca}/help/book/numberingtype.html (100%) rename lang/{ca_utf8 => ca}/help/book/summary.html (100%) rename lang/{cs_utf8 => cs}/book.php (100%) rename lang/{cs_utf8 => cs}/help/book/customtitles.html (100%) rename lang/{cs_utf8 => cs}/help/book/disableprinting.html (100%) rename lang/{cs_utf8 => cs}/help/book/edit.html (100%) rename lang/{cs_utf8 => cs}/help/book/faq.html (100%) rename lang/{cs_utf8 => cs}/help/book/import.html (100%) rename lang/{cs_utf8 => cs}/help/book/index.html (100%) rename lang/{cs_utf8 => cs}/help/book/mods.html (100%) rename lang/{cs_utf8 => cs}/help/book/numberingtype.html (100%) rename lang/{cs_utf8 => cs}/help/book/summary.html (100%) rename lang/{de_utf8 => de}/book.php (100%) rename lang/{de_utf8 => de}/help/book/customtitles.html (100%) rename lang/{de_utf8 => de}/help/book/disableprinting.html (100%) rename lang/{de_utf8 => de}/help/book/edit.html (100%) rename lang/{de_utf8 => de}/help/book/faq.html (100%) rename lang/{de_utf8 => de}/help/book/import.html (100%) rename lang/{de_utf8 => de}/help/book/index.html (100%) rename lang/{de_utf8 => de}/help/book/mods.html (100%) rename lang/{de_utf8 => de}/help/book/numberingtype.html (100%) rename lang/{de_utf8 => de}/help/book/summary.html (100%) rename lang/{en_utf8 => en}/help/book/customtitles.html (100%) rename lang/{en_utf8 => en}/help/book/disableprinting.html (100%) rename lang/{en_utf8 => en}/help/book/edit.html (100%) rename lang/{en_utf8 => en}/help/book/faq.html (100%) rename lang/{en_utf8 => en}/help/book/import.html (100%) rename lang/{en_utf8 => en}/help/book/index.html (100%) rename lang/{en_utf8 => en}/help/book/mods.html (100%) rename lang/{en_utf8 => en}/help/book/numberingtype.html (100%) rename lang/{en_utf8 => en}/help/book/summary.html (100%) delete mode 100644 lang/en_utf8/book.php rename lang/{es_utf8 => es}/book.php (100%) rename lang/{fi_utf8 => fi}/book.php (100%) rename lang/{fi_utf8 => fi}/help/book/customtitles.html (100%) rename lang/{fi_utf8 => fi}/help/book/disableprinting.html (100%) rename lang/{fi_utf8 => fi}/help/book/edit.html (100%) rename lang/{fi_utf8 => fi}/help/book/faq.html (100%) rename lang/{fi_utf8 => fi}/help/book/import.html (100%) rename lang/{fi_utf8 => fi}/help/book/index.html (100%) rename lang/{fi_utf8 => fi}/help/book/mods.html (100%) rename lang/{fi_utf8 => fi}/help/book/numberingtype.html (100%) rename lang/{fi_utf8 => fi}/help/book/summary.html (100%) rename lang/{fr_utf8 => fr}/book.php (100%) rename lang/{id_utf8 => id}/book.php (100%) rename lang/{id_utf8 => id}/help/book/faq.html (100%) rename lang/{id_utf8 => id}/help/book/index.html (100%) rename lang/{id_utf8 => id}/help/book/mods.html (100%) rename lang/{id_utf8 => id}/help/book/numberingtype.html (100%) rename lang/{id_utf8 => id}/help/book/summary.html (100%) rename lang/{it_utf8 => it}/book.php (100%) rename lang/{it_utf8 => it}/help/book/customtitles.html (100%) rename lang/{it_utf8 => it}/help/book/disableprinting.html (100%) rename lang/{it_utf8 => it}/help/book/edit.html (100%) rename lang/{it_utf8 => it}/help/book/faq.html (100%) rename lang/{it_utf8 => it}/help/book/import.html (100%) rename lang/{it_utf8 => it}/help/book/index.html (100%) rename lang/{it_utf8 => it}/help/book/mods.html (100%) rename lang/{it_utf8 => it}/help/book/numberingtype.html (100%) rename lang/{it_utf8 => it}/help/book/summary.html (100%) rename lang/{ja_utf8 => ja}/book.php (100%) rename lang/{ja_utf8 => ja}/help/book/customtitles.html (100%) rename lang/{ja_utf8 => ja}/help/book/disableprinting.html (100%) rename lang/{ja_utf8 => ja}/help/book/edit.html (100%) rename lang/{ja_utf8 => ja}/help/book/faq.html (100%) rename lang/{ja_utf8 => ja}/help/book/import.html (100%) rename lang/{ja_utf8 => ja}/help/book/index.html (100%) rename lang/{ja_utf8 => ja}/help/book/mods.html (100%) rename lang/{ja_utf8 => ja}/help/book/numberingtype.html (100%) rename lang/{ja_utf8 => ja}/help/book/summary.html (100%) rename lang/{nl_utf8 => nl}/book.php (100%) rename lang/{nl_utf8 => nl}/help/book/customtitles.html (100%) rename lang/{nl_utf8 => nl}/help/book/disableprinting.html (100%) rename lang/{nl_utf8 => nl}/help/book/edit.html (100%) rename lang/{nl_utf8 => nl}/help/book/faq.html (100%) rename lang/{nl_utf8 => nl}/help/book/import.html (100%) rename lang/{nl_utf8 => nl}/help/book/index.html (100%) rename lang/{nl_utf8 => nl}/help/book/mods.html (100%) rename lang/{nl_utf8 => nl}/help/book/numberingtype.html (100%) rename lang/{nl_utf8 => nl}/help/book/summary.html (100%) rename lang/{pl_utf8 => pl}/book.php (100%) rename lang/{pl_utf8 => pl}/help/book/customtitles.html (100%) rename lang/{pl_utf8 => pl}/help/book/disableprinting.html (100%) rename lang/{pl_utf8 => pl}/help/book/edit.html (100%) rename lang/{pl_utf8 => pl}/help/book/faq.html (100%) rename lang/{pl_utf8 => pl}/help/book/import.html (100%) rename lang/{pl_utf8 => pl}/help/book/index.html (100%) rename lang/{pl_utf8 => pl}/help/book/mods.html (100%) rename lang/{pl_utf8 => pl}/help/book/numberingtype.html (100%) rename lang/{pl_utf8 => pl}/help/book/summary.html (100%) rename lang/{pt_br_utf8 => pt_br}/book.php (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/customtitles.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/disableprinting.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/edit.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/faq.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/import.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/index.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/mods.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/numberingtype.html (100%) rename lang/{pt_br_utf8 => pt_br}/help/book/summary.html (100%) rename lang/{sk_utf8 => sk}/book.php (100%) rename lang/{sk_utf8 => sk}/help/book/customtitles.html (100%) rename lang/{sk_utf8 => sk}/help/book/disableprinting.html (100%) rename lang/{sk_utf8 => sk}/help/book/edit.html (100%) rename lang/{sk_utf8 => sk}/help/book/faq.html (100%) rename lang/{sk_utf8 => sk}/help/book/import.html (100%) rename lang/{sk_utf8 => sk}/help/book/index.html (100%) rename lang/{sk_utf8 => sk}/help/book/mods.html (100%) rename lang/{sk_utf8 => sk}/help/book/numberingtype.html (100%) rename lang/{sk_utf8 => sk}/help/book/summary.html (100%) rename lang/{sl_utf8 => sl}/book.php (100%) rename lang/{sl_utf8 => sl}/help/book/customtitles.html (100%) rename lang/{sl_utf8 => sl}/help/book/disableprinting.html (100%) rename lang/{sl_utf8 => sl}/help/book/edit.html (100%) rename lang/{sl_utf8 => sl}/help/book/faq.html (100%) rename lang/{sl_utf8 => sl}/help/book/import.html (100%) rename lang/{sl_utf8 => sl}/help/book/index.html (100%) rename lang/{sl_utf8 => sl}/help/book/mods.html (100%) rename lang/{sl_utf8 => sl}/help/book/numberingtype.html (100%) rename lang/{sl_utf8 => sl}/help/book/summary.html (100%) rename lang/{sv_utf8 => sv}/book.php (100%) rename lang/{sv_utf8 => sv}/help/book/customtitles.html (100%) rename lang/{sv_utf8 => sv}/help/book/disableprinting.html (100%) rename lang/{sv_utf8 => sv}/help/book/edit.html (100%) rename lang/{sv_utf8 => sv}/help/book/faq.html (100%) rename lang/{sv_utf8 => sv}/help/book/import.html (100%) rename lang/{sv_utf8 => sv}/help/book/index.html (100%) rename lang/{sv_utf8 => sv}/help/book/mods.html (100%) rename lang/{sv_utf8 => sv}/help/book/numberingtype.html (100%) rename lang/{sv_utf8 => sv}/help/book/summary.html (100%) diff --git a/lang/be_utf8/book.php b/lang/be/book.php similarity index 100% rename from lang/be_utf8/book.php rename to lang/be/book.php diff --git a/lang/be_utf8/help/book/customtitles.html b/lang/be/help/book/customtitles.html similarity index 100% rename from lang/be_utf8/help/book/customtitles.html rename to lang/be/help/book/customtitles.html diff --git a/lang/be_utf8/help/book/disableprinting.html b/lang/be/help/book/disableprinting.html similarity index 100% rename from lang/be_utf8/help/book/disableprinting.html rename to lang/be/help/book/disableprinting.html diff --git a/lang/be_utf8/help/book/edit.html b/lang/be/help/book/edit.html similarity index 100% rename from lang/be_utf8/help/book/edit.html rename to lang/be/help/book/edit.html diff --git a/lang/be_utf8/help/book/faq.html b/lang/be/help/book/faq.html similarity index 100% rename from lang/be_utf8/help/book/faq.html rename to lang/be/help/book/faq.html diff --git a/lang/be_utf8/help/book/import.html b/lang/be/help/book/import.html similarity index 100% rename from lang/be_utf8/help/book/import.html rename to lang/be/help/book/import.html diff --git a/lang/be_utf8/help/book/index.html b/lang/be/help/book/index.html similarity index 100% rename from lang/be_utf8/help/book/index.html rename to lang/be/help/book/index.html diff --git a/lang/be_utf8/help/book/mods.html b/lang/be/help/book/mods.html similarity index 100% rename from lang/be_utf8/help/book/mods.html rename to lang/be/help/book/mods.html diff --git a/lang/be_utf8/help/book/numberingtype.html b/lang/be/help/book/numberingtype.html similarity index 100% rename from lang/be_utf8/help/book/numberingtype.html rename to lang/be/help/book/numberingtype.html diff --git a/lang/be_utf8/help/book/summary.html b/lang/be/help/book/summary.html similarity index 100% rename from lang/be_utf8/help/book/summary.html rename to lang/be/help/book/summary.html diff --git a/lang/ca_utf8/book.php b/lang/ca/book.php similarity index 100% rename from lang/ca_utf8/book.php rename to lang/ca/book.php diff --git a/lang/ca_utf8/help/book/customtitles.html b/lang/ca/help/book/customtitles.html similarity index 100% rename from lang/ca_utf8/help/book/customtitles.html rename to lang/ca/help/book/customtitles.html diff --git a/lang/ca_utf8/help/book/disableprinting.html b/lang/ca/help/book/disableprinting.html similarity index 100% rename from lang/ca_utf8/help/book/disableprinting.html rename to lang/ca/help/book/disableprinting.html diff --git a/lang/ca_utf8/help/book/edit.html b/lang/ca/help/book/edit.html similarity index 100% rename from lang/ca_utf8/help/book/edit.html rename to lang/ca/help/book/edit.html diff --git a/lang/ca_utf8/help/book/faq.html b/lang/ca/help/book/faq.html similarity index 100% rename from lang/ca_utf8/help/book/faq.html rename to lang/ca/help/book/faq.html diff --git a/lang/ca_utf8/help/book/import.html b/lang/ca/help/book/import.html similarity index 100% rename from lang/ca_utf8/help/book/import.html rename to lang/ca/help/book/import.html diff --git a/lang/ca_utf8/help/book/index.html b/lang/ca/help/book/index.html similarity index 100% rename from lang/ca_utf8/help/book/index.html rename to lang/ca/help/book/index.html diff --git a/lang/ca_utf8/help/book/mods.html b/lang/ca/help/book/mods.html similarity index 100% rename from lang/ca_utf8/help/book/mods.html rename to lang/ca/help/book/mods.html diff --git a/lang/ca_utf8/help/book/numberingtype.html b/lang/ca/help/book/numberingtype.html similarity index 100% rename from lang/ca_utf8/help/book/numberingtype.html rename to lang/ca/help/book/numberingtype.html diff --git a/lang/ca_utf8/help/book/summary.html b/lang/ca/help/book/summary.html similarity index 100% rename from lang/ca_utf8/help/book/summary.html rename to lang/ca/help/book/summary.html diff --git a/lang/cs_utf8/book.php b/lang/cs/book.php similarity index 100% rename from lang/cs_utf8/book.php rename to lang/cs/book.php diff --git a/lang/cs_utf8/help/book/customtitles.html b/lang/cs/help/book/customtitles.html similarity index 100% rename from lang/cs_utf8/help/book/customtitles.html rename to lang/cs/help/book/customtitles.html diff --git a/lang/cs_utf8/help/book/disableprinting.html b/lang/cs/help/book/disableprinting.html similarity index 100% rename from lang/cs_utf8/help/book/disableprinting.html rename to lang/cs/help/book/disableprinting.html diff --git a/lang/cs_utf8/help/book/edit.html b/lang/cs/help/book/edit.html similarity index 100% rename from lang/cs_utf8/help/book/edit.html rename to lang/cs/help/book/edit.html diff --git a/lang/cs_utf8/help/book/faq.html b/lang/cs/help/book/faq.html similarity index 100% rename from lang/cs_utf8/help/book/faq.html rename to lang/cs/help/book/faq.html diff --git a/lang/cs_utf8/help/book/import.html b/lang/cs/help/book/import.html similarity index 100% rename from lang/cs_utf8/help/book/import.html rename to lang/cs/help/book/import.html diff --git a/lang/cs_utf8/help/book/index.html b/lang/cs/help/book/index.html similarity index 100% rename from lang/cs_utf8/help/book/index.html rename to lang/cs/help/book/index.html diff --git a/lang/cs_utf8/help/book/mods.html b/lang/cs/help/book/mods.html similarity index 100% rename from lang/cs_utf8/help/book/mods.html rename to lang/cs/help/book/mods.html diff --git a/lang/cs_utf8/help/book/numberingtype.html b/lang/cs/help/book/numberingtype.html similarity index 100% rename from lang/cs_utf8/help/book/numberingtype.html rename to lang/cs/help/book/numberingtype.html diff --git a/lang/cs_utf8/help/book/summary.html b/lang/cs/help/book/summary.html similarity index 100% rename from lang/cs_utf8/help/book/summary.html rename to lang/cs/help/book/summary.html diff --git a/lang/de_utf8/book.php b/lang/de/book.php similarity index 100% rename from lang/de_utf8/book.php rename to lang/de/book.php diff --git a/lang/de_utf8/help/book/customtitles.html b/lang/de/help/book/customtitles.html similarity index 100% rename from lang/de_utf8/help/book/customtitles.html rename to lang/de/help/book/customtitles.html diff --git a/lang/de_utf8/help/book/disableprinting.html b/lang/de/help/book/disableprinting.html similarity index 100% rename from lang/de_utf8/help/book/disableprinting.html rename to lang/de/help/book/disableprinting.html diff --git a/lang/de_utf8/help/book/edit.html b/lang/de/help/book/edit.html similarity index 100% rename from lang/de_utf8/help/book/edit.html rename to lang/de/help/book/edit.html diff --git a/lang/de_utf8/help/book/faq.html b/lang/de/help/book/faq.html similarity index 100% rename from lang/de_utf8/help/book/faq.html rename to lang/de/help/book/faq.html diff --git a/lang/de_utf8/help/book/import.html b/lang/de/help/book/import.html similarity index 100% rename from lang/de_utf8/help/book/import.html rename to lang/de/help/book/import.html diff --git a/lang/de_utf8/help/book/index.html b/lang/de/help/book/index.html similarity index 100% rename from lang/de_utf8/help/book/index.html rename to lang/de/help/book/index.html diff --git a/lang/de_utf8/help/book/mods.html b/lang/de/help/book/mods.html similarity index 100% rename from lang/de_utf8/help/book/mods.html rename to lang/de/help/book/mods.html diff --git a/lang/de_utf8/help/book/numberingtype.html b/lang/de/help/book/numberingtype.html similarity index 100% rename from lang/de_utf8/help/book/numberingtype.html rename to lang/de/help/book/numberingtype.html diff --git a/lang/de_utf8/help/book/summary.html b/lang/de/help/book/summary.html similarity index 100% rename from lang/de_utf8/help/book/summary.html rename to lang/de/help/book/summary.html diff --git a/lang/en_utf8/help/book/customtitles.html b/lang/en/help/book/customtitles.html similarity index 100% rename from lang/en_utf8/help/book/customtitles.html rename to lang/en/help/book/customtitles.html diff --git a/lang/en_utf8/help/book/disableprinting.html b/lang/en/help/book/disableprinting.html similarity index 100% rename from lang/en_utf8/help/book/disableprinting.html rename to lang/en/help/book/disableprinting.html diff --git a/lang/en_utf8/help/book/edit.html b/lang/en/help/book/edit.html similarity index 100% rename from lang/en_utf8/help/book/edit.html rename to lang/en/help/book/edit.html diff --git a/lang/en_utf8/help/book/faq.html b/lang/en/help/book/faq.html similarity index 100% rename from lang/en_utf8/help/book/faq.html rename to lang/en/help/book/faq.html diff --git a/lang/en_utf8/help/book/import.html b/lang/en/help/book/import.html similarity index 100% rename from lang/en_utf8/help/book/import.html rename to lang/en/help/book/import.html diff --git a/lang/en_utf8/help/book/index.html b/lang/en/help/book/index.html similarity index 100% rename from lang/en_utf8/help/book/index.html rename to lang/en/help/book/index.html diff --git a/lang/en_utf8/help/book/mods.html b/lang/en/help/book/mods.html similarity index 100% rename from lang/en_utf8/help/book/mods.html rename to lang/en/help/book/mods.html diff --git a/lang/en_utf8/help/book/numberingtype.html b/lang/en/help/book/numberingtype.html similarity index 100% rename from lang/en_utf8/help/book/numberingtype.html rename to lang/en/help/book/numberingtype.html diff --git a/lang/en_utf8/help/book/summary.html b/lang/en/help/book/summary.html similarity index 100% rename from lang/en_utf8/help/book/summary.html rename to lang/en/help/book/summary.html diff --git a/lang/en_utf8/book.php b/lang/en_utf8/book.php deleted file mode 100644 index 5a7e88cc6ab..00000000000 --- a/lang/en_utf8/book.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -$string['modulename'] = 'Book'; -$string['modulenameplural'] = 'Books'; - -$string['toc'] = 'Table of Contents'; -$string['tocwidth'] = 'Select width of the Table of Contents for all books.'; -$string['book_tocwidth'] = 'Table of Contents width'; -$string['faq'] = 'Book FAQ'; - -$string['disableprinting'] = 'Disable Printing'; -$string['customtitles'] = 'Custom Titles'; - -$string['editingchapter'] = 'Editing chapter'; -$string['chaptertitle'] = 'Chapter Title'; -$string['content'] = 'Content'; -$string['subchapter'] = 'Subchapter'; - -$string['numbering'] = 'Chapter Numbering'; -$string['numbering0'] = 'None'; -$string['numbering1'] = 'Numbers'; -$string['numbering2'] = 'Bullets'; -$string['numbering3'] = 'Indented'; - -$string['chapterscount'] = 'Chapters'; - -$string['addafter'] = 'Add new chapter'; -$string['confchapterdelete'] = 'Do you really want to delete this chapter?'; -$string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?'; - -$string['generateimscp'] = 'Generate IMS content package'; -$string['printbook'] = 'Print Complete Book'; -$string['printchapter'] = 'Print This Chapter'; -$string['printdate'] = 'Date'; -$string['printedby'] = 'Printed by'; -$string['top'] = 'top'; - -$string['navprev'] = 'Previous'; -$string['navnext'] = 'Next'; -$string['navexit'] = 'Exit Book'; - -$string['importingchapters'] = 'Importing chapters into book'; -$string['import'] = 'Import'; -$string['doimport'] = 'Import'; -$string['doexport'] = 'Export'; -$string['importing'] = 'Importing'; -$string['relinking'] = 'Relinking'; -$string['importinfo'] = 'Import selected HTML file or directory.<br />Chapters are sorted alphabetically using file names.<br />Files named \'sub_*.*\' are always imported as subchapters.'; -$string['maindirectory'] = 'Main directory'; -$string['fileordir'] = 'File or directory'; - -$string['book:read'] = 'Read book'; -$string['book:edit'] = 'Edit book chapters'; -$string['book:viewhiddenchapters'] = 'View hidden book chapters'; -$string['book:import'] = 'Import chapters'; -$string['book:print'] = 'Print book'; -$string['book:exportimscp'] = 'Export book as IMS content package'; diff --git a/lang/es_utf8/book.php b/lang/es/book.php similarity index 100% rename from lang/es_utf8/book.php rename to lang/es/book.php diff --git a/lang/fi_utf8/book.php b/lang/fi/book.php similarity index 100% rename from lang/fi_utf8/book.php rename to lang/fi/book.php diff --git a/lang/fi_utf8/help/book/customtitles.html b/lang/fi/help/book/customtitles.html similarity index 100% rename from lang/fi_utf8/help/book/customtitles.html rename to lang/fi/help/book/customtitles.html diff --git a/lang/fi_utf8/help/book/disableprinting.html b/lang/fi/help/book/disableprinting.html similarity index 100% rename from lang/fi_utf8/help/book/disableprinting.html rename to lang/fi/help/book/disableprinting.html diff --git a/lang/fi_utf8/help/book/edit.html b/lang/fi/help/book/edit.html similarity index 100% rename from lang/fi_utf8/help/book/edit.html rename to lang/fi/help/book/edit.html diff --git a/lang/fi_utf8/help/book/faq.html b/lang/fi/help/book/faq.html similarity index 100% rename from lang/fi_utf8/help/book/faq.html rename to lang/fi/help/book/faq.html diff --git a/lang/fi_utf8/help/book/import.html b/lang/fi/help/book/import.html similarity index 100% rename from lang/fi_utf8/help/book/import.html rename to lang/fi/help/book/import.html diff --git a/lang/fi_utf8/help/book/index.html b/lang/fi/help/book/index.html similarity index 100% rename from lang/fi_utf8/help/book/index.html rename to lang/fi/help/book/index.html diff --git a/lang/fi_utf8/help/book/mods.html b/lang/fi/help/book/mods.html similarity index 100% rename from lang/fi_utf8/help/book/mods.html rename to lang/fi/help/book/mods.html diff --git a/lang/fi_utf8/help/book/numberingtype.html b/lang/fi/help/book/numberingtype.html similarity index 100% rename from lang/fi_utf8/help/book/numberingtype.html rename to lang/fi/help/book/numberingtype.html diff --git a/lang/fi_utf8/help/book/summary.html b/lang/fi/help/book/summary.html similarity index 100% rename from lang/fi_utf8/help/book/summary.html rename to lang/fi/help/book/summary.html diff --git a/lang/fr_utf8/book.php b/lang/fr/book.php similarity index 100% rename from lang/fr_utf8/book.php rename to lang/fr/book.php diff --git a/lang/id_utf8/book.php b/lang/id/book.php similarity index 100% rename from lang/id_utf8/book.php rename to lang/id/book.php diff --git a/lang/id_utf8/help/book/faq.html b/lang/id/help/book/faq.html similarity index 100% rename from lang/id_utf8/help/book/faq.html rename to lang/id/help/book/faq.html diff --git a/lang/id_utf8/help/book/index.html b/lang/id/help/book/index.html similarity index 100% rename from lang/id_utf8/help/book/index.html rename to lang/id/help/book/index.html diff --git a/lang/id_utf8/help/book/mods.html b/lang/id/help/book/mods.html similarity index 100% rename from lang/id_utf8/help/book/mods.html rename to lang/id/help/book/mods.html diff --git a/lang/id_utf8/help/book/numberingtype.html b/lang/id/help/book/numberingtype.html similarity index 100% rename from lang/id_utf8/help/book/numberingtype.html rename to lang/id/help/book/numberingtype.html diff --git a/lang/id_utf8/help/book/summary.html b/lang/id/help/book/summary.html similarity index 100% rename from lang/id_utf8/help/book/summary.html rename to lang/id/help/book/summary.html diff --git a/lang/it_utf8/book.php b/lang/it/book.php similarity index 100% rename from lang/it_utf8/book.php rename to lang/it/book.php diff --git a/lang/it_utf8/help/book/customtitles.html b/lang/it/help/book/customtitles.html similarity index 100% rename from lang/it_utf8/help/book/customtitles.html rename to lang/it/help/book/customtitles.html diff --git a/lang/it_utf8/help/book/disableprinting.html b/lang/it/help/book/disableprinting.html similarity index 100% rename from lang/it_utf8/help/book/disableprinting.html rename to lang/it/help/book/disableprinting.html diff --git a/lang/it_utf8/help/book/edit.html b/lang/it/help/book/edit.html similarity index 100% rename from lang/it_utf8/help/book/edit.html rename to lang/it/help/book/edit.html diff --git a/lang/it_utf8/help/book/faq.html b/lang/it/help/book/faq.html similarity index 100% rename from lang/it_utf8/help/book/faq.html rename to lang/it/help/book/faq.html diff --git a/lang/it_utf8/help/book/import.html b/lang/it/help/book/import.html similarity index 100% rename from lang/it_utf8/help/book/import.html rename to lang/it/help/book/import.html diff --git a/lang/it_utf8/help/book/index.html b/lang/it/help/book/index.html similarity index 100% rename from lang/it_utf8/help/book/index.html rename to lang/it/help/book/index.html diff --git a/lang/it_utf8/help/book/mods.html b/lang/it/help/book/mods.html similarity index 100% rename from lang/it_utf8/help/book/mods.html rename to lang/it/help/book/mods.html diff --git a/lang/it_utf8/help/book/numberingtype.html b/lang/it/help/book/numberingtype.html similarity index 100% rename from lang/it_utf8/help/book/numberingtype.html rename to lang/it/help/book/numberingtype.html diff --git a/lang/it_utf8/help/book/summary.html b/lang/it/help/book/summary.html similarity index 100% rename from lang/it_utf8/help/book/summary.html rename to lang/it/help/book/summary.html diff --git a/lang/ja_utf8/book.php b/lang/ja/book.php similarity index 100% rename from lang/ja_utf8/book.php rename to lang/ja/book.php diff --git a/lang/ja_utf8/help/book/customtitles.html b/lang/ja/help/book/customtitles.html similarity index 100% rename from lang/ja_utf8/help/book/customtitles.html rename to lang/ja/help/book/customtitles.html diff --git a/lang/ja_utf8/help/book/disableprinting.html b/lang/ja/help/book/disableprinting.html similarity index 100% rename from lang/ja_utf8/help/book/disableprinting.html rename to lang/ja/help/book/disableprinting.html diff --git a/lang/ja_utf8/help/book/edit.html b/lang/ja/help/book/edit.html similarity index 100% rename from lang/ja_utf8/help/book/edit.html rename to lang/ja/help/book/edit.html diff --git a/lang/ja_utf8/help/book/faq.html b/lang/ja/help/book/faq.html similarity index 100% rename from lang/ja_utf8/help/book/faq.html rename to lang/ja/help/book/faq.html diff --git a/lang/ja_utf8/help/book/import.html b/lang/ja/help/book/import.html similarity index 100% rename from lang/ja_utf8/help/book/import.html rename to lang/ja/help/book/import.html diff --git a/lang/ja_utf8/help/book/index.html b/lang/ja/help/book/index.html similarity index 100% rename from lang/ja_utf8/help/book/index.html rename to lang/ja/help/book/index.html diff --git a/lang/ja_utf8/help/book/mods.html b/lang/ja/help/book/mods.html similarity index 100% rename from lang/ja_utf8/help/book/mods.html rename to lang/ja/help/book/mods.html diff --git a/lang/ja_utf8/help/book/numberingtype.html b/lang/ja/help/book/numberingtype.html similarity index 100% rename from lang/ja_utf8/help/book/numberingtype.html rename to lang/ja/help/book/numberingtype.html diff --git a/lang/ja_utf8/help/book/summary.html b/lang/ja/help/book/summary.html similarity index 100% rename from lang/ja_utf8/help/book/summary.html rename to lang/ja/help/book/summary.html diff --git a/lang/nl_utf8/book.php b/lang/nl/book.php similarity index 100% rename from lang/nl_utf8/book.php rename to lang/nl/book.php diff --git a/lang/nl_utf8/help/book/customtitles.html b/lang/nl/help/book/customtitles.html similarity index 100% rename from lang/nl_utf8/help/book/customtitles.html rename to lang/nl/help/book/customtitles.html diff --git a/lang/nl_utf8/help/book/disableprinting.html b/lang/nl/help/book/disableprinting.html similarity index 100% rename from lang/nl_utf8/help/book/disableprinting.html rename to lang/nl/help/book/disableprinting.html diff --git a/lang/nl_utf8/help/book/edit.html b/lang/nl/help/book/edit.html similarity index 100% rename from lang/nl_utf8/help/book/edit.html rename to lang/nl/help/book/edit.html diff --git a/lang/nl_utf8/help/book/faq.html b/lang/nl/help/book/faq.html similarity index 100% rename from lang/nl_utf8/help/book/faq.html rename to lang/nl/help/book/faq.html diff --git a/lang/nl_utf8/help/book/import.html b/lang/nl/help/book/import.html similarity index 100% rename from lang/nl_utf8/help/book/import.html rename to lang/nl/help/book/import.html diff --git a/lang/nl_utf8/help/book/index.html b/lang/nl/help/book/index.html similarity index 100% rename from lang/nl_utf8/help/book/index.html rename to lang/nl/help/book/index.html diff --git a/lang/nl_utf8/help/book/mods.html b/lang/nl/help/book/mods.html similarity index 100% rename from lang/nl_utf8/help/book/mods.html rename to lang/nl/help/book/mods.html diff --git a/lang/nl_utf8/help/book/numberingtype.html b/lang/nl/help/book/numberingtype.html similarity index 100% rename from lang/nl_utf8/help/book/numberingtype.html rename to lang/nl/help/book/numberingtype.html diff --git a/lang/nl_utf8/help/book/summary.html b/lang/nl/help/book/summary.html similarity index 100% rename from lang/nl_utf8/help/book/summary.html rename to lang/nl/help/book/summary.html diff --git a/lang/pl_utf8/book.php b/lang/pl/book.php similarity index 100% rename from lang/pl_utf8/book.php rename to lang/pl/book.php diff --git a/lang/pl_utf8/help/book/customtitles.html b/lang/pl/help/book/customtitles.html similarity index 100% rename from lang/pl_utf8/help/book/customtitles.html rename to lang/pl/help/book/customtitles.html diff --git a/lang/pl_utf8/help/book/disableprinting.html b/lang/pl/help/book/disableprinting.html similarity index 100% rename from lang/pl_utf8/help/book/disableprinting.html rename to lang/pl/help/book/disableprinting.html diff --git a/lang/pl_utf8/help/book/edit.html b/lang/pl/help/book/edit.html similarity index 100% rename from lang/pl_utf8/help/book/edit.html rename to lang/pl/help/book/edit.html diff --git a/lang/pl_utf8/help/book/faq.html b/lang/pl/help/book/faq.html similarity index 100% rename from lang/pl_utf8/help/book/faq.html rename to lang/pl/help/book/faq.html diff --git a/lang/pl_utf8/help/book/import.html b/lang/pl/help/book/import.html similarity index 100% rename from lang/pl_utf8/help/book/import.html rename to lang/pl/help/book/import.html diff --git a/lang/pl_utf8/help/book/index.html b/lang/pl/help/book/index.html similarity index 100% rename from lang/pl_utf8/help/book/index.html rename to lang/pl/help/book/index.html diff --git a/lang/pl_utf8/help/book/mods.html b/lang/pl/help/book/mods.html similarity index 100% rename from lang/pl_utf8/help/book/mods.html rename to lang/pl/help/book/mods.html diff --git a/lang/pl_utf8/help/book/numberingtype.html b/lang/pl/help/book/numberingtype.html similarity index 100% rename from lang/pl_utf8/help/book/numberingtype.html rename to lang/pl/help/book/numberingtype.html diff --git a/lang/pl_utf8/help/book/summary.html b/lang/pl/help/book/summary.html similarity index 100% rename from lang/pl_utf8/help/book/summary.html rename to lang/pl/help/book/summary.html diff --git a/lang/pt_br_utf8/book.php b/lang/pt_br/book.php similarity index 100% rename from lang/pt_br_utf8/book.php rename to lang/pt_br/book.php diff --git a/lang/pt_br_utf8/help/book/customtitles.html b/lang/pt_br/help/book/customtitles.html similarity index 100% rename from lang/pt_br_utf8/help/book/customtitles.html rename to lang/pt_br/help/book/customtitles.html diff --git a/lang/pt_br_utf8/help/book/disableprinting.html b/lang/pt_br/help/book/disableprinting.html similarity index 100% rename from lang/pt_br_utf8/help/book/disableprinting.html rename to lang/pt_br/help/book/disableprinting.html diff --git a/lang/pt_br_utf8/help/book/edit.html b/lang/pt_br/help/book/edit.html similarity index 100% rename from lang/pt_br_utf8/help/book/edit.html rename to lang/pt_br/help/book/edit.html diff --git a/lang/pt_br_utf8/help/book/faq.html b/lang/pt_br/help/book/faq.html similarity index 100% rename from lang/pt_br_utf8/help/book/faq.html rename to lang/pt_br/help/book/faq.html diff --git a/lang/pt_br_utf8/help/book/import.html b/lang/pt_br/help/book/import.html similarity index 100% rename from lang/pt_br_utf8/help/book/import.html rename to lang/pt_br/help/book/import.html diff --git a/lang/pt_br_utf8/help/book/index.html b/lang/pt_br/help/book/index.html similarity index 100% rename from lang/pt_br_utf8/help/book/index.html rename to lang/pt_br/help/book/index.html diff --git a/lang/pt_br_utf8/help/book/mods.html b/lang/pt_br/help/book/mods.html similarity index 100% rename from lang/pt_br_utf8/help/book/mods.html rename to lang/pt_br/help/book/mods.html diff --git a/lang/pt_br_utf8/help/book/numberingtype.html b/lang/pt_br/help/book/numberingtype.html similarity index 100% rename from lang/pt_br_utf8/help/book/numberingtype.html rename to lang/pt_br/help/book/numberingtype.html diff --git a/lang/pt_br_utf8/help/book/summary.html b/lang/pt_br/help/book/summary.html similarity index 100% rename from lang/pt_br_utf8/help/book/summary.html rename to lang/pt_br/help/book/summary.html diff --git a/lang/sk_utf8/book.php b/lang/sk/book.php similarity index 100% rename from lang/sk_utf8/book.php rename to lang/sk/book.php diff --git a/lang/sk_utf8/help/book/customtitles.html b/lang/sk/help/book/customtitles.html similarity index 100% rename from lang/sk_utf8/help/book/customtitles.html rename to lang/sk/help/book/customtitles.html diff --git a/lang/sk_utf8/help/book/disableprinting.html b/lang/sk/help/book/disableprinting.html similarity index 100% rename from lang/sk_utf8/help/book/disableprinting.html rename to lang/sk/help/book/disableprinting.html diff --git a/lang/sk_utf8/help/book/edit.html b/lang/sk/help/book/edit.html similarity index 100% rename from lang/sk_utf8/help/book/edit.html rename to lang/sk/help/book/edit.html diff --git a/lang/sk_utf8/help/book/faq.html b/lang/sk/help/book/faq.html similarity index 100% rename from lang/sk_utf8/help/book/faq.html rename to lang/sk/help/book/faq.html diff --git a/lang/sk_utf8/help/book/import.html b/lang/sk/help/book/import.html similarity index 100% rename from lang/sk_utf8/help/book/import.html rename to lang/sk/help/book/import.html diff --git a/lang/sk_utf8/help/book/index.html b/lang/sk/help/book/index.html similarity index 100% rename from lang/sk_utf8/help/book/index.html rename to lang/sk/help/book/index.html diff --git a/lang/sk_utf8/help/book/mods.html b/lang/sk/help/book/mods.html similarity index 100% rename from lang/sk_utf8/help/book/mods.html rename to lang/sk/help/book/mods.html diff --git a/lang/sk_utf8/help/book/numberingtype.html b/lang/sk/help/book/numberingtype.html similarity index 100% rename from lang/sk_utf8/help/book/numberingtype.html rename to lang/sk/help/book/numberingtype.html diff --git a/lang/sk_utf8/help/book/summary.html b/lang/sk/help/book/summary.html similarity index 100% rename from lang/sk_utf8/help/book/summary.html rename to lang/sk/help/book/summary.html diff --git a/lang/sl_utf8/book.php b/lang/sl/book.php similarity index 100% rename from lang/sl_utf8/book.php rename to lang/sl/book.php diff --git a/lang/sl_utf8/help/book/customtitles.html b/lang/sl/help/book/customtitles.html similarity index 100% rename from lang/sl_utf8/help/book/customtitles.html rename to lang/sl/help/book/customtitles.html diff --git a/lang/sl_utf8/help/book/disableprinting.html b/lang/sl/help/book/disableprinting.html similarity index 100% rename from lang/sl_utf8/help/book/disableprinting.html rename to lang/sl/help/book/disableprinting.html diff --git a/lang/sl_utf8/help/book/edit.html b/lang/sl/help/book/edit.html similarity index 100% rename from lang/sl_utf8/help/book/edit.html rename to lang/sl/help/book/edit.html diff --git a/lang/sl_utf8/help/book/faq.html b/lang/sl/help/book/faq.html similarity index 100% rename from lang/sl_utf8/help/book/faq.html rename to lang/sl/help/book/faq.html diff --git a/lang/sl_utf8/help/book/import.html b/lang/sl/help/book/import.html similarity index 100% rename from lang/sl_utf8/help/book/import.html rename to lang/sl/help/book/import.html diff --git a/lang/sl_utf8/help/book/index.html b/lang/sl/help/book/index.html similarity index 100% rename from lang/sl_utf8/help/book/index.html rename to lang/sl/help/book/index.html diff --git a/lang/sl_utf8/help/book/mods.html b/lang/sl/help/book/mods.html similarity index 100% rename from lang/sl_utf8/help/book/mods.html rename to lang/sl/help/book/mods.html diff --git a/lang/sl_utf8/help/book/numberingtype.html b/lang/sl/help/book/numberingtype.html similarity index 100% rename from lang/sl_utf8/help/book/numberingtype.html rename to lang/sl/help/book/numberingtype.html diff --git a/lang/sl_utf8/help/book/summary.html b/lang/sl/help/book/summary.html similarity index 100% rename from lang/sl_utf8/help/book/summary.html rename to lang/sl/help/book/summary.html diff --git a/lang/sv_utf8/book.php b/lang/sv/book.php similarity index 100% rename from lang/sv_utf8/book.php rename to lang/sv/book.php diff --git a/lang/sv_utf8/help/book/customtitles.html b/lang/sv/help/book/customtitles.html similarity index 100% rename from lang/sv_utf8/help/book/customtitles.html rename to lang/sv/help/book/customtitles.html diff --git a/lang/sv_utf8/help/book/disableprinting.html b/lang/sv/help/book/disableprinting.html similarity index 100% rename from lang/sv_utf8/help/book/disableprinting.html rename to lang/sv/help/book/disableprinting.html diff --git a/lang/sv_utf8/help/book/edit.html b/lang/sv/help/book/edit.html similarity index 100% rename from lang/sv_utf8/help/book/edit.html rename to lang/sv/help/book/edit.html diff --git a/lang/sv_utf8/help/book/faq.html b/lang/sv/help/book/faq.html similarity index 100% rename from lang/sv_utf8/help/book/faq.html rename to lang/sv/help/book/faq.html diff --git a/lang/sv_utf8/help/book/import.html b/lang/sv/help/book/import.html similarity index 100% rename from lang/sv_utf8/help/book/import.html rename to lang/sv/help/book/import.html diff --git a/lang/sv_utf8/help/book/index.html b/lang/sv/help/book/index.html similarity index 100% rename from lang/sv_utf8/help/book/index.html rename to lang/sv/help/book/index.html diff --git a/lang/sv_utf8/help/book/mods.html b/lang/sv/help/book/mods.html similarity index 100% rename from lang/sv_utf8/help/book/mods.html rename to lang/sv/help/book/mods.html diff --git a/lang/sv_utf8/help/book/numberingtype.html b/lang/sv/help/book/numberingtype.html similarity index 100% rename from lang/sv_utf8/help/book/numberingtype.html rename to lang/sv/help/book/numberingtype.html diff --git a/lang/sv_utf8/help/book/summary.html b/lang/sv/help/book/summary.html similarity index 100% rename from lang/sv_utf8/help/book/summary.html rename to lang/sv/help/book/summary.html From 7d7adc4d3aebffde1411d958b8f680acc1dc282f Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 13:39:46 +0100 Subject: [PATCH 040/455] updated readme --- README | 111 +++++++++++++++++++++++++++++++++++++++++++++++- README.txt | 122 ----------------------------------------------------- 2 files changed, 110 insertions(+), 123 deletions(-) delete mode 100644 README.txt diff --git a/README b/README index 347ef90930c..d8d127e0e88 100644 --- a/README +++ b/README @@ -1 +1,110 @@ -Book module for Moodle \ No newline at end of file +Book module for Moodle +Copyright (C) 2004-2010 Petr Skoda (http:skodak.org) + + +This program 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. + +This program 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: + +http:www.gnu.org/copyleft/gpl.html + + +Book module for Moodle - version 2.0dev +=============================================================================== +Created by: + Petr Skoda (skodak) - most of the coding & design + Mojmir Volf - CSS formatted printer friendly format + +Developed for Technical University of Liberec (Czech Republic). +Many ideas and code were taken from other Moodle modules and Moodle itself + +Installation: + * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins + +List of features - version 2.0: + + * easy to use - new teachers can quickly create multipage study materials + * two levels - only chapters and subchapters + * possible automatic chapter numbering + * chapters authored in build-in HTML editor (html stored in database, + images in course data) + * printing support - all chapters can be displayed on one CSS formatted page + * backup/restore with internal link preservation + * support for global searching in study materials (see contrib/search) + * import from html files (relinking of images, flash, Java applets and + relative links) + * works with MySQL and PostgreSQL databases + + +Intentionally omitted features: + + * more chapter levels - it would encourage teachers to write too much + complex and long books, better use standard standalone HTML editor and + import it as Resource. DocBook format is another suitable solution. + * TOC hiding in normal view - instead use printer friendly view + * PDF export - there is no elegant way AFAIK to convert HTML to PDF, + use virtual PDF printer or better use DocBook format for authoring + * detailed student tracking (postponed till officially supported) + * export as zipped set of HTML pages - instead use browser command + Save page as... in print view + +Future: + * I like eXe editor, I would like to improve Book in this direction ... ;-) + +CHANGELOG: +== 1.1RC1 - 2004/11/15 ======================================================= + * compatible ONLY with 1.4.2 and later !!! + * added sesskey for enhanced security + * navigation links do not enter hidden chapters + * import - correct linking when slasharguments are off + * removed coursefiles.php +== 1.1 - 2005/01/01 ======================================================= + * compatible ONLY with 1.4.3 and later! + * removed some unused searching stuff + * fixed headers in print.php +== 1.2RC - 2005/07/13 ========================================================== + * compatible with 1.5.1 + only + * improved restore + * fixed selection of directories for import + * html editor for summary + * fixed postgresql upgrade + * no need to move language packs +== 1.2 - 2006/03/11 ========================================================== + * removed 64kB page content limit in mysql + * exit button now goes to course section anchor + * chater title now in browser title bar + * added translations be and sv + * during import chapters with names "*_sub.htm?" are imported as subchapters + * deleting in import selection windows now works + * last version before transition to 1.6 +== 1.3alpha - 2006/03/12 ====================================================== + * compatible with 1.6dev only, use previous version for 1.5.x + * unicode upgrade supported - not much tested + * backup fixes - from Penny Leach, thanks! + * all languages converted to utf-8 + * moved to contrib/book_16 directory + * added proper content encoding conversion during import +== 1.4alpha - 2007/05/20 ==================================================== + * compatible with 1.8 + * export link enabled - thanks Eloy! + * no new features +== 1.5beta - 2008/08/14 ==================================================== + * compatible with 1.9.1 and above + * xhtml strict and css improvements + * formslib conversion + * capabilities implemented + * no new features +== 1.5 2009/11/11 ============================================================ + * minor cleanup + * new Slovenian language pack - thanks Mitja Podreka + * updated German Language pack - thanks Ralf Hilgenstock +== 2.0dev ============================================================ + * Moodle 2.0 conversion - no new features + +Petr diff --git a/README.txt b/README.txt deleted file mode 100644 index 6b1276b92fd..00000000000 --- a/README.txt +++ /dev/null @@ -1,122 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// // -// NOTICE OF COPYRIGHT // -// // -// Moodle - Modular Object-Oriented Dynamic Learning Environment // -// http://moodle.org // -// // -// Copyright (C) 1999-2004 Martin Dougiamas http://dougiamas.com // -// // -/////////////////////////////////////////////////////////////////////////// -// // -// Book module original code // -// Copyright (C) 2004 Petr Skoda (info@skodak.org) // -// // -/////////////////////////////////////////////////////////////////////////// -// // -// This program 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 2 of the License, or // -// (at your option) any later version. // -// // -// This program 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: // -// // -// http://www.gnu.org/copyleft/gpl.html // -// // -/////////////////////////////////////////////////////////////////////////// - -Book module for Moodle - version 1.5 (stable release) -=============================================================================== -Created by: - Petr Skoda (skodak) - most of the coding & design - Mojmir Volf - CSS formatted printer friendly format - -Developed for Technical University of Liberec (Czech Republic). -Many ideas and code were taken from other Moodle modules and Moodle itself;-) - -Installation: - * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins - -List of features - version 1.5: - - * easy to use - new teachers can quickly create multipage study materials - * two levels - only chapters and subchapters - * possible automatic chapter numbering - * chapters authored in build-in HTML editor (html stored in database, - images in course data) - * printing support - all chapters can be displayed on one CSS formatted page - * backup/restore with internal link preservation - * support for global searching in study materials (see contrib/search) - * import from html files (relinking of images, flash, Java applets and - relative links) - * works with MySQL and PostgreSQL databases - * no need to move language packs any more - - -Intentionally omitted features: - - * more chapter levels - it would encourage teachers to write too much - complex and long books, better use standard standalone HTML editor and - import it as Resource. DocBook format is another suitable solution. - * TOC hiding in normal view - instead use printer friendly view - * PDF export - there is no elegant way AFAIK to convert HTML to PDF, - use virtual PDF printer or better use DocBook format for authoring - * detailed student tracking (postponed till officially supported) - * export as zipped set of HTML pages - instead use browser command - Save page as... in print view - -Future: - * I like eXe editor, I would like to improve Book in this direction ... ;-) - -CHANGELOG: -== 1.1RC1 - 2004/11/15 ======================================================= - * compatible ONLY with 1.4.2 and later !!! - * added sesskey for enhanced security - * navigation links do not enter hidden chapters - * import - correct linking when slasharguments are off - * removed coursefiles.php -== 1.1 - 2005/01/01 ======================================================= - * compatible ONLY with 1.4.3 and later! - * removed some unused searching stuff - * fixed headers in print.php -== 1.2RC - 2005/07/13 ========================================================== - * compatible with 1.5.1 + only - * improved restore - * fixed selection of directories for import - * html editor for summary - * fixed postgresql upgrade - * no need to move language packs -== 1.2 - 2006/03/11 ========================================================== - * removed 64kB page content limit in mysql - * exit button now goes to course section anchor - * chater title now in browser title bar - * added translations be and sv - * during import chapters with names "*_sub.htm?" are imported as subchapters - * deleting in import selection windows now works - * last version before transition to 1.6 -== 1.3alpha - 2006/03/12 ====================================================== - * compatible with 1.6dev only, use previous version for 1.5.x - * unicode upgrade supported - not much tested - * backup fixes - from Penny Leach, thanks! - * all languages converted to utf-8 - * moved to contrib/book_16 directory - * added proper content encoding conversion during import -== 1.4alpha - 2007/05/20 ==================================================== - * compatible with 1.8 - * export link enabled - thanks Eloy! - * no new features -== 1.5beta - 2008/08/14 ==================================================== - * compatible with 1.9.1 and above - * xhtml strict and css improvements - * formslib conversion - * capabilities implemented - * no new features -== 1.5 2009/11/11 ============================================================ - * minor cleanup - * new Slovenian language pack - thanks Mitja Podreka - * updated German Language pack - thanks Ralf Hilgenstock - -skodak From b0d99b9384dbbaed3a051e89178735cb2ea07148 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 14:27:12 +0100 Subject: [PATCH 041/455] moving all icons to new locations --- edit.php | 2 +- import.php | 2 +- icon.gif => pix/icon.gif | Bin icon_chapter.gif => pix/icon_chapter.gif | Bin 4 files changed, 2 insertions(+), 2 deletions(-) rename icon.gif => pix/icon.gif (100%) rename icon_chapter.gif => pix/icon_chapter.gif (100%) diff --git a/edit.php b/edit.php index 393cb6be15a..1e1ffa9c99a 100644 --- a/edit.php +++ b/edit.php @@ -115,7 +115,7 @@ $navigation = build_navigation($navlinks, $cm); print_header("$course->shortname: $book->name", $course->fullname, $navigation); -$icon = '<img class="icon" src="icon_chapter.gif" alt="" /> '; +$icon = '<img class="icon" src="pix/chapter.gif" alt="" /> '; print_heading_with_help($pageheading, 'edit', 'book', $icon); $mform->display(); diff --git a/import.php b/import.php index 07a4c5ed9f8..386d854f151 100644 --- a/import.php +++ b/import.php @@ -132,7 +132,7 @@ $strdoimport = get_string('doimport', 'book'); $strchoose = get_string('choose'); $pageheading = get_string('importingchapters', 'book'); -$icon = '<img class="icon" src="icon_chapter.gif" alt="" /> '; +$icon = '<img class="icon" src="pix/chapter.gif" alt="" /> '; print_heading_with_help($pageheading, 'import', 'book', $icon); $mform->display(); diff --git a/icon.gif b/pix/icon.gif similarity index 100% rename from icon.gif rename to pix/icon.gif diff --git a/icon_chapter.gif b/pix/icon_chapter.gif similarity index 100% rename from icon_chapter.gif rename to pix/icon_chapter.gif From 3543758a9fdb50ef06401a0830f62a57ef041654 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 14:27:38 +0100 Subject: [PATCH 042/455] removing obsolete install files --- db/mysql.php | 34 -------------------------- db/postgres7.php | 63 ------------------------------------------------ 2 files changed, 97 deletions(-) delete mode 100644 db/mysql.php delete mode 100644 db/postgres7.php diff --git a/db/mysql.php b/db/mysql.php deleted file mode 100644 index 56d367748a8..00000000000 --- a/db/mysql.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -function book_upgrade($oldversion) { -/// This function does anything necessary to upgrade -/// older versions to match current functionality - - global $CFG; - - if ($oldversion < 2004060600) { - execute_sql ("ALTER TABLE {$CFG->prefix}book - CHANGE intro summary TEXT NOT NULL; - "); - } - if ($oldversion < 2004071100) { - execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters - ADD importsrc VARCHAR(255) NOT NULL DEFAULT '' AFTER timemodified; - "); - } - if ($oldversion < 2004071201) { - execute_sql ("UPDATE {$CFG->prefix}log_display - SET action = 'print' - WHERE action = 'prINT'; - "); - } - if ($oldversion < 2004072400) { - execute_sql ("ALTER TABLE {$CFG->prefix}book - ADD disableprinting TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER numbering; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book - ADD customtitles TINYINT(2) UNSIGNED NOT NULL DEFAULT '0' AFTER disableprinting; - "); - } - return true; -} diff --git a/db/postgres7.php b/db/postgres7.php deleted file mode 100644 index a1b6e7a4e3b..00000000000 --- a/db/postgres7.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php - -function book_upgrade($oldversion) { -// This function does anything necessary to upgrade -// older versions to match current functionality - - global $CFG; - - if ($oldversion < 2004060600) { - execute_sql ("ALTER TABLE {$CFG->prefix}book - CHANGE intro summary TEXT NOT NULL; - "); - } - if ($oldversion < 2004071100) { - - execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters - ADD importsrc VARCHAR(255); - "); - execute_sql ("UPDATE {$CFG->prefix}book_chapters - SET importsrc = ''; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters - ALTER importsrc SET NOT NULL; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book_chapters - ALTER importsrc SET DEFAULT ''; - "); - } - if ($oldversion < 2004071201) { - execute_sql ("UPDATE {$CFG->prefix}log_display - SET action = 'print' - WHERE action = 'prINT'; - "); - } - if ($oldversion < 2004081100) { - execute_sql ("ALTER TABLE {$CFG->prefix}book - ADD disableprinting INT2; - "); - execute_sql ("UPDATE {$CFG->prefix}book - SET disableprinting = '0'; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book - ALTER disableprinting SET NOT NULL; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book - ALTER disableprinting SET DEFAULT '0'; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book - ADD customtitles INT2; - "); - execute_sql ("UPDATE {$CFG->prefix}book - SET customtitles = '0'; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book - ALTER customtitles SET NOT NULL; - "); - execute_sql ("ALTER TABLE {$CFG->prefix}book - ALTER customtitles SET DEFAULT '0'; - "); - } - - return true; -} From 7bc1a381ccd135634cbcb498b34ebbeacca7472f Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 14:28:48 +0100 Subject: [PATCH 043/455] fixing invalid icon name --- pix/{icon_chapter.gif => chapter.gif} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename pix/{icon_chapter.gif => chapter.gif} (100%) diff --git a/pix/icon_chapter.gif b/pix/chapter.gif similarity index 100% rename from pix/icon_chapter.gif rename to pix/chapter.gif From 28d16c16e3c3cdd31e9624e06cf3557faff5bd26 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 14:39:43 +0100 Subject: [PATCH 044/455] removing cvs tags and closing php tags --- db/upgrade.php | 2 +- edit_form.php | 4 +--- import_form.php | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/db/upgrade.php b/db/upgrade.php index a85e9d8e4c3..a0eea5ebff1 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,4 +1,4 @@ -<?php //$Id: upgrade.php,v 1.6 2010/08/01 13:10:36 skodak Exp $ +<?php // This file keeps track of upgrades to // the assignment module diff --git a/edit_form.php b/edit_form.php index 93b7fa8ecad..0efb8f535bb 100644 --- a/edit_form.php +++ b/edit_form.php @@ -1,4 +1,4 @@ -<?php //$Id: edit_form.php,v 1.3 2010/08/01 13:10:37 skodak Exp $ +<?php require_once($CFG->libdir.'/formslib.php'); @@ -49,5 +49,3 @@ class book_chapter_edit_form extends moodleform { } } } - -?> diff --git a/import_form.php b/import_form.php index dbe88bd1cae..74f2a3cf838 100644 --- a/import_form.php +++ b/import_form.php @@ -1,4 +1,4 @@ -<?php //$Id: import_form.php,v 1.3 2010/08/01 13:10:37 skodak Exp $ +<?php require_once($CFG->libdir.'/formslib.php'); From 0f0ba61167d3ceea8b96dc4f0a9e9c05691acaab Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 14:56:55 +0100 Subject: [PATCH 045/455] first part of upgrade --- db/access.php | 42 ++++++++++++++------ db/install.xml | 19 +++------ db/log.php | 34 ++++++++++++++++ db/upgrade.php | 98 ++++++++++++++++++++++++++++++++++------------- db/upgradelib.php | 0 version.php | 6 +-- 6 files changed, 145 insertions(+), 54 deletions(-) create mode 100644 db/log.php create mode 100644 db/upgradelib.php diff --git a/db/access.php b/db/access.php index be2f89cc7ab..3b999f9fd25 100644 --- a/db/access.php +++ b/db/access.php @@ -1,13 +1,28 @@ <?php + +// This file is part of Moodle - http://moodle.org/ // -// Capability definitions for the assignment module. +// 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. // -// The capabilities are loaded into the database table when the module is -// installed or updated. Whenever the capability definitions are updated, -// the module version number should be bumped up. +// 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. // -// The system has four possible values for a capability: -// CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT, and inherit (not set). +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. + +/** + * Book module capability definition + * + * @package mod + * @subpackage book + * @copyright 2009-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ $mod_book_capabilities = array( @@ -18,7 +33,8 @@ $mod_book_capabilities = array( 'guest' => CAP_ALLOW, 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, ) ), @@ -27,7 +43,8 @@ $mod_book_capabilities = array( 'contextlevel' => CONTEXT_MODULE, 'legacy' => array( 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, ) ), @@ -36,7 +53,8 @@ $mod_book_capabilities = array( 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'legacy' => array( - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, ) ), @@ -45,7 +63,8 @@ $mod_book_capabilities = array( 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, 'legacy' => array( - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, ) ), @@ -56,7 +75,8 @@ $mod_book_capabilities = array( 'guest' => CAP_ALLOW, 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, ) ), diff --git a/db/install.xml b/db/install.xml index dd4ca0be9b2..f6a2bf5b916 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<XMLDB PATH="mod/book/db" VERSION="20070924" COMMENT="XMLDB file for Moodle mod/book" +<XMLDB PATH="mod/book/db" VERSION="20101208" COMMENT="XMLDB file for Moodle mod/book" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd" > @@ -8,9 +8,10 @@ <FIELDS> <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="course"/> <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="name"/> - <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="summary"/> - <FIELD NAME="summary" TYPE="text" LENGTH="medium" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="name" NEXT="numbering"/> - <FIELD NAME="numbering" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="summary" NEXT="disableprinting"/> + <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="intro"/> + <FIELD NAME="intro" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/> + <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="intro" NEXT="numbering"/> + <FIELD NAME="numbering" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="introformat" NEXT="disableprinting"/> <FIELD NAME="disableprinting" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="2" SEQUENCE="false" ENUM="false" PREVIOUS="numbering" NEXT="customtitles"/> <FIELD NAME="customtitles" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="disableprinting" NEXT="timecreated"/> <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="customtitles" NEXT="timemodified"/> @@ -38,14 +39,4 @@ </KEYS> </TABLE> </TABLES> - <STATEMENTS> - <STATEMENT NAME="insert log_display" TYPE="insert" TABLE="log_display" COMMENT="Initial insert of records on table log_display"> - <SENTENCES> - <SENTENCE TEXT="(module, action, mtable, field) VALUES ('book', 'update', 'book', 'name')" /> - <SENTENCE TEXT="(module, action, mtable, field) VALUES ('book', 'view', 'book', 'name')" /> - <SENTENCE TEXT="(module, action, mtable, field) VALUES ('book', 'view all', 'book', 'name')" /> - <SENTENCE TEXT="(module, action, mtable, field) VALUES ('book', 'print', 'book', 'name')" /> - </SENTENCES> - </STATEMENT> - </STATEMENTS> </XMLDB> diff --git a/db/log.php b/db/log.php new file mode 100644 index 00000000000..3485104842c --- /dev/null +++ b/db/log.php @@ -0,0 +1,34 @@ +<?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/>. + +/** + * Definition of log events + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$logs = array( + array('module'=>'book', 'action'=>'update', 'mtable'=>'book', 'field'=>'name'), + array('module'=>'book', 'action'=>'view', 'mtable'=>'book', 'field'=>'name'), + array('module'=>'book', 'action'=>'view all', 'mtable'=>'book', 'field'=>'name'), + array('module'=>'book', 'action'=>'print', 'mtable'=>'book', 'field'=>'name'), +); diff --git a/db/upgrade.php b/db/upgrade.php index a0eea5ebff1..923a4680cde 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,43 +1,89 @@ <?php -// This file keeps track of upgrades to -// the assignment module +// This file is part of Moodle - http://moodle.org/ // -// Sometimes, changes between versions involve -// alterations to database structures and other -// major things that may break installations. +// 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. // -// The upgrade function in this file will attempt -// to perform all the necessary actions to upgrade -// your older installtion to the current 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. // -// If there's something it cannot do itself, it -// will tell you what you need to do. -// -// The commands in here will all be database-neutral, -// using the functions defined in lib/ddllib.php +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see <http://www.gnu.org/licenses/>. -function xmldb_book_upgrade($oldversion=0) { +/** + * Book module upgrade code + * + * @package mod + * @subpackage book + * @copyright 2009-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ - global $CFG, $THEME, $db; +defined('MOODLE_INTERNAL') || die; - $result = true; +function xmldb_book_upgrade($oldversion) { + global $CFG, $DB; + require_once("$CFG->dirroot/mod/book/db/upgradelib.php"); -/// And upgrade begins here. For each one, you'll need one -/// block of code similar to the next one. Please, delete -/// this comment lines once this file start handling proper -/// upgrade code. + $dbman = $DB->get_manager(); - if ($result && $oldversion < 2007052001) { + if ($oldversion < 2007052001) { /// Changing type of field importsrc on table book_chapters to char - $table = new XMLDBTable('book_chapters'); - $field = new XMLDBField('importsrc'); - $field->setAttributes(XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, null, null, 'timemodified'); + $table = new xmldb_table('book_chapters'); + $field = new xmldb_field('importsrc', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'timemodified'); /// Launch change of type for field importsrc - $result = $result && change_field_type($table, $field); + $dbman->change_field_type($table, $field); + + upgrade_mod_savepoint(true, 2007052001, 'book'); } - return $result; +//===== 1.9.0 upgrade line ======// + + if ($oldversion < 2010120801) { + // Rename field summary on table book to intro + $table = new xmldb_table('book'); + $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'name'); + + // Launch rename field summary + $dbman->rename_field($table, $field, 'intro'); + + // book savepoint reached + upgrade_mod_savepoint(true, 2010120801, 'book'); + } + + if ($oldversion < 2010120802) { + // Define field introformat to be added to book + $table = new xmldb_table('book'); + $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro'); + + // Launch add field introformat + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // conditionally migrate to html format in intro + if ($CFG->texteditors !== 'textarea') { + $rs = $DB->get_recordset('book', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat'); + foreach ($rs as $r) { + $r->intro = text_to_html($r->intro, false, false, true); + $r->introformat = FORMAT_HTML; + $DB->update_record('book', $r); + upgrade_set_timeout(); + } + $rs->close(); + } + + // book savepoint reached + upgrade_mod_savepoint(true, 2010120802, 'book'); + } + + + return true; } diff --git a/db/upgradelib.php b/db/upgradelib.php new file mode 100644 index 00000000000..e69de29bb2d diff --git a/version.php b/version.php index 002cdf99e10..442890ca45f 100644 --- a/version.php +++ b/version.php @@ -4,8 +4,8 @@ /// Called by moodle_needs_upgrading() and /admin/index.php ///////////////////////////////////////////////////////////////////////////////// -$module->version = 2008081402; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2007101512; // Requires this Moodle version +$module->version = 2010120802; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) -$release = "1.5beta"; // User-friendly version number +$release = "2.0dev"; // User-friendly version number From e6e946c1d0c8d4eca08a97db0e63424d067af079 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 15:28:32 +0100 Subject: [PATCH 046/455] licenses and more upgrade --- db/access.php | 2 +- db/log.php | 2 +- db/upgrade.php | 38 ++++++++++++++++- db/upgradelib.php | 103 ++++++++++++++++++++++++++++++++++++++++++++++ version.php | 2 +- 5 files changed, 142 insertions(+), 5 deletions(-) diff --git a/db/access.php b/db/access.php index 3b999f9fd25..992941e3cdc 100644 --- a/db/access.php +++ b/db/access.php @@ -1,6 +1,6 @@ <?php -// This file is part of Moodle - http://moodle.org/ +// This file is part of Book module for 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 diff --git a/db/log.php b/db/log.php index 3485104842c..2e078870e61 100644 --- a/db/log.php +++ b/db/log.php @@ -1,6 +1,6 @@ <?php -// This file is part of Moodle - http://moodle.org/ +// This file is part of Book module for 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 diff --git a/db/upgrade.php b/db/upgrade.php index 923a4680cde..cd4eaff34bb 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,6 +1,6 @@ <?php -// This file is part of Moodle - http://moodle.org/ +// This file is part of Book module for 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 @@ -28,7 +28,6 @@ defined('MOODLE_INTERNAL') || die; function xmldb_book_upgrade($oldversion) { global $CFG, $DB; - require_once("$CFG->dirroot/mod/book/db/upgradelib.php"); $dbman = $DB->get_manager(); @@ -84,6 +83,41 @@ function xmldb_book_upgrade($oldversion) { upgrade_mod_savepoint(true, 2010120802, 'book'); } + if ($oldversion < 2010120803) { + require_once("$CFG->dirroot/mod/book/db/upgradelib.php"); + + $sqlfrom = "FROM {book} b + JOIN {modules} m ON m.name = 'book' + JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = b.id)"; + + $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom"); + + if ($rs = $DB->get_recordset_sql("SELECT b.id, b.course, cm.id AS cmid $sqlfrom ORDER BY b.course, b.id")) { + + $pbar = new progress_bar('migratebookfiles', 500, true); + + $i = 0; + foreach ($rs as $book) { + $i++; + upgrade_set_timeout(360); // set up timeout, may also abort execution + $pbar->update($i, $count, "Migrating book files - $i/$count."); + + $context = get_context_instance(CONTEXT_MODULE, $book->cmid); + + book_migrate_moddata_dir_to_legacy($book, $context, '/'); + + // remove dirs if empty + @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id/"); + @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/"); + @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/"); + } + $rs->close(); + } + + // book savepoint reached + upgrade_mod_savepoint(true, 2010120803, 'book'); + } + return true; } diff --git a/db/upgradelib.php b/db/upgradelib.php index e69de29bb2d..a5ed29a3ff9 100644 --- a/db/upgradelib.php +++ b/db/upgradelib.php @@ -0,0 +1,103 @@ +<?php + +// This file is part of Book module for 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/>. + +/** + * Resource module upgrade related helper functions + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +/** + * Migrate book files stored in moddata folders. + * + * Please note it was a big mistake to store the files there in the first place! + * + * @param stdClass $book + * @param stdClass $context + * @param string $path + * @return void + */ +function book_migrate_moddata_dir_to_legacy($book, $context, $path) { + global $OUTPUT, $CFG; + + $base = "$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id"; + $fulldir = $base.$path; + + if (!is_dir($fulldir)) { + // does not exist + return; + } + + $fs = get_file_storage(); + $items = new DirectoryIterator($fulldir); + $textlib = textlib_get_instance(); + + foreach ($items as $item) { + if ($item->isDot()) { + unset($item); // release file handle + continue; + } + + if ($item->isLink()) { + // do not follow symlinks - they were never supported in moddata, sorry + unset($item); // release file handle + continue; + } + + if ($item->isFile()) { + if (!$item->isReadable()) { + echo $OUTPUT->notification(" File not readable, skipping: ".$fulldir.$item->getFilename()); + unset($item); // release file handle + continue; + } + + $filepath = clean_param("/$CFG->moddata/book/$book->id".$path, PARAM_PATH); + $filename = clean_param($item->getFilename(), PARAM_FILE); + + if ($filename === '') { + //unsupported chars, sorry + continue; + } + + if ($textlib->strlen($filepath) > 255) { + echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fulldir.$item->getFilename()); + continue; + } + + if (!$fs->file_exists($context->id, 'course', 'legacy', '0', $filepath, $filename)) { + $file_record = array('contextid'=>$context->id, 'component'=>'course', 'filearea'=>'legacy', 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename, + 'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime()); + $fs->create_file_from_pathname($file_record, $fulldir.$item->getFilename()); + } + @unlink($fulldir.$item->getFilename()); + + } else { + //migrate recursively all subdirectories + $oldpathname = $base.$item->getFilename().'/'; + $subpath = $path.$item->getFilename().'/'; + unset($item); // release file handle + book_migrate_moddata_dir_to_legacy($book, $context, $subpath); + @rmdir($oldpathname); // deletes dir if empty + } + } + unset($items); //release file handles +} \ No newline at end of file diff --git a/version.php b/version.php index 442890ca45f..66ee6036b99 100644 --- a/version.php +++ b/version.php @@ -4,7 +4,7 @@ /// Called by moodle_needs_upgrading() and /admin/index.php ///////////////////////////////////////////////////////////////////////////////// -$module->version = 2010120802; // The current module version (Date: YYYYMMDDXX) +$module->version = 2010120803; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) From f76a94d192b357dc71ce81b9c2e1863978acad03 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 15:29:28 +0100 Subject: [PATCH 047/455] coursefiles not used any more --- coursefiles.php | 915 ------------------------------------------------ 1 file changed, 915 deletions(-) delete mode 100644 coursefiles.php diff --git a/coursefiles.php b/coursefiles.php deleted file mode 100644 index c5400ce036a..00000000000 --- a/coursefiles.php +++ /dev/null @@ -1,915 +0,0 @@ -<?php - -// Manage all uploaded files in a course file area - -// All the Moodle-specific stuff is in this top section -// Configuration and access control occurs here. -// Must define: USER, basedir, baseweb, html_header and html_footer -// USER is a persistent variable using sessions - - require('../../config.php'); - require($CFG->libdir.'/filelib.php'); - require($CFG->libdir.'/adminlib.php'); - - $id = required_param('id', PARAM_INT); - $file = optional_param('file', '', PARAM_PATH); - $wdir = optional_param('wdir', '', PARAM_PATH); - $action = optional_param('action', '', PARAM_ACTION); - $name = optional_param('name', '', PARAM_FILE); - $oldname = optional_param('oldname', '', PARAM_FILE); - $choose = optional_param('choose', '', PARAM_FILE); //in fact it is always 'formname.inputname' - $userfile= optional_param('userfile','',PARAM_FILE); - $save = optional_param('save', 0, PARAM_BOOL); - $text = optional_param('text', '', PARAM_RAW); - $confirm = optional_param('confirm', 0, PARAM_BOOL); - - if ($choose) { - if (count(explode('.', $choose)) > 2) { - error('Incorrect format for choose parameter'); - } - } - - - if (! $course = get_record("course", "id", $id) ) { - error("That's an invalid course id"); - } - - require_login($course); - - require_capability('moodle/course:managefiles', get_context_instance(CONTEXT_COURSE, $course->id)); - - function html_footer() { - global $course, $choose, $adminroot; - - echo '</td></tr></table>'; - - if ($course->id == SITEID) { - admin_externalpage_print_footer($adminroot); - } else { - print_footer($course); - } - } - - function html_header($course, $wdir, $formfield=""){ - global $CFG, $ME, $choose; - - if ($course->id == SITEID) { - $strfiles = get_string("sitefiles"); - } else { - $strfiles = get_string("files"); - } - - if ($wdir == "/") { - $fullnav = "$strfiles"; - } else { - $dirs = explode("/", $wdir); - $numdirs = count($dirs); - $link = ""; - $navigation = ""; - for ($i=1; $i<$numdirs-1; $i++) { - $navigation .= " -> "; - $link .= "/".urlencode($dirs[$i]); - $navigation .= "<a href=\"".$ME."?id=$course->id&wdir=$link&choose=$choose\">".$dirs[$i]."</a>"; - } - $fullnav = "<a href=\"".$ME."?id=$course->id&wdir=/&choose=$choose\">$strfiles</a> $navigation -> ".$dirs[$numdirs-1]; - } - - - if ($choose) { - print_header(); - - $chooseparts = explode('.', $choose); - if (count($chooseparts)==2){ - ?> - <script type="text/javascript"> - //<![CDATA[ - function set_value(txt) { - opener.document.forms['<?php echo $chooseparts[0]."'].".$chooseparts[1] ?>.value = txt; - window.close(); - } - //]]> - </script> - - <?php - } elseif (count($chooseparts)==1){ - ?> - <script type="text/javascript"> - //<![CDATA[ - function set_value(txt) { - opener.document.getElementById('<?php echo $chooseparts[0] ?>').value = txt; - window.close(); - } - //]]> - </script> - - <?php - - } - $fullnav = str_replace('->', '»', format_string($course->shortname) . " -> $fullnav"); - echo '<div id="nav-bar">'.$fullnav.'</div>'; - - if ($course->id == SITEID and $wdir != "/backupdata") { - print_heading(get_string("publicsitefileswarning"), "center", 2); - } - - } else { - - if ($course->id == SITEID) { - - if ($wdir == "/backupdata") { - $adminroot = admin_get_root(); - admin_externalpage_setup('frontpagerestore', $adminroot); - admin_externalpage_print_header($adminroot); - } else { - $adminroot = admin_get_root(); - admin_externalpage_setup('sitefiles', $adminroot); - admin_externalpage_print_header($adminroot); - - print_heading(get_string("publicsitefileswarning"), "center", 2); - - } - - } else { - print_header("$course->shortname: $strfiles", $course->fullname, - "<a href=\"../course/view.php?id=$course->id\">$course->shortname". - "</a> -> $fullnav", $formfield); - } - } - - - echo "<table border=\"0\" style=\"margin-left:auto;margin-right:auto\" cellspacing=\"3\" cellpadding=\"3\" width=\"640\">"; - echo "<tr>"; - echo "<td colspan=\"2\">"; - - } - - - if (! $basedir = make_upload_directory("$course->id")) { - error("The site administrator needs to fix the file permissions"); - } - - $baseweb = $CFG->wwwroot; - -// End of configuration and access control - - - if ($wdir == '') { - $wdir = "/"; - } - - if ($wdir{0} != '/') { //make sure $wdir starts with slash - $wdir = "/".$wdir; - } - - if ($wdir == "/backupdata") { - if (! make_upload_directory("$course->id/backupdata")) { // Backup folder - error("Could not create backupdata folder. The site administrator needs to fix the file permissions"); - } - } - - if (!is_dir($basedir.$wdir)) { - html_header($course, $wdir); - error("Requested directory does not exist.", "$CFG->wwwroot/files/index.php?id=$id"); - } - - switch ($action) { - - case "upload": - html_header($course, $wdir); - require_once($CFG->dirroot.'/lib/uploadlib.php'); - - if ($save and confirm_sesskey()) { - $course->maxbytes = 0; // We are ignoring course limits - $um = new upload_manager('userfile',false,false,$course,false,0); - $dir = "$basedir$wdir"; - if ($um->process_file_uploads($dir)) { - notify(get_string('uploadedfile')); - } - // um will take care of error reporting. - displaydir($wdir); - } else { - $upload_max_filesize = get_max_upload_file_size($CFG->maxbytes); - $filesize = display_size($upload_max_filesize); - - $struploadafile = get_string("uploadafile"); - $struploadthisfile = get_string("uploadthisfile"); - $strmaxsize = get_string("maxsize", "", $filesize); - $strcancel = get_string("cancel"); - - echo "<p>$struploadafile ($strmaxsize) --> <b>$wdir</b></p>"; - echo "<form enctype=\"multipart/form-data\" method=\"post\" action=\"coursefiles.php\">"; - echo "<div>"; - echo "<table><tr><td colspan=\"2\">"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"upload\" />"; - echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - upload_print_form_fragment(1,array('userfile'),null,false,null,$upload_max_filesize,0,false); - echo " </td></tr></table>"; - echo " <input type=\"submit\" name=\"save\" value=\"$struploadthisfile\" />"; - echo "</div>"; - echo "</form>"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"$strcancel\" />"; - echo "</div>"; - echo "</form>"; - } - html_footer(); - break; - - case "delete": - if ($confirm and confirm_sesskey()) { - html_header($course, $wdir); - if (!empty($USER->filelist)) { - foreach ($USER->filelist as $file) { - $fullfile = $basedir.'/'.$file; - if (! fulldelete($fullfile)) { - echo "<br />Error: Could not delete: $fullfile"; - } - } - } - clearfilelist(); - displaydir($wdir); - html_footer(); - - } else { - html_header($course, $wdir); - - if (setfilelist($_POST)) { - notify(get_string('deletecheckwarning').':'); - print_simple_box_start("center"); - printfilelist($USER->filelist); - print_simple_box_end(); - echo "<br />"; - - require_once($CFG->dirroot.'/mod/resource/lib.php'); - $block = resource_delete_warning($course, $USER->filelist); - - if (empty($CFG->resource_blockdeletingfile) or $block == '') { - $optionsyes = array('id'=>$id, 'wdir'=>$wdir, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey(), 'choose'=>$choose); - $optionsno = array('id'=>$id, 'wdir'=>$wdir, 'action'=>'cancel', 'choose'=>$choose); - notice_yesno (get_string('deletecheckfiles'), 'coursefiles.php', 'coursefiles.php', $optionsyes, $optionsno, 'post', 'get'); - } else { - - notify(get_string('warningblockingdelete', 'resource')); - $options = array('id'=>$id, 'wdir'=>$wdir, 'action'=>'cancel', 'choose'=>$choose); - print_continue("coursefiles.php?id=$id&wdir=$wdir&action=cancel&choose=$choose"); - } - } else { - displaydir($wdir); - } - html_footer(); - } - break; - - case "move": - html_header($course, $wdir); - if (($count = setfilelist($_POST)) and confirm_sesskey()) { - $USER->fileop = $action; - $USER->filesource = $wdir; - echo "<p class=\"centerpara\">"; - print_string("selectednowmove", "moodle", $count); - echo "</p>"; - } - displaydir($wdir); - html_footer(); - break; - - case "paste": - html_header($course, $wdir); - if (isset($USER->fileop) and ($USER->fileop == "move") and confirm_sesskey()) { - foreach ($USER->filelist as $file) { - $shortfile = basename($file); - $oldfile = $basedir.'/'.$file; - $newfile = $basedir.$wdir."/".$shortfile; - if (!rename($oldfile, $newfile)) { - echo "<p>Error: $shortfile not moved</p>"; - } - } - } - clearfilelist(); - displaydir($wdir); - html_footer(); - break; - - case "rename": - if (($name != '') and confirm_sesskey()) { - html_header($course, $wdir); - $name = clean_filename($name); - if (file_exists($basedir.$wdir."/".$name)) { - echo "<center>Error: $name already exists!</center>"; - } else if (!rename($basedir.$wdir."/".$oldname, $basedir.$wdir."/".$name)) { - echo "<p align=\"center\">Error: could not rename $oldname to $name</p>"; - } else { - //file was renamed now update resources if needed - require_once($CFG->dirroot.'/mod/resource/lib.php'); - resource_renamefiles($course, $wdir, $oldname, $name); - } - displaydir($wdir); - - } else { - $strrename = get_string("rename"); - $strcancel = get_string("cancel"); - $strrenamefileto = get_string("renamefileto", "moodle", $file); - html_header($course, $wdir, "form.name"); - echo "<p>$strrenamefileto:</p>"; - echo "<table><tr><td>"; - echo "<form action=\"coursefiles.php\" method=\"post\">"; - echo "<fieldset class=\"invisiblefieldset\">"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"rename\" />"; - echo " <input type=\"hidden\" name=\"oldname\" value=\"$file\" />"; - echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - echo " <input type=\"text\" name=\"name\" size=\"35\" value=\"$file\" />"; - echo " <input type=\"submit\" value=\"$strrename\" />"; - echo "</fieldset>"; - echo "</form>"; - echo "</td><td>"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"$strcancel\" />"; - echo "</div>"; - echo "</form>"; - echo "</td></tr></table>"; - } - html_footer(); - break; - - case "makedir": - if (($name != '') and confirm_sesskey()) { - html_header($course, $wdir); - $name = clean_filename($name); - if (file_exists("$basedir$wdir/$name")) { - echo "Error: $name already exists!"; - } else if (! make_upload_directory("$course->id$wdir/$name")) { - echo "Error: could not create $name"; - } - displaydir($wdir); - - } else { - $strcreate = get_string("create"); - $strcancel = get_string("cancel"); - $strcreatefolder = get_string("createfolder", "moodle", $wdir); - html_header($course, $wdir, "form.name"); - echo "<p>$strcreatefolder:</p>"; - echo "<table><tr><td>"; - echo "<form action=\"coursefiles.php\" method=\"post\">"; - echo "<fieldset class=\"invisiblefieldset\">"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"makedir\" />"; - echo " <input type=\"text\" name=\"name\" size=\"35\" />"; - echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - echo " <input type=\"submit\" value=\"$strcreate\" />"; - echo "</fieldset>"; - echo "</form>"; - echo "</td><td>"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"$strcancel\" />"; - echo "</div>"; - echo "</form>"; - echo "</td></tr></table>"; - } - html_footer(); - break; - - case "edit": - html_header($course, $wdir); - if (($text != '') and confirm_sesskey()) { - $fileptr = fopen($basedir.'/'.$file,"w"); - $text = preg_replace('/\x0D/', '', $text); // http://moodle.org/mod/forum/discuss.php?d=38860 - fputs($fileptr, stripslashes($text)); - fclose($fileptr); - displaydir($wdir); - - } else { - $streditfile = get_string("edit", "", "<b>$file</b>"); - $fileptr = fopen($basedir.'/'.$file, "r"); - $contents = fread($fileptr, filesize($basedir.'/'.$file)); - fclose($fileptr); - - if (mimeinfo("type", $file) == "text/html") { - $usehtmleditor = can_use_html_editor(); - } else { - $usehtmleditor = false; - } - $usehtmleditor = false; // Always keep it off for now - - print_heading("$streditfile"); - - echo "<table><tr><td colspan=\"2\">"; - echo "<form action=\"coursefiles.php\" method=\"post\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"file\" value=\"$file\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"edit\" />"; - echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - print_textarea($usehtmleditor, 25, 80, 680, 400, "text", $contents); - echo "</td></tr><tr><td>"; - echo " <input type=\"submit\" value=\"".get_string("savechanges")."\" />"; - echo "</div>"; - echo "</form>"; - echo "</td><td>"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"".get_string("cancel")."\" />"; - echo "</div>"; - echo "</form>"; - echo "</td></tr></table>"; - - if ($usehtmleditor) { - use_html_editor(); - } - - - } - html_footer(); - break; - - case "zip": - if (($name != '') and confirm_sesskey()) { - html_header($course, $wdir); - $name = clean_filename($name); - - $files = array(); - foreach ($USER->filelist as $file) { - $files[] = "$basedir/$file"; - } - - if (!zip_files($files,"$basedir$wdir/$name")) { - error(get_string("zipfileserror","error")); - } - - clearfilelist(); - displaydir($wdir); - - } else { - html_header($course, $wdir, "form.name"); - - if (setfilelist($_POST)) { - echo "<p align=\"center\">".get_string("youareabouttocreatezip").":</p>"; - print_simple_box_start("center"); - printfilelist($USER->filelist); - print_simple_box_end(); - echo "<br />"; - echo "<p align=\"center\">".get_string("whattocallzip")."</p>"; - echo "<table><tr><td>"; - echo "<form action=\"coursefiles.php\" method=\"post\">"; - echo "<fieldset class=\"invisiblefieldset\">"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"zip\" />"; - echo " <input type=\"text\" name=\"name\" size=\"35\" value=\"new.zip\" />"; - echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - echo " <input type=\"submit\" value=\"".get_string("createziparchive")."\" />"; - echo "<fieldset>"; - echo "</form>"; - echo "</td><td>"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"".get_string("cancel")."\" />"; - echo "</div>"; - echo "</form>"; - echo "</td></tr></table>"; - } else { - displaydir($wdir); - clearfilelist(); - } - } - html_footer(); - break; - - case "unzip": - html_header($course, $wdir); - if (($file != '') and confirm_sesskey()) { - $strok = get_string("ok"); - $strunpacking = get_string("unpacking", "", $file); - - echo "<p align=\"center\">$strunpacking:</p>"; - - $file = basename($file); - - if (!unzip_file("$basedir$wdir/$file")) { - error(get_string("unzipfileserror","error")); - } - - echo "<div style=\"text-align:center\"><form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"$strok\" />"; - echo "</div>"; - echo "</form>"; - echo "</div>"; - } else { - displaydir($wdir); - } - html_footer(); - break; - - case "listzip": - html_header($course, $wdir); - if (($file != '') and confirm_sesskey()) { - $strname = get_string("name"); - $strsize = get_string("size"); - $strmodified = get_string("modified"); - $strok = get_string("ok"); - $strlistfiles = get_string("listfiles", "", $file); - - echo "<p align=\"center\">$strlistfiles:</p>"; - $file = basename($file); - - include_once("$CFG->libdir/pclzip/pclzip.lib.php"); - $archive = new PclZip(cleardoubleslashes("$basedir$wdir/$file")); - if (!$list = $archive->listContent(cleardoubleslashes("$basedir$wdir"))) { - notify($archive->errorInfo(true)); - - } else { - echo "<table cellpadding=\"4\" cellspacing=\"2\" border=\"0\" width=\"640\" class=\"files\">"; - echo "<tr class=\"file\"><th align=\"left\" class=\"header name\" scope=\"col\">$strname</th><th align=\"right\" class=\"header size\" scope=\"col\">$strsize</th><th align=\"right\" class=\"header date\" scope=\"col\">$strmodified</th></tr>"; - foreach ($list as $item) { - echo "<tr>"; - print_cell("left", s($item['filename']), 'name'); - if (! $item['folder']) { - print_cell("right", display_size($item['size']), 'size'); - } else { - echo "<td> </td>"; - } - $filedate = userdate($item['mtime'], get_string("strftimedatetime")); - print_cell("right", $filedate, 'date'); - echo "</tr>"; - } - echo "</table>"; - } - echo "<br /><center><form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"cancel\" />"; - echo " <input type=\"submit\" value=\"$strok\" />"; - echo "</div>"; - echo "</form>"; - echo "</center>"; - } else { - displaydir($wdir); - } - html_footer(); - break; - - case "restore": - html_header($course, $wdir); - if (($file != '') and confirm_sesskey()) { - echo "<p align=\"center\">".get_string("youaregoingtorestorefrom").":</p>"; - print_simple_box_start("center"); - echo $file; - print_simple_box_end(); - echo "<br />"; - echo "<p align=\"center\">".get_string("areyousuretorestorethisinfo")."</p>"; - $restore_path = "$CFG->wwwroot/backup/restore.php"; - notice_yesno (get_string("areyousuretorestorethis"), - $restore_path."?id=".$id."&file=".cleardoubleslashes($id.$wdir."/".$file)."&method=manual", - "coursefiles.php?id=$id&wdir=$wdir&action=cancel"); - } else { - displaydir($wdir); - } - html_footer(); - break; - - case "cancel": - clearfilelist(); - - default: - html_header($course, $wdir); - displaydir($wdir); - html_footer(); - break; -} - - -/// FILE FUNCTIONS /////////////////////////////////////////////////////////// - - -function setfilelist($VARS) { - global $USER; - - $USER->filelist = array (); - $USER->fileop = ""; - - $count = 0; - foreach ($VARS as $key => $val) { - if (substr($key,0,4) == "file") { - $count++; - $val = rawurldecode($val); - $USER->filelist[] = clean_param($val, PARAM_PATH); - } - } - return $count; -} - -function clearfilelist() { - global $USER; - - $USER->filelist = array (); - $USER->fileop = ""; -} - - -function printfilelist($filelist) { - global $CFG, $basedir; - - $strfolder = get_string("folder"); - $strfile = get_string("file"); - - foreach ($filelist as $file) { - if (is_dir($basedir.'/'.$file)) { - echo "<img src=\"$CFG->pixpath/f/folder.gif\" class=\"icon\" alt=\"$strfolder\" /> $file<br />"; - $subfilelist = array(); - $currdir = opendir($basedir.'/'.$file); - while (false !== ($subfile = readdir($currdir))) { - if ($subfile <> ".." && $subfile <> ".") { - $subfilelist[] = $file."/".$subfile; - } - } - printfilelist($subfilelist); - - } else { - $icon = mimeinfo("icon", $file); - echo "<img src=\"$CFG->pixpath/f/$icon\" class=\"icon\" alt=\"$strfile\" /> $file<br />"; - } - } -} - - -function print_cell($alignment='center', $text=' ', $class='') { - if ($class) { - $class = ' class="'.$class.'"'; - } - echo '<td align="'.$alignment.'" style="white-space:nowrap "'.$class.'>'.$text.'</td>'; -} - -function displaydir ($wdir) { -// $wdir == / or /a or /a/b/c/d etc - - global $basedir; - global $id; - global $USER, $CFG; - global $choose; - - $fullpath = $basedir.$wdir; - $dirlist = array(); - - $directory = opendir($fullpath); // Find all files - while (false !== ($file = readdir($directory))) { - if ($file == "." || $file == "..") { - continue; - } - - if (is_dir($fullpath."/".$file)) { - $dirlist[] = $file; - } else { - $filelist[] = $file; - } - } - closedir($directory); - - $strname = get_string("name"); - $strsize = get_string("size"); - $strmodified = get_string("modified"); - $straction = get_string("action"); - $strmakeafolder = get_string("makeafolder"); - $struploadafile = get_string("uploadafile"); - $strselectall = get_string("selectall"); - $strselectnone = get_string("deselectall"); - $strwithchosenfiles = get_string("withchosenfiles"); - $strmovetoanotherfolder = get_string("movetoanotherfolder"); - $strmovefilestohere = get_string("movefilestohere"); - $strdeletecompletely = get_string("deletecompletely"); - $strcreateziparchive = get_string("createziparchive"); - $strrename = get_string("rename"); - $stredit = get_string("edit"); - $strunzip = get_string("unzip"); - $strlist = get_string("list"); - $strrestore= get_string("restore"); - $strchoose = get_string("choose"); - $strfolder = get_string("folder"); - $strfile = get_string("file"); - - - echo "<form action=\"coursefiles.php\" method=\"post\" id=\"dirform\">"; - echo "<div>"; - echo '<input type="hidden" name="choose" value="'.$choose.'" />'; - // echo "<hr align=\"center\" noshade=\"noshade\" size=\"1\" />"; - echo "<hr/>"; - echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\" class=\"files\">"; - echo "<tr>"; - echo "<th scope=\"col\"></th>"; - echo "<th class=\"header name\" scope=\"col\">$strname</th>"; - echo "<th class=\"header size\" scope=\"col\">$strsize</th>"; - echo "<th class=\"header date\" scope=\"col\">$strmodified</th>"; - echo "<th class=\"header commands\" scope=\"col\">$straction</th>"; - echo "</tr>\n"; - - if ($wdir != "/") { - $dirlist[] = '..'; - } - - $count = 0; - - if (!empty($dirlist)) { - asort($dirlist); - foreach ($dirlist as $dir) { - echo "<tr class=\"folder\">"; - - if ($dir == '..') { - $fileurl = rawurlencode(dirname($wdir)); - print_cell(); - // alt attribute intentionally empty to prevent repetition in screen reader - print_cell('left', '<a href="coursefiles.php?id='.$id.'&wdir='.$fileurl.'&choose='.$choose.'"><img src="'.$CFG->pixpath.'/f/parent.gif" class="icon" alt="" /> '.get_string('parentfolder').'</a>', 'name'); - print_cell(); - print_cell(); - print_cell(); - - } else { - $count++; - $filename = $fullpath."/".$dir; - $fileurl = rawurlencode($wdir."/".$dir); - $filesafe = rawurlencode($dir); - $filesize = display_size(get_directory_size("$fullpath/$dir")); - $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p"); - $selectfile = trim($wdir."/".$dir, "/"); - print_cell("center", "<input type=\"checkbox\" name=\"file$count\" value=\"$fileurl\" />", 'checkbox'); - print_cell("left", "<a href=\"coursefiles.php?id=$id&wdir=$fileurl&choose=$choose\"><img src=\"$CFG->pixpath/f/folder.gif\" class=\"icon\" alt=\"$strfolder\" /> ".htmlspecialchars($dir)."</a>", 'name'); - print_cell("right", $filesize, 'size'); - print_cell("right", $filedate, 'date'); - if ($choose) { - $edittext = "<b><a onclick=\"return set_value('$selectfile')\" href=\"\">$strchoose</a></b> "; - } else { - $edittext = ''; - } - print_cell("right", "$edittext <a href=\"coursefiles.php?id=$id&wdir=$wdir&file=$filesafe&action=rename&choose=$choose\">$strrename</a>", 'commands'); - } - - echo "</tr>"; - } - } - - - if (!empty($filelist)) { - asort($filelist); - foreach ($filelist as $file) { - - $icon = mimeinfo("icon", $file); - - $count++; - $filename = $fullpath."/".$file; - $fileurl = trim($wdir, "/")."/$file"; - $filesafe = rawurlencode($file); - $fileurlsafe = rawurlencode($fileurl); - $filedate = userdate(filemtime($filename), "%d %b %Y, %I:%M %p"); - - $selectfile = trim($fileurl, "/"); - - echo "<tr class=\"file\">"; - - print_cell("center", "<input type=\"checkbox\" name=\"file$count\" value=\"$fileurl\" />", 'checkbox'); - echo "<td align=\"left\" style=\"white-space:nowrap\" class=\"name\">"; - if ($CFG->slasharguments) { - $ffurl = str_replace('//', '/', "/file.php/$id/$fileurl"); - } else { - $ffurl = str_replace('//', '/', "/file.php?file=/$id/$fileurl"); - } - link_to_popup_window ($ffurl, "display", - "<img src=\"$CFG->pixpath/f/$icon\" class=\"icon\" alt=\"$strfile\" /> ".htmlspecialchars($file), - 480, 640); - echo "</td>"; - - $file_size = filesize($filename); - print_cell("right", display_size($file_size), 'size'); - print_cell("right", $filedate, 'date'); - - if ($choose) { - $edittext = "<strong><a onclick=\"return set_value('$selectfile')\" href=\"#\">$strchoose</a></strong> "; - } else { - $edittext = ''; - } - - - if ($icon == "text.gif" || $icon == "html.gif") { - $edittext .= "<a href=\"coursefiles.php?id=$id&wdir=$wdir&file=$fileurl&action=edit&choose=$choose\">$stredit</a>"; - } else if ($icon == "zip.gif") { - $edittext .= "<a href=\"coursefiles.php?id=$id&wdir=$wdir&file=$fileurl&action=unzip&sesskey=$USER->sesskey&choose=$choose\">$strunzip</a> "; - $edittext .= "<a href=\"coursefiles.php?id=$id&wdir=$wdir&file=$fileurl&action=listzip&sesskey=$USER->sesskey&choose=$choose\">$strlist</a> "; - if (!empty($CFG->backup_version) and has_capability('moodle/site:restore', get_context_instance(CONTEXT_COURSE, $id))) { - $edittext .= "<a href=\"coursefiles.php?id=$id&wdir=$wdir&file=$filesafe&action=restore&sesskey=$USER->sesskey&choose=$choose\">$strrestore</a> "; - } - } - - print_cell("right", "$edittext <a href=\"coursefiles.php?id=$id&wdir=$wdir&file=$filesafe&action=rename&choose=$choose\">$strrename</a>", 'commands'); - - echo "</tr>"; - } - } - echo "</table>"; - echo "<hr />"; - //echo "<hr width=\"640\" align=\"center\" noshade=\"noshade\" size=\"1\" />"; - - echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\">"; - echo "<tr><td>"; - echo "<input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo '<input type="hidden" name="choose" value="'.$choose.'" />'; - echo "<input type=\"hidden\" name=\"wdir\" value=\"$wdir\" /> "; - echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - $options = array ( - "move" => "$strmovetoanotherfolder", - "delete" => "$strdeletecompletely", - "zip" => "$strcreateziparchive" - ); - if (!empty($count)) { - choose_from_menu ($options, "action", "", "$strwithchosenfiles...", "javascript:getElementById('dirform').submit()"); - } - echo "</td></tr></table>"; - echo "</div>"; - echo "</form>"; - echo "<table border=\"0\" cellspacing=\"2\" cellpadding=\"2\" width=\"640\"><tr>"; - echo "<td align=\"center\">"; - if (!empty($USER->fileop) and ($USER->fileop == "move") and ($USER->filesource <> $wdir)) { - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"paste\" />"; - echo " <input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />"; - echo " <input type=\"submit\" value=\"$strmovefilestohere\" />"; - echo "</div>"; - echo "</form>"; - } - echo "</td>"; - echo "<td align=\"right\">"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"makedir\" />"; - echo " <input type=\"submit\" value=\"$strmakeafolder\" />"; - echo "</div>"; - echo "</form>"; - echo "</td>"; - echo "<td align=\"right\">"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; //dummy form - alignment only - echo "<fieldset class=\"invisiblefieldset\">"; - echo " <input type=\"button\" value=\"$strselectall\" onclick=\"checkall();\" />"; - echo " <input type=\"button\" value=\"$strselectnone\" onclick=\"uncheckall();\" />"; - echo "</fieldset>"; - echo "</form>"; - echo "</td>"; - echo "<td align=\"right\">"; - echo "<form action=\"coursefiles.php\" method=\"get\">"; - echo "<div>"; - echo ' <input type="hidden" name="choose" value="'.$choose.'" />'; - echo " <input type=\"hidden\" name=\"id\" value=\"$id\" />"; - echo " <input type=\"hidden\" name=\"wdir\" value=\"$wdir\" />"; - echo " <input type=\"hidden\" name=\"action\" value=\"upload\" />"; - echo " <input type=\"submit\" value=\"$struploadafile\" />"; - echo "</div>"; - echo "</form>"; - echo "</td></tr>"; - echo "</table>"; - echo "<hr/>"; - //echo "<hr width=\"640\" align=\"center\" noshade=\"noshade\" size=\"1\" />"; - -} - From 73861c80d5d4af32c50ab198618cc4f19f76954a Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 15:30:51 +0100 Subject: [PATCH 048/455] missing upgrade step info --- db/upgrade.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/upgrade.php b/db/upgrade.php index cd4eaff34bb..396840c9d76 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -114,6 +114,10 @@ function xmldb_book_upgrade($oldversion) { $rs->close(); } + + //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter + + // book savepoint reached upgrade_mod_savepoint(true, 2010120803, 'book'); } From e355240d597414bddc4b40eaa2a65fe9e08f3190 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 15:41:55 +0100 Subject: [PATCH 049/455] more upgrades --- db/access.php | 1 - db/log.php | 1 - db/upgrade.php | 1 - db/upgradelib.php | 1 - delete.php | 3 + edit.php | 4 +- edit_form.php | 2 + generateimscp.php | 2 +- import.php | 2 +- index.php | 2 +- lib.php | 303 +----------------------------------- locallib.php | 323 +++++++++++++++++++++++++++++++++++++++ mod_form.php | 7 +- move.php | 3 + print.php | 2 +- settings.php | 9 +- show.php | 2 + styles.php => styles.css | 0 toc.php | 26 ++-- view.php | 2 +- 20 files changed, 364 insertions(+), 332 deletions(-) create mode 100644 locallib.php rename styles.php => styles.css (100%) diff --git a/db/access.php b/db/access.php index 992941e3cdc..769e497264a 100644 --- a/db/access.php +++ b/db/access.php @@ -1,5 +1,4 @@ <?php - // This file is part of Book module for Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify diff --git a/db/log.php b/db/log.php index 2e078870e61..a829c262912 100644 --- a/db/log.php +++ b/db/log.php @@ -1,5 +1,4 @@ <?php - // This file is part of Book module for Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify diff --git a/db/upgrade.php b/db/upgrade.php index 396840c9d76..c2496c9fd58 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,5 +1,4 @@ <?php - // This file is part of Book module for Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify diff --git a/db/upgradelib.php b/db/upgradelib.php index a5ed29a3ff9..323af38867c 100644 --- a/db/upgradelib.php +++ b/db/upgradelib.php @@ -1,5 +1,4 @@ <?php - // This file is part of Book module for Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify diff --git a/delete.php b/delete.php index e21fe24c98c..90e371d004a 100644 --- a/delete.php +++ b/delete.php @@ -1,6 +1,9 @@ <?php require('teacheraccess.php'); //page only for teachers + +require_once($CFG->dirroot.'/mod/book/locallib.php'); + $confirm = optional_param('confirm', 0, PARAM_BOOL); diff --git a/edit.php b/edit.php index 1e1ffa9c99a..0e6ddc0f27b 100644 --- a/edit.php +++ b/edit.php @@ -1,7 +1,7 @@ <?php -require_once('../../config.php'); -require_once('lib.php'); +require('../../config.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once('edit_form.php'); $cmid = required_param('cmid', PARAM_INT); // Book Course Module ID diff --git a/edit_form.php b/edit_form.php index 0efb8f535bb..3c53e66476a 100644 --- a/edit_form.php +++ b/edit_form.php @@ -1,5 +1,7 @@ <?php +defined('MOODLE_INTERNAL') || die; + require_once($CFG->libdir.'/formslib.php'); class book_chapter_edit_form extends moodleform { diff --git a/generateimscp.php b/generateimscp.php index 4068cb1622a..78147435362 100644 --- a/generateimscp.php +++ b/generateimscp.php @@ -25,7 +25,7 @@ /////////////////////////////////////////////////////////////////////////// require('../../config.php'); -require_once('lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once($CFG->dirroot.'/backup/lib.php'); require_once($CFG->libdir.'/filelib.php'); diff --git a/import.php b/import.php index 386d854f151..a5e9cffd3e4 100644 --- a/import.php +++ b/import.php @@ -1,7 +1,7 @@ <?php require('../../config.php'); -require_once('lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once('import_form.php'); $id = required_param('id', PARAM_INT); // Course Module ID diff --git a/index.php b/index.php index 74e6b5e6032..1420a85802b 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ /// This page lists all the instances of book in a particular course require_once('../../config.php'); -require_once('lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID diff --git a/lib.php b/lib.php index a3ac84725bd..903ddc30cc0 100644 --- a/lib.php +++ b/lib.php @@ -1,18 +1,8 @@ <?php -define('NUM_NONE', '0'); -define('NUM_NUMBERS', '1'); -define('NUM_BULLETS', '2'); -define('NUM_INDENTED', '3'); +defined('MOODLE_INTERNAL') || die; -function book_get_numbering_types() { - return array (NUM_NONE => get_string('numbering0', 'book'), - NUM_NUMBERS => get_string('numbering1', 'book'), - NUM_BULLETS => get_string('numbering2', 'book'), - NUM_INDENTED => get_string('numbering3', 'book') ); -} - /// Library of functions and constants for module 'book' function book_add_instance($book) { @@ -173,294 +163,3 @@ function book_get_view_actions() { function book_get_post_actions() { return array('update'); } - -////////////////////////////////////////////////////////////////////////////////////// -/// Any other book functions go here. Each of them must have a name that -/// starts with book_ - -//check chapter ordering and -//make sure subchapter is not first in book -//hidden chapter must have all subchapters hidden too -function book_check_structure($bookid) { - if ($chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, subchapter, hidden')) { - $first = true; - $hidesub = true; - $i = 1; - foreach($chapters as $ch) { - if ($first and $ch->subchapter) { - $ch->subchapter = 0; - } - $first = false; - if (!$ch->subchapter) { - $hidesub = $ch->hidden; - } else { - $ch->hidden = $hidesub ? true : $ch->hidden; - } - $ch->pagenum = $i; - update_record('book_chapters', $ch); - $i++; - } - } -} - - -/// prepare button to turn chapter editing on - connected with course editing -function book_edit_button($id, $courseid, $chapterid) { - global $CFG, $USER; - - - if (isteacheredit($courseid)) { - if (!empty($USER->editing)) { - $string = get_string("turneditingoff"); - $edit = '0'; - } else { - $string = get_string("turneditingon"); - $edit = '1'; - } - return '<form method="get" action="'.$CFG->wwwroot.'/mod/book/view.php"><div>'. - '<input type="hidden" name="id" value="'.$id.'" />'. - '<input type="hidden" name="chapterid" value="'.$chapterid.'" />'. - '<input type="hidden" name="edit" value="'.$edit.'" />'. - '<input type="submit" value="'.$string.'" /></div></form>'; - } else { - return ''; - } -} - -/// general function for logging to table -function book_log($str1, $str2, $level = 0) { - switch ($level) { - case 1: - echo '<tr><td><span class="dimmed_text">'.$str1.'</span></td><td><span class="dimmed_text">'.$str2.'</span></td></tr>'; - break; - case 2: - echo '<tr><td><span style="color: rgb(255, 0, 0);">'.$str1.'</span></td><td><span style="color: rgb(255, 0, 0);">'.$str2.'</span></td></tr>'; - break; - default: - echo '<tr><td>'.$str1.'</class></td><td>'.$str2.'</td></tr>'; - break; - } -} - -//================================================= -// import functions -//================================================= - -/// normalize relative links (= remove ..) -function book_prepare_link($ref) { - if ($ref == '') { - return ''; - } - $ref = str_replace('\\','/',$ref); //anti MS hack - $cnt = substr_count($ref, '..'); - for($i=0; $i<$cnt; $i++) { - $ref = ereg_replace('[^/]+/\.\./', '', $ref); - } - //still any '..' left?? == error! error! - if (substr_count($ref, '..') > 0) { - return ''; - } - if (ereg('[\|\`]', $ref)) { // check for other bad characters - return ''; - } - return $ref; -} - -/// read chapter content from file -function book_read_chapter($base, $ref) { - $file = $base.'/'.$ref; - if (filesize($file) <= 0 or !is_readable($file)) { - book_log($ref, get_string('error'), 2); - return; - } - //first read data - $handle = fopen($file, "rb"); - $contents = fread($handle, filesize($file)); - fclose($handle); - //extract title - $chapter = new object(); - if (preg_match('/<title>([^<]+)<\/title>/i', $contents, $matches)) { - $chapter->title = $matches[1]; - } else { - $chapter->title = $ref; - } - //extract page body - if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { - $chapter->content = $matches[1]; - } else { - book_log($ref, get_string('error'), 2); - return; - } - book_log($ref, get_string('ok')); - $chapter->importsrc = $ref; - //extract page head - if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { - $head = $matches[1]; - if (preg_match('/charset=([^"]+)/is', $head, $matches)) { - $enc = $matches[1]; - $textlib = textlib_get_instance(); - $chapter->content = $textlib->convert($chapter->content, $enc, current_charset()); - $chapter->title = $textlib->convert($chapter->title, $enc, current_charset()); - } - if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css - for($i=0; $i<count($matches[0]); $i++){ - $chapter->content = $matches[0][$i]."\n".$chapter->content; - } - } - } - return $chapter; -} - -///relink images and relative links -function book_relink($id, $bookid, $courseid) { - global $CFG; - if ($CFG->slasharguments) { - $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; - } else { - $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; - } - $chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, title, content, importsrc'); - $originals = array(); - foreach($chapters as $ch) { - $originals[$ch->importsrc] = $ch; - } - foreach($chapters as $ch) { - $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); - $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) - $modified = false; - //image relinking - if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { - for($i = 0; $i<count($images[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link - $link = book_prepare_link($base.$images[2][$i]); - if ($link == '') { - continue; - } - $origtag = $images[0][$i]; - $newtag = $images[1][$i].$link.$images[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $images[2][$i].' --> '.$link); - } - } - } - //css relinking (dlnsk) - if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { - for($i = 0; $i<count($csslinks[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link - $link = book_prepare_link($base.$csslinks[2][$i]); - if ($link == '') { - continue; - } - $origtag = $csslinks[0][$i]; - $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $csslinks[2][$i].' --> '.$link); - } - } - } - //general embed relinking - flash and others?? - if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { - for($i = 0; $i<count($embeds[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link - $link = book_prepare_link($base.$embeds[2][$i]); - if ($link == '') { - continue; - } - $origtag = $embeds[0][$i]; - $newtag = $embeds[1][$i].$link.$embeds[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $embeds[2][$i].' --> '.$link); - } - } - } - //flash in IE <param name=movie value="something" - I do hate IE! - if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { - for($i = 0; $i<count($params[0]); $i++) { - if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { - if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link - $link = book_prepare_link($base.$values[2]); - if ($link == '') { - continue; - } - $newvalue = $values[1].$link.$values[3]; - $newparam = str_replace($values[0], $newvalue, $params[0][$i]); - $ch->content = str_replace($params[0][$i], $newparam, $ch->content); - $modified = true; - book_log($ch->title, $values[2].' --> '.$link); - } - } - } - } - //java applet - add code bases if not present!!!! - if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { - for($i = 0; $i<count($applets[0]); $i++) { - if (!stripos($applets[0][$i], 'codebase')) { - $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); - $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); - $modified = true; - } - } - } - //relink java applet code bases - if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { - for($i = 0; $i<count($codebases[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link - $link = book_prepare_link($base.$codebases[2][$i]); - if ($link == '') { - continue; - } - $origtag = $codebases[0][$i]; - $newtag = $codebases[1][$i].$link.$codebases[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $codebases[2][$i].' --> '.$link); - } - } - } - //relative link conversion - if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { - for($i = 0; $i<count($links[0]); $i++) { - if ($links[2][$i] != '' //check for inner anchor links - && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link - $origtag = $links[0][$i]; - $target = book_prepare_link($rel.$links[2][$i]); //target chapter - if ($target != '' && array_key_exists($target, $originals)) { - $o = $originals[$target]; - $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; - $newtag = preg_replace('/target=[^\s>]/i','', $newtag); - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); - } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links - $target = book_prepare_link($base.$links[2][$i]); - $origtag = $links[0][$i]; - $newtag = $links[1][$i].$target.$links[4][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $links[2][$i].' --> '.$target); - } - } - } - } - if ($modified) { - $ch->title = addslashes($ch->title); - $ch->content = addslashes($ch->content); - $ch->importsrc = addslashes($ch->importsrc); - if (!update_record('book_chapters', $ch)) { - error('Could not update your book'); - } - } - } -} - -/** - * Tells if files in moddata are trusted and can be served without XSS protection. - * @return bool true if file can be submitted by teacher only (trusted), false otherwise - */ -function book_is_moddata_trusted() { - return true; -} - diff --git a/locallib.php b/locallib.php new file mode 100644 index 00000000000..3b8f833d9b4 --- /dev/null +++ b/locallib.php @@ -0,0 +1,323 @@ +<?php +// This file is part of Book module for 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/>. + +/** + * Book module local lib functions + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +define('BOOK_NUM_NONE', '0'); +define('BOOK_NUM_NUMBERS', '1'); +define('BOOK_NUM_BULLETS', '2'); +define('BOOK_NUM_INDENTED', '3'); + +require_once($CFG->dirroot.'/mod/book/lib.php'); + +function book_get_numbering_types() { + return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), + BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), + BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), + BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); +} + + +////////////////////////////////////////////////////////////////////////////////////// +/// Any other book functions go here. Each of them must have a name that +/// starts with book_ + +//check chapter ordering and +//make sure subchapter is not first in book +//hidden chapter must have all subchapters hidden too +function book_check_structure($bookid) { + if ($chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, subchapter, hidden')) { + $first = true; + $hidesub = true; + $i = 1; + foreach($chapters as $ch) { + if ($first and $ch->subchapter) { + $ch->subchapter = 0; + } + $first = false; + if (!$ch->subchapter) { + $hidesub = $ch->hidden; + } else { + $ch->hidden = $hidesub ? true : $ch->hidden; + } + $ch->pagenum = $i; + update_record('book_chapters', $ch); + $i++; + } + } +} + + +/// prepare button to turn chapter editing on - connected with course editing +function book_edit_button($id, $courseid, $chapterid) { + global $CFG, $USER; + + + if (isteacheredit($courseid)) { + if (!empty($USER->editing)) { + $string = get_string("turneditingoff"); + $edit = '0'; + } else { + $string = get_string("turneditingon"); + $edit = '1'; + } + return '<form method="get" action="'.$CFG->wwwroot.'/mod/book/view.php"><div>'. + '<input type="hidden" name="id" value="'.$id.'" />'. + '<input type="hidden" name="chapterid" value="'.$chapterid.'" />'. + '<input type="hidden" name="edit" value="'.$edit.'" />'. + '<input type="submit" value="'.$string.'" /></div></form>'; + } else { + return ''; + } +} + +/// general function for logging to table +function book_log($str1, $str2, $level = 0) { + switch ($level) { + case 1: + echo '<tr><td><span class="dimmed_text">'.$str1.'</span></td><td><span class="dimmed_text">'.$str2.'</span></td></tr>'; + break; + case 2: + echo '<tr><td><span style="color: rgb(255, 0, 0);">'.$str1.'</span></td><td><span style="color: rgb(255, 0, 0);">'.$str2.'</span></td></tr>'; + break; + default: + echo '<tr><td>'.$str1.'</class></td><td>'.$str2.'</td></tr>'; + break; + } +} + +//================================================= +// import functions +//================================================= + +/// normalize relative links (= remove ..) +function book_prepare_link($ref) { + if ($ref == '') { + return ''; + } + $ref = str_replace('\\','/',$ref); //anti MS hack + $cnt = substr_count($ref, '..'); + for($i=0; $i<$cnt; $i++) { + $ref = ereg_replace('[^/]+/\.\./', '', $ref); + } + //still any '..' left?? == error! error! + if (substr_count($ref, '..') > 0) { + return ''; + } + if (ereg('[\|\`]', $ref)) { // check for other bad characters + return ''; + } + return $ref; +} + +/// read chapter content from file +function book_read_chapter($base, $ref) { + $file = $base.'/'.$ref; + if (filesize($file) <= 0 or !is_readable($file)) { + book_log($ref, get_string('error'), 2); + return; + } + //first read data + $handle = fopen($file, "rb"); + $contents = fread($handle, filesize($file)); + fclose($handle); + //extract title + $chapter = new object(); + if (preg_match('/<title>([^<]+)<\/title>/i', $contents, $matches)) { + $chapter->title = $matches[1]; + } else { + $chapter->title = $ref; + } + //extract page body + if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { + $chapter->content = $matches[1]; + } else { + book_log($ref, get_string('error'), 2); + return; + } + book_log($ref, get_string('ok')); + $chapter->importsrc = $ref; + //extract page head + if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { + $head = $matches[1]; + if (preg_match('/charset=([^"]+)/is', $head, $matches)) { + $enc = $matches[1]; + $textlib = textlib_get_instance(); + $chapter->content = $textlib->convert($chapter->content, $enc, current_charset()); + $chapter->title = $textlib->convert($chapter->title, $enc, current_charset()); + } + if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css + for($i=0; $i<count($matches[0]); $i++){ + $chapter->content = $matches[0][$i]."\n".$chapter->content; + } + } + } + return $chapter; +} + +///relink images and relative links +function book_relink($id, $bookid, $courseid) { + global $CFG; + if ($CFG->slasharguments) { + $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; + } else { + $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; + } + $chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, title, content, importsrc'); + $originals = array(); + foreach($chapters as $ch) { + $originals[$ch->importsrc] = $ch; + } + foreach($chapters as $ch) { + $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); + $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) + $modified = false; + //image relinking + if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { + for($i = 0; $i<count($images[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link + $link = book_prepare_link($base.$images[2][$i]); + if ($link == '') { + continue; + } + $origtag = $images[0][$i]; + $newtag = $images[1][$i].$link.$images[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $images[2][$i].' --> '.$link); + } + } + } + //css relinking (dlnsk) + if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { + for($i = 0; $i<count($csslinks[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link + $link = book_prepare_link($base.$csslinks[2][$i]); + if ($link == '') { + continue; + } + $origtag = $csslinks[0][$i]; + $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $csslinks[2][$i].' --> '.$link); + } + } + } + //general embed relinking - flash and others?? + if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { + for($i = 0; $i<count($embeds[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link + $link = book_prepare_link($base.$embeds[2][$i]); + if ($link == '') { + continue; + } + $origtag = $embeds[0][$i]; + $newtag = $embeds[1][$i].$link.$embeds[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $embeds[2][$i].' --> '.$link); + } + } + } + //flash in IE <param name=movie value="something" - I do hate IE! + if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { + for($i = 0; $i<count($params[0]); $i++) { + if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { + if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link + $link = book_prepare_link($base.$values[2]); + if ($link == '') { + continue; + } + $newvalue = $values[1].$link.$values[3]; + $newparam = str_replace($values[0], $newvalue, $params[0][$i]); + $ch->content = str_replace($params[0][$i], $newparam, $ch->content); + $modified = true; + book_log($ch->title, $values[2].' --> '.$link); + } + } + } + } + //java applet - add code bases if not present!!!! + if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { + for($i = 0; $i<count($applets[0]); $i++) { + if (!stripos($applets[0][$i], 'codebase')) { + $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); + $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); + $modified = true; + } + } + } + //relink java applet code bases + if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { + for($i = 0; $i<count($codebases[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link + $link = book_prepare_link($base.$codebases[2][$i]); + if ($link == '') { + continue; + } + $origtag = $codebases[0][$i]; + $newtag = $codebases[1][$i].$link.$codebases[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $codebases[2][$i].' --> '.$link); + } + } + } + //relative link conversion + if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { + for($i = 0; $i<count($links[0]); $i++) { + if ($links[2][$i] != '' //check for inner anchor links + && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link + $origtag = $links[0][$i]; + $target = book_prepare_link($rel.$links[2][$i]); //target chapter + if ($target != '' && array_key_exists($target, $originals)) { + $o = $originals[$target]; + $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; + $newtag = preg_replace('/target=[^\s>]/i','', $newtag); + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); + } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links + $target = book_prepare_link($base.$links[2][$i]); + $origtag = $links[0][$i]; + $newtag = $links[1][$i].$target.$links[4][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $links[2][$i].' --> '.$target); + } + } + } + } + if ($modified) { + $ch->title = addslashes($ch->title); + $ch->content = addslashes($ch->content); + $ch->importsrc = addslashes($ch->importsrc); + if (!update_record('book_chapters', $ch)) { + error('Could not update your book'); + } + } + } +} diff --git a/mod_form.php b/mod_form.php index ac5634c5382..3b3a48d4f84 100644 --- a/mod_form.php +++ b/mod_form.php @@ -1,6 +1,9 @@ <?php -require_once($CFG->dirroot.'/mod/book/lib.php'); -require_once ($CFG->dirroot.'/course/moodleform_mod.php'); + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot.'/mod/book/locallib.php'); +require_once($CFG->dirroot.'/course/moodleform_mod.php'); class mod_book_mod_form extends moodleform_mod { diff --git a/move.php b/move.php index ba4ee24ddd3..f20edd9a3f6 100644 --- a/move.php +++ b/move.php @@ -1,6 +1,9 @@ <?php require('teacheraccess.php'); //page only for teachers + +require_once($CFG->dirroot.'/mod/book/locallib.php'); + $up = optional_param('up', 0, PARAM_BOOL); diff --git a/print.php b/print.php index b09166f0ece..e83299d1041 100644 --- a/print.php +++ b/print.php @@ -1,7 +1,7 @@ <?php require_once('../../config.php'); -require_once('lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID diff --git a/settings.php b/settings.php index 00fea531d4e..c0de9f7486d 100644 --- a/settings.php +++ b/settings.php @@ -1,9 +1,10 @@ <?php -$choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', - '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); +defined('MOODLE_INTERNAL') || die; +if ($ADMIN->fulltree) { -$settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'book'), - get_string('tocwidth', 'book'), '180', $choices)); + $choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); + $settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'book'), get_string('tocwidth', 'book'), '180', $choices)); +} \ No newline at end of file diff --git a/show.php b/show.php index c244c652e8b..c8eeca65e58 100644 --- a/show.php +++ b/show.php @@ -2,6 +2,8 @@ require('teacheraccess.php'); //page only for teachers +require_once($CFG->dirroot.'/mod/book/locallib.php'); + ///switch hidden state $chapter->hidden = $chapter->hidden ? 0 : 1; diff --git a/styles.php b/styles.css similarity index 100% rename from styles.php rename to styles.css diff --git a/toc.php b/toc.php index 1c51c9a7070..c165590f585 100644 --- a/toc.php +++ b/toc.php @@ -1,6 +1,6 @@ <?php -defined('MOODLE_INTERNAL') or die('Direct access to this script is forbidden.'); +defined('MOODLE_INTERNAL') || die(); /// included from mod/book/view.php and print.php /// @@ -27,16 +27,16 @@ $title = ''; $first = 1; switch ($book->numbering) { - case NUM_NONE: + case BOOK_NUM_NONE: $toc .= '<div class="book_toc_none">'; break; - case NUM_NUMBERS: + case BOOK_NUM_NUMBERS: $toc .= '<div class="book_toc_numbered">'; break; - case NUM_BULLETS: + case BOOK_NUM_BULLETS: $toc .= '<div class="book_toc_bullets">'; break; - case NUM_INDENTED: + case BOOK_NUM_INDENTED: $toc .= '<div class="book_toc_indented">'; break; } @@ -58,13 +58,13 @@ if ($print) { ///TOC for printing $nch++; $ns = 0; $toc .= ($first) ? '<li>' : '</ul></li><li>'; - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch $title"; } } else { $ns++; $toc .= ($first) ? '<li><ul><li>' : '<li>'; - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch.$ns $title"; } } @@ -86,11 +86,11 @@ if ($print) { ///TOC for printing if (!$ch->hidden) { $nch++; $ns = 0; - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch $title"; } } else { - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "x $title"; } $title = '<span class="dimmed_text">'.$title.'</span>'; @@ -100,11 +100,11 @@ if ($print) { ///TOC for printing $toc .= ($first) ? '<li><ul><li>' : '<li>'; if (!$ch->hidden) { $ns++; - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch.$ns $title"; } } else { - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "x.x $title"; } $title = '<span class="dimmed_text">'.$title.'</span>'; @@ -152,14 +152,14 @@ if ($print) { ///TOC for printing $nch++; $ns = 0; $toc .= ($first) ? '<li>' : '</ul></li><li>'; - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch $title"; } $prevtitle = $title; } else { $ns++; $toc .= ($first) ? '<li><ul><li>' : '<li>'; - if ($book->numbering == NUM_NUMBERS) { + if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch.$ns $title"; } } diff --git a/view.php b/view.php index 2e1ca50a208..afc4387751c 100644 --- a/view.php +++ b/view.php @@ -1,7 +1,7 @@ <?php require('../../config.php'); -require_once('lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID From 3c5e59cbac5a681f60200363f9129dd8419fa6a3 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 15:54:17 +0100 Subject: [PATCH 050/455] conversion to 2.0 --- lib.php | 172 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 67 deletions(-) diff --git a/lib.php b/lib.php index 903ddc30cc0..f9ebfabb0c7 100644 --- a/lib.php +++ b/lib.php @@ -1,15 +1,39 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book module core interaction API + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die; - -/// Library of functions and constants for module 'book' - +/** + * Add book instance. + * + * @param stdClass $data + * @param stdClass $mform + * @return int new book instance id + */ function book_add_instance($book) { -/// Given an object containing all the necessary data, -/// (defined by the form in mod.html) this function -/// will create a new instance and return the id number -/// of the new instance. + global $DB; $book->timecreated = time(); $book->timemodified = $book->timecreated; @@ -20,14 +44,18 @@ function book_add_instance($book) { $book->disableprinting = 0; } - return insert_record('book', $book); + return $DB->insert_record('book', $book); } - +/** + * Update book instance. + * + * @param stdClass $data + * @param stdClass $mform + * @return bool true + */ function book_update_instance($book) { -/// Given an object containing all the necessary data, -/// (defined by the form in mod.html) this function -/// will update an existing instance with new data. + global $DB; $book->timemodified = time(); $book->id = $book->instance; @@ -38,96 +66,85 @@ function book_update_instance($book) { $book->disableprinting = 0; } - # May have to add extra stuff in here # + $DB->update_record('book', $book); - return update_record('book', $book); + return true; } - +/** + * + * Given an ID of an instance of this module, + * this function will permanently delete the instance + * and any data that depends on it. + * + * @param int $id + * @return bool success + */ function book_delete_instance($id) { -/// Given an ID of an instance of this module, -/// this function will permanently delete the instance -/// and any data that depends on it. + global $DB; - if (! $book = get_record('book', 'id', $id)) { + if (!$book = $DB->get_record('book', array('id'=>$id))) { return false; } - $result = true; + $DB->delete_records('book_chapters', array('bookid'=>$book->id)); + $DB->delete_records('book', array('id'=>$book->id)); - delete_records('book_chapters', 'bookid', $book->id); - - if (! delete_records('book', 'id', $book->id)) { - $result = false; - } - - return $result; + return true; } - function book_get_types() { - global $CFG; - - $types = array(); - - $type = new object(); + $type = new stdClass(); $type->modclass = MOD_CLASS_RESOURCE; - $type->type = 'book'; - $type->typestr = get_string('modulename', 'book'); - $types[] = $type; + $type->type = 'book'; + $type->typestr = get_string('modulename', 'book'); - return $types; + return array($type); } -function book_user_outline($course, $user, $mod, $book) { -/// Return a small object with summary information about what a -/// user has done with a given particular instance of this module -/// Used for user activity reports. -/// $return->time = the time they did it -/// $return->info = a short text description - $return = null; - return $return; +function book_user_outline($course, $user, $mod, $book) { + // Return a small object with summary information about what a + // user has done with a given particular instance of this module + // Used for user activity reports. + // $return->time = the time they did it + // $return->info = a short text description + + return null; } function book_user_complete($course, $user, $mod, $book) { -/// Print a detailed representation of what a user has done with -/// a given particular instance of this module, for user activity reports. + // Print a detailed representation of what a user has done with + // a given particular instance of this module, for user activity reports. return true; } function book_print_recent_activity($course, $isteacher, $timestart) { -/// Given a course and a time, this module should find recent activity -/// that has occurred in book activities and print it out. -/// Return true if there was output, or false is there was none. - - global $CFG; - + // Given a course and a time, this module should find recent activity + // that has occurred in book activities and print it out. + // Return true if there was output, or false is there was none. return false; // True if anything was printed, otherwise false } function book_cron () { -/// Function to be run periodically according to the moodle cron -/// This function searches for things that need to be done, such -/// as sending out mail, toggling flags etc ... - - global $CFG; - + // Function to be run periodically according to the moodle cron + // This function searches for things that need to be done, such + // as sending out mail, toggling flags etc ... return true; } function book_grades($bookid) { -/// Must return an array of grades for a given instance of this module, -/// indexed by user. It also returns a maximum allowed grade. + // Must return an array of grades for a given instance of this module, + // indexed by user. It also returns a maximum allowed grade. - return NULL; + return null; } function book_get_participants($bookid) { -//Must return an array of user records (all data) who are participants -//for a given instance of book. Must include every user involved -//in the instance, independient of his role (student, teacher, admin...) -//See other modules as example. + //Must return an array of user records (all data) who are participants + //for a given instance of book. Must include every user involved + //in the instance, independent of his role (student, teacher, admin...) + //See other modules as example. return false; } @@ -137,11 +154,12 @@ function book_get_participants($bookid) { * it it has support for grading and scales. Commented code should be * modified if necessary. See forum, glossary or journal modules * as reference. + * * @param $bookid int * @param $scaleid int * @return boolean True if the scale is used by any journal */ -function book_scale_used ($bookid,$scaleid) { +function book_scale_used($bookid,$scaleid) { return false; } @@ -149,6 +167,7 @@ function book_scale_used ($bookid,$scaleid) { * Checks if scale is being used by any instance of book * * This is used to find out if scale used anywhere + * * @param $scaleid int * @return boolean True if the scale is used by any journal */ @@ -163,3 +182,22 @@ function book_get_view_actions() { function book_get_post_actions() { return array('update'); } + +/** + * Supported features + * + * @param string $feature FEATURE_xx constant for requested feature + * @return mixed True if module supports feature, false if not, null if doesn't know + */ +function book_supports($feature) { + switch($feature) { + case FEATURE_GROUPS: return false; + case FEATURE_GROUPINGS: return false; + case FEATURE_GROUPMEMBERSONLY: return true; + case FEATURE_MOD_INTRO: return true; + case FEATURE_COMPLETION_TRACKS_VIEWS: return false; //TODO + case FEATURE_BACKUP_MOODLE2: return false; //TODO + + default: return null; + } +} From 2c1e98e663e4dfa316b48fe2b098e177ad7983e6 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 16:04:20 +0100 Subject: [PATCH 051/455] conversion to 2.0 --- README | 8 +++--- db/upgrade.php | 13 ++-------- delete.php | 53 ++++++++++++++++++++++++++++++-------- edit.php | 65 ++++++++++++++++++++++++++--------------------- edit_form.php | 28 +++++++++++++++++--- import.php | 51 ++++++++++++++++++++++--------------- import_form.php | 27 ++++++++++++++++++-- index.php | 8 +++--- locallib.php | 35 ++++++++++++------------- mod_form.php | 43 ++++++++++++++++++++++++------- move.php | 46 ++++++++++++++++++++++++++++++--- print.php | 49 +++++++++++++++++++++-------------- restorelib.php | 4 +-- settings.php | 23 +++++++++++++++++ show.php | 56 ++++++++++++++++++++++++++++++++-------- teacheraccess.php | 42 ------------------------------ toc.php | 23 +++++++++++++++++ version.php | 25 +++++++++++++++--- view.php | 49 +++++++++++++++++++++-------------- 19 files changed, 437 insertions(+), 211 deletions(-) delete mode 100644 teacheraccess.php diff --git a/README b/README index d8d127e0e88..d9308a4d9fe 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ Book module for Moodle -Copyright (C) 2004-2010 Petr Skoda (http:skodak.org) +Copyright (C) 2004-2010 Petr Skoda (http://skodak.org) This program is free software; you can redistribute it and/or modify @@ -28,7 +28,6 @@ Installation: * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins List of features - version 2.0: - * easy to use - new teachers can quickly create multipage study materials * two levels - only chapters and subchapters * possible automatic chapter numbering @@ -39,11 +38,10 @@ List of features - version 2.0: * support for global searching in study materials (see contrib/search) * import from html files (relinking of images, flash, Java applets and relative links) - * works with MySQL and PostgreSQL databases + * works with all supported databases Intentionally omitted features: - * more chapter levels - it would encourage teachers to write too much complex and long books, better use standard standalone HTML editor and import it as Resource. DocBook format is another suitable solution. @@ -55,7 +53,7 @@ Intentionally omitted features: Save page as... in print view Future: - * I like eXe editor, I would like to improve Book in this direction ... ;-) + * I like eXe editor, I would like to improve Book in this direction ... CHANGELOG: == 1.1RC1 - 2004/11/15 ======================================================= diff --git a/db/upgrade.php b/db/upgrade.php index c2496c9fd58..957faa5ccf6 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -66,17 +66,7 @@ function xmldb_book_upgrade($oldversion) { $dbman->add_field($table, $field); } - // conditionally migrate to html format in intro - if ($CFG->texteditors !== 'textarea') { - $rs = $DB->get_recordset('book', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat'); - foreach ($rs as $r) { - $r->intro = text_to_html($r->intro, false, false, true); - $r->introformat = FORMAT_HTML; - $DB->update_record('book', $r); - upgrade_set_timeout(); - } - $rs->close(); - } + $DB->set_field('book', 'introformat', FORMAT_HTML, array()); // book savepoint reached upgrade_mod_savepoint(true, 2010120802, 'book'); @@ -114,6 +104,7 @@ function xmldb_book_upgrade($oldversion) { } + //TODO: add contentformat into book_chapters //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter diff --git a/delete.php b/delete.php index 90e371d004a..271bf962962 100644 --- a/delete.php +++ b/delete.php @@ -1,10 +1,46 @@ <?php +// This file is part of Book module for 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/>. -require('teacheraccess.php'); //page only for teachers +/** + * Delete book chapter + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); -$confirm = optional_param('confirm', 0, PARAM_BOOL); +$id = required_param('id', PARAM_INT); // Course Module ID +$chapterid = required_param('chapterid', PARAM_INT); // Chapter ID +$confirm = optional_param('confirm', 0, PARAM_BOOL); + +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); + +require_login($course, false, $cm); +require_sesskey(); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/book:edit', $context); + +$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); ///header and strings @@ -18,29 +54,26 @@ print_header("$course->shortname: $book->name", $course->fullname, $navigation); ///form processing if ($confirm) { // the operation was confirmed. if (!$chapter->subchapter) { //delete all its subchapters if any - $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, subchapter'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter'); $found = false; foreach($chapters as $ch) { if ($ch->id == $chapter->id) { $found = true; } else if ($found and $ch->subchapter) { - if (!delete_records('book_chapters', 'id', $ch->id)) { - error('Could not update your book'); - } + $DB->delete_records('book_chapters', array('id'=>$ch->id)); } else if ($found) { break; } } } - if (!delete_records('book_chapters', 'id', $chapter->id)) { - error('Could not update your book'); - } + $DB->delete_records('book_chapters', array('id'=>$chapter->id)); add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); + book_check_structure($book->id); redirect('view.php?id='.$cm->id); - die; + } else { // the operation has not been confirmed yet so ask the user to do so if ($chapter->subchapter) { diff --git a/edit.php b/edit.php index 0e6ddc0f27b..8b31df38491 100644 --- a/edit.php +++ b/edit.php @@ -1,8 +1,31 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Edit book chapter + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); -require_once('edit_form.php'); +require_once($CFG->dirroot.'edit_form.php'); $cmid = required_param('cmid', PARAM_INT); // Book Course Module ID $chapterid = optional_param('id', 0, PARAM_INT); // Chapter ID @@ -13,30 +36,17 @@ $subchapter = optional_param('subchapter', 0, PARAM_BOOL); // security checks START - only teachers edit // ========================================================================= -if (!$cm = get_coursemodule_from_id('book', $cmid)) { - error('Course Module ID was incorrect'); -} - -if (!$course = get_record('course', 'id', $cm->course)) { - error('Course is misconfigured'); -} +$cm = get_coursemodule_from_id('book', $cmid, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:edit', $context); -if (!$book = get_record('book', 'id', $cm->instance)) { - error('Course module is incorrect'); -} - if ($chapterid) { - if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { - error('Incorrect chapter id'); - } - if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! - error('Chapter not part of this book!'); - } + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); } else { $chapter = null; } @@ -66,12 +76,11 @@ if ($mform->is_cancelled()) { redirect("view.php?id=$cm->id&chapterid=$chapter->id"); } -} else if ($data = $mform->get_data(false)) { +} else if ($data = $mform->get_data()) { if ($data->id) { - if (!update_record('book_chapters', addslashes_recursive($data))) { - error('Could not update your book'); - } + $DB->update_record('book_chapters', $data); + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); @@ -84,21 +93,19 @@ if ($mform->is_cancelled()) { $data->importsrc = ''; // make room for new page - $sql = "UPDATE {$CFG->prefix}book_chapters + $sql = "UPDATE {book_chapters} SET pagenum = pagenum + 1 - WHERE bookid = $book->id AND pagenum >= $data->pagenum"; - execute_sql($sql, false); + WHERE bookid = ? AND pagenum >= ?"; + $DB->execute($sql, array($book->id, $data->pagenum)); + + $data->id = $DB->insert_record('book_chapters', $data); - if (!$data->id = insert_record('book_chapters', addslashes_recursive($data))) { - error('Could not insert a new chapter'); - } add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); } book_check_structure($book->id); redirect("view.php?id=$cm->id&chapterid=$data->id"); - die; } /// Otherwise fill and print the form. diff --git a/edit_form.php b/edit_form.php index 3c53e66476a..c51e4fae9de 100644 --- a/edit_form.php +++ b/edit_form.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Chapter edit form + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die; @@ -8,7 +31,7 @@ class book_chapter_edit_form extends moodleform { function definition() { global $CFG; - $mform =& $this->_form; + $mform = $this->_form; $cm = $this->_customdata; $mform->addElement('header', 'general', get_string('edit')); @@ -21,7 +44,6 @@ class book_chapter_edit_form extends moodleform { $mform->addElement('htmleditor', 'content', get_string('content', 'book'), array('cols'=>50, 'rows'=>30)); $mform->setType('content', PARAM_RAW); - $mform->setHelpButton('content', array('reading', 'writing', 'questions', 'richtext'), false, 'editorhelpbutton'); $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); @@ -42,7 +64,7 @@ class book_chapter_edit_form extends moodleform { function definition_after_data() { global $CFG; - $mform =& $this->_form; + $mform = $this->_form; if ($mform->getElementValue('id')) { if ($mform->elementExists('doimport')) { diff --git a/import.php b/import.php index a5e9cffd3e4..6905da7430e 100644 --- a/import.php +++ b/import.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book import + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); @@ -10,23 +33,15 @@ $id = required_param('id', PARAM_INT); // Course Module ID // security checks START - only teachers edit // ========================================================================= -if (!$cm = get_coursemodule_from_id('book', $id)) { - error('Course Module ID was incorrect'); -} - -if (!$course = get_record('course', 'id', $cm->course)) { - error('Course is misconfigured'); -} +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:import', $context); -if (!$book = get_record('book', 'id', $cm->instance)) { - error('Course module is incorrect'); -} - //check all variables unset($id); @@ -94,12 +109,9 @@ if ($mform->is_cancelled()) { foreach($refs as $ref) { $chapter = book_read_chapter($coursebase, $ref); if ($chapter) { - $chapter->title = addslashes($chapter->title); - $chapter->content = addslashes($chapter->content); - $chapter->importsrc = addslashes($chapter->importsrc); - $chapter->bookid = $book->id; - $chapter->pagenum = count_records('book_chapters', 'bookid', $book->id)+1; - $chapter->timecreated = time(); + $chapter->bookid = $book->id; + $chapter->pagenum = $DB->count_records('book_chapters', array('bookid'=>$book->id)+1; + $chapter->timecreated = time(); $chapter->timemodified = time(); echo "imsrc:".$chapter->importsrc; if (($data->subchapter) || preg_match('/_sub\.htm/i', $chapter->importsrc)) { //if filename or directory starts with sub_* treat as subdirecotories @@ -107,9 +119,8 @@ if ($mform->is_cancelled()) { } else { $chapter->subchapter = 0; } - if (!$chapter->id = insert_record('book_chapters', $chapter)) { - error('Could not update your book'); - } + $chapter->id = $DB->insert_record('book_chapters', $chapter); + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); } diff --git a/import_form.php b/import_form.php index 74f2a3cf838..aeb76764ced 100644 --- a/import_form.php +++ b/import_form.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book import form + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require_once($CFG->libdir.'/formslib.php'); @@ -6,7 +29,7 @@ class book_import_form extends moodleform { function definition() { global $CFG; - $mform =& $this->_form; + $mform = $this->_form; $cm = $this->_customdata; $mform->addElement('header', 'general', get_string('import')); @@ -36,7 +59,7 @@ class book_import_form extends moodleform { $cm = $this->_customdata; $errors = parent::validation($data, $files); - $reference = stripslashes($data['reference']); + $reference = $data['reference']; if ($reference != '') { //null path is root $reference = book_prepare_link($reference); diff --git a/index.php b/index.php index 1420a85802b..eb7c4e67865 100644 --- a/index.php +++ b/index.php @@ -11,9 +11,7 @@ $id = required_param('id', PARAM_INT); // Course Module ID // security checks START - teachers and students view // ========================================================================= -if (!$course = get_record('course', 'id', $id)) { - error('Course ID is incorrect'); -} +$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST); require_course_login($course, true); @@ -65,7 +63,7 @@ $currentsection = ''; foreach ($books as $book) { $nocleanoption = new object(); $nocleanoption->noclean = true; - $book->summary = format_text($book->summary, FORMAT_HTML, $nocleanoption, $course->id); + $book->summary = format_text($book->intro, $book->introformat, $nocleanoption, $course->id); $book->summary = '<span style="font-size:x-small;">'.$book->summary.'</span>'; if (!$book->visible) { @@ -76,7 +74,7 @@ foreach ($books as $book) { $link = '<a href="view.php?id='.$book->coursemodule.'">'.$book->name.'</a>'; } - $count = count_records('book_chapters', 'bookid', $book->id, 'hidden', '0'); + $count = $DB->count_records('book_chapters', array('bookid'=>$book->id, 'hidden'=>'0')); if ($course->format == 'weeks' or $course->format == 'topics') { $printsection = ''; diff --git a/locallib.php b/locallib.php index 3b8f833d9b4..3d1d8601dff 100644 --- a/locallib.php +++ b/locallib.php @@ -44,11 +44,16 @@ function book_get_numbering_types() { /// Any other book functions go here. Each of them must have a name that /// starts with book_ -//check chapter ordering and -//make sure subchapter is not first in book -//hidden chapter must have all subchapters hidden too +/** + * check chapter ordering and make sure subchapter is not first + * in book hidden chapter must have all subchapters hidden too + * @param int $id + * @return void + */ function book_check_structure($bookid) { - if ($chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, subchapter, hidden')) { + global $DB; + + if ($chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, subchapter, hidden')) { $first = true; $hidesub = true; $i = 1; @@ -63,7 +68,7 @@ function book_check_structure($bookid) { $ch->hidden = $hidesub ? true : $ch->hidden; } $ch->pagenum = $i; - update_record('book_chapters', $ch); + $DB->update_record('book_chapters', $ch); $i++; } } @@ -71,11 +76,11 @@ function book_check_structure($bookid) { /// prepare button to turn chapter editing on - connected with course editing -function book_edit_button($id, $courseid, $chapterid) { +function book_edit_button($book, $cm, $chapter) { global $CFG, $USER; - if (isteacheredit($courseid)) { + if (has_capability('mod/book:edit', get_context_instance(CONTEXT_MODULE, $cm->id))) { if (!empty($USER->editing)) { $string = get_string("turneditingoff"); $edit = '0'; @@ -84,8 +89,8 @@ function book_edit_button($id, $courseid, $chapterid) { $edit = '1'; } return '<form method="get" action="'.$CFG->wwwroot.'/mod/book/view.php"><div>'. - '<input type="hidden" name="id" value="'.$id.'" />'. - '<input type="hidden" name="chapterid" value="'.$chapterid.'" />'. + '<input type="hidden" name="id" value="'.$cm->id.'" />'. + '<input type="hidden" name="chapterid" value="'.$chapter->id.'" />'. '<input type="hidden" name="edit" value="'.$edit.'" />'. '<input type="submit" value="'.$string.'" /></div></form>'; } else { @@ -179,13 +184,14 @@ function book_read_chapter($base, $ref) { ///relink images and relative links function book_relink($id, $bookid, $courseid) { - global $CFG; + global $CFG, $DB; + if ($CFG->slasharguments) { $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; } else { $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; } - $chapters = get_records('book_chapters', 'bookid', $bookid, 'pagenum', 'id, pagenum, title, content, importsrc'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, title, content, importsrc'); $originals = array(); foreach($chapters as $ch) { $originals[$ch->importsrc] = $ch; @@ -312,12 +318,7 @@ function book_relink($id, $bookid, $courseid) { } } if ($modified) { - $ch->title = addslashes($ch->title); - $ch->content = addslashes($ch->content); - $ch->importsrc = addslashes($ch->importsrc); - if (!update_record('book_chapters', $ch)) { - error('Could not update your book'); - } + $DB->update_record('book_chapters', $ch); } } } diff --git a/mod_form.php b/mod_form.php index 3b3a48d4f84..86465f112b8 100644 --- a/mod_form.php +++ b/mod_form.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Instance add/edit form + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die; @@ -8,21 +31,23 @@ require_once($CFG->dirroot.'/course/moodleform_mod.php'); class mod_book_mod_form extends moodleform_mod { function definition() { - global $CFG; - $mform =& $this->_form; + + $mform = $this->_form; //------------------------------------------------------------------------------- $mform->addElement('header', 'general', get_string('general', 'form')); $mform->addElement('text', 'name', get_string('name'), array('size'=>'64')); - $mform->setType('name', PARAM_TEXT); + if (!empty($CFG->formatstringstriptags)) { + $mform->setType('name', PARAM_TEXT); + } else { + $mform->setType('name', PARAM_CLEANHTML); + } $mform->addRule('name', null, 'required', null, 'client'); - $mform->addElement('htmleditor', 'summary', get_string('summary')); - $mform->setType('summary', PARAM_RAW); - $mform->addRule('summary', null, 'required', null, 'client'); - $mform->setHelpButton('summary', array('writing', 'questions', 'richtext'), false, 'editorhelpbutton'); + $this->add_intro_editor(true, get_string('summary')); + $mform->addElement('select', 'numbering', get_string('numbering', 'book'), book_get_numbering_types()); $mform->setHelpButton('numbering', array('numberingtype', get_string('numbering', 'book'), 'book')); @@ -35,10 +60,10 @@ class mod_book_mod_form extends moodleform_mod { $mform->setHelpButton('customtitles', array('customtitles', get_string('customtitles', 'book'), 'book')); $mform->setDefault('customtitles', 0); - $this->standard_coursemodule_elements(array('groups'=>false, 'groupmembersonly'=>true, 'gradecat'=>false)); +//------------------------------------------------------------------------------- + $this->standard_coursemodule_elements(); //------------------------------------------------------------------------------- - // buttons $this->add_action_buttons(); } diff --git a/move.php b/move.php index f20edd9a3f6..b7a10b47fcb 100644 --- a/move.php +++ b/move.php @@ -1,10 +1,47 @@ <?php +// This file is part of Book module for 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/>. -require('teacheraccess.php'); //page only for teachers +/** + * Move book chapter + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); -$up = optional_param('up', 0, PARAM_BOOL); +$id = required_param('id', PARAM_INT); // Course Module ID +$chapterid = required_param('chapterid', PARAM_INT); // Chapter ID +$up = optional_param('up', 0, PARAM_BOOL); + +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); + +require_login($course, false, $cm); +require_sesskey(); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/book:edit', $context); + +$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); $oldchapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, pagenum, subchapter'); @@ -137,13 +174,14 @@ if (!$nothing) { $i = 1; foreach ($newchapters as $ch) { $ch->pagenum = $i; - update_record('book_chapters', $ch); + $DB->update_record('book_chapters', $ch); $i++; } } add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); + book_check_structure($book->id); redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); -die; + diff --git a/print.php b/print.php index e83299d1041..c6d4d7c9401 100644 --- a/print.php +++ b/print.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book printing + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require_once('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); @@ -9,20 +32,13 @@ $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID // ========================================================================= // security checks START - teachers and students view // ========================================================================= -if (!$cm = get_coursemodule_from_id('book', $id)) { - error('Course Module ID was incorrect'); -} -if (!$course = get_record('course', 'id', $cm->course)) { - error('Course is misconfigured'); -} +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); require_course_login($course, true, $cm); -if (!$book = get_record('book', 'id', $cm->instance)) { - error('Course module is incorrect'); -} - if ($book->disableprinting) { error('Printing is disabled'); } @@ -34,12 +50,7 @@ require_capability('mod/book:print', $context); //check all variables if ($chapterid) { //single chapter printing - if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { - error('Incorrect chapter ID'); - } - if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! - error('Chapter not in this book!'); - } + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); if ($chapter->hidden) { error('Only visible chapters can be printed'); } @@ -63,13 +74,13 @@ $strtop = get_string('top', 'book'); @header('Accept-Ranges: none'); @header('Content-type: text/html; charset=utf-8'); -$formatoptions = new object(); +$formatoptions = new stdClass(); $formatoptions->noclean = true; if ($chapter) { add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); - $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum, title'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum, title'); $print = 0; $edit = 0; @@ -119,7 +130,7 @@ if ($chapter) { <body> <a name="top"></a> <p class="book_title"><?PHP echo format_string($book->name) ?></p> - <p class="book_summary"><?PHP echo format_string($book->summary) ?></p> + <p class="book_summary"><?PHP echo format_text($book->intro, $book->introformat) ?></p> <div class="book_info"><table> <tr> <td><?PHP echo get_string('site') ?>:</td> diff --git a/restorelib.php b/restorelib.php index b3dcf158bb7..d56f715dfd3 100644 --- a/restorelib.php +++ b/restorelib.php @@ -318,7 +318,7 @@ $result = restore_decode_content_links_worker($content,$restore); if ($result != $content) { //Update record - $book->summary = addslashes($result); + $book->intro $result; $status = update_record('book',$book); if ($CFG->debug>7) { if (!defined('RESTORE_SILENTLY')) { @@ -354,7 +354,7 @@ $result = restore_decode_content_links_worker($content,$restore); if ($result != $content) { //Update record - $chapter->content = addslashes($result); + $chapter->content = $result; $status = update_record('book_chapters',$chapter); if ($CFG->debug>7) { if (!defined('RESTORE_SILENTLY')) { diff --git a/settings.php b/settings.php index c0de9f7486d..e961d6afc0c 100644 --- a/settings.php +++ b/settings.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book plugin settings + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die; diff --git a/show.php b/show.php index c8eeca65e58..5adede206aa 100644 --- a/show.php +++ b/show.php @@ -1,30 +1,63 @@ <?php +// This file is part of Book module for 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/>. -require('teacheraccess.php'); //page only for teachers +/** + * Show/hide book chapter + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); +$id = required_param('id', PARAM_INT); // Course Module ID +$chapterid = required_param('chapterid', PARAM_INT); // Chapter ID + +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); + +require_login($course, false, $cm); +require_sesskey(); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/book:edit', $context); + +$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); + + ///switch hidden state $chapter->hidden = $chapter->hidden ? 0 : 1; -///add slashes to all text fields -$chapter->content = addslashes($chapter->content); -$chapter->title = addslashes($chapter->title); -$chapter->importsrc = addslashes($chapter->importsrc); -if (!update_record('book_chapters', $chapter)) { - error('Could not update your book'); -} +// update record +$DB->update_record('book_chapters', $chapter); ///change visibility of subchapters too if (!$chapter->subchapter) { - $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, subchapter, hidden'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter, hidden'); $found = 0; foreach($chapters as $ch) { if ($ch->id == $chapter->id) { $found = 1; } else if ($found and $ch->subchapter) { $ch->hidden = $chapter->hidden; - update_record('book_chapters', $ch); + $DB->update_record('book_chapters', $ch); } else if ($found) { break; } @@ -33,6 +66,7 @@ if (!$chapter->subchapter) { add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); + book_check_structure($book->id); redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); -die; + diff --git a/teacheraccess.php b/teacheraccess.php deleted file mode 100644 index a3f6807c3a3..00000000000 --- a/teacheraccess.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -///standard routine to allow only teachers in -///check of $id and $chapterid parameters - -require('../../config.php'); -require_once('lib.php'); - -$id = required_param('id', PARAM_INT); // Course Module ID -$chapterid = required_param('chapterid', PARAM_INT); // Chapter ID - -if (!confirm_sesskey()) { - error(get_string('confirmsesskeybad', 'error')); -} -if (!$cm = get_coursemodule_from_id('book', $id)) { - error('Course Module ID was incorrect'); -} - -if (!$course = get_record('course', 'id', $cm->course)) { - error('Course is misconfigured'); -} - -require_login($course, false, $cm); - -$context = get_context_instance(CONTEXT_MODULE, $cm->id); -require_capability('mod/book:edit', $context); - -if (!$book = get_record('book', 'id', $cm->instance)) { - error('Course module is incorrect'); -} - -if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { - error('Incorrect chapter ID'); -} - -if ($chapter->bookid != $book->id) {//chapter id not in this book!!!! - error('Chapter not in this book!'); -} - -//check all variables -unset($id); -unset($chapterid); diff --git a/toc.php b/toc.php index c165590f585..1c6ebe0b3df 100644 --- a/toc.php +++ b/toc.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book toc printing + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ defined('MOODLE_INTERNAL') || die(); diff --git a/version.php b/version.php index 66ee6036b99..2ebf092ba39 100644 --- a/version.php +++ b/version.php @@ -1,8 +1,27 @@ <?php +// This file is part of Book module for 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/>. -///////////////////////////////////////////////////////////////////////////////// -/// Called by moodle_needs_upgrading() and /admin/index.php -///////////////////////////////////////////////////////////////////////////////// +/** + * Book plugin version info + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ $module->version = 2010120803; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version diff --git a/view.php b/view.php index afc4387751c..4c6390e27da 100644 --- a/view.php +++ b/view.php @@ -1,4 +1,27 @@ <?php +// This file is part of Book module for 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/>. + +/** + * Book view page + * + * @package mod + * @subpackage book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); @@ -10,17 +33,9 @@ $edit = optional_param('edit', -1, PARAM_BOOL); // Edit mode // ========================================================================= // security checks START - teachers edit; students view // ========================================================================= -if (!$cm = get_coursemodule_from_id('book', $id)) { - error('Course Module ID was incorrect'); -} - -if (!$course = get_record('course', 'id', $cm->course)) { - error('Course is misconfigured'); -} - -if (!$book = get_record('book', 'id', $cm->instance)) { - error('Course module is incorrect'); -} +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); require_course_login($course, true, $cm); @@ -48,8 +63,8 @@ if ($allowedit) { } /// read chapters -$select = $viewhidden ? "bookid = $book->id" : "bookid = $book->id AND hidden = 0"; -$chapters = get_records_select('book_chapters', $select, 'pagenum', 'id, pagenum, subchapter, title, hidden'); +$select = $viewhidden ? array('bookid' => $book->id) : array('bookid' => $book->id, 'hidden' => 0); +$chapters = $DB->get_records('book_chapters', $select, 'pagenum', 'id, pagenum, subchapter, title, hidden'); if (!$chapters) { if ($allowedit) { @@ -74,7 +89,7 @@ if ($chapterid == '0') { // go to first chapter if no given } -if (!$chapter = get_record('book_chapters', 'id', $chapterid)) { +if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id))) { error('Error reading book chapters.'); } @@ -87,10 +102,6 @@ if (!$viewhidden and $chapter->hidden) { error('Error reading book chapters.'); } -/// chapter not part of this book! -if ($chapter->bookid != $book->id) { - error('Chapter not part of this book!'); -} // ========================================================================= // security checks END // ========================================================================= @@ -107,7 +118,7 @@ $strTOC = get_string('TOC', 'book'); $navigation = build_navigation('', $cm); $buttons = $allowedit ? '<table cellspacing="0" cellpadding="0"><tr><td>'.update_module_button($cm->id, $course->id, $strbook).'</td>'. - '<td> </td><td>'.book_edit_button($cm->id, $course->id, $chapter->id).'</td></tr></table>' + '<td> </td><td>'.book_edit_button($book, $cm, $chapter).'</td></tr></table>' : ' '; print_header( "$course->shortname: $book->name ($chapter->title)", From bd4eba6716e441cdc58b6491d51c1325b1d1b301 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:01:48 +0100 Subject: [PATCH 052/455] fixed upgrade path --- db/install.xml | 5 +++-- db/upgrade.php | 46 ++++++++++++++++++++++++++++++++++++++-------- version.php | 2 +- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/db/install.xml b/db/install.xml index f6a2bf5b916..92ee3b275c0 100644 --- a/db/install.xml +++ b/db/install.xml @@ -28,8 +28,9 @@ <FIELD NAME="pagenum" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="bookid" NEXT="subchapter"/> <FIELD NAME="subchapter" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="pagenum" NEXT="title"/> <FIELD NAME="title" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="subchapter" NEXT="content"/> - <FIELD NAME="content" TYPE="text" LENGTH="big" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="title" NEXT="hidden"/> - <FIELD NAME="hidden" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="content" NEXT="timecreated"/> + <FIELD NAME="content" TYPE="text" LENGTH="big" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="title" NEXT="contentformat"/> + <FIELD NAME="contentformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="content" NEXT="hidden"/> + <FIELD NAME="hidden" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="contentformat" NEXT="timecreated"/> <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="hidden" NEXT="timemodified"/> <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timecreated" NEXT="importsrc"/> <FIELD NAME="importsrc" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="timemodified"/> diff --git a/db/upgrade.php b/db/upgrade.php index 957faa5ccf6..67e46c4c76f 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -52,11 +52,26 @@ function xmldb_book_upgrade($oldversion) { // Launch rename field summary $dbman->rename_field($table, $field, 'intro'); + // Launch rename field summary + $dbman->change_field_precision($table, $field, 'intro'); + // book savepoint reached upgrade_mod_savepoint(true, 2010120801, 'book'); } if ($oldversion < 2010120802) { + // Rename field summary on table book to intro + $table = new xmldb_table('book'); + $field = new xmldb_field('intro', XMLDB_TYPE_TEXT, 'large', null, null, null, null, 'name'); + + // Launch rename field summary + $dbman->change_field_precision($table, $field); + + // book savepoint reached + upgrade_mod_savepoint(true, 2010120802, 'book'); + } + + if ($oldversion < 2010120803) { // Define field introformat to be added to book $table = new xmldb_table('book'); $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro'); @@ -69,10 +84,26 @@ function xmldb_book_upgrade($oldversion) { $DB->set_field('book', 'introformat', FORMAT_HTML, array()); // book savepoint reached - upgrade_mod_savepoint(true, 2010120802, 'book'); + upgrade_mod_savepoint(true, 2010120803, 'book'); } - if ($oldversion < 2010120803) { + if ($oldversion < 2010120804) { + // Define field introformat to be added to book + $table = new xmldb_table('book_chapters'); + $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'content'); + + // Launch add field introformat + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $DB->set_field('book_chapters', 'contentformat', FORMAT_HTML, array()); + + // book savepoint reached + upgrade_mod_savepoint(true, 2010120804, 'book'); + } + + if ($oldversion < 2010120805) { require_once("$CFG->dirroot/mod/book/db/upgradelib.php"); $sqlfrom = "FROM {book} b @@ -103,15 +134,14 @@ function xmldb_book_upgrade($oldversion) { $rs->close(); } - - //TODO: add contentformat into book_chapters - //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter - - // book savepoint reached - upgrade_mod_savepoint(true, 2010120803, 'book'); + upgrade_mod_savepoint(true, 2010120805, 'book'); } + + //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter + + return true; } diff --git a/version.php b/version.php index 2ebf092ba39..029d3ed0a26 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2010120803; // The current module version (Date: YYYYMMDDXX) +$module->version = 2010120805; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) From 3eccc86133ea726a3e1771fd2c530c3a8074f7b7 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:08:28 +0100 Subject: [PATCH 053/455] adding pluginname string --- lang/be/book.php | 1 + lang/ca/book.php | 1 + lang/cs/book.php | 1 + lang/de/book.php | 1 + lang/en/book.php | 1 + lang/es/book.php | 1 + lang/fi/book.php | 1 + lang/fr/book.php | 1 + lang/id/book.php | 1 + lang/it/book.php | 1 + lang/ja/book.php | 1 + lang/nl/book.php | 1 + lang/pl/book.php | 1 + lang/pt_br/book.php | 1 + lang/sk/book.php | 1 + lang/sl/book.php | 1 + lang/sv/book.php | 1 + 17 files changed, 17 insertions(+) diff --git a/lang/be/book.php b/lang/be/book.php index da69c253376..95868b6bb44 100644 --- a/lang/be/book.php +++ b/lang/be/book.php @@ -29,6 +29,7 @@ $string['numbering0'] = 'Няма'; $string['numbering1'] = 'Нумары'; $string['numbering2'] = 'Маркеры'; $string['numbering3'] = 'Павялічыць водступ'; +$string['pluginname'] = 'Падручнік'; $string['printbook'] = 'Друкаваць увесь падручнік'; $string['printchapter'] = 'Друкаваць раздзел'; $string['printdate'] = 'Дата'; diff --git a/lang/ca/book.php b/lang/ca/book.php index b89826e6d3b..475bff58b2b 100644 --- a/lang/ca/book.php +++ b/lang/ca/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'Llibre'; $string['modulenameplural'] = 'Llibres'; +$string['pluginname'] = 'Llibre'; $string['toc'] = 'Índex'; $string['tocwidth'] = 'Escolliu l\'amplada de l\'índex per tots els llibres.'; diff --git a/lang/cs/book.php b/lang/cs/book.php index 70e64584504..044842a7d49 100644 --- a/lang/cs/book.php +++ b/lang/cs/book.php @@ -29,6 +29,7 @@ $string['numbering0'] = 'Žádné'; $string['numbering1'] = 'Čísla'; $string['numbering2'] = 'Puntíky'; $string['numbering3'] = 'Odsazené'; +$string['pluginname'] = 'Kniha'; $string['printbook'] = 'Vytisknout celou knihu'; $string['printchapter'] = 'Vytisknout jednu kapitolu'; $string['printdate'] = 'Datum'; diff --git a/lang/de/book.php b/lang/de/book.php index 122ac9aa6e2..20a80d4e213 100644 --- a/lang/de/book.php +++ b/lang/de/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'Buch'; $string['modulenameplural'] = 'Bücher'; +$string['pluginname'] = 'Buch'; $string['toc'] = 'Inhaltsverzeichnis'; $string['tocwidth'] = 'Wählen Sie die Breite des Inhaltsverzeichnisses für alle Bücher aus.'; diff --git a/lang/en/book.php b/lang/en/book.php index 5a7e88cc6ab..654a72741af 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'Book'; $string['modulenameplural'] = 'Books'; +$string['pluginname'] = 'Book'; $string['toc'] = 'Table of Contents'; $string['tocwidth'] = 'Select width of the Table of Contents for all books.'; diff --git a/lang/es/book.php b/lang/es/book.php index f0ac4a64879..fa6746a4222 100644 --- a/lang/es/book.php +++ b/lang/es/book.php @@ -19,6 +19,7 @@ $string['numbering0'] = 'Nada'; $string['numbering1'] = 'Númerica'; $string['numbering2'] = 'Viñetas'; $string['numbering3'] = 'Indentidad'; +$string['pluginname'] = 'Libro'; $string['printbook'] = 'Imprimir el Libro Completo'; $string['printchapter'] = 'Imprimir este Cápitulo'; $string['printdate'] = 'Día'; diff --git a/lang/fi/book.php b/lang/fi/book.php index bf678769a0c..698ab0ca0e6 100644 --- a/lang/fi/book.php +++ b/lang/fi/book.php @@ -28,6 +28,7 @@ $string['numbering0'] = 'Ei mitään'; $string['numbering1'] = 'Numerot'; $string['numbering2'] = 'Luettelomerkit'; $string['numbering3'] = 'Sisennys'; +$string['pluginname'] = 'Kirja'; $string['printbook'] = 'Tulosta koko kirja'; $string['printchapter'] = 'Tulosta tämä luku'; $string['printdate'] = 'Tulostettu'; diff --git a/lang/fr/book.php b/lang/fr/book.php index 54b604ae86d..1a0ebf8f602 100644 --- a/lang/fr/book.php +++ b/lang/fr/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'Livre'; $string['modulenameplural'] = 'Livre'; +$string['pluginname'] = 'Livre'; $string['toc'] = 'Table des matières'; $string['faq'] = 'FAQ sur les livres'; diff --git a/lang/id/book.php b/lang/id/book.php index 73f11047c6c..4f07de44132 100644 --- a/lang/id/book.php +++ b/lang/id/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'Buku'; $string['modulenameplural'] = 'Buku-buku'; +$string['pluginname'] = 'Buku'; $string['toc'] = 'Daftar Isi'; $string['faq'] = 'Pertanyaan yang Sering Diajukan tentang Buku'; diff --git a/lang/it/book.php b/lang/it/book.php index 27a5406e79d..2b137bfde96 100644 --- a/lang/it/book.php +++ b/lang/it/book.php @@ -36,6 +36,7 @@ $string['numbering0'] = 'Senza numerazione'; $string['numbering1'] = 'Numeri'; $string['numbering2'] = 'Elenco puntato'; $string['numbering3'] = 'Elenco rientrato'; +$string['pluginname'] = 'Libro'; $string['printbook'] = 'Stampa tutto'; $string['printchapter'] = 'Stampa capitolo'; $string['printdate'] = 'Data'; diff --git a/lang/ja/book.php b/lang/ja/book.php index 00a1964210f..52494661308 100644 --- a/lang/ja/book.php +++ b/lang/ja/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'ブック'; $string['modulenameplural'] = 'ブック'; +$string['pluginname'] = 'ブック'; $string['toc'] = '目次'; $string['tocwidth'] = 'コンテンツのテーブル幅を選んでください。'; diff --git a/lang/nl/book.php b/lang/nl/book.php index 3806da05367..3018d1f5d1f 100644 --- a/lang/nl/book.php +++ b/lang/nl/book.php @@ -28,6 +28,7 @@ $string['numbering0'] = 'Geen'; $string['numbering1'] = 'Nummering'; $string['numbering2'] = 'Bolletjes'; $string['numbering3'] = 'Inspringen'; +$string['pluginname'] = 'Boek'; $string['printbook'] = 'Druk het hele boek af'; $string['printchapter'] = 'Druk dit hoofdstuk af'; $string['printdate'] = 'Datum'; diff --git a/lang/pl/book.php b/lang/pl/book.php index 123d5cb6ecd..b6b881ebb56 100644 --- a/lang/pl/book.php +++ b/lang/pl/book.php @@ -29,6 +29,7 @@ $string['numbering0'] = 'żaden'; $string['numbering1'] = 'Liczby'; $string['numbering2'] = 'Wypunktowanie'; $string['numbering3'] = 'Wcięte'; +$string['pluginname'] = 'Książka'; $string['printbook'] = 'Drukuj kopletną książkę'; $string['printchapter'] = 'Drukuj ten rozdział'; $string['printdate'] = 'Data'; diff --git a/lang/pt_br/book.php b/lang/pt_br/book.php index 4006f9f83cb..00d65ed5bcb 100644 --- a/lang/pt_br/book.php +++ b/lang/pt_br/book.php @@ -2,6 +2,7 @@ $string['modulename'] = 'Livro'; $string['modulenameplural'] = 'Livros'; +$string['pluginname'] = 'Livro'; $string['toc'] = 'Sumário'; $string['tocwidth'] = 'Selecione a largura do Sumário para todos os livros.'; diff --git a/lang/sk/book.php b/lang/sk/book.php index bdff3e4d242..d9f15300215 100644 --- a/lang/sk/book.php +++ b/lang/sk/book.php @@ -29,6 +29,7 @@ $string['numbering0'] = 'Žiadne'; $string['numbering1'] = 'Čísla'; $string['numbering2'] = 'Odrážky'; $string['numbering3'] = 'Odsadené'; +$string['pluginname'] = 'Kniha'; $string['printbook'] = 'Vytlačiť celú knihu'; $string['printchapter'] = 'Vytlačiť jednu kapitolu'; $string['printdate'] = 'Dátum'; diff --git a/lang/sl/book.php b/lang/sl/book.php index e7153fb44b8..15f8da25f13 100644 --- a/lang/sl/book.php +++ b/lang/sl/book.php @@ -4,6 +4,7 @@ $string['modulename'] = 'Knjiga'; $string['modulenameplural'] = 'Knjige'; +$string['pluginname'] = 'Knjiga'; $string['toc'] = 'Kazalo vsebine'; $string['tocwidth'] = 'Izberite širino kazala vsebine za vse knjige.'; $string['faq'] = 'Knjiga - pogosta vprašanja'; diff --git a/lang/sv/book.php b/lang/sv/book.php index 6fc026c2375..33aa7b53a2b 100644 --- a/lang/sv/book.php +++ b/lang/sv/book.php @@ -29,6 +29,7 @@ $string['numbering0'] = 'Ingen'; $string['numbering1'] = 'Tal'; $string['numbering2'] = 'Bullets'; $string['numbering3'] = 'Indragen'; +$string['pluginname'] = 'Bok'; $string['printbook'] = 'Skriv ut hela boken'; $string['printchapter'] = 'Skriv ut det här kapitlet'; $string['printdate'] = 'Datum'; From 08440ca95868a2660e5945865bd96780f9245d5a Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:08:50 +0100 Subject: [PATCH 054/455] newc capability coding style --- db/access.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/access.php b/db/access.php index 769e497264a..5bdf05ddd9b 100644 --- a/db/access.php +++ b/db/access.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$mod_book_capabilities = array( +$capabilities = array( 'mod/book:read' => array( 'captype' => 'read', From 8708eb636fa3be37812ea0c6687ebc1b9c8b3679 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:09:16 +0100 Subject: [PATCH 055/455] remove old course dir if empty --- db/upgrade.php | 1 + 1 file changed, 1 insertion(+) diff --git a/db/upgrade.php b/db/upgrade.php index 67e46c4c76f..5a5574bbc90 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -130,6 +130,7 @@ function xmldb_book_upgrade($oldversion) { @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id/"); @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/"); @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/"); + @rmdir("$CFG->dataroot/$book->course/"); } $rs->close(); } From 0834c016922f8bc2eb5e2dd3fb964e942752f573 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:19:51 +0100 Subject: [PATCH 056/455] new help --- lang/en/book.php | 7 +++++++ lang/en/help/book/customtitles.html | 3 --- lang/en/help/book/disableprinting.html | 3 --- lang/en/help/book/numberingtype.html | 14 -------------- lang/en/help/book/summary.html | 5 ----- mod_form.php | 6 +++--- 6 files changed, 10 insertions(+), 28 deletions(-) delete mode 100644 lang/en/help/book/customtitles.html delete mode 100644 lang/en/help/book/disableprinting.html delete mode 100644 lang/en/help/book/numberingtype.html delete mode 100644 lang/en/help/book/summary.html diff --git a/lang/en/book.php b/lang/en/book.php index 654a72741af..c0755f22c29 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -10,7 +10,9 @@ $string['book_tocwidth'] = 'Table of Contents width'; $string['faq'] = 'Book FAQ'; $string['disableprinting'] = 'Disable Printing'; +$string['disableprinting_help'] = 'Hide print icons.'; $string['customtitles'] = 'Custom Titles'; +$string['customtitles_help'] = 'Chapter titles are displayed automatically only in TOC.'; $string['editingchapter'] = 'Editing chapter'; $string['chaptertitle'] = 'Chapter Title'; @@ -18,6 +20,11 @@ $string['content'] = 'Content'; $string['subchapter'] = 'Subchapter'; $string['numbering'] = 'Chapter Numbering'; +$string['numbering_help'] = '* None - chapter and subchapter titles are not formatted at all, use if you want to define special numbering styles. For example letters: in chapter title type "A First Chapter", "A.1 Some Subchapter",... +* Numbers - chapters and subchapters are numbered (1, 1.1, 1.2, 2, ...) +* Bullets - subchapters are indented and displayed with bullets +* Indented - subchapters are indented'; + $string['numbering0'] = 'None'; $string['numbering1'] = 'Numbers'; $string['numbering2'] = 'Bullets'; diff --git a/lang/en/help/book/customtitles.html b/lang/en/help/book/customtitles.html deleted file mode 100644 index 0e5b330b453..00000000000 --- a/lang/en/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -<p align="center"><b>Custom Titles</b></p> - -<p>Chapter titles are displayed automatically only in TOC.</p> diff --git a/lang/en/help/book/disableprinting.html b/lang/en/help/book/disableprinting.html deleted file mode 100644 index 2f3635725a0..00000000000 --- a/lang/en/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -<p align="center"><b>Disable Printing</b></p> - -<p>Hide print icons.</p> diff --git a/lang/en/help/book/numberingtype.html b/lang/en/help/book/numberingtype.html deleted file mode 100644 index d2f94764a94..00000000000 --- a/lang/en/help/book/numberingtype.html +++ /dev/null @@ -1,14 +0,0 @@ -<p align="center"><b>Numbering of Chapters</b></p> - -<p>There are several predefined numbering types: - -<p><b>None</b> - chapter and subchapter titles are not formatted at all, use -if you want to define special numbering styles. For example letters: in chapter -title type "A First Chapter", "A.1 Some Subchapter",...</p> - -<p><b>Numbers</b> - chapters and subchapters are numbered (1, 1.1, 1.2, 2, -...)<p> - -<p><b>Bullets</b> - subchapters are indented and displayed with bullets.<p> - -<p><b>Indented</b> - subchapters are indented.</p> diff --git a/lang/en/help/book/summary.html b/lang/en/help/book/summary.html deleted file mode 100644 index 5f04a706af8..00000000000 --- a/lang/en/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -<p align="center"><b>Reading Summary</b></p> - -<p>The summary is a very short description of the book.</p> - -<p>Do not be tempted to write too much here!</p> \ No newline at end of file diff --git a/mod_form.php b/mod_form.php index 86465f112b8..652f506170c 100644 --- a/mod_form.php +++ b/mod_form.php @@ -50,14 +50,14 @@ class mod_book_mod_form extends moodleform_mod { $mform->addElement('select', 'numbering', get_string('numbering', 'book'), book_get_numbering_types()); - $mform->setHelpButton('numbering', array('numberingtype', get_string('numbering', 'book'), 'book')); + $mform->addHelpButton('numbering', 'numbering', 'mod_book'); $mform->addElement('checkbox', 'disableprinting', get_string('disableprinting', 'book')); - $mform->setHelpButton('disableprinting', array('disableprinting', get_string('disableprinting', 'book'), 'book')); + $mform->addHelpButton('disableprinting', 'disableprinting', 'mod_book'); $mform->setDefault('disableprinting', 0); $mform->addElement('checkbox', 'customtitles', get_string('customtitles', 'book')); - $mform->setHelpButton('customtitles', array('customtitles', get_string('customtitles', 'book'), 'book')); + $mform->addHelpButton('customtitles', 'customtitles', 'mod_book'); $mform->setDefault('customtitles', 0); //------------------------------------------------------------------------------- From bf9b62ea0a564f027567c09cdf0c010ee9cb599a Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:20:15 +0100 Subject: [PATCH 057/455] more conversion --- edit.php | 2 +- view.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/edit.php b/edit.php index 8b31df38491..ef4559bb677 100644 --- a/edit.php +++ b/edit.php @@ -25,7 +25,7 @@ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); -require_once($CFG->dirroot.'edit_form.php'); +require_once($CFG->dirroot.'/mod/book/edit_form.php'); $cmid = required_param('cmid', PARAM_INT); // Book Course Module ID $chapterid = optional_param('id', 0, PARAM_INT); // Chapter ID diff --git a/view.php b/view.php index 4c6390e27da..c89eb0d3008 100644 --- a/view.php +++ b/view.php @@ -161,7 +161,7 @@ if ($nextid) { $chnavigation .= '<a title="'.get_string('navnext', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$nextid.'"><img src="pix/nav_next.gif" class="bigicon" alt="'.get_string('navnext', 'book').'" /></a>'; } else { $sec = ''; - if ($section = get_record('course_sections', 'id', $cm->section)) { + if ($section = $DB->get_record('course_sections', array('id'=>$cm->section))) { $sec = $section->section; } $chnavigation .= '<a title="'.get_string('navexit', 'book').'" href="../../course/view.php?id='.$course->id.'#section-'.$sec.'"><img src="pix/nav_exit.gif" class="bigicon" alt="'.get_string('navexit', 'book').'" /></a>'; From f19d95175a916d864a8bf2f030648589fe204b76 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 17:33:56 +0100 Subject: [PATCH 058/455] more help cleanup --- lang/en/book.php | 28 ++++++++++++++++++++ lang/en/help/book/faq.html | 51 ------------------------------------ lang/en/help/book/index.html | 11 -------- lang/en/help/book/mods.html | 4 --- view.php | 20 +++++++------- 5 files changed, 38 insertions(+), 76 deletions(-) delete mode 100644 lang/en/help/book/faq.html delete mode 100644 lang/en/help/book/index.html delete mode 100644 lang/en/help/book/mods.html diff --git a/lang/en/book.php b/lang/en/book.php index c0755f22c29..d1044f9ba48 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -2,12 +2,40 @@ $string['modulename'] = 'Book'; $string['modulenameplural'] = 'Books'; +$string['modulename_help'] = 'Book is a simple multipage study material.'; $string['pluginname'] = 'Book'; +$string['pluginadministration'] = 'Book administration'; $string['toc'] = 'Table of Contents'; $string['tocwidth'] = 'Select width of the Table of Contents for all books.'; $string['book_tocwidth'] = 'Table of Contents width'; $string['faq'] = 'Book FAQ'; +$string['faq_help'] = ' +*Why only two levels?* + +Two levels are generally enough for all books, three levels would lead to poorly structured documents. Book module is designed for +creation of short multipage study materials. It is usually better to use PDF format for longer documents. The easiest way to create PDFs are +virtual printers (see +<a href="http://sector7g.wurzel6.de/pdfcreator/index_en.htm" target="_blank">PDFCreator</a>, +<a href="http://fineprint.com/products/pdffactory/index.html" target="_blank">PDFFactory</a>, +<a href="http://www.adobe.com/products/acrobatstd/main.html" target="_blank">Adobe Acrobat</a>, +etc.). + +*Can students edit books?* + +Only teachers can create and edit books. There are no plans to implement student editing for books, but somebody may create something +similar for students (Portfolio?). The main reason is to keep Book module as simple as possible. + +*How do I search the books?* + +At present there is only one way, use browser\'s search capability in print page. Global searching is now possible only in Moodle forums. +It would be nice to have global searching for all resources including books, any volunteers? + +*My titles do not fit on one line.* + +Either rephrase your titles or ask your site admin to change TOC +width. It is defined globally for all books in module configuration +page.'; $string['disableprinting'] = 'Disable Printing'; $string['disableprinting_help'] = 'Hide print icons.'; diff --git a/lang/en/help/book/faq.html b/lang/en/help/book/faq.html deleted file mode 100644 index 6f42283cf43..00000000000 --- a/lang/en/help/book/faq.html +++ /dev/null @@ -1,51 +0,0 @@ -<p align="center"> - <b>Frequently Asked Questions about Books</b> -</p> -<dl> - <dt> - <b>Why only two levels?</b> - </dt> - <dd> - Two levels are generally enough for all books, three levels would - lead to poorly structured documents. Book module is designed for - creation of short multipage study materials. It is usually better to - use PDF format for longer documents. The easiest way to create PDFs are - virtual printers (see - <a href="http://sector7g.wurzel6.de/pdfcreator/index_en.htm" target="_blank">PDFCreator</a>, - <a href="http://fineprint.com/products/pdffactory/index.html" target="_blank"> - PDFFactory</a>, - <a href="http://www.adobe.com/products/acrobatstd/main.html" target="_blank">Adobe Acrobat</a>, - etc.). - <br /> - </dd> - <br /> - <dt> - <b>Can students edit books?</b> - </dt> - <dd> - Only teachers can create and edit books. There are no plans to - implement student editing for books, but somebody may create something - similar for students (Portfolio?). The main reason is to keep Book - module as simple as possible. - </dd> - <br /> - <dt> - <b>How do I search the books?</b> - </dt> - <dd> - At present there is only one way, use browser's search capability - in print page. Global searching is now possible only in Moodle forums. - It would be nice to have global searching for all resources including - books, any volunteers? - </dd> - <br /> - <dt> - <b>My titles do not fit on one line.</b> - </dt> - <dd> - Either rephrase your titles or ask your site admin to change TOC - width. It is defined globally for all books in module configuration - page. - </dd> - <br /> -</dl> diff --git a/lang/en/help/book/index.html b/lang/en/help/book/index.html deleted file mode 100644 index 87397c1e450..00000000000 --- a/lang/en/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -<h2>Book module</h2> -<ul> - <li><a href="help.php?module=book&file=numberingtype.html">Chapter Numbering</a></li> - <li><a href="help.php?module=book&file=disableprinting.html">Disable Printing</a></li> - <li><a href="help.php?module=book&file=customtitles.html">Custom Titles</a></li> - <li><a href="help.php?module=book&file=summary.html">Reading Summary</a></li> - <li><a href="help.php?module=book&file=edit.html">Chapter editing</a></li> - <li><a href="help.php?module=book&file=import.html">Import</a></li> - <li><a href="help.php?module=book&file=faq.html">Book FAQ</a></li> -</ul> - diff --git a/lang/en/help/book/mods.html b/lang/en/help/book/mods.html deleted file mode 100644 index a29ff575cdf..00000000000 --- a/lang/en/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -<p><img valign="absmiddle" src="<?php echo $CFG->wwwroot?>/mod/book/icon.gif"> <b>Books</b></p> -<ul> -<p>Book is a simple multipage study material</p> -</ul> diff --git a/view.php b/view.php index c89eb0d3008..64f3d47323b 100644 --- a/view.php +++ b/view.php @@ -48,6 +48,8 @@ $allowprint = has_capability('mod/book:print', $context) and !$book->disablepri $allowexport = has_capability('mod/book:exportimscp', $context); $viewhidden = has_capability('mod/book:viewhiddenchapters', $context); +$PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chpterid'=>'chapterid')); + if ($allowedit) { if ($edit != -1) { $USER->editing = $edit; @@ -112,14 +114,12 @@ add_to_log($course->id, 'book', 'view', 'view.php?id='.$cm->id.'&chapterid=' ///read standard strings $strbooks = get_string('modulenameplural', 'book'); $strbook = get_string('modulename', 'book'); -$strTOC = get_string('TOC', 'book'); +$strtoc = get_string('toc', 'book'); /// prepare header $navigation = build_navigation('', $cm); -$buttons = $allowedit ? '<table cellspacing="0" cellpadding="0"><tr><td>'.update_module_button($cm->id, $course->id, $strbook).'</td>'. - '<td> </td><td>'.book_edit_button($book, $cm, $chapter).'</td></tr></table>' - : ' '; +$buttons = $allowedit ? book_edit_button($book, $cm, $chapter) : ' '; print_header( "$course->shortname: $book->name ($chapter->title)", $course->fullname, @@ -217,19 +217,19 @@ $generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book <tr class="tocandchapter"> <td style="width:<?php echo $tocwidth ?>px" align="left"><div class="clearer"> </div> <?php - print_box_start('generalbox'); + echo $OUTPUT->box_start('generalbox'); echo $toc; - print_box_end(); + echo $OUTPUT->box_end(); if ($allowedit and $edit) { echo '<div class="faq">'; - helpbutton('faq', get_string('faq','book'), 'book', true, true); + echo $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book')); echo '</div>'; } ?> </td> <td align="right"><div class="clearer"> </div> <?php - print_box_start('generalbox'); + echo $OUTPUT->box_start('generalbox'); $content = ''; if (!$book->customtitles) { if ($currsubtitle == ' ') { @@ -245,7 +245,7 @@ $generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book echo '<div class="book_content">'; echo format_text($content, FORMAT_HTML, $nocleanoption, $course->id); echo '</div>'; - print_box_end(); + echo $OUTPUT->box_end(); /// lower navigation echo '<div class="booknav">'.$chnavigation.'</div>'; ?> @@ -254,5 +254,5 @@ $generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book </table> <?php -print_footer($course); +echo $OUTPUT->footer(); From 9d2fe17901d01a1b58f75bca6ca7a65bfa272556 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 18:10:21 +0100 Subject: [PATCH 059/455] conversion --- delete.php | 37 +++++++++++++++++++------------------ edit.php | 23 ++++++++--------------- generateimscp.php | 2 ++ import.php | 2 ++ lib.php | 40 ++++++++++++++++++++++++++++++++++++++++ locallib.php | 24 ------------------------ move.php | 2 +- print.php | 5 ++--- show.php | 2 ++ toc.php | 14 +++++++------- view.php | 37 ++++++++++++++----------------------- 11 files changed, 97 insertions(+), 91 deletions(-) diff --git a/delete.php b/delete.php index 271bf962962..e2f29b8944a 100644 --- a/delete.php +++ b/delete.php @@ -40,16 +40,15 @@ require_sesskey(); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:edit', $context); +$PAGE->set_url('/mod/book/delete.php', array('id'=>$id, 'chapterid'=>$chapterid)); + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); ///header and strings -$strbooks = get_string('modulenameplural', 'book'); -$strbook = get_string('modulename', 'book'); - -$navigation = build_navigation('', $cm); - -print_header("$course->shortname: $book->name", $course->fullname, $navigation); +$PAGE->set_title(format_string($book->name)); +$PAGE->add_body_class('mod_book'); +$PAGE->set_heading(format_string($course->fullname)); ///form processing if ($confirm) { // the operation was confirmed. @@ -74,17 +73,19 @@ if ($confirm) { // the operation was confirmed. book_check_structure($book->id); redirect('view.php?id='.$cm->id); -} else { - // the operation has not been confirmed yet so ask the user to do so - if ($chapter->subchapter) { - $strconfirm = get_string('confchapterdelete','book'); - } else { - $strconfirm = get_string('confchapterdeleteall','book'); - } - echo '<br />'; - notice_yesno("<b>$chapter->title</b><p>$strconfirm</p>", - "delete.php?id=$cm->id&chapterid=$chapter->id&confirm=1&sesskey=$USER->sesskey", - "view.php?id=$cm->id&chapterid=$chapter->id"); } -print_footer($course); +echo $OUTPUT->header(); + +// the operation has not been confirmed yet so ask the user to do so +if ($chapter->subchapter) { + $strconfirm = get_string('confchapterdelete','book'); +} else { + $strconfirm = get_string('confchapterdeleteall','book'); +} +echo '<br />'; +$continue = new moodle_url('/mod/book/delete.php', array('id'=>$cm->id, 'chapterid'=>$chapter->id, 'confirm'=>1)); +$cancel = new moodle_url('/mod/book/view.php', array('id'=>$cm->id, 'chapterid'=>$chapter->id)); +echo $OUTPUT->confirm("<strong>$chapter->title</strong><p>$strconfirm</p>", $continue, $cancel); + +echo $OUTPUT->footer(); diff --git a/edit.php b/edit.php index ef4559bb677..ffcd66df5a1 100644 --- a/edit.php +++ b/edit.php @@ -45,6 +45,8 @@ require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:edit', $context); +$PAGE->set_url('/mod/book/edit.php', array('cmid'=>$cmid, 'id'=>$chapterid, 'pagenum'=>$pagenum, 'subchapter'=>$subchapter)); + if ($chapterid) { $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); } else { @@ -109,23 +111,14 @@ if ($mform->is_cancelled()) { } /// Otherwise fill and print the form. -$strbook = get_string('modulename', 'book'); -$strbooks = get_string('modulenameplural', 'book'); -$stredit = get_string('edit'); -$pageheading = get_string('editingchapter', 'book'); +$PAGE->set_title(format_string($book->name)); +$PAGE->add_body_class('mod_book'); +$PAGE->set_heading(format_string($course->fullname)); -///prepare the page header -$navlinks = array(); -$navlinks[] = array('name' => $stredit, 'link' => '', 'type' => 'title'); - -$navigation = build_navigation($navlinks, $cm); - -print_header("$course->shortname: $book->name", $course->fullname, $navigation); - -$icon = '<img class="icon" src="pix/chapter.gif" alt="" /> '; -print_heading_with_help($pageheading, 'edit', 'book', $icon); +echo $OUTPUT->header(); +echo $OUTPUT->heading(get_string('editingchapter', 'book')); $mform->display(); -print_footer($course); +echo $OUTPUT->footer(); diff --git a/generateimscp.php b/generateimscp.php index 78147435362..a2c12ee72ee 100644 --- a/generateimscp.php +++ b/generateimscp.php @@ -31,6 +31,8 @@ require_once($CFG->libdir.'/filelib.php'); $id = required_param('id', PARAM_INT); // Course Module ID +die('Not converted to 2.0 yet, sorry'); + if (!$cm = get_coursemodule_from_id('book', $id)) { error('Course Module ID was incorrect'); } diff --git a/import.php b/import.php index 6905da7430e..1831bbad4b6 100644 --- a/import.php +++ b/import.php @@ -42,6 +42,8 @@ require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:import', $context); +$PAGE->set_url('/mod/book/import.php', array('id'=>$id)); + //check all variables unset($id); diff --git a/lib.php b/lib.php index f9ebfabb0c7..e74d1d6f9b4 100644 --- a/lib.php +++ b/lib.php @@ -201,3 +201,43 @@ function book_supports($feature) { default: return null; } } + +/** + * Adds module specific settings to the settings block + * + * @param settings_navigation $settings The settings navigation object + * @param navigation_node $forumnode The node to add module settings to + * @return void + */ +function book_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { + global $USER, $PAGE, $CFG, $DB, $OUTPUT; + + if ($PAGE->cm->modname !== 'book') { + return; + } + + if (empty($PAGE->cm->context)) { + $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); + } + + if (!has_capability('mod/book:edit', $PAGE->cm->context)) { + return; + } + + $params = $PAGE->url->params(); + + if (empty($params['id']) or empty($params['chapterid'])) { + return; + } + + if (!empty($USER->editing)) { + $string = get_string("turneditingoff"); + $edit = '0'; + } else { + $string = get_string("turneditingon"); + $edit = '1'; + } + + $url = new moodle_url('/mod/book/view.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'], 'edit'=>$edit, 'sesskey'=>sesskey())); + $booknode->add($string, $url, navigation_node::TYPE_SETTING); +} \ No newline at end of file diff --git a/locallib.php b/locallib.php index 3d1d8601dff..295b8b7fb6a 100644 --- a/locallib.php +++ b/locallib.php @@ -74,30 +74,6 @@ function book_check_structure($bookid) { } } - -/// prepare button to turn chapter editing on - connected with course editing -function book_edit_button($book, $cm, $chapter) { - global $CFG, $USER; - - - if (has_capability('mod/book:edit', get_context_instance(CONTEXT_MODULE, $cm->id))) { - if (!empty($USER->editing)) { - $string = get_string("turneditingoff"); - $edit = '0'; - } else { - $string = get_string("turneditingon"); - $edit = '1'; - } - return '<form method="get" action="'.$CFG->wwwroot.'/mod/book/view.php"><div>'. - '<input type="hidden" name="id" value="'.$cm->id.'" />'. - '<input type="hidden" name="chapterid" value="'.$chapter->id.'" />'. - '<input type="hidden" name="edit" value="'.$edit.'" />'. - '<input type="submit" value="'.$string.'" /></div></form>'; - } else { - return ''; - } -} - /// general function for logging to table function book_log($str1, $str2, $level = 0) { switch ($level) { diff --git a/move.php b/move.php index b7a10b47fcb..d0f28231a8b 100644 --- a/move.php +++ b/move.php @@ -44,7 +44,7 @@ require_capability('mod/book:edit', $context); $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); -$oldchapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum', 'id, pagenum, subchapter'); +$oldchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, pagenum, subchapter'); $nothing = 0; diff --git a/print.php b/print.php index c6d4d7c9401..4183a7e9c3d 100644 --- a/print.php +++ b/print.php @@ -114,8 +114,7 @@ if ($chapter) { } else { add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id, $book->id, $cm->id); - $site = get_record('course','id',1); - $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); /// page header ?> @@ -134,7 +133,7 @@ if ($chapter) { <div class="book_info"><table> <tr> <td><?PHP echo get_string('site') ?>:</td> - <td><a href="<?PHP echo $CFG->wwwroot ?>"><?PHP echo format_string($site->fullname) ?></a></td> + <td><a href="<?PHP echo $CFG->wwwroot ?>"><?PHP echo format_string($SITE->fullname) ?></a></td> </tr><tr> <td><?PHP echo get_string('course') ?>:</td> <td><?PHP echo format_string($course->fullname) ?></td> diff --git a/show.php b/show.php index 5adede206aa..0d8ee9c4040 100644 --- a/show.php +++ b/show.php @@ -39,6 +39,8 @@ require_sesskey(); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:edit', $context); +$PAGE->set_url('/mod/book/show.php', array('id'=>$id, 'chapterid'=>$chapterid)); + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); diff --git a/toc.php b/toc.php index 1c6ebe0b3df..b87f694b4a6 100644 --- a/toc.php +++ b/toc.php @@ -148,19 +148,19 @@ if ($print) { ///TOC for printing } $toc .= '  '; if ($i != 1) { - $toc .= ' <a title="'.get_string('up').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=1&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/up.gif" height="11" class="iconsmall" alt="'.get_string('up').'" /></a>'; + $toc .= ' <a title="'.get_string('up').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=1&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/up').'" height="11" class="iconsmall" alt="'.get_string('up').'" /></a>'; } if ($i != count($chapters)) { - $toc .= ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=0&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/down.gif" height="11" class="iconsmall" alt="'.get_string('down').'" /></a>'; + $toc .= ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=0&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/down').'" height="11" class="iconsmall" alt="'.get_string('down').'" /></a>'; } - $toc .= ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&id='.$ch->id.'"><img src="'.$CFG->pixpath.'/t/edit.gif" height="11" class="iconsmall" alt="'.get_string('edit').'" /></a>'; - $toc .= ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/delete.gif" height="11" class="iconsmall" alt="'.get_string('delete').'" /></a>'; + $toc .= ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&id='.$ch->id.'"><img src="'.$OUTPUT->pix_url('t/edit').'" height="11" class="iconsmall" alt="'.get_string('edit').'" /></a>'; + $toc .= ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/delete').'" height="11" class="iconsmall" alt="'.get_string('delete').'" /></a>'; if ($ch->hidden) { - $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/show.gif" height="11" class="iconsmall" alt="'.get_string('show').'" /></a>'; + $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/show').'" height="11" class="iconsmall" alt="'.get_string('show').'" /></a>'; } else { - $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$CFG->pixpath.'/t/hide.gif" height="11" class="iconsmall" alt="'.get_string('hide').'" /></a>'; + $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/hide').'" height="11" class="iconsmall" alt="'.get_string('hide').'" /></a>'; } - $toc .= ' <a title="'.get_string('addafter', 'book').'" href="edit.php?cmid='.$cm->id.'&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="pix/add.gif" height="11" class="iconsmall" alt="'.get_string('addafter', 'book').'" /></a>'; + $toc .= ' <a title="'.get_string('addafter', 'book').'" href="edit.php?cmid='.$cm->id.'&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="'.$OUTPUT->pix_url('add', 'mod_book').'" height="11" class="iconsmall" alt="'.get_string('addafter', 'book').'" /></a>'; $toc .= (!$ch->subchapter) ? '<ul>' : '</li>'; $first = 0; diff --git a/view.php b/view.php index 64f3d47323b..b52b851a5f7 100644 --- a/view.php +++ b/view.php @@ -48,10 +48,10 @@ $allowprint = has_capability('mod/book:print', $context) and !$book->disablepri $allowexport = has_capability('mod/book:exportimscp', $context); $viewhidden = has_capability('mod/book:viewhiddenchapters', $context); -$PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chpterid'=>'chapterid')); +$PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chapterid'=>$chapterid)); if ($allowedit) { - if ($edit != -1) { + if ($edit != -1 and confirm_sesskey()) { $USER->editing = $edit; } else { if (isset($USER->editing)) { @@ -117,20 +117,10 @@ $strbook = get_string('modulename', 'book'); $strtoc = get_string('toc', 'book'); /// prepare header -$navigation = build_navigation('', $cm); - -$buttons = $allowedit ? book_edit_button($book, $cm, $chapter) : ' '; - -print_header( "$course->shortname: $book->name ($chapter->title)", - $course->fullname, - $navigation, - '', - '', - true, - $buttons, - navmenu($course, $cm) - ); - +$PAGE->set_title(format_string($book->name)); +$PAGE->add_body_class('mod_book'); +$PAGE->set_heading(format_string($course->fullname)); +echo $OUTPUT->header(); /// prepare chapter navigation icons $previd = null; @@ -153,18 +143,18 @@ if ($ch == current($chapters)) { } $chnavigation = ''; if ($previd) { - $chnavigation .= '<a title="'.get_string('navprev', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$previd.'"><img src="pix/nav_prev.gif" class="bigicon" alt="'.get_string('navprev', 'book').'"/></a>'; + $chnavigation .= '<a title="'.get_string('navprev', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$previd.'"><img src="'.$OUTPUT->pix_url('nav_prev', 'mod_book').'" class="bigicon" alt="'.get_string('navprev', 'book').'"/></a>'; } else { $chnavigation .= '<img src="pix/nav_prev_dis.gif" class="bigicon" alt="" />'; } if ($nextid) { - $chnavigation .= '<a title="'.get_string('navnext', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$nextid.'"><img src="pix/nav_next.gif" class="bigicon" alt="'.get_string('navnext', 'book').'" /></a>'; + $chnavigation .= '<a title="'.get_string('navnext', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$nextid.'"><img src="'.$OUTPUT->pix_url('nav_next', 'mod_book').'" class="bigicon" alt="'.get_string('navnext', 'book').'" /></a>'; } else { $sec = ''; if ($section = $DB->get_record('course_sections', array('id'=>$cm->section))) { $sec = $section->section; } - $chnavigation .= '<a title="'.get_string('navexit', 'book').'" href="../../course/view.php?id='.$course->id.'#section-'.$sec.'"><img src="pix/nav_exit.gif" class="bigicon" alt="'.get_string('navexit', 'book').'" /></a>'; + $chnavigation .= '<a title="'.get_string('navexit', 'book').'" href="../../course/view.php?id='.$course->id.'#section-'.$sec.'"><img src="'.$OUTPUT->pix_url('nav_exit', 'mod_book').'" class="bigicon" alt="'.get_string('navexit', 'book').'" /></a>'; } /// prepare print icons @@ -172,13 +162,13 @@ if (!$allowprint) { $printbook = ''; $printchapter = ''; } else { - $printbook = '<a title="'.get_string('printbook', 'book').'" href="print.php?id='.$cm->id.'" onclick="this.target=\'_blank\'"><img src="pix/print_book.gif" class="bigicon" alt="'.get_string('printbook', 'book').'"/></a>'; - $printchapter = '<a title="'.get_string('printchapter', 'book').'" href="print.php?id='.$cm->id.'&chapterid='.$chapter->id.'" onclick="this.target=\'_blank\'"><img src="pix/print_chapter.gif" class="bigicon" alt="'.get_string('printchapter', 'book').'"/></a>'; + $printbook = '<a title="'.get_string('printbook', 'book').'" href="print.php?id='.$cm->id.'" onclick="this.target=\'_blank\'"><img src="'.$OUTPUT->pix_url('print_book', 'mod_book').'" class="bigicon" alt="'.get_string('printbook', 'book').'"/></a>'; + $printchapter = '<a title="'.get_string('printchapter', 'book').'" href="print.php?id='.$cm->id.'&chapterid='.$chapter->id.'" onclick="this.target=\'_blank\'"><img src="'.$OUTPUT->pix_url('print_chapter', 'mod_book').'" class="bigicon" alt="'.get_string('printchapter', 'book').'"/></a>'; } // prepare $toc and $currtitle, $currsubtitle $print = 0; -require('toc.php'); +include('toc.php'); if ($edit) { $tocwidth = $CFG->book_tocwidth + 80; @@ -189,7 +179,8 @@ if ($edit) { $doimport = ($allowimport and $edit) ? '<div>(<a href="import.php?id='.$cm->id.'">'.get_string('doimport', 'book').'</a>)</div>' : ''; /// Enable the IMS CP button -$generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book').'" href="generateimscp.php?id='.$cm->id.'"><img class="bigicon" src="pix/generateimscp.gif" alt="'.get_string('generateimscp', 'book').'"></img></a>' : ''; +//$generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book').'" href="generateimscp.php?id='.$cm->id.'"><img class="bigicon" src="'.$OUTPUT->pix_url('generateimscp', 'mod_book').'" alt="'.get_string('generateimscp', 'book').'"></img></a>' : ''; +$generateimscp = ''; //TODO after new file handling // ===================================================== From be28c4b52a58bb58cd7b931f5823d4526aa42965 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 18:46:40 +0100 Subject: [PATCH 060/455] fixed intro upgrade --- db/install.xml | 2 +- db/upgrade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/install.xml b/db/install.xml index 92ee3b275c0..51f393b74bd 100644 --- a/db/install.xml +++ b/db/install.xml @@ -9,7 +9,7 @@ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="course"/> <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="name"/> <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="course" NEXT="intro"/> - <FIELD NAME="intro" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/> + <FIELD NAME="intro" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/> <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="intro" NEXT="numbering"/> <FIELD NAME="numbering" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="introformat" NEXT="disableprinting"/> <FIELD NAME="disableprinting" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="2" SEQUENCE="false" ENUM="false" PREVIOUS="numbering" NEXT="customtitles"/> diff --git a/db/upgrade.php b/db/upgrade.php index 5a5574bbc90..72d4c69903b 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -62,7 +62,7 @@ function xmldb_book_upgrade($oldversion) { if ($oldversion < 2010120802) { // Rename field summary on table book to intro $table = new xmldb_table('book'); - $field = new xmldb_field('intro', XMLDB_TYPE_TEXT, 'large', null, null, null, null, 'name'); + $field = new xmldb_field('intro', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'name'); // Launch rename field summary $dbman->change_field_precision($table, $field); From 989af7b32852008292f571d767d0302b9eb6e0ce Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 18:49:32 +0100 Subject: [PATCH 061/455] minor file migration improvements --- db/upgradelib.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/db/upgradelib.php b/db/upgradelib.php index 323af38867c..952cb82c5bf 100644 --- a/db/upgradelib.php +++ b/db/upgradelib.php @@ -47,8 +47,8 @@ function book_migrate_moddata_dir_to_legacy($book, $context, $path) { } $fs = get_file_storage(); - $items = new DirectoryIterator($fulldir); $textlib = textlib_get_instance(); + $items = new DirectoryIterator($fulldir); foreach ($items as $item) { if ($item->isDot()) { @@ -74,11 +74,13 @@ function book_migrate_moddata_dir_to_legacy($book, $context, $path) { if ($filename === '') { //unsupported chars, sorry + unset($item); // release file handle continue; } if ($textlib->strlen($filepath) > 255) { echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fulldir.$item->getFilename()); + unset($item); // release file handle continue; } @@ -87,7 +89,9 @@ function book_migrate_moddata_dir_to_legacy($book, $context, $path) { 'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime()); $fs->create_file_from_pathname($file_record, $fulldir.$item->getFilename()); } - @unlink($fulldir.$item->getFilename()); + $oldpathname = $fulldir.$item->getFilename(); + unset($item); // release file handle + @unlink($oldpathname); } else { //migrate recursively all subdirectories From 4f49e7caec526934ffba3304bff6d37e71e0dda9 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 18:50:32 +0100 Subject: [PATCH 062/455] cleaning up old help --- lang/en/help/book/edit.html | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 lang/en/help/book/edit.html diff --git a/lang/en/help/book/edit.html b/lang/en/help/book/edit.html deleted file mode 100644 index 9c51f792f24..00000000000 --- a/lang/en/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -<p align="center"><b>Chapter editing</b></p> - -<p>Try to keep the chapter title short.</p> - -<p>Maximum level of subchapters is two.</p> - -<p>If you have encounter problems when using WYSIWYG html editor, try switching to another browser (such as Mozilla Firefox) or turn off the editor completely in your profile.</p> \ No newline at end of file From 8da51a16501c53318f2ad5d55dbf6a079bcccdd0 Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 18:52:50 +0100 Subject: [PATCH 063/455] helps converted, import disabled for now --- import.php | 2 ++ lang/en/book.php | 1 + lang/en/help/book/import.html | 5 ----- view.php | 3 ++- 4 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 lang/en/help/book/import.html diff --git a/import.php b/import.php index 1831bbad4b6..666c751baca 100644 --- a/import.php +++ b/import.php @@ -29,6 +29,8 @@ require_once('import_form.php'); $id = required_param('id', PARAM_INT); // Course Module ID +die('Not converted to 2.0 yet, sorry'); + // ========================================================================= // security checks START - only teachers edit // ========================================================================= diff --git a/lang/en/book.php b/lang/en/book.php index d1044f9ba48..99955cfb239 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -77,6 +77,7 @@ $string['navexit'] = 'Exit Book'; $string['importingchapters'] = 'Importing chapters into book'; $string['import'] = 'Import'; +$string['import_help'] = 'You can import a single HTML file or every HTML file in a direcory. Relative file links are converted to absolute chapter links. Images, flash and Java are relinked too.'; $string['doimport'] = 'Import'; $string['doexport'] = 'Export'; $string['importing'] = 'Importing'; diff --git a/lang/en/help/book/import.html b/lang/en/help/book/import.html deleted file mode 100644 index 7a62bebea17..00000000000 --- a/lang/en/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -<p align="center"><b>Import</b></p> - -<p>You can import a single HTML file or every HTML file in a direcory.</p> - -<p>Relative file links are converted to absolute chapter links. Images, flash and Java are relinked too.</p> diff --git a/view.php b/view.php index b52b851a5f7..b016b4af152 100644 --- a/view.php +++ b/view.php @@ -176,7 +176,8 @@ if ($edit) { $tocwidth = $CFG->book_tocwidth; } -$doimport = ($allowimport and $edit) ? '<div>(<a href="import.php?id='.$cm->id.'">'.get_string('doimport', 'book').'</a>)</div>' : ''; +//$doimport = ($allowimport and $edit) ? '<div>(<a href="import.php?id='.$cm->id.'">'.get_string('doimport', 'book').'</a>)</div>' : ''; +$doimport = ''; //TODO: after new file handling /// Enable the IMS CP button //$generateimscp = ($allowexport) ? '<a title="'.get_string('generateimscp', 'book').'" href="generateimscp.php?id='.$cm->id.'"><img class="bigicon" src="'.$OUTPUT->pix_url('generateimscp', 'mod_book').'" alt="'.get_string('generateimscp', 'book').'"></img></a>' : ''; From 661b9ea2e87a79f70ce7f3cb1373463b69eec9ba Mon Sep 17 00:00:00 2001 From: Petr Skoda <info@skodak.org> Date: Wed, 8 Dec 2010 18:59:03 +0100 Subject: [PATCH 064/455] text formatting --- print.php | 45 +++++++++++++++++++++------------------------ view.php | 13 ++++--------- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/print.php b/print.php index 4183a7e9c3d..693c06a96cd 100644 --- a/print.php +++ b/print.php @@ -74,9 +74,6 @@ $strtop = get_string('top', 'book'); @header('Accept-Ranges: none'); @header('Content-type: text/html; charset=utf-8'); -$formatoptions = new stdClass(); -$formatoptions->noclean = true; - if ($chapter) { add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); @@ -91,15 +88,15 @@ if ($chapter) { <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> - <title><?PHP echo format_string($book->name) ?> + <?php echo format_string($book->name) ?> - +
        - customtitles) { if ($currsubtitle == ' ') { @@ -108,7 +105,7 @@ if ($chapter) { echo '

        '.$currtitle.'
        '.$currsubtitle.'

        '; } } - echo format_text($chapter->content, FORMAT_HTML, $formatoptions, $course->id); + echo format_text($chapter->content, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); echo '
        '; echo ' '; @@ -121,35 +118,35 @@ if ($chapter) { - <?PHP echo format_string(name) ?> - - + <?php echo format_string(name) ?> + + -

        name) ?>

        -

        intro, $book->introformat) ?>

        +

        name) ?>

        +

        intro, $book->introformat) ?>

        - - + + - - + + - - + + - - + + - - + +
        :fullname) ?>:fullname) ?>
        :fullname) ?>:fullname) ?>
        :name) ?>:name) ?>
        ::
        ::
        - content); $content = str_replace($link2, '#top', $content); - echo format_text($content, FORMAT_HTML, $formatoptions, $course->id); + echo format_text($content, $ch->contentformat, array('noclean'=>true, 'context'=>$context)); echo '
        '; //echo ''.$strtop.''; diff --git a/view.php b/view.php index b016b4af152..631216c9ab0 100644 --- a/view.php +++ b/view.php @@ -222,20 +222,15 @@ $generateimscp = ''; //TODO after new file handling
         
        box_start('generalbox'); - $content = ''; + echo '
        '; if (!$book->customtitles) { if ($currsubtitle == ' ') { - $content .= '

        '.$currtitle.'

        '; + echo '

        '.$currtitle.'

        '; } else { - $content .= '

        '.$currtitle.'
        '.$currsubtitle.'

        '; + echo '

        '.$currtitle.'
        '.$currsubtitle.'

        '; } } - $content .= $chapter->content; - - $nocleanoption = new object(); - $nocleanoption->noclean = true; - echo '
        '; - echo format_text($content, FORMAT_HTML, $nocleanoption, $course->id); + echo format_text($chapter->content, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); echo '
        '; echo $OUTPUT->box_end(); /// lower navigation From 210ed611a8285d0b555638df3f581a62ff25daa4 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 8 Dec 2010 19:00:25 +0100 Subject: [PATCH 065/455] only print visible pages --- print.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/print.php b/print.php index 693c06a96cd..cd504248aab 100644 --- a/print.php +++ b/print.php @@ -49,11 +49,8 @@ require_capability('mod/book:print', $context); //check all variables if ($chapterid) { - //single chapter printing - $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); - if ($chapter->hidden) { - error('Only visible chapters can be printed'); - } + //single chapter printing - only visible! + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id, 'visible'=>1), '*', MUST_EXIST); } else { //complete book $chapter = false; @@ -77,7 +74,7 @@ $strtop = get_string('top', 'book'); if ($chapter) { add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); - $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum, title'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id, 'visible'=>1), 'pagenum, title'); $print = 0; $edit = 0; From 58eda86a66b13d22b1a3a89d32a11b8d7a70614d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 8 Dec 2010 19:02:01 +0100 Subject: [PATCH 066/455] improved coding style --- print.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/print.php b/print.php index cd504248aab..884c2d9882c 100644 --- a/print.php +++ b/print.php @@ -39,14 +39,14 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); require_course_login($course, true, $cm); -if ($book->disableprinting) { - error('Printing is disabled'); -} - $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:read', $context); require_capability('mod/book:print', $context); +if ($book->disableprinting) { + error('Printing is disabled'); +} + //check all variables if ($chapterid) { //single chapter printing - only visible! From 6708d7d430dc2557b56ad810cdb1a076ccc18799 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 8 Dec 2010 19:02:11 +0100 Subject: [PATCH 067/455] disable import for now --- edit_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edit_form.php b/edit_form.php index c51e4fae9de..2e4d4b9e953 100644 --- a/edit_form.php +++ b/edit_form.php @@ -55,7 +55,7 @@ class book_chapter_edit_form extends moodleform { $mform->setType('pagenum', PARAM_INT); $context = get_context_instance(CONTEXT_MODULE, $cm->id); - if (has_capability('mod/book:import', $context)) { + if (false and has_capability('mod/book:import', $context)) { //TODO: after files $mform->addElement('static', 'doimport', get_string('importingchapters', 'book').':', ''.get_string('doimport', 'book').''); } From f4e1849ed9a913c7618cff9cb82b9fcce930e43b Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 8 Dec 2010 20:13:56 +0100 Subject: [PATCH 068/455] new file api support --- edit.php | 46 ++++++++++++++++++++++------------------- edit_form.php | 33 +++++++++++++++-------------- lib.php | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-- locallib.php | 1 + print.php | 27 ++++++++++++------------ view.php | 7 ++++--- 6 files changed, 114 insertions(+), 57 deletions(-) diff --git a/edit.php b/edit.php index ffcd66df5a1..09b4d5f6f1e 100644 --- a/edit.php +++ b/edit.php @@ -47,28 +47,24 @@ require_capability('mod/book:edit', $context); $PAGE->set_url('/mod/book/edit.php', array('cmid'=>$cmid, 'id'=>$chapterid, 'pagenum'=>$pagenum, 'subchapter'=>$subchapter)); -if ($chapterid) { - $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); -} else { - $chapter = null; -} - -//check all variables -unset($cmid); -unset($chapterid); - // ========================================================================= // security checks END // ========================================================================= -$mform = new book_chapter_edit_form(null, $cm); - -if ($chapter) { - $chapter->cmid = $cm->id; - $mform->set_data($chapter); +if ($chapterid) { + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); } else { - $mform->set_data(array('cmid'=>$cm->id, 'pagenum'=>($pagenum+1), 'subchapter'=>$subchapter)); + $chapter = new stdClass(); + $chapter->id = null; + $chapter->subchapter = $subchapter; + $chapter->pagenum = $pagenum + 1; } +$chapter->cmid = $cm->id; + +$options = array('noclean'=>true, 'subdirs'=>true, 'maxfiles'=>-1, 'maxbytes'=>0, 'context'=>$context); +$chapter = file_prepare_standard_editor($chapter, 'content', $options, $context, 'mod_book', 'chapter', $chapter->id); + +$mform = new book_chapter_edit_form(null, array('chapter'=>$chapter, 'options'=>$options)); /// If data submitted, then process and store. if ($mform->is_cancelled()) { @@ -81,6 +77,8 @@ if ($mform->is_cancelled()) { } else if ($data = $mform->get_data()) { if ($data->id) { + // store the files + $data = file_postupdate_standard_editor($data, 'content', $options, $context, 'mod_book', 'chapter', $data->id); $DB->update_record('book_chapters', $data); add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); @@ -88,11 +86,13 @@ if ($mform->is_cancelled()) { } else { /// adding new chapter - $data->bookid = $book->id; - $data->hidden = 0; - $data->timecreated = time(); - $data->timemodified = time(); - $data->importsrc = ''; + $data->bookid = $book->id; + $data->hidden = 0; + $data->timecreated = time(); + $data->timemodified = time(); + $data->importsrc = ''; + $data->content = ''; // updated later + $data->contentformat = FORMAT_HTML; // updated later // make room for new page $sql = "UPDATE {book_chapters} @@ -102,6 +102,10 @@ if ($mform->is_cancelled()) { $data->id = $DB->insert_record('book_chapters', $data); + // store the files + $data = file_postupdate_standard_editor($data, 'content', $options, $context, 'mod_book', 'chapter', $data->id); + $DB->update_record('book_chapters', $data); + add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); } diff --git a/edit_form.php b/edit_form.php index 2e4d4b9e953..bf972a64b8b 100644 --- a/edit_form.php +++ b/edit_form.php @@ -31,8 +31,12 @@ class book_chapter_edit_form extends moodleform { function definition() { global $CFG; + + $chapter = $this->_customdata['chapter']; + $options = $this->_customdata['options']; + $mform = $this->_form; - $cm = $this->_customdata; + $context = $options['context']; $mform->addElement('header', 'general', get_string('edit')); @@ -42,8 +46,15 @@ class book_chapter_edit_form extends moodleform { $mform->addElement('advcheckbox', 'subchapter', get_string('subchapter', 'book')); - $mform->addElement('htmleditor', 'content', get_string('content', 'book'), array('cols'=>50, 'rows'=>30)); - $mform->setType('content', PARAM_RAW); + $mform->addElement('editor', 'content_editor', get_string('content', 'book'), null, $options); + $mform->setType('content_editor', PARAM_RAW); + $mform->addRule('content_editor', get_string('required'), 'required', null, 'client'); + + if ($chapter->id and has_capability('mod/book:import', $context)) { + //TODO: after files + //$mform->addElement('static', 'doimport', get_string('importingchapters', 'book').':', ''.get_string('doimport', 'book').''); + } + $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); @@ -54,22 +65,10 @@ class book_chapter_edit_form extends moodleform { $mform->addElement('hidden', 'pagenum'); $mform->setType('pagenum', PARAM_INT); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - if (false and has_capability('mod/book:import', $context)) { //TODO: after files - $mform->addElement('static', 'doimport', get_string('importingchapters', 'book').':', ''.get_string('doimport', 'book').''); - } $this->add_action_buttons(true); - } - function definition_after_data() { - global $CFG; - $mform = $this->_form; - - if ($mform->getElementValue('id')) { - if ($mform->elementExists('doimport')) { - $mform->removeElement('doimport'); - } - } + // set the defaults + $this->set_data($chapter); } } diff --git a/lib.php b/lib.php index e74d1d6f9b4..18567825c89 100644 --- a/lib.php +++ b/lib.php @@ -152,7 +152,7 @@ function book_get_participants($bookid) { /** * This function returns if a scale is being used by one book * it it has support for grading and scales. Commented code should be - * modified if necessary. See forum, glossary or journal modules + * modified if necessary. See book, glossary or journal modules * as reference. * * @param $bookid int @@ -206,7 +206,7 @@ function book_supports($feature) { * Adds module specific settings to the settings block * * @param settings_navigation $settings The settings navigation object - * @param navigation_node $forumnode The node to add module settings to + * @param navigation_node $booknode The node to add module settings to * @return void */ function book_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { @@ -240,4 +240,57 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig $url = new moodle_url('/mod/book/view.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'], 'edit'=>$edit, 'sesskey'=>sesskey())); $booknode->add($string, $url, navigation_node::TYPE_SETTING); +} + +/** + * Serves the book attachments. Implements needed access control ;-) + * + * @param object $course + * @param object $cm + * @param object $context + * @param string $filearea + * @param array $args + * @param bool $forcedownload + * @return bool false if file not found, does not return if found - justsend the file + */ +function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { + global $CFG, $DB; + + if ($context->contextlevel != CONTEXT_MODULE) { + return false; + } + + require_course_login($course, true, $cm); + + if ($filearea !== 'chapter') { + return false; + } + + if (!has_capability('mod/book:read', $context)) { + return false; + } + + $chid = (int)array_shift($args); + + if (!$book = $DB->get_record('book', array('id'=>$cm->instance))) { + return false; + } + + if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chid, 'bookid'=>$book->id))) { + return false; + } + + if ($chapter->hidden and !has_capability('mod/book:viewhiddenchapters', $context)) { + return false; + } + + $fs = get_file_storage(); + $relativepath = implode('/', $args); + $fullpath = "/$context->id/mod_book/chapter/$chid/$relativepath"; + if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { + return false; + } + + // finally send the file + send_stored_file($file, 360, 0, false); } \ No newline at end of file diff --git a/locallib.php b/locallib.php index 295b8b7fb6a..a608379e3a2 100644 --- a/locallib.php +++ b/locallib.php @@ -31,6 +31,7 @@ define('BOOK_NUM_BULLETS', '2'); define('BOOK_NUM_INDENTED', '3'); require_once($CFG->dirroot.'/mod/book/lib.php'); +require_once($CFG->libdir.'/filelib.php'); function book_get_numbering_types() { return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), diff --git a/print.php b/print.php index 884c2d9882c..68938c1ed1e 100644 --- a/print.php +++ b/print.php @@ -50,7 +50,7 @@ if ($book->disableprinting) { //check all variables if ($chapterid) { //single chapter printing - only visible! - $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id, 'visible'=>1), '*', MUST_EXIST); + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id, 'hidden'=>0), '*', MUST_EXIST); } else { //complete book $chapter = false; @@ -74,7 +74,7 @@ $strtop = get_string('top', 'book'); if ($chapter) { add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); - $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id, 'visible'=>1), 'pagenum, title'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id, 'hidden'=>0), 'pagenum, title'); $print = 0; $edit = 0; @@ -102,7 +102,8 @@ if ($chapter) { echo '

        '.$currtitle.'
        '.$currsubtitle.'

        '; } } - echo format_text($chapter->content, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); + $chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id); + echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); echo '
        '; echo ' '; @@ -151,18 +152,16 @@ if ($chapter) { $link1 = $CFG->wwwroot.'/mod/book/view.php?id='.$course->id.'&chapterid='; $link2 = $CFG->wwwroot.'/mod/book/view.php?id='.$course->id; foreach ($chapters as $ch) { - if (!$ch->hidden) { - echo '
        '; - if (!$book->customtitles) { - echo '

        '.$titles[$ch->id].'

        '; - } - $content = str_replace($link1, '#ch', $ch->content); - $content = str_replace($link2, '#top', $content); - echo format_text($content, $ch->contentformat, array('noclean'=>true, 'context'=>$context)); - echo '
        '; - //echo ''.$strtop.''; - + echo '
        '; + if (!$book->customtitles) { + echo '

        '.$titles[$ch->id].'

        '; } + $content = str_replace($link1, '#ch', $ch->content); + $content = str_replace($link2, '#top', $content); + $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $ch->id); + echo format_text($content, $ch->contentformat, array('noclean'=>true, 'context'=>$context)); + echo '
        '; + //echo ''.$strtop.''; } echo ' '; } diff --git a/view.php b/view.php index 631216c9ab0..8737884a348 100644 --- a/view.php +++ b/view.php @@ -48,8 +48,6 @@ $allowprint = has_capability('mod/book:print', $context) and !$book->disablepri $allowexport = has_capability('mod/book:exportimscp', $context); $viewhidden = has_capability('mod/book:viewhiddenchapters', $context); -$PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chapterid'=>$chapterid)); - if ($allowedit) { if ($edit != -1 and confirm_sesskey()) { $USER->editing = $edit; @@ -90,6 +88,7 @@ if ($chapterid == '0') { // go to first chapter if no given } } +$PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chapterid'=>$chapterid)); if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id))) { error('Error reading book chapters.'); @@ -230,7 +229,8 @@ $generateimscp = ''; //TODO after new file handling echo '

        '.$currtitle.'
        '.$currsubtitle.'

        '; } } - echo format_text($chapter->content, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); + $chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id); + echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); echo ''; echo $OUTPUT->box_end(); /// lower navigation @@ -241,5 +241,6 @@ $generateimscp = ''; //TODO after new file handling
        footer(); From e6bf43cd0e97dbdda1b890794bd8b7a019d766ee Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 8 Dec 2010 21:21:35 +0100 Subject: [PATCH 069/455] b view.php param support --- view.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/view.php b/view.php index 8737884a348..9f49f3407b2 100644 --- a/view.php +++ b/view.php @@ -26,16 +26,24 @@ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); -$id = required_param('id', PARAM_INT); // Course Module ID +$id = optional_param('id', 0, PARAM_INT); // Course Module ID +$bid = optional_param('b', 0, PARAM_INT); // Book id $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID $edit = optional_param('edit', -1, PARAM_BOOL); // Edit mode // ========================================================================= // security checks START - teachers edit; students view // ========================================================================= -$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); -$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); -$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); +if ($id) { + $cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); + $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); + $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); +} else { + $book = $DB->get_record('book', array('id'=>$bid), '*', MUST_EXIST); + $cm = get_coursemodule_from_instance('book', $book->id, 0, false, MUget_record('course', array('id'=>$cm->course), '*', MUST_EXIST); + $id = $cm->id; +} require_course_login($course, true, $cm); @@ -96,6 +104,7 @@ if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid //check all variables unset($id); +unset($bid); unset($chapterid); /// chapter is hidden for students From 5c0ff68d516c113a800d0afc7753c30dc883496d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 8 Dec 2010 21:39:35 +0100 Subject: [PATCH 070/455] backup/restore support --- .../backup_book_activity_task.class.php | 88 ++++ backup/moodle2/backup_book_settingslib.php | 30 ++ backup/moodle2/backup_book_stepslib.php | 54 +++ .../restore_book_activity_task.class.php | 130 ++++++ backup/moodle2/restore_book_stepslib.php | 74 ++++ backuplib.php | 155 ------- lib.php | 2 +- restorelib.php | 380 ------------------ 8 files changed, 377 insertions(+), 536 deletions(-) create mode 100644 backup/moodle2/backup_book_activity_task.class.php create mode 100644 backup/moodle2/backup_book_settingslib.php create mode 100644 backup/moodle2/backup_book_stepslib.php create mode 100644 backup/moodle2/restore_book_activity_task.class.php create mode 100644 backup/moodle2/restore_book_stepslib.php delete mode 100644 backuplib.php delete mode 100644 restorelib.php diff --git a/backup/moodle2/backup_book_activity_task.class.php b/backup/moodle2/backup_book_activity_task.class.php new file mode 100644 index 00000000000..61fd1da8304 --- /dev/null +++ b/backup/moodle2/backup_book_activity_task.class.php @@ -0,0 +1,88 @@ +. + +/** + * Description of book backup task + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot.'/mod/book/backup/moodle2/backup_book_stepslib.php'); // Because it exists (must) +require_once($CFG->dirroot.'/mod/book/backup/moodle2/backup_book_settingslib.php'); // Because it exists (optional) + +/** + * book backup task that provides all the settings and steps to perform one + * complete backup of the activity + */ +class backup_book_activity_task extends backup_activity_task { + + /** + * Define (add) particular settings this activity can have + * + * @return void + */ + protected function define_my_settings() { + // No particular settings for this activity + } + + /** + * Define (add) particular steps this activity can have + * + * @return void + */ + protected function define_my_steps() { + // book only has one structure step + $this->add_step(new backup_book_activity_structure_step('book structure', 'book.xml')); + } + + /** + * Code the transformations to perform in the activity in + * order to get transportable (encoded) links + * + * @param string $content + * @return $string encoded content + */ + static public function encode_content_links($content) { + global $CFG; + + $base = preg_quote($CFG->wwwroot,"/"); + + // Link to the list of books + $search = "/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/"; + $content = preg_replace($search, '$@bookINDEX*$2@$', $content); + + // Link to book view by moduleid + $search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/"; + $content = preg_replace($search, '$@bookVIEWBYID*$2@$', $content); + + $search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)&chapterid=([0-9]+)/"; + $content = preg_replace($search, '$@bookVIEWBYIDCH*$2*$3@$', $content); + + // Link to book view by bookid + $search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)/"; + $content = preg_replace($search, '$@bookVIEWBYB*$2@$', $content); + + $search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)&chapterid=([0-9]+)/"; + $content = preg_replace($search, '$@bookVIEWBYBCH*$2*$3@$', $content); + + return $content; + } +} diff --git a/backup/moodle2/backup_book_settingslib.php b/backup/moodle2/backup_book_settingslib.php new file mode 100644 index 00000000000..58157d1e393 --- /dev/null +++ b/backup/moodle2/backup_book_settingslib.php @@ -0,0 +1,30 @@ +. + +/** + * Description of book backup settings + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + + // This activity has not particular settings but the inherited from the generic + // backup_activity_task so here there isn't any class definition, like the ones + // existing in /backup/moodle2/backup_settingslib.php (activities section) diff --git a/backup/moodle2/backup_book_stepslib.php b/backup/moodle2/backup_book_stepslib.php new file mode 100644 index 00000000000..2be4d942a68 --- /dev/null +++ b/backup/moodle2/backup_book_stepslib.php @@ -0,0 +1,54 @@ +. + +/** + * Define all the backup steps that will be used by the backup_book_activity_task + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +/** + * Define the complete book structure for backup, with file and id annotations + */ +class backup_book_activity_structure_step extends backup_activity_structure_step { + + protected function define_structure() { + + // Define each element separated + $book = new backup_nested_element('book', array('id'), array('name', 'intro', 'introformat', 'numbering', 'disableprinting', 'customtitles', 'timecreated', 'timemodified')); + $chapters = new backup_nested_element('chapters'); + $chapter = new backup_nested_element('chapter', array('id'), array('pagenum', 'subchapter', 'title', 'content', 'contentormat', 'hidden', 'timemcreated', 'timemodified', 'importsrc',)); + + $book->add_child($chapters); + $chapters->add_child($chapter); + + // Define sources + $book->set_source_table('book', array('id' => backup::VAR_ACTIVITYID)); + + + // Define file annotations + $book->annotate_files('mod_book', 'intro', null); // This file area hasn't itemid + $chapter->annotate_files('mod_book', 'chapter', 'id'); + + // Return the root element (book), wrapped into standard activity structure + return $this->prepare_activity_structure($book); + } +} diff --git a/backup/moodle2/restore_book_activity_task.class.php b/backup/moodle2/restore_book_activity_task.class.php new file mode 100644 index 00000000000..4d51718417f --- /dev/null +++ b/backup/moodle2/restore_book_activity_task.class.php @@ -0,0 +1,130 @@ +. + +/** + * Define all the restore tasks + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->dirroot . '/mod/book/backup/moodle2/restore_book_stepslib.php'); // Because it exists (must) + +/** + * book restore task that provides all the settings and steps to perform one + * complete restore of the activity + */ +class restore_book_activity_task extends restore_activity_task { + + /** + * Define (add) particular settings this activity can have + * + * @return void + */ + protected function define_my_settings() { + // No particular settings for this activity + } + + /** + * Define (add) particular steps this activity can have + * + * @return void + */ + protected function define_my_steps() { + // Choice only has one structure step + $this->add_step(new restore_book_activity_structure_step('book_structure', 'book.xml')); + } + + /** + * Define the contents in the activity that must be + * processed by the link decoder + * + * @return array + */ + static public function define_decode_contents() { + $contents = array(); + + $contents[] = new restore_decode_content('book', array('intro'), 'book'); + $contents[] = new restore_decode_content('book_chapters', array('content'), 'book_chapter'); + + return $contents; + } + + /** + * Define the decoding rules for links belonging + * to the activity to be executed by the link decoder + * + * @return array + */ + static public function define_decode_rules() { + $rules = array(); + + // List of books in course + $rules[] = new restore_decode_rule('bookINDEX', '/mod/book/index.php?id=$1', 'course'); + + // book by cm->id + $rules[] = new restore_decode_rule('bookVIEWBYID', '/mod/book/view.php?id=$1', 'course_module'); + $rules[] = new restore_decode_rule('bookVIEWBYIDCH', '/mod/book/view.php?id=$1&chapterid=$2', array('course_module', 'book_chapter')); + + // book by book->id + $rules[] = new restore_decode_rule('bookVIEWBYB', '/mod/book/view.php?b=$1', 'book'); + $rules[] = new restore_decode_rule('bookVIEWBYBCH', '/mod/book/view.php?b=$1&chapterid=$2', array('book', 'book_chapter')); + + return $rules; + } + + /** + * Define the restore log rules that will be applied + * by the {@link restore_logs_processor} when restoring + * book logs. It must return one array + * of {@link restore_log_rule} objects + * + * @return array + */ + static public function define_restore_log_rules() { + $rules = array(); + + $rules[] = new restore_log_rule('book', 'update', 'view.php?id={course_module}', '{book}'); + $rules[] = new restore_log_rule('book', 'view', 'view.php?id={course_module}', '{book}'); + $rules[] = new restore_log_rule('book', 'view all', 'view.php?id={course_module}', '{book}'); + $rules[] = new restore_log_rule('book', 'print', 'view.php?id={course_module}', '{book}'); + + return $rules; + } + + /** + * Define the restore log rules that will be applied + * by the {@link restore_logs_processor} when restoring + * course logs. It must return one array + * of {@link restore_log_rule} objects + * + * Note this rules are applied when restoring course logs + * by the restore final task, but are defined here at + * activity level. All them are rules not linked to any module instance (cmid = 0) + * + * @return array + */ + static public function define_restore_log_rules_for_course() { + $rules = array(); + + return $rules; + } +} diff --git a/backup/moodle2/restore_book_stepslib.php b/backup/moodle2/restore_book_stepslib.php new file mode 100644 index 00000000000..55fee35335c --- /dev/null +++ b/backup/moodle2/restore_book_stepslib.php @@ -0,0 +1,74 @@ +. + +/** + * Define all the restore steps that will be used by the restore_book_activity_task + * + * @package mod + * @subpackage book + * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Structure step to restore one book activity + */ +class restore_book_activity_structure_step extends restore_activity_structure_step { + + protected function define_structure() { + + $paths = array(); + + $paths[] = new restore_path_element('book', '/activity/book'); + $paths[] = new restore_path_element('book_chapter', '/activity/book/chapters/chapter'); + + // Return the paths wrapped into standard activity structure + return $this->prepare_activity_structure($paths); + } + + protected function process_book($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + $data->course = $this->get_courseid(); + + $newitemid = $DB->insert_record('book', $data); + $this->apply_activity_instance($newitemid); + } + + protected function process_book_chapter($data) { + global $DB; + + $data = (object)$data; + $oldid = $data->id; + $data->course = $this->get_courseid(); + + $data->bookid = $this->get_new_parentid('book'); + + $newitemid = $DB->insert_record('book_chapters', $data); + $this->set_mapping('book_chapter', $oldid, $newitemid); + } + + protected function after_execute() { + global $DB; + + // Add book related files + $this->add_related_files('mod_book', 'intro', null); + $this->add_related_files('mod_book', 'chapter', 'book_chapter'); + } +} diff --git a/backuplib.php b/backuplib.php deleted file mode 100644 index 3b9f5df0369..00000000000 --- a/backuplib.php +++ /dev/null @@ -1,155 +0,0 @@ -id) - // | - // | - // | - // book_chapters - // (CL,pk->id, fk->bookid) - // - // Meaning: pk->primary key field of the table - // fk->foreign key to link with parent - // nt->nested field (recursive data) - // CL->course level info - // UL->user level info - // files->table may have files) - // - //----------------------------------------------------------- - - //This function executes all the backup procedure about this mod - function book_backup_mods($bf,$preferences) { - global $CFG; - - $status = true; - - ////Iterate over book table - if ($books = get_records ('book', 'course', $preferences->backup_course, 'id')) { - foreach ($books as $book) { - if (backup_mod_selected($preferences,'book',$book->id)) { - $status = book_backup_one_mod($bf,$preferences,$book); - } - } - } - return $status; - } - - function book_backup_one_mod($bf,$preferences,$book) { - - global $CFG; - - if (is_numeric($book)) { - $book = get_record('book','id',$book); - } - - $status = true; - - //Start mod - fwrite ($bf,start_tag('MOD',3,true)); - //Print book data - fwrite ($bf,full_tag('ID',4,false,$book->id)); - fwrite ($bf,full_tag('MODTYPE',4,false,'book')); - fwrite ($bf,full_tag('NAME',4,false,$book->name)); - fwrite ($bf,full_tag('SUMMARY',4,false,$book->summary)); - fwrite ($bf,full_tag('NUMBERING',4,false,$book->numbering)); - fwrite ($bf,full_tag('DISABLEPRINTING',4,false,$book->disableprinting)); - fwrite ($bf,full_tag('CUSTOMTITLES',4,false,$book->customtitles)); - fwrite ($bf,full_tag('TIMECREATED',4,false,$book->timecreated)); - fwrite ($bf,full_tag('TIMEMODIFIED',4,false,$book->timemodified)); - //back up the chapters - $status = backup_book_chapters($bf,$preferences,$book); - //End mod - $status = fwrite($bf,end_tag('MOD',3,true)); - - return $status; - } - - //Backup book_chapters contents (executed from book_backup_mods) - function backup_book_chapters($bf,$preferences,$book) { - - global $CFG; - - $status = true; - //Print book's chapters - if ($chapters = get_records('book_chapters', 'bookid', $book->id, 'id')) { - //Write start tag - $status =fwrite ($bf,start_tag('CHAPTERS',4,true)); - foreach ($chapters as $ch) { - //Start chapter - fwrite ($bf,start_tag('CHAPTER',5,true)); - //Print chapter data - fwrite ($bf,full_tag('ID',6,false,$ch->id)); - fwrite ($bf,full_tag('PAGENUM',6,false,$ch->pagenum)); - fwrite ($bf,full_tag('SUBCHAPTER',6,false,$ch->subchapter)); - fwrite ($bf,full_tag('TITLE',6,false,$ch->title)); - fwrite ($bf,full_tag('CONTENT',6,false,$ch->content)); - fwrite ($bf,full_tag('HIDDEN',6,false,$ch->hidden)); - fwrite ($bf,full_tag('TIMECREATED',6,false,$ch->timecreated)); - fwrite ($bf,full_tag('TIMEMODIFIED',6,false,$ch->timemodified)); - fwrite ($bf,full_tag('IMPORTSRC',6,false,$ch->importsrc)); - //End chapter - $status = fwrite ($bf,end_tag('CHAPTER',5,true)); - } - //Write end tag - $status = fwrite ($bf,end_tag('CHAPTERS',4,true)); - } - return $status; - } - - //Return a content encoded to support interactivities linking. Every module - //should have its own. They are called automatically from the backup procedure. - function book_encode_content_links ($content,$preferences) { - - global $CFG; - - $base = preg_quote($CFG->wwwroot,"/"); - - $result = $content; - - //Link to the list of books - $buscar="/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar,'$@BOOKINDEX*$2@$',$result); - - //Link to book's specific chapter - $buscar="/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)\&chapterid\=([0-9]+)/"; - $result= preg_replace($buscar,'$@BOOKCHAPTER*$2*$3@$',$result); - - //Link to book's first chapter - $buscar="/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar,'$@BOOKSTART*$2@$',$result); - - return $result; - } - - - ////Return an array of info (name,value) - function book_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) { - - if (!empty($instances) && is_array($instances) && count($instances)) { - $info = array(); - foreach ($instances as $id => $instance) { - $info += book_check_backup_mods_instances($instance,$backup_unique_code); - } - return $info; - } - - //First the course data - $info[0][0] = get_string('modulenameplural','book'); - $info[0][1] = count_records('book', 'course', $course); - - //No user data for books ;-) - - return $info; - } - - ////Return an array of info (name,value) - function book_check_backup_mods_instances($instance,$backup_unique_code) { - $info[$instance->id.'0'][0] = ''.$instance->name.''; - $info[$instance->id.'0'][1] = ''; - - return $info; - } diff --git a/lib.php b/lib.php index 18567825c89..2484fd2c596 100644 --- a/lib.php +++ b/lib.php @@ -196,7 +196,7 @@ function book_supports($feature) { case FEATURE_GROUPMEMBERSONLY: return true; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return false; //TODO - case FEATURE_BACKUP_MOODLE2: return false; //TODO + case FEATURE_BACKUP_MOODLE2: return true; default: return null; } diff --git a/restorelib.php b/restorelib.php deleted file mode 100644 index d56f715dfd3..00000000000 --- a/restorelib.php +++ /dev/null @@ -1,380 +0,0 @@ -id) - // | - // | - // | - // book_chapters - // (CL,pk->id, fk->bookid) - // - // Meaning: pk->primary key field of the table - // fk->foreign key to link with parent - // nt->nested field (recursive data) - // CL->course level info - // UL->user level info - // files->table may have files) - // - //----------------------------------------------------------- - - - //This function executes all the restore procedure about this mod - function book_restore_mods($mod,$restore) { - - global $CFG; - - $status = true; - - //Get record from backup_ids - $data = backup_getid($restore->backup_unique_code,$mod->modtype,$mod->id); - - if ($data) { - //Now get completed xmlized object - $info = $data->info; - //traverse_xmlize($info); //Debug - //print_object ($GLOBALS['traverse_array']); //Debug - //$GLOBALS['traverse_array']=""; //Debug - - //Now, build the BOOK record structure - $book = new object(); - $book->course = $restore->course_id; - $book->name = backup_todb($info['MOD']['#']['NAME']['0']['#']); - $book->summary = backup_todb($info['MOD']['#']['SUMMARY']['0']['#']); - $book->numbering = backup_todb($info['MOD']['#']['NUMBERING']['0']['#']); - $book->disableprinting = backup_todb($info['MOD']['#']['DISABLEPRINTING']['0']['#']); - $book->customtitles = backup_todb($info['MOD']['#']['CUSTOMTITLES']['0']['#']); - $book->timecreated = $info['MOD']['#']['TIMECREATED']['0']['#']; - $book->timemodified = $info['MOD']['#']['TIMEMODIFIED']['0']['#']; - - //The structure is equal to the db, so insert the book - $newid = insert_record ('book',$book); - - //Do some output - if (!defined('RESTORE_SILENTLY')) { - echo '
        • '.get_string('modulename','book').' "'.$book->name.'"
          '; - } - backup_flush(300); - - if ($newid) { - //We have the newid, update backup_ids - backup_putid($restore->backup_unique_code,$mod->modtype, - $mod->id, $newid); - //now restore chapters - $status = book_chapters_restore($mod->id,$newid,$info,$restore); - - } else { - $status = false; - } - //Finalize ul - if (!defined('RESTORE_SILENTLY')) { - echo "
        "; - } - - } else { - $status = false; - } - - return $status; - } - - //This function restores the book_chapters - function book_chapters_restore($old_book_id, $new_book_id,$info,$restore) { - - global $CFG; - - $status = true; - - //Get the chapters array - $chapters = $info['MOD']['#']['CHAPTERS']['0']['#']['CHAPTER']; - - //Iterate over chapters - for($i = 0; $i < sizeof($chapters); $i++) { - $sub_info = $chapters[$i]; - //traverse_xmlize($sub_info); //Debug - //print_object ($GLOBALS['traverse_array']); //Debug - //$GLOBALS['traverse_array']=""; //Debug - - //We'll need this later!! - $old_id = backup_todb($sub_info['#']['ID']['0']['#']); - - //Now, build the ASSIGNMENT_CHAPTERS record structure - $chapter = new object(); - $chapter->bookid = $new_book_id; - $chapter->pagenum = backup_todb($sub_info['#']['PAGENUM']['0']['#']); - $chapter->subchapter = backup_todb($sub_info['#']['SUBCHAPTER']['0']['#']); - $chapter->title = backup_todb($sub_info['#']['TITLE']['0']['#']); - $chapter->content = backup_todb($sub_info['#']['CONTENT']['0']['#']); - $chapter->hidden = backup_todb($sub_info['#']['HIDDEN']['0']['#']); - $chapter->timecreated = backup_todb($sub_info['#']['TIMECREATED']['0']['#']); - $chapter->timemodified = backup_todb($sub_info['#']['TIMEMODIFIED']['0']['#']); - $chapter->importsrc = backup_todb($sub_info['#']['IMPORTSRC']['0']['#']); - - //The structure is equal to the db, so insert the book_chapters - $newid = insert_record ('book_chapters',$chapter); - - //Do some output - if (($i+1) % 50 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo '.'; - if (($i+1) % 1000 == 0) { - echo '
        '; - } - } - backup_flush(300); - } - - if ($newid) { - //We have the newid, update backup_ids - backup_putid($restore->backup_unique_code,'book_chapters',$old_id, - $newid); - } else { - $status = false; - } - } - return $status; - } - - //This function returns a log record with all the necessay transformations - //done. It's used by restore_log_module() to restore modules log. - function book_restore_logs($restore,$log) { - - $status = false; - - //Depending of the action, we recode different things - switch ($log->action) { - case "update": - case "view": //TO DO ... verify!!! - if ($log->cmid) { - //Get the new_id of the chapter (to recode the url field) - $ch = backup_getid($restore->backup_unique_code,"book_chapters",$log->info); - if ($ch) { - $log->url = "view.php?id=".$log->cmid."&chapterid=".$ch->new_id; - $log->info = $ch->new_id; - $status = true; - } - } - break; - case "view all": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "view.php?id=".$log->cmid; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "export": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "export.php?id=".$log->cmid; - $log->info = $mod->new_id; - $status = true; - } - } - break; - case "print": - if ($log->cmid) { - //Get the new_id of the module (to recode the info field) - $mod = backup_getid($restore->backup_unique_code,$log->module,$log->info); - if ($mod) { - $log->url = "print.php?id=".$log->cmid; - $log->info = $mod->new_id; - $status = true; - } - } - break; - default: - if (!defined('RESTORE_SILENTLY')) { - echo "action (".$log->module."-".$log->action.") unknown. Not restored
        "; //Debug - } - break; - } - - if ($status) { - $status = $log; - } - return $status; - } - - //Return a content decoded to support interactivities linking. Every module - //should have its own. They are called automatically from - //book_decode_content_links_caller() function in each module - //in the restore process - function book_decode_content_links ($content,$restore) { - - global $CFG; - - $result = $content; - - //Link to the list of books - - $searchstring='/\$@(BOOKINDEX)\*([0-9]+)@\$/'; - //We look for it - preg_match_all($searchstring,$content,$foundset); - //If found, then we are going to look for its new id (in backup tables) - if ($foundset[0]) { - //print_object($foundset); //Debug - //Iterate over foundset[2]. They are the old_ids - foreach($foundset[2] as $old_id) { - //We get the needed variables here (course id) - $rec = backup_getid($restore->backup_unique_code,"course",$old_id); - //Personalize the searchstring - $searchstring='/\$@(BOOKINDEX)\*('.$old_id.')@\$/'; - //If it is a link to this course, update the link to its new location - if($rec->new_id) { - //Now replace it - $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/book/index.php?id='.$rec->new_id,$result); - } else { - //It's a foreign link so leave it as original - $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/book/index.php?id='.$old_id,$result); - } - } - } - - - //Links to specific chapters of books - - $searchstring='/\$@(BOOKCHAPTER)\*([0-9]+)\*([0-9]+)@\$/'; - //We look for it - preg_match_all($searchstring,$result,$foundset); - //If found, then we are going to look for its new id (in backup tables) - if ($foundset[0]) { - //print_object($foundset); //Debug - //Iterate over foundset[2] and foundset[3]. They are the old_ids - foreach($foundset[2] as $key => $old_id) { - $old_id2 = $foundset[3][$key]; - //We get the needed variables here (discussion id and post id) - $rec = backup_getid($restore->backup_unique_code,'course_modules',$old_id); - $rec2 = backup_getid($restore->backup_unique_code,'book_chapters',$old_id2); - //Personalize the searchstring - $searchstring='/\$@(BOOKCHAPTER)\*('.$old_id.')\*('.$old_id2.')@\$/'; - //If it is a link to this course, update the link to its new location - if($rec->new_id && $rec2->new_id) { - //Now replace it - $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/book/view.php?id='.$rec->new_id.'&chapterid='.$rec2->new_id,$result); - } else { - //It's a foreign link so leave it as original - $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/book/view.php?id='.$old_id.'&chapterid='.$old_id2,$result); - } - } - } - - - //Links to first chapters of books - - $searchstring='/\$@(BOOKSTART)\*([0-9]+)@\$/'; - //We look for it - preg_match_all($searchstring,$result,$foundset); - //If found, then we are going to look for its new id (in backup tables) - if ($foundset[0]) { - //print_object($foundset); //Debug - //Iterate over foundset[2]. They are the old_ids - foreach($foundset[2] as $old_id) { - //We get the needed variables here (course_modules id) - $rec = backup_getid($restore->backup_unique_code,"course_modules",$old_id); - //Personalize the searchstring - $searchstring='/\$@(BOOKSTART)\*('.$old_id.')@\$/'; - //If it is a link to this course, update the link to its new location - if($rec->new_id) { - //Now replace it - $result= preg_replace($searchstring,$CFG->wwwroot.'/mod/book/view.php?id='.$rec->new_id,$result); - } else { - //It's a foreign link so leave it as original - $result= preg_replace($searchstring,$restore->original_wwwroot.'/mod/book/view.php?id='.$old_id,$result); - } - } - } - - return $result; - } - - //This function makes all the necessary calls to xxxx_decode_content_links() - //function in each module, passing them the desired contents to be decoded - //from backup format to destination site/course in order to mantain inter-activities - //working in the backup/restore process. It's called from restore_decode_content_links() - //function in restore process - function book_decode_content_links_caller($restore) { - global $CFG; - $status = true; - - //Decode every BOOK (summary) in the coure - if ($books = get_records_sql ("SELECT b.id, b.summary - FROM {$CFG->prefix}book b - WHERE b.course = $restore->course_id")) { - //Iterate over each book->summary - $i = 0; //Counter to send some output to the browser to avoid timeouts - foreach ($books as $book) { - //Increment counter - $i++; - $content = $book->summary; - $result = restore_decode_content_links_worker($content,$restore); - if ($result != $content) { - //Update record - $book->intro $result; - $status = update_record('book',$book); - if ($CFG->debug>7) { - if (!defined('RESTORE_SILENTLY')) { - echo '

        '.htmlentities($content).'
        changed to
        '.htmlentities($result).'

        '; - } - } - } - //Do some output - if (($i+1) % 5 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo '.'; - if (($i+1) % 100 == 0) { - echo '
        '; - } - } - backup_flush(300); - } - } - } - - //Decode every CHAPTER in the course - if ($chapters = get_records_sql ("SELECT ch.id, ch.content - FROM {$CFG->prefix}book b, - {$CFG->prefix}book_chapters ch - WHERE b.course = $restore->course_id AND - ch.bookid = b.id")) { - //Iterate over each chapter->content - $i = 0; //Counter to send some output to the browser to avoid timeouts - foreach ($chapters as $chapter) { - //Increment counter - $i++; - $content = $chapter->content; - $result = restore_decode_content_links_worker($content,$restore); - if ($result != $content) { - //Update record - $chapter->content = $result; - $status = update_record('book_chapters',$chapter); - if ($CFG->debug>7) { - if (!defined('RESTORE_SILENTLY')) { - echo '

        '.htmlentities($content).'
        changed to
        '.htmlentities($result).'

        '; - } - } - } - //Do some output - if (($i+1) % 5 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo '.'; - if (($i+1) % 100 == 0) { - echo '
        '; - } - } - backup_flush(300); - } - } - } - - return $status; - } - From 22b8fa4dda2e1a368fb47a8b2b2c563ee55307c9 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 10 Dec 2010 15:52:36 +0100 Subject: [PATCH 071/455] fixed upgrade typo --- db/upgrade.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/db/upgrade.php b/db/upgrade.php index 72d4c69903b..a4fa099b716 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -52,9 +52,6 @@ function xmldb_book_upgrade($oldversion) { // Launch rename field summary $dbman->rename_field($table, $field, 'intro'); - // Launch rename field summary - $dbman->change_field_precision($table, $field, 'intro'); - // book savepoint reached upgrade_mod_savepoint(true, 2010120801, 'book'); } From 58aa4b57185ecd8575696469bf2c9c22798c7be4 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 10 Dec 2010 15:54:37 +0100 Subject: [PATCH 072/455] recover from previous error --- db/upgrade.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/db/upgrade.php b/db/upgrade.php index a4fa099b716..1b2759924e8 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -50,7 +50,9 @@ function xmldb_book_upgrade($oldversion) { $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'name'); // Launch rename field summary - $dbman->rename_field($table, $field, 'intro'); + if ($dbman->field_exists($table, $field)) { + $dbman->rename_field($table, $field, 'intro'); + } // book savepoint reached upgrade_mod_savepoint(true, 2010120801, 'book'); From 292a46eb1bd290e50bbd8bac1a1fb5fa1075942d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 2 Jan 2011 21:20:12 +0100 Subject: [PATCH 073/455] fixed toc allignment --- view.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view.php b/view.php index 9f49f3407b2..f9a648728da 100644 --- a/view.php +++ b/view.php @@ -214,7 +214,7 @@ $generateimscp = ''; //TODO after new file handling
         
        box_start('generalbox'); @@ -227,7 +227,7 @@ $generateimscp = ''; //TODO after new file handling } ?>
         
        +
         
        box_start('generalbox'); echo '
        '; From 74b6860a784ba529f6457e50b40cb98b938d0903 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 11:31:34 +0100 Subject: [PATCH 074/455] CONTRIB-2656 fix disabling of printing --- view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view.php b/view.php index f9a648728da..da5eb08a777 100644 --- a/view.php +++ b/view.php @@ -52,7 +52,7 @@ require_capability('mod/book:read', $context); $allowedit = has_capability('mod/book:edit', $context); $allowimport = has_capability('mod/book:import', $context); -$allowprint = has_capability('mod/book:print', $context) and !$book->disableprinting; +$allowprint = (has_capability('mod/book:print', $context) and !$book->disableprinting); $allowexport = has_capability('mod/book:exportimscp', $context); $viewhidden = has_capability('mod/book:viewhiddenchapters', $context); From 8ecb96add3633a745de8ce117e649c9d3b0d8719 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 11:44:02 +0100 Subject: [PATCH 075/455] CONTRIB-2154 add user outline --- lib.php | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/lib.php b/lib.php index 2484fd2c596..aad407dfac0 100644 --- a/lib.php +++ b/lib.php @@ -102,14 +102,30 @@ function book_get_types() { return array($type); } -function book_user_outline($course, $user, $mod, $book) { - // Return a small object with summary information about what a - // user has done with a given particular instance of this module - // Used for user activity reports. - // $return->time = the time they did it - // $return->info = a short text description +/** + * Return use outline + * @param object $course + * @param object $user + * @param object $mod + * @param object $page + * @return object|null + */ +function page_user_outline($course, $user, $mod, $book) { + global $DB; - return null; + if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'book', + 'action'=>'view', 'info'=>$book->id), 'time ASC')) { + + $numviews = count($logs); + $lastlog = array_pop($logs); + + $result = new stdClass(); + $result->info = get_string('numviews', '', $numviews); + $result->time = $lastlog->time; + + return $result; + } + return NULL; } function book_user_complete($course, $user, $mod, $book) { From 7c44a1a2063cf9c4efb9c727c63d94c1499a2abc Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 12:22:10 +0100 Subject: [PATCH 076/455] fixed release info and copyrights --- README | 4 ++++ version.php | 10 +++++----- view.php | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/README b/README index d9308a4d9fe..7a2b390c9ef 100644 --- a/README +++ b/README @@ -102,6 +102,10 @@ CHANGELOG: * minor cleanup * new Slovenian language pack - thanks Mitja Podreka * updated German Language pack - thanks Ralf Hilgenstock +== 1.9 2011/01/15 ============================================================ + * fixed print icons + * implemented user outline + * fixed page title formatting == 2.0dev ============================================================ * Moodle 2.0 conversion - no new features diff --git a/version.php b/version.php index 029d3ed0a26..0b5b957661e 100644 --- a/version.php +++ b/version.php @@ -19,12 +19,12 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2010120805; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2010120700; // Requires this Moodle version -$module->cron = 0; // Period for cron to check this module (secs) +$module->version = 2011011500; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2010120700; // Requires this Moodle version +$module->cron = 0; // Period for cron to check this module (secs) -$release = "2.0dev"; // User-friendly version number +$release = "2.0dev (2011011500)"; // User-friendly version number diff --git a/view.php b/view.php index da5eb08a777..45edbb93d0f 100644 --- a/view.php +++ b/view.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 5572147bc1c45efbd92b1eb6e4055478d08b8f62 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 12:52:36 +0100 Subject: [PATCH 077/455] standard gitignore --- .gitignore | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..043a39ba30d --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# See gitignore(5) man page for more details +# +*~ +*.swp +/tags +/TAGS +/cscope.* +/.patches/ +/.idea/ +/nbproject/ +CVS +.DS_Store +/.settings/ +/.project +/.buildpath +/.cache From dcf3a920d1f8e4282afb15ff5213b10765a17487 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 16:42:29 +0100 Subject: [PATCH 078/455] fixed lib.php typo --- lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib.php b/lib.php index aad407dfac0..d8b4ad009d8 100644 --- a/lib.php +++ b/lib.php @@ -110,7 +110,7 @@ function book_get_types() { * @param object $page * @return object|null */ -function page_user_outline($course, $user, $mod, $book) { +function book_user_outline($course, $user, $mod, $book) { global $DB; if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'book', From 7c6c37466f379536a3f1e5952b4d3d4f3179f852 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 21:28:43 +0100 Subject: [PATCH 079/455] update book index page --- README | 2 +- index.php | 117 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 62 insertions(+), 57 deletions(-) diff --git a/README b/README index 7a2b390c9ef..1971d9b8751 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ Book module for Moodle -Copyright (C) 2004-2010 Petr Skoda (http://skodak.org) +Copyright (C) 2004-2011 Petr Skoda (http://skodak.org) This program is free software; you can redistribute it and/or modify diff --git a/index.php b/index.php index eb7c4e67865..6bebe640a37 100644 --- a/index.php +++ b/index.php @@ -1,100 +1,105 @@ . -/// This page lists all the instances of book in a particular course +/** + * This page lists all the instances of book in a particular course + * + * @package mod + * @subpackage book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ require_once('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID -// ========================================================================= -// security checks START - teachers and students view -// ========================================================================= - $course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST); -require_course_login($course, true); - -//check all variables unset($id); -// ========================================================================= -// security checks END -// ========================================================================= +require_course_login($course, true); +$PAGE->set_pagelayout('incourse'); /// Get all required strings -$strbooks = get_string('modulenameplural', 'book'); -$strbook = get_string('modulename', 'book'); +$strbooks = get_string('modulenameplural', 'book'); +$strbook = get_string('modulename', 'book'); +$strsectionname = get_string('sectionname', 'format_'.$course->format); +$strname = get_string('name'); +$strintro = get_string('moduleintro'); +$strlastmodified = get_string('lastmodified'); - -$navlinks = array(); -$navlinks[] = array('name' => $strbooks, 'link' => '', 'type' => 'activity'); -$navigation = build_navigation($navlinks); - -print_header_simple($strbooks, '', $navigation, '', '', true, '', navmenu($course)); +$PAGE->set_url('/mod/book/index.php', array('id' => $course->id)); +$PAGE->set_title($course->shortname.': '.$strbooks); +$PAGE->set_heading($course->fullname); +$PAGE->navbar->add($strbooks); +echo $OUTPUT->header(); add_to_log($course->id, 'book', 'view all', 'index.php?id='.$course->id, ''); /// Get all the appropriate data if (!$books = get_all_instances_in_course('book', $course)) { - notice('There are no books', '../../course/view.php?id='.$course->id); + notice(get_string('thereareno', 'moodle', $strbooks), "$CFG->wwwroot/course/view.php?id=$course->id"); die; } -/// Print the list of instances -$strname = get_string('name'); -$strweek = get_string('week'); -$strtopic = get_string('topic'); -$strsummary = get_string('summary'); -$strchapters = get_string('chapterscount', 'book'); +$usesections = course_format_uses_sections($course->format); +if ($usesections) { + $sections = get_all_sections($course->id); +} -if ($course->format == 'weeks') { - $table->head = array ($strweek, $strname, $strsummary, $strchapters); - $table->align = array ('center', 'left', 'left', 'center'); -} else if ($course->format == 'topics') { - $table->head = array ($strtopic, $strname, $strsummary, $strchapters); - $table->align = array ('center', 'left', 'left', 'center'); +$table = new html_table(); +$table->attributes['class'] = 'generaltable mod_index'; + +if ($usesections) { + $table->head = array ($strsectionname, $strname, $strintro); + $table->align = array ('center', 'left', 'left'); } else { - $table->head = array ($strname, $strsummary, $strchapters); + $table->head = array ($strlastmodified, $strname, $strintro); $table->align = array ('left', 'left', 'left'); } +$modinfo = get_fast_modinfo($course); $currentsection = ''; foreach ($books as $book) { - $nocleanoption = new object(); - $nocleanoption->noclean = true; - $book->summary = format_text($book->intro, $book->introformat, $nocleanoption, $course->id); - $book->summary = ''.$book->summary.''; - - if (!$book->visible) { - //Show dimmed if the mod is hidden - $link = ''.$book->name.''; - } else { - //Show normal if the mod is visible - $link = ''.$book->name.''; - } - - $count = $DB->count_records('book_chapters', array('bookid'=>$book->id, 'hidden'=>'0')); - - if ($course->format == 'weeks' or $course->format == 'topics') { + $cm = $modinfo->cms[$book->coursemodule]; + if ($usesections) { $printsection = ''; if ($book->section !== $currentsection) { if ($book->section) { - $printsection = $book->section; + $printsection = get_section_name($course, $sections[$book->section]); } if ($currentsection !== '') { $table->data[] = 'hr'; } $currentsection = $book->section; } - $table->data[] = array ($printsection, $link, $book->summary, $count); } else { - $table->data[] = array ($link, $book->summary, $count); + $printsection = ''.userdate($book->timemodified).""; } + + $class = $book->visible ? '' : 'class="dimmed"'; // hidden modules are dimmed + + $table->data[] = array ( + $printsection, + "id\">".format_string($book->name)."", + format_module_intro('book', $book, $cm->id)); } -echo '
        '; -print_table($table); - -print_footer($course); +echo html_writer::table($table); +echo $OUTPUT->footer(); From 4171f20dbffd8a1deceef0ba18de01ec96d1dfe6 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 21:46:45 +0100 Subject: [PATCH 080/455] refactor toc to locallib function --- locallib.php | 189 +++++++++++++++++++++++++++++++++++++++++++++ print.php | 7 +- toc.php | 211 --------------------------------------------------- view.php | 3 +- 4 files changed, 192 insertions(+), 218 deletions(-) delete mode 100644 toc.php diff --git a/locallib.php b/locallib.php index a608379e3a2..74b852de9f7 100644 --- a/locallib.php +++ b/locallib.php @@ -299,3 +299,192 @@ function book_relink($id, $bookid, $courseid) { } } } + +function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { + global $USER, $OUTPUT; + + /// included from mod/book/view.php and print.php + /// + /// uses: + /// $chapters - all book chapters + /// $chapter - may be false + /// $cm - course module + /// $book - book + /// $edit - force editing view + + + /// fills: + /// $toc + /// $title (not for print) + + $currtitle = ''; //active chapter title (plain text) + $currsubtitle = ''; //active subchapter if any + $prevtitle = ' '; + $toc = ''; //representation of toc (HTML) + + $nch = 0; //chapter number + $ns = 0; //subchapter number + $first = 1; + $titles = array(); + + switch ($book->numbering) { + case BOOK_NUM_NONE: + $toc .= '
        '; + break; + case BOOK_NUM_NUMBERS: + $toc .= '
        '; + break; + case BOOK_NUM_BULLETS: + $toc .= '
        '; + break; + case BOOK_NUM_INDENTED: + $toc .= '
        '; + break; + } + + + if ($print) { ///TOC for printing + $toc .= ''; + if ($book->customtitles) { + $toc .= '

        '.get_string('toc', 'book').'

        '; + } else { + $toc .= '

        '.get_string('toc', 'book').'

        '; + } + $toc .= '
          '; + foreach($chapters as $ch) { + $title = trim(strip_tags($ch->title)); + if (!$ch->hidden) { + if (!$ch->subchapter) { + $nch++; + $ns = 0; + $toc .= ($first) ? '
        • ' : '
      • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch $title"; + } + } else { + $ns++; + $toc .= ($first) ? '
        • ' : '
        • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } + $titles[$ch->id] = $title; + $toc .= ''.$title.''; + $toc .= (!$ch->subchapter) ? '
            ' : ''; + $first = 0; + } + } + $toc .= '
        '; + } else if ($edit) { ///teacher's TOC + $toc .= '
          '; + $i = 0; + foreach($chapters as $ch) { + $i++; + $title = trim(strip_tags($ch->title)); + if (!$ch->subchapter) { + $toc .= ($first) ? '
        • ' : '
      • '; + if (!$ch->hidden) { + $nch++; + $ns = 0; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch $title"; + } + } else { + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "x $title"; + } + $title = ''.$title.''; + } + $prevtitle = $title; + } else { + $toc .= ($first) ? '
        • ' : '
        • '; + if (!$ch->hidden) { + $ns++; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } else { + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "x.x $title"; + } + $title = ''.$title.''; + } + } + + if ($ch->id == $chapter->id) { + $toc .= ''.$title.''; + if ($ch->subchapter) { + $currtitle = $prevtitle; + $currsubtitle = $title; + } else { + $currtitle = $title; + $currsubtitle = ' '; + } + } else { + $toc .= ''.$title.''; + } + $toc .= '  '; + if ($i != 1) { + $toc .= ' '.get_string('up').''; + } + if ($i != count($chapters)) { + $toc .= ' '.get_string('down').''; + } + $toc .= ' '.get_string('edit').''; + $toc .= ' '.get_string('delete').''; + if ($ch->hidden) { + $toc .= ' '.get_string('show').''; + } else { + $toc .= ' '.get_string('hide').''; + } + $toc .= ' '.get_string('addafter', 'book').''; + + $toc .= (!$ch->subchapter) ? '
            ' : ''; + $first = 0; + } + $toc .= '
        '; + } else { //normal students view + $toc .= '
          '; + foreach($chapters as $ch) { + $title = trim(strip_tags($ch->title)); + if (!$ch->hidden) { + if (!$ch->subchapter) { + $nch++; + $ns = 0; + $toc .= ($first) ? '
        • ' : '
      • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch $title"; + } + $prevtitle = $title; + } else { + $ns++; + $toc .= ($first) ? '
        • ' : '
        • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } + if ($ch->id == $chapter->id) { + $toc .= ''.$title.''; + if ($ch->subchapter) { + $currtitle = $prevtitle; + $currsubtitle = $title; + } else { + $currtitle = $title; + $currsubtitle = ' '; + } + } else { + $toc .= ''.$title.''; + } + $toc .= (!$ch->subchapter) ? '
            ' : ''; + $first = 0; + } + } + $toc .= '
        '; + } + + $toc .= '
      • '; + + $toc = str_replace('
          ', '', $toc); //cleanup of invalid structures + + return array($toc, $currtitle, $currsubtitle, $titles); +} \ No newline at end of file diff --git a/print.php b/print.php index 68938c1ed1e..2f1bf950660 100644 --- a/print.php +++ b/print.php @@ -76,9 +76,7 @@ if ($chapter) { $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id, 'hidden'=>0), 'pagenum, title'); - $print = 0; - $edit = 0; - require('toc.php'); + list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, 0, 0); /// page header ?> @@ -145,8 +143,7 @@ if ($chapter) {
        wwwroot.'/mod/book/view.php?id='.$course->id.'&chapterid='; diff --git a/toc.php b/toc.php deleted file mode 100644 index b87f694b4a6..00000000000 --- a/toc.php +++ /dev/null @@ -1,211 +0,0 @@ -. - -/** - * Book toc printing - * - * @package mod - * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/// included from mod/book/view.php and print.php -/// -/// uses: -/// $chapters - all book chapters -/// $chapter - may be false -/// $cm - course module -/// $book - book -/// $edit - force editing view - - -/// fills: -/// $toc -/// $title (not for print) - -$currtitle = ''; //active chapter title (plain text) -$currsubtitle = ''; //active subchapter if any -$prevtitle = ' '; -$toc = ''; //representation of toc (HTML) - -$nch = 0; //chapter number -$ns = 0; //subchapter number -$title = ''; -$first = 1; - -switch ($book->numbering) { - case BOOK_NUM_NONE: - $toc .= '
        '; - break; - case BOOK_NUM_NUMBERS: - $toc .= '
        '; - break; - case BOOK_NUM_BULLETS: - $toc .= '
        '; - break; - case BOOK_NUM_INDENTED: - $toc .= '
        '; - break; -} - - -if ($print) { ///TOC for printing - $toc .= ''; - if ($book->customtitles) { - $toc .= '

        '.get_string('toc', 'book').'

        '; - } else { - $toc .= '

        '.get_string('toc', 'book').'

        '; - } - $titles = array(); - $toc .= '
          '; - foreach($chapters as $ch) { - $title = trim(strip_tags($ch->title)); - if (!$ch->hidden) { - if (!$ch->subchapter) { - $nch++; - $ns = 0; - $toc .= ($first) ? '
        • ' : '
      • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - } else { - $ns++; - $toc .= ($first) ? '
        • ' : '
        • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } - $titles[$ch->id] = $title; - $toc .= ''.$title.''; - $toc .= (!$ch->subchapter) ? '
            ' : ''; - $first = 0; - } - } - $toc .= '
        '; -} else if ($edit) { ///teacher's TOC - $toc .= '
          '; - $i = 0; - foreach($chapters as $ch) { - $i++; - $title = trim(strip_tags($ch->title)); - if (!$ch->subchapter) { - $toc .= ($first) ? '
        • ' : '
      • '; - if (!$ch->hidden) { - $nch++; - $ns = 0; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - } else { - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "x $title"; - } - $title = ''.$title.''; - } - $prevtitle = $title; - } else { - $toc .= ($first) ? '
        • ' : '
        • '; - if (!$ch->hidden) { - $ns++; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } else { - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "x.x $title"; - } - $title = ''.$title.''; - } - } - - if ($ch->id == $chapter->id) { - $toc .= ''.$title.''; - if ($ch->subchapter) { - $currtitle = $prevtitle; - $currsubtitle = $title; - } else { - $currtitle = $title; - $currsubtitle = ' '; - } - } else { - $toc .= ''.$title.''; - } - $toc .= '  '; - if ($i != 1) { - $toc .= ' '.get_string('up').''; - } - if ($i != count($chapters)) { - $toc .= ' '.get_string('down').''; - } - $toc .= ' '.get_string('edit').''; - $toc .= ' '.get_string('delete').''; - if ($ch->hidden) { - $toc .= ' '.get_string('show').''; - } else { - $toc .= ' '.get_string('hide').''; - } - $toc .= ' '.get_string('addafter', 'book').''; - - $toc .= (!$ch->subchapter) ? '
            ' : ''; - $first = 0; - } - $toc .= '
        '; -} else { //normal students view - $toc .= '
          '; - foreach($chapters as $ch) { - $title = trim(strip_tags($ch->title)); - if (!$ch->hidden) { - if (!$ch->subchapter) { - $nch++; - $ns = 0; - $toc .= ($first) ? '
        • ' : '
      • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - $prevtitle = $title; - } else { - $ns++; - $toc .= ($first) ? '
        • ' : '
        • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } - if ($ch->id == $chapter->id) { - $toc .= ''.$title.''; - if ($ch->subchapter) { - $currtitle = $prevtitle; - $currsubtitle = $title; - } else { - $currtitle = $title; - $currsubtitle = ' '; - } - } else { - $toc .= ''.$title.''; - } - $toc .= (!$ch->subchapter) ? '
            ' : ''; - $first = 0; - } - } - $toc .= '
        '; -} - -$toc .= '
      • '; - -$toc = str_replace('
          ', '', $toc); //cleanup of invalid structures - diff --git a/view.php b/view.php index 45edbb93d0f..cfc699c927d 100644 --- a/view.php +++ b/view.php @@ -175,8 +175,7 @@ if (!$allowprint) { } // prepare $toc and $currtitle, $currsubtitle -$print = 0; -include('toc.php'); +list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); if ($edit) { $tocwidth = $CFG->book_tocwidth + 80; From 608826922a74089a344d43269f361c8415b3cd76 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 21:51:38 +0100 Subject: [PATCH 081/455] fix extra height attribute --- locallib.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locallib.php b/locallib.php index 74b852de9f7..49965ccb6b3 100644 --- a/locallib.php +++ b/locallib.php @@ -425,19 +425,19 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { } $toc .= '  '; if ($i != 1) { - $toc .= ' '.get_string('up').''; + $toc .= ' '.get_string('up').''; } if ($i != count($chapters)) { - $toc .= ' '.get_string('down').''; + $toc .= ' '.get_string('down').''; } - $toc .= ' '.get_string('edit').''; - $toc .= ' '.get_string('delete').''; + $toc .= ' '.get_string('edit').''; + $toc .= ' '.get_string('delete').''; if ($ch->hidden) { - $toc .= ' '.get_string('show').''; + $toc .= ' '.get_string('show').''; } else { - $toc .= ' '.get_string('hide').''; + $toc .= ' '.get_string('hide').''; } - $toc .= ' '.get_string('addafter', 'book').''; + $toc .= ' '.get_string('addafter', 'book').''; $toc .= (!$ch->subchapter) ? '
            ' : ''; $first = 0; From f6ca19aed06f0b7131c7b296a4db1823abb1b7a2 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 21:55:37 +0100 Subject: [PATCH 082/455] locallib cleanup --- locallib.php | 406 ++++++++++++++++++++++++++------------------------- 1 file changed, 205 insertions(+), 201 deletions(-) diff --git a/locallib.php b/locallib.php index 49965ccb6b3..70154c0e432 100644 --- a/locallib.php +++ b/locallib.php @@ -25,14 +25,19 @@ defined('MOODLE_INTERNAL') || die; +require_once($CFG->dirroot.'/mod/book/lib.php'); +require_once($CFG->libdir.'/filelib.php'); + + define('BOOK_NUM_NONE', '0'); define('BOOK_NUM_NUMBERS', '1'); define('BOOK_NUM_BULLETS', '2'); define('BOOK_NUM_INDENTED', '3'); -require_once($CFG->dirroot.'/mod/book/lib.php'); -require_once($CFG->libdir.'/filelib.php'); - +/** + * Returns list of available numbering types + * @return array + */ function book_get_numbering_types() { return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), @@ -40,15 +45,10 @@ function book_get_numbering_types() { BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); } - -////////////////////////////////////////////////////////////////////////////////////// -/// Any other book functions go here. Each of them must have a name that -/// starts with book_ - /** - * check chapter ordering and make sure subchapter is not first + * Check chapter ordering and make sure subchapter is not first * in book hidden chapter must have all subchapters hidden too - * @param int $id + * @param int $bookid * @return void */ function book_check_structure($bookid) { @@ -75,7 +75,13 @@ function book_check_structure($bookid) { } } -/// general function for logging to table +/** + * General logging to table + * @param string $str1 + * @param string $str2 + * @param int $level + * @return void + */ function book_log($str1, $str2, $level = 0) { switch ($level) { case 1: @@ -90,8 +96,195 @@ function book_log($str1, $str2, $level = 0) { } } +/** + * Generate toc structure and titles + * + * @param array $chapters + * @param stdClass $chapter + * @param stdClass $book + * @param stdClass $cm + * @param bool $edit + * @param bool $print + * @return array + */ +function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { + global $USER, $OUTPUT; + + $currtitle = ''; //active chapter title (plain text) + $currsubtitle = ''; //active subchapter if any + $prevtitle = ' '; + $toc = ''; //representation of toc (HTML) + + $nch = 0; //chapter number + $ns = 0; //subchapter number + $first = 1; + $titles = array(); + + switch ($book->numbering) { + case BOOK_NUM_NONE: + $toc .= '
            '; + break; + case BOOK_NUM_NUMBERS: + $toc .= '
            '; + break; + case BOOK_NUM_BULLETS: + $toc .= '
            '; + break; + case BOOK_NUM_INDENTED: + $toc .= '
            '; + break; + } + + + if ($print) { ///TOC for printing + $toc .= ''; + if ($book->customtitles) { + $toc .= '

            '.get_string('toc', 'book').'

            '; + } else { + $toc .= '

            '.get_string('toc', 'book').'

            '; + } + $toc .= '
              '; + foreach($chapters as $ch) { + $title = trim(strip_tags($ch->title)); + if (!$ch->hidden) { + if (!$ch->subchapter) { + $nch++; + $ns = 0; + $toc .= ($first) ? '
            • ' : '
          • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch $title"; + } + } else { + $ns++; + $toc .= ($first) ? '
            • ' : '
            • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } + $titles[$ch->id] = $title; + $toc .= ''.$title.''; + $toc .= (!$ch->subchapter) ? '
                ' : ''; + $first = 0; + } + } + $toc .= '
            '; + } else if ($edit) { ///teacher's TOC + $toc .= '
              '; + $i = 0; + foreach($chapters as $ch) { + $i++; + $title = trim(strip_tags($ch->title)); + if (!$ch->subchapter) { + $toc .= ($first) ? '
            • ' : '
          • '; + if (!$ch->hidden) { + $nch++; + $ns = 0; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch $title"; + } + } else { + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "x $title"; + } + $title = ''.$title.''; + } + $prevtitle = $title; + } else { + $toc .= ($first) ? '
            • ' : '
            • '; + if (!$ch->hidden) { + $ns++; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } else { + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "x.x $title"; + } + $title = ''.$title.''; + } + } + + if ($ch->id == $chapter->id) { + $toc .= ''.$title.''; + if ($ch->subchapter) { + $currtitle = $prevtitle; + $currsubtitle = $title; + } else { + $currtitle = $title; + $currsubtitle = ' '; + } + } else { + $toc .= ''.$title.''; + } + $toc .= '  '; + if ($i != 1) { + $toc .= ' '.get_string('up').''; + } + if ($i != count($chapters)) { + $toc .= ' '.get_string('down').''; + } + $toc .= ' '.get_string('edit').''; + $toc .= ' '.get_string('delete').''; + if ($ch->hidden) { + $toc .= ' '.get_string('show').''; + } else { + $toc .= ' '.get_string('hide').''; + } + $toc .= ' '.get_string('addafter', 'book').''; + + $toc .= (!$ch->subchapter) ? '
                ' : ''; + $first = 0; + } + $toc .= '
            '; + } else { //normal students view + $toc .= '
              '; + foreach($chapters as $ch) { + $title = trim(strip_tags($ch->title)); + if (!$ch->hidden) { + if (!$ch->subchapter) { + $nch++; + $ns = 0; + $toc .= ($first) ? '
            • ' : '
          • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch $title"; + } + $prevtitle = $title; + } else { + $ns++; + $toc .= ($first) ? '
            • ' : '
            • '; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $title = "$nch.$ns $title"; + } + } + if ($ch->id == $chapter->id) { + $toc .= ''.$title.''; + if ($ch->subchapter) { + $currtitle = $prevtitle; + $currsubtitle = $title; + } else { + $currtitle = $title; + $currsubtitle = ' '; + } + } else { + $toc .= ''.$title.''; + } + $toc .= (!$ch->subchapter) ? '
                ' : ''; + $first = 0; + } + } + $toc .= '
            '; + } + + $toc .= '
          • '; + + $toc = str_replace('
              ', '', $toc); //cleanup of invalid structures + + return array($toc, $currtitle, $currsubtitle, $titles); +} + + //================================================= -// import functions +// import functions - not converted yet! //================================================= /// normalize relative links (= remove ..) @@ -299,192 +492,3 @@ function book_relink($id, $bookid, $courseid) { } } } - -function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { - global $USER, $OUTPUT; - - /// included from mod/book/view.php and print.php - /// - /// uses: - /// $chapters - all book chapters - /// $chapter - may be false - /// $cm - course module - /// $book - book - /// $edit - force editing view - - - /// fills: - /// $toc - /// $title (not for print) - - $currtitle = ''; //active chapter title (plain text) - $currsubtitle = ''; //active subchapter if any - $prevtitle = ' '; - $toc = ''; //representation of toc (HTML) - - $nch = 0; //chapter number - $ns = 0; //subchapter number - $first = 1; - $titles = array(); - - switch ($book->numbering) { - case BOOK_NUM_NONE: - $toc .= '
              '; - break; - case BOOK_NUM_NUMBERS: - $toc .= '
              '; - break; - case BOOK_NUM_BULLETS: - $toc .= '
              '; - break; - case BOOK_NUM_INDENTED: - $toc .= '
              '; - break; - } - - - if ($print) { ///TOC for printing - $toc .= ''; - if ($book->customtitles) { - $toc .= '

              '.get_string('toc', 'book').'

              '; - } else { - $toc .= '

              '.get_string('toc', 'book').'

              '; - } - $toc .= '
                '; - foreach($chapters as $ch) { - $title = trim(strip_tags($ch->title)); - if (!$ch->hidden) { - if (!$ch->subchapter) { - $nch++; - $ns = 0; - $toc .= ($first) ? '
              • ' : '
            • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - } else { - $ns++; - $toc .= ($first) ? '
              • ' : '
              • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } - $titles[$ch->id] = $title; - $toc .= ''.$title.''; - $toc .= (!$ch->subchapter) ? '
                  ' : ''; - $first = 0; - } - } - $toc .= '
              '; - } else if ($edit) { ///teacher's TOC - $toc .= '
                '; - $i = 0; - foreach($chapters as $ch) { - $i++; - $title = trim(strip_tags($ch->title)); - if (!$ch->subchapter) { - $toc .= ($first) ? '
              • ' : '
            • '; - if (!$ch->hidden) { - $nch++; - $ns = 0; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - } else { - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "x $title"; - } - $title = ''.$title.''; - } - $prevtitle = $title; - } else { - $toc .= ($first) ? '
              • ' : '
              • '; - if (!$ch->hidden) { - $ns++; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } else { - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "x.x $title"; - } - $title = ''.$title.''; - } - } - - if ($ch->id == $chapter->id) { - $toc .= ''.$title.''; - if ($ch->subchapter) { - $currtitle = $prevtitle; - $currsubtitle = $title; - } else { - $currtitle = $title; - $currsubtitle = ' '; - } - } else { - $toc .= ''.$title.''; - } - $toc .= '  '; - if ($i != 1) { - $toc .= ' '.get_string('up').''; - } - if ($i != count($chapters)) { - $toc .= ' '.get_string('down').''; - } - $toc .= ' '.get_string('edit').''; - $toc .= ' '.get_string('delete').''; - if ($ch->hidden) { - $toc .= ' '.get_string('show').''; - } else { - $toc .= ' '.get_string('hide').''; - } - $toc .= ' '.get_string('addafter', 'book').''; - - $toc .= (!$ch->subchapter) ? '
                  ' : ''; - $first = 0; - } - $toc .= '
              '; - } else { //normal students view - $toc .= '
                '; - foreach($chapters as $ch) { - $title = trim(strip_tags($ch->title)); - if (!$ch->hidden) { - if (!$ch->subchapter) { - $nch++; - $ns = 0; - $toc .= ($first) ? '
              • ' : '
            • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - $prevtitle = $title; - } else { - $ns++; - $toc .= ($first) ? '
              • ' : '
              • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } - if ($ch->id == $chapter->id) { - $toc .= ''.$title.''; - if ($ch->subchapter) { - $currtitle = $prevtitle; - $currsubtitle = $title; - } else { - $currtitle = $title; - $currsubtitle = ' '; - } - } else { - $toc .= ''.$title.''; - } - $toc .= (!$ch->subchapter) ? '
                  ' : ''; - $first = 0; - } - } - $toc .= '
              '; - } - - $toc .= '
            • '; - - $toc = str_replace('
                ', '', $toc); //cleanup of invalid structures - - return array($toc, $currtitle, $currsubtitle, $titles); -} \ No newline at end of file From dc888a311cf5f12fba7a9545d5589b92f1ce083c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 21:58:04 +0100 Subject: [PATCH 083/455] fix multilang suppport in chapter titles --- locallib.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/locallib.php b/locallib.php index 70154c0e432..917da7b2e6d 100644 --- a/locallib.php +++ b/locallib.php @@ -120,6 +120,8 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { $first = 1; $titles = array(); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + switch ($book->numbering) { case BOOK_NUM_NONE: $toc .= '
                '; @@ -145,7 +147,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { } $toc .= '
                  '; foreach($chapters as $ch) { - $title = trim(strip_tags($ch->title)); + $title = trim(format_string($ch->title, true, array('context'=>$context))); if (!$ch->hidden) { if (!$ch->subchapter) { $nch++; @@ -173,7 +175,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { $i = 0; foreach($chapters as $ch) { $i++; - $title = trim(strip_tags($ch->title)); + $title = trim(format_string($ch->title, true, array('context'=>$context))); if (!$ch->subchapter) { $toc .= ($first) ? '
                • ' : '
              • '; if (!$ch->hidden) { @@ -239,7 +241,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { } else { //normal students view $toc .= '
                  '; foreach($chapters as $ch) { - $title = trim(strip_tags($ch->title)); + $title = trim(format_string($ch->title, true, array('context'=>$context))); if (!$ch->hidden) { if (!$ch->subchapter) { $nch++; From 9221a71122e6406977f1be2eb3be00c59b0a2a32 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 22:33:08 +0100 Subject: [PATCH 084/455] fix case --- lang/en/book.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lang/en/book.php b/lang/en/book.php index 99955cfb239..cd76f30e242 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -6,7 +6,7 @@ $string['modulename_help'] = 'Book is a simple multipage study material.'; $string['pluginname'] = 'Book'; $string['pluginadministration'] = 'Book administration'; -$string['toc'] = 'Table of Contents'; +$string['toc'] = 'Table of contents'; $string['tocwidth'] = 'Select width of the Table of Contents for all books.'; $string['book_tocwidth'] = 'Table of Contents width'; $string['faq'] = 'Book FAQ'; @@ -37,17 +37,17 @@ Either rephrase your titles or ask your site admin to change TOC width. It is defined globally for all books in module configuration page.'; -$string['disableprinting'] = 'Disable Printing'; +$string['disableprinting'] = 'Disable printing'; $string['disableprinting_help'] = 'Hide print icons.'; -$string['customtitles'] = 'Custom Titles'; +$string['customtitles'] = 'Custom citles'; $string['customtitles_help'] = 'Chapter titles are displayed automatically only in TOC.'; $string['editingchapter'] = 'Editing chapter'; -$string['chaptertitle'] = 'Chapter Title'; +$string['chaptertitle'] = 'Chapter title'; $string['content'] = 'Content'; $string['subchapter'] = 'Subchapter'; -$string['numbering'] = 'Chapter Numbering'; +$string['numbering'] = 'Chapter numbering'; $string['numbering_help'] = '* None - chapter and subchapter titles are not formatted at all, use if you want to define special numbering styles. For example letters: in chapter title type "A First Chapter", "A.1 Some Subchapter",... * Numbers - chapters and subchapters are numbered (1, 1.1, 1.2, 2, ...) * Bullets - subchapters are indented and displayed with bullets @@ -65,15 +65,15 @@ $string['confchapterdelete'] = 'Do you really want to delete this chapter?'; $string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?'; $string['generateimscp'] = 'Generate IMS content package'; -$string['printbook'] = 'Print Complete Book'; -$string['printchapter'] = 'Print This Chapter'; +$string['printbook'] = 'Print book'; +$string['printchapter'] = 'Print this chapter'; $string['printdate'] = 'Date'; $string['printedby'] = 'Printed by'; $string['top'] = 'top'; $string['navprev'] = 'Previous'; $string['navnext'] = 'Next'; -$string['navexit'] = 'Exit Book'; +$string['navexit'] = 'Exit book'; $string['importingchapters'] = 'Importing chapters into book'; $string['import'] = 'Import'; From 758f7dde8018f12ae2a1f7bb690da04cc308906b Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 22:33:33 +0100 Subject: [PATCH 085/455] move print and other functions to the settings block --- README | 6 ++++++ lib.php | 46 +++++++++++++++++++++++++++++++++++----------- view.php | 27 ++------------------------- 3 files changed, 43 insertions(+), 36 deletions(-) diff --git a/README b/README index 1971d9b8751..a580816bf7c 100644 --- a/README +++ b/README @@ -109,4 +109,10 @@ CHANGELOG: == 2.0dev ============================================================ * Moodle 2.0 conversion - no new features +TODO: +* upgrade imscp export code (disabled for now) +* upgrade import code (disabled for now) +* open print links in new windows (needs fix in navlib) + + Petr diff --git a/lib.php b/lib.php index d8b4ad009d8..d79904618bf 100644 --- a/lib.php +++ b/lib.php @@ -236,9 +236,6 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); } - if (!has_capability('mod/book:edit', $PAGE->cm->context)) { - return; - } $params = $PAGE->url->params(); @@ -246,16 +243,43 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig return; } - if (!empty($USER->editing)) { - $string = get_string("turneditingoff"); - $edit = '0'; - } else { - $string = get_string("turneditingon"); - $edit = '1'; + if (has_capability('mod/book:print', $PAGE->cm->context)) { + $book = $DB->get_record('book', array('id'=>$PAGE->cm->instance)); + if (!$book->disableprinting) { + $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); + $booknode->add(get_string('printbook', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); + + // buggy navlib - actions not supported!! + //$action = new action_link($url, get_string('printbook', 'book'), new popup_action('onclick', $url)); + //$booknode->add('', $action, navigation_node::TYPE_SETTING); + + $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); + $booknode->add(get_string('printchapter', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); + } } - $url = new moodle_url('/mod/book/view.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'], 'edit'=>$edit, 'sesskey'=>sesskey())); - $booknode->add($string, $url, navigation_node::TYPE_SETTING); + if (has_capability('mod/book:import', $PAGE->cm->context)) { + //TODO + //$doimport = ($allowimport and $edit) ? '' : ''; + } + + if (has_capability('mod/book:exportimscp', $PAGE->cm->context)) { + //TODO + /// Enable the IMS CP button + //$generateimscp = ($allowexport) ? ''.get_string('generateimscp', 'book').'' : ''; + } + + if (has_capability('mod/book:edit', $PAGE->cm->context)) { + if (!empty($USER->editing)) { + $string = get_string("turneditingoff"); + $edit = '0'; + } else { + $string = get_string("turneditingon"); + $edit = '1'; + } + $url = new moodle_url('/mod/book/view.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'], 'edit'=>$edit, 'sesskey'=>sesskey())); + $booknode->add($string, $url, navigation_node::TYPE_SETTING); + } } /** diff --git a/view.php b/view.php index cfc699c927d..231d58c921a 100644 --- a/view.php +++ b/view.php @@ -51,9 +51,6 @@ $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:read', $context); $allowedit = has_capability('mod/book:edit', $context); -$allowimport = has_capability('mod/book:import', $context); -$allowprint = (has_capability('mod/book:print', $context) and !$book->disableprinting); -$allowexport = has_capability('mod/book:exportimscp', $context); $viewhidden = has_capability('mod/book:viewhiddenchapters', $context); if ($allowedit) { @@ -96,11 +93,10 @@ if ($chapterid == '0') { // go to first chapter if no given } } +$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); + $PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chapterid'=>$chapterid)); -if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id))) { - error('Error reading book chapters.'); -} //check all variables unset($id); @@ -165,15 +161,6 @@ if ($nextid) { $chnavigation .= ''.get_string('navexit', 'book').''; } -/// prepare print icons -if (!$allowprint) { - $printbook = ''; - $printchapter = ''; -} else { - $printbook = ''.get_string('printbook', 'book').''; - $printchapter = ''.get_string('printchapter', 'book').''; -} - // prepare $toc and $currtitle, $currsubtitle list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); @@ -183,14 +170,6 @@ if ($edit) { $tocwidth = $CFG->book_tocwidth; } -//$doimport = ($allowimport and $edit) ? '' : ''; -$doimport = ''; //TODO: after new file handling - -/// Enable the IMS CP button -//$generateimscp = ($allowexport) ? ''.get_string('generateimscp', 'book').'' : ''; -$generateimscp = ''; //TODO after new file handling - - // ===================================================== // Book display HTML code // ===================================================== @@ -203,11 +182,9 @@ $generateimscp = ''; //TODO after new file handling -
                  From 75b38e9864a47b0dccca15ec056a00c0ef0b1c44 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 22:34:40 +0100 Subject: [PATCH 086/455] completion todo --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index a580816bf7c..13de725cfa7 100644 --- a/README +++ b/README @@ -113,6 +113,7 @@ TODO: * upgrade imscp export code (disabled for now) * upgrade import code (disabled for now) * open print links in new windows (needs fix in navlib) +* completion tracking Petr From 8e277fe5fcb366605b9546a8f4ab0a0549de9ff7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 23:41:10 +0100 Subject: [PATCH 087/455] fix overriding of CSS --- book_print.css | 1 - 1 file changed, 1 deletion(-) diff --git a/book_print.css b/book_print.css index 57574ed20d6..7b7ccede3c1 100644 --- a/book_print.css +++ b/book_print.css @@ -34,7 +34,6 @@ h1, h2, h3, h4, h5, h6 { border-bottom-width: 1px; border-left-width: 0px; - margin-left: -40px; margin-left: 0px; margin-bottom: 20px; } From ad1e18e20952334c3adf2d58f7d8e3f15a4f9aba Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 23:41:36 +0100 Subject: [PATCH 088/455] fix old style format_string and text + errors detected by code inspection --- print.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/print.php b/print.php index 2f1bf950660..bdf51e83ebe 100644 --- a/print.php +++ b/print.php @@ -83,9 +83,9 @@ if ($chapter) { - <?php echo format_string($book->name) ?> + <?php echo format_string($book->name, true, array('context'=>$context)) ?> - + @@ -114,28 +114,28 @@ if ($chapter) { - <?php echo format_string(name) ?> - - + <?php echo format_string($book->name, true, array('context'=>$context)) ?> + + -

                  name) ?>

                  -

                  intro, $book->introformat) ?>

                  +

                  name, true, array('context'=>$context)) ?>

                  +

                  intro, $book->introformat, array('noclean'=>true, 'context'=>$context)) ?>

                  - + - + - + - + From db4d90886f9f88b7388dfc01bb0b80ba4fb5f5cd Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 23:42:00 +0100 Subject: [PATCH 089/455] fix missing ) --- import.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/import.php b/import.php index 666c751baca..87360c51252 100644 --- a/import.php +++ b/import.php @@ -114,7 +114,7 @@ if ($mform->is_cancelled()) { $chapter = book_read_chapter($coursebase, $ref); if ($chapter) { $chapter->bookid = $book->id; - $chapter->pagenum = $DB->count_records('book_chapters', array('bookid'=>$book->id)+1; + $chapter->pagenum = $DB->count_records('book_chapters', array('bookid'=>$book->id)+1); $chapter->timecreated = time(); $chapter->timemodified = time(); echo "imsrc:".$chapter->importsrc; From c60d3ab331c27675689eddc5b15b392865dfd6de Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 23:42:15 +0100 Subject: [PATCH 090/455] fix error detected by code inspeaction --- view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view.php b/view.php index 231d58c921a..85a50805c95 100644 --- a/view.php +++ b/view.php @@ -40,7 +40,7 @@ if ($id) { $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); } else { $book = $DB->get_record('book', array('id'=>$bid), '*', MUST_EXIST); - $cm = get_coursemodule_from_instance('book', $book->id, 0, false, MUid, 0, false, MUST_EXIST); $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); $id = $cm->id; } From 3223060316f023e6410d879421a22959ef392108 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 15 Jan 2011 23:45:42 +0100 Subject: [PATCH 091/455] fix charset --- locallib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locallib.php b/locallib.php index 917da7b2e6d..81ed766b8da 100644 --- a/locallib.php +++ b/locallib.php @@ -342,8 +342,8 @@ function book_read_chapter($base, $ref) { if (preg_match('/charset=([^"]+)/is', $head, $matches)) { $enc = $matches[1]; $textlib = textlib_get_instance(); - $chapter->content = $textlib->convert($chapter->content, $enc, current_charset()); - $chapter->title = $textlib->convert($chapter->title, $enc, current_charset()); + $chapter->content = $textlib->convert($chapter->content, $enc, 'utf-8'); + $chapter->title = $textlib->convert($chapter->title, $enc, 'utf-8'); } if (preg_match_all('/]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css for($i=0; $i Date: Sat, 15 Jan 2011 23:45:51 +0100 Subject: [PATCH 092/455] conversion todo --- import.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/import.php b/import.php index 87360c51252..fc797aa94df 100644 --- a/import.php +++ b/import.php @@ -68,7 +68,7 @@ $mform->set_data(array('id'=>$cm->id)); /// If data submitted, then process and store. if ($mform->is_cancelled()) { - if (empty($chapter->id)) { + if (empty($chapter->id)) { //TODO: problem redirect("view.php?id=$cm->id"); } else { redirect("view.php?id=$cm->id&chapterid=$chapter->id"); From e2790e4bf740cb4c5568ed77b63c3ef901632e8a Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 10:51:22 +0100 Subject: [PATCH 093/455] improt conversion and other cleanup --- edit.php | 8 ------- import.php | 61 ++++++++++++++++++++++--------------------------- import_form.php | 46 +++++++++---------------------------- print.php | 2 +- 4 files changed, 39 insertions(+), 78 deletions(-) diff --git a/edit.php b/edit.php index 09b4d5f6f1e..721c6e374db 100644 --- a/edit.php +++ b/edit.php @@ -32,10 +32,6 @@ $chapterid = optional_param('id', 0, PARAM_INT); // Chapter ID $pagenum = optional_param('pagenum', 0, PARAM_INT); $subchapter = optional_param('subchapter', 0, PARAM_BOOL); -// ========================================================================= -// security checks START - only teachers edit -// ========================================================================= - $cm = get_coursemodule_from_id('book', $cmid, 0, false, MUST_EXIST); $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); @@ -47,10 +43,6 @@ require_capability('mod/book:edit', $context); $PAGE->set_url('/mod/book/edit.php', array('cmid'=>$cmid, 'id'=>$chapterid, 'pagenum'=>$pagenum, 'subchapter'=>$subchapter)); -// ========================================================================= -// security checks END -// ========================================================================= - if ($chapterid) { $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); } else { diff --git a/import.php b/import.php index fc797aa94df..6907d47b74a 100644 --- a/import.php +++ b/import.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,13 +27,8 @@ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once('import_form.php'); -$id = required_param('id', PARAM_INT); // Course Module ID - -die('Not converted to 2.0 yet, sorry'); - -// ========================================================================= -// security checks START - only teachers edit -// ========================================================================= +$id = required_param('id', PARAM_INT); // Course Module ID +$chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID $cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); $course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); @@ -44,37 +39,40 @@ require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:import', $context); -$PAGE->set_url('/mod/book/import.php', array('id'=>$id)); +$PAGE->set_url('/mod/book/import.php', array('id'=>$id, 'chapterid'=>$chapterid)); -//check all variables -unset($id); +if ($chapterid) { + if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id))) { + $chapterid = 0; + } +} else { + $chapter = false; +} -// ========================================================================= -// security checks END -// ========================================================================= +$PAGE->set_title(format_string($book->name)); +$PAGE->add_body_class('mod_book'); +$PAGE->set_heading(format_string($course->fullname)); ///prepare the page header $strbook = get_string('modulename', 'book'); $strbooks = get_string('modulenameplural', 'book'); -$strimport = get_string('import', 'book'); -$navlinks = array(); -$navlinks[] = array('name' => $strimport, 'link' => '', 'type' => 'title'); - -$navigation = build_navigation($navlinks, $cm); - -$mform = new book_import_form(null, $cm); -$mform->set_data(array('id'=>$cm->id)); +$mform = new book_import_form(null, array('id'=>$id, 'chapterid'=>$chapterid)); /// If data submitted, then process and store. if ($mform->is_cancelled()) { - if (empty($chapter->id)) { //TODO: problem + if (empty($chapter->id)) { redirect("view.php?id=$cm->id"); } else { redirect("view.php?id=$cm->id&chapterid=$chapter->id"); } -} else if ($data = $mform->get_data(false)) { +} else if ($data = $mform->get_data()) { + + + die('TODO'); +/* + $coursebase = $CFG->dataroot.'/'.$book->course; $reference = book_prepare_link($data->reference); @@ -139,18 +137,13 @@ if ($mform->is_cancelled()) { print_continue('view.php?id='.$cm->id); print_footer($course); die; + + */ } -print_header("$course->shortname: $book->name", $course->fullname, $navigation); - -$strdoimport = get_string('doimport', 'book'); -$strchoose = get_string('choose'); -$pageheading = get_string('importingchapters', 'book'); - -$icon = ' '; -print_heading_with_help($pageheading, 'import', 'book', $icon); +echo $OUTPUT->header(); +echo $OUTPUT->heading(get_string('importingchapters', 'book')); $mform->display(); -print_footer($course); - +echo $OUTPUT->footer(); diff --git a/import_form.php b/import_form.php index aeb76764ced..a3a9f04c713 100644 --- a/import_form.php +++ b/import_form.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -30,54 +30,30 @@ class book_import_form extends moodleform { function definition() { global $CFG; $mform = $this->_form; - $cm = $this->_customdata; + $data = $this->_customdata; $mform->addElement('header', 'general', get_string('import')); - $group = array(); - $group[0] =& MoodleQuickForm::createElement('text', 'reference', get_string('fileordir', 'book'), array('size'=>'48')); - $group[1] =& MoodleQuickForm::createElement('button', 'popup', get_string('chooseafile', 'resource') .' ...'); + $mform->addElement('filepicker', 'importfile', get_string('file')); + $mform->addRule('importfile', null, 'required'); - $options = 'menubar=0,location=0,scrollbars,resizable,width=600,height=400'; - $url = '/mod/book/coursefiles.php?choose=id_reference&id='.$cm->course; - $buttonattributes = array('title'=>get_string('chooseafile', 'resource'), 'onclick'=>"return openpopup('$url', '".$group[1]->getName()."', '$options', 0);"); - $group[1]->updateAttributes($buttonattributes); - - $mform->addGroup($group, 'choosesomething', get_string('fileordir', 'book'), array(''), false); - - $mform->addElement('checkbox', 'subchapter', get_string('subchapter', 'book')); - $mform->addElement('static', 'importfileinfo', get_string('help'), get_string('importinfo', 'book')); - - $mform->addElement('hidden', 'id', $cm->id); + $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); + $mform->addElement('hidden', 'chapterid'); + $mform->setType('chapterid', PARAM_INT); + $this->add_action_buttons(true, get_string('import', 'book')); + + $this->set_data($data); } function validation($data, $files) { global $CFG; - $cm = $this->_customdata; $errors = parent::validation($data, $files); - $reference = $data['reference']; - if ($reference != '') { //null path is root - $reference = book_prepare_link($reference); - if ($reference == '') { //evil characters in $ref! - $errors['choosesomething'] = get_string('error'); - } else { - $coursebase = $CFG->dataroot.'/'.$cm->course; - - if ($reference == '') { - $base = $coursebase; - } else { - $base = $coursebase.'/'.$reference; - } - if (!is_dir($base) and !is_file($base)) { - $errors['choosesomething'] = get_string('error'); - } - } - } + //TODO: validate package return $errors; } diff --git a/print.php b/print.php index bdf51e83ebe..a92bdbe1f20 100644 --- a/print.php +++ b/print.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 5dc5d0354863f117c37031d7f1c24a3df50c4e05 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:00:29 +0100 Subject: [PATCH 094/455] remove obsole disableprinting - use capabilities instead --- backup/moodle2/backup_book_stepslib.php | 2 +- db/install.xml | 7 +++---- db/upgrade.php | 15 ++++++++++++++- lang/be/book.php | 1 - lang/be/help/book/disableprinting.html | 3 --- lang/be/help/book/index.html | 10 ---------- lang/ca/book.php | 1 - lang/ca/help/book/disableprinting.html | 3 --- lang/ca/help/book/index.html | 11 ----------- lang/cs/book.php | 1 - lang/cs/help/book/disableprinting.html | 3 --- lang/cs/help/book/index.html | 11 ----------- lang/de/book.php | 1 - lang/de/help/book/disableprinting.html | 1 - lang/de/help/book/index.html | 1 - lang/en/book.php | 2 -- lang/fi/book.php | 1 - lang/fi/help/book/disableprinting.html | 3 --- lang/fi/help/book/index.html | 11 ----------- lang/it/book.php | 1 - lang/it/help/book/disableprinting.html | 3 --- lang/it/help/book/index.html | 10 ---------- lang/ja/book.php | 1 - lang/ja/help/book/disableprinting.html | 3 --- lang/ja/help/book/index.html | 11 ----------- lang/nl/book.php | 1 - lang/nl/help/book/disableprinting.html | 6 ------ lang/nl/help/book/index.html | 11 ----------- lang/pl/book.php | 1 - lang/pl/help/book/index.html | 10 ---------- lang/pt_br/book.php | 1 - lang/pt_br/help/book/disableprinting.html | 3 --- lang/pt_br/help/book/index.html | 11 ----------- lang/sk/book.php | 1 - lang/sk/help/book/disableprinting.html | 3 --- lang/sk/help/book/index.html | 11 ----------- lang/sl/book.php | 1 - lang/sl/help/book/disableprinting.html | 3 --- lang/sl/help/book/index.html | 11 ----------- lang/sv/book.php | 1 - lang/sv/help/book/disableprinting.html | 2 -- lang/sv/help/book/index.html | 11 ----------- lib.php | 23 +++++++---------------- mod_form.php | 4 ---- print.php | 4 ---- version.php | 2 +- 46 files changed, 26 insertions(+), 212 deletions(-) delete mode 100644 lang/be/help/book/disableprinting.html delete mode 100644 lang/be/help/book/index.html delete mode 100644 lang/ca/help/book/disableprinting.html delete mode 100644 lang/ca/help/book/index.html delete mode 100644 lang/cs/help/book/disableprinting.html delete mode 100644 lang/cs/help/book/index.html delete mode 100644 lang/de/help/book/disableprinting.html delete mode 100644 lang/de/help/book/index.html delete mode 100644 lang/fi/help/book/disableprinting.html delete mode 100644 lang/fi/help/book/index.html delete mode 100644 lang/it/help/book/disableprinting.html delete mode 100644 lang/it/help/book/index.html delete mode 100644 lang/ja/help/book/disableprinting.html delete mode 100644 lang/ja/help/book/index.html delete mode 100644 lang/nl/help/book/disableprinting.html delete mode 100644 lang/nl/help/book/index.html delete mode 100644 lang/pl/help/book/index.html delete mode 100644 lang/pt_br/help/book/disableprinting.html delete mode 100644 lang/pt_br/help/book/index.html delete mode 100644 lang/sk/help/book/disableprinting.html delete mode 100644 lang/sk/help/book/index.html delete mode 100644 lang/sl/help/book/disableprinting.html delete mode 100644 lang/sl/help/book/index.html delete mode 100644 lang/sv/help/book/disableprinting.html delete mode 100644 lang/sv/help/book/index.html diff --git a/backup/moodle2/backup_book_stepslib.php b/backup/moodle2/backup_book_stepslib.php index 2be4d942a68..a0800cf8ac7 100644 --- a/backup/moodle2/backup_book_stepslib.php +++ b/backup/moodle2/backup_book_stepslib.php @@ -33,7 +33,7 @@ class backup_book_activity_structure_step extends backup_activity_structure_step protected function define_structure() { // Define each element separated - $book = new backup_nested_element('book', array('id'), array('name', 'intro', 'introformat', 'numbering', 'disableprinting', 'customtitles', 'timecreated', 'timemodified')); + $book = new backup_nested_element('book', array('id'), array('name', 'intro', 'introformat', 'numbering', 'customtitles', 'timecreated', 'timemodified')); $chapters = new backup_nested_element('chapters'); $chapter = new backup_nested_element('chapter', array('id'), array('pagenum', 'subchapter', 'title', 'content', 'contentormat', 'hidden', 'timemcreated', 'timemodified', 'importsrc',)); diff --git a/db/install.xml b/db/install.xml index 51f393b74bd..d01db999547 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -11,9 +11,8 @@ - - - + + diff --git a/db/upgrade.php b/db/upgrade.php index 1b2759924e8..7a30e002e73 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2009-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2009-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -138,6 +138,19 @@ function xmldb_book_upgrade($oldversion) { upgrade_mod_savepoint(true, 2010120805, 'book'); } + if ($oldversion < 2011011600) { + // Define field disableprinting to be dropped from book + $table = new xmldb_table('book'); + $field = new xmldb_field('disableprinting'); + + // Conditionally launch drop field disableprinting + if ($dbman->field_exists($table, $field)) { + $dbman->drop_field($table, $field); + } + + // book savepoint reached + upgrade_mod_savepoint(true, 2011011600, 'book'); + } //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter diff --git a/lang/be/book.php b/lang/be/book.php index 95868b6bb44..654e769d290 100644 --- a/lang/be/book.php +++ b/lang/be/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Вы сапраўды жадаеце выдал $string['confchapterdeleteall'] = 'Ці сапраўды Вы жадаеце выдаліць гэты раздзел і ўсе параграфы?'; $string['content'] = 'Змест'; $string['customtitles'] = 'Прыватныя назвы'; -$string['disableprinting'] = 'Забараніць друкаванне'; $string['doimport'] = 'Імпарт'; $string['editingchapter'] = 'Рэдагаваць радзел'; $string['faq'] = 'FAQ па падручніку'; diff --git a/lang/be/help/book/disableprinting.html b/lang/be/help/book/disableprinting.html deleted file mode 100644 index a9b457fe03b..00000000000 --- a/lang/be/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Забараніць друкаванне

                  - -

                  Схаваць цэтлік друку.

                  \ No newline at end of file diff --git a/lang/be/help/book/index.html b/lang/be/help/book/index.html deleted file mode 100644 index f6a03549276..00000000000 --- a/lang/be/help/book/index.html +++ /dev/null @@ -1,10 +0,0 @@ -

                  Book module

                  - \ No newline at end of file diff --git a/lang/ca/book.php b/lang/ca/book.php index 475bff58b2b..1d724bcbd58 100644 --- a/lang/ca/book.php +++ b/lang/ca/book.php @@ -8,7 +8,6 @@ $string['toc'] = 'Índex'; $string['tocwidth'] = 'Escolliu l\'amplada de l\'índex per tots els llibres.'; $string['faq'] = 'PMF dels llibres (FAQ)'; -$string['disableprinting'] = 'Desactiva la impressió'; $string['customtitles'] = 'Títols personalitzats'; $string['editingchapter'] = 'S\'està editant el capítol'; diff --git a/lang/ca/help/book/disableprinting.html b/lang/ca/help/book/disableprinting.html deleted file mode 100644 index 78c66b0dbf3..00000000000 --- a/lang/ca/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Deshabilita la impressió

                  - -

                  Oculta les icones d'imprimir.

                  diff --git a/lang/ca/help/book/index.html b/lang/ca/help/book/index.html deleted file mode 100644 index 725a957f9c2..00000000000 --- a/lang/ca/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Mòdul de Llibres

                  - - diff --git a/lang/cs/book.php b/lang/cs/book.php index 044842a7d49..87edcf35c85 100644 --- a/lang/cs/book.php +++ b/lang/cs/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Opravdu chcete odstranit tuto kapitolu?'; $string['confchapterdeleteall'] = 'Opravdu chcete odstranit tuto kapitolu včetně podkapitol?'; $string['content'] = 'Text'; $string['customtitles'] = 'Uživatelské nadpisy'; -$string['disableprinting'] = 'Zakázat tisk'; $string['doimport'] = 'Importovat'; $string['editingchapter'] = 'Úprava kapitoly'; $string['faq'] = 'Časté otázky'; diff --git a/lang/cs/help/book/disableprinting.html b/lang/cs/help/book/disableprinting.html deleted file mode 100644 index 42c9cb6cad1..00000000000 --- a/lang/cs/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Zakázat tisknutí

                  - -

                  Skrýt ikony pro tisk.

                  diff --git a/lang/cs/help/book/index.html b/lang/cs/help/book/index.html deleted file mode 100644 index b867e3397c9..00000000000 --- a/lang/cs/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Modul Kniha

                  - - diff --git a/lang/de/book.php b/lang/de/book.php index 20a80d4e213..0b3f44c47cf 100644 --- a/lang/de/book.php +++ b/lang/de/book.php @@ -8,7 +8,6 @@ $string['toc'] = 'Inhaltsverzeichnis'; $string['tocwidth'] = 'Wählen Sie die Breite des Inhaltsverzeichnisses für alle Bücher aus.'; $string['faq'] = 'Buch FAQ'; -$string['disableprinting'] = 'Drucken deaktivieren'; $string['customtitles'] = 'Angepasster Titel'; $string['editingchapter'] = 'Kapitel ändern'; diff --git a/lang/de/help/book/disableprinting.html b/lang/de/help/book/disableprinting.html deleted file mode 100644 index 024a7eaed42..00000000000 --- a/lang/de/help/book/disableprinting.html +++ /dev/null @@ -1 +0,0 @@ -

                  Druckfunktion ausschalten

                  Verbirgt die Funktion zum Ausdruck einzelner Seiten oder des gesamten Buches.

                  \ No newline at end of file diff --git a/lang/de/help/book/index.html b/lang/de/help/book/index.html deleted file mode 100644 index 312fb42b9a1..00000000000 --- a/lang/de/help/book/index.html +++ /dev/null @@ -1 +0,0 @@ -

                  Buch-Modul

                  \ No newline at end of file diff --git a/lang/en/book.php b/lang/en/book.php index cd76f30e242..18985ba0c96 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -37,8 +37,6 @@ Either rephrase your titles or ask your site admin to change TOC width. It is defined globally for all books in module configuration page.'; -$string['disableprinting'] = 'Disable printing'; -$string['disableprinting_help'] = 'Hide print icons.'; $string['customtitles'] = 'Custom citles'; $string['customtitles_help'] = 'Chapter titles are displayed automatically only in TOC.'; diff --git a/lang/fi/book.php b/lang/fi/book.php index 698ab0ca0e6..ae30ebb722b 100644 --- a/lang/fi/book.php +++ b/lang/fi/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Haluatko varmasti poistaa tämän luvun?'; $string['confchapterdeleteall'] = 'Haluatko varmasti poistaa tämän luvun ja sen alaluvut?'; $string['content'] = 'Sisältö'; $string['customtitles'] = 'Mukautetut otsikot'; -$string['disableprinting'] = 'Estä tulostus'; $string['doimport'] = 'Tuo'; $string['editingchapter'] = 'Luvun muokkaus'; $string['faq'] = 'Usein kysytyt kysymykset'; diff --git a/lang/fi/help/book/disableprinting.html b/lang/fi/help/book/disableprinting.html deleted file mode 100644 index 3bade0237a9..00000000000 --- a/lang/fi/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Estä tulostus

                  - -

                  Piilottaa tulostuspainikkeet.

                  diff --git a/lang/fi/help/book/index.html b/lang/fi/help/book/index.html deleted file mode 100644 index 752692e009b..00000000000 --- a/lang/fi/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Book module

                  - - diff --git a/lang/it/book.php b/lang/it/book.php index 2b137bfde96..04fe1b49fa2 100644 --- a/lang/it/book.php +++ b/lang/it/book.php @@ -14,7 +14,6 @@ $string['confchapterdelete'] = 'Sei sicuro di eliminare questo capitolo?'; $string['confchapterdeleteall'] = 'Sei sicuro di eliminare questo capitolo e tutti i suoi paragrafi?'; $string['content'] = 'Contenuto'; $string['customtitles'] = 'Titoli personalizzati'; -$string['disableprinting'] = 'Disabilita la stampa'; $string['doexport'] = 'Esporta'; $string['doimport'] = 'Importa'; $string['editingchapter'] = 'Modifica capitolo'; diff --git a/lang/it/help/book/disableprinting.html b/lang/it/help/book/disableprinting.html deleted file mode 100644 index 389d77a0fae..00000000000 --- a/lang/it/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Esclusione stampa

                  - -

                  L'icona per la stampa viene nascosta.

                  \ No newline at end of file diff --git a/lang/it/help/book/index.html b/lang/it/help/book/index.html deleted file mode 100644 index 7890e73dea7..00000000000 --- a/lang/it/help/book/index.html +++ /dev/null @@ -1,10 +0,0 @@ -

                  Libro

                  - \ No newline at end of file diff --git a/lang/ja/book.php b/lang/ja/book.php index 52494661308..e394ddff83f 100644 --- a/lang/ja/book.php +++ b/lang/ja/book.php @@ -8,7 +8,6 @@ $string['toc'] = '目次'; $string['tocwidth'] = 'コンテンツのテーブル幅を選んでください。'; $string['faq'] = 'ブック FAQ'; -$string['disableprinting'] = 'プリント不可'; $string['customtitles'] = 'カスタムタイトル'; $string['editingchapter'] = '章を編集'; diff --git a/lang/ja/help/book/disableprinting.html b/lang/ja/help/book/disableprinting.html deleted file mode 100644 index 99f9b80b783..00000000000 --- a/lang/ja/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  印刷不可

                  - -

                  印刷アイコンを隠します。

                  diff --git a/lang/ja/help/book/index.html b/lang/ja/help/book/index.html deleted file mode 100644 index ab97206904c..00000000000 --- a/lang/ja/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Book module

                  - - diff --git a/lang/nl/book.php b/lang/nl/book.php index 3018d1f5d1f..7014e6ee72f 100644 --- a/lang/nl/book.php +++ b/lang/nl/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Wil je dit hoofdstuk echt verwijderen?'; $string['confchapterdeleteall'] = 'Wil je dit hoofdstuk en alle paragrafen echt verwijderen?'; $string['content'] = 'Inhoud'; $string['customtitles'] = 'Titels alleen in inhoudstafel'; -$string['disableprinting'] = 'Schakel afdrukken uit'; $string['doimport'] = 'Importeer'; $string['editingchapter'] = 'Bewerk hoofdstuk'; $string['faq'] = 'Boek FAQ'; diff --git a/lang/nl/help/book/disableprinting.html b/lang/nl/help/book/disableprinting.html deleted file mode 100644 index 3f6827c5dd5..00000000000 --- a/lang/nl/help/book/disableprinting.html +++ /dev/null @@ -1,6 +0,0 @@ -

                  Schakel afdrukken uit

                  - - - -

                  Verberg alle icoontjes om af te drukken.

                  - diff --git a/lang/nl/help/book/index.html b/lang/nl/help/book/index.html deleted file mode 100644 index 1afd2ebd7c1..00000000000 --- a/lang/nl/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Boekmodule

                  - - diff --git a/lang/pl/book.php b/lang/pl/book.php index b6b881ebb56..0522b4bf992 100644 --- a/lang/pl/book.php +++ b/lang/pl/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Czy napewno chcesz usunąć ten rozdział'; $string['confchapterdeleteall'] = 'Czy napewno chcesz usunąć ten rozdział i wszystkie jego podrozdziały?'; $string['content'] = 'Zawartość'; $string['customtitles'] = 'Tytuły użytkownika'; -$string['disableprinting'] = 'Wyłącz drukowanie'; $string['doimport'] = 'Import'; $string['editingchapter'] = 'Edycja rozdziału'; $string['faq'] = 'FAQ Książki'; diff --git a/lang/pl/help/book/index.html b/lang/pl/help/book/index.html deleted file mode 100644 index 65e71583d2e..00000000000 --- a/lang/pl/help/book/index.html +++ /dev/null @@ -1,10 +0,0 @@ -

                  ModuŁ Książka

                  - \ No newline at end of file diff --git a/lang/pt_br/book.php b/lang/pt_br/book.php index 00d65ed5bcb..22d0591146a 100644 --- a/lang/pt_br/book.php +++ b/lang/pt_br/book.php @@ -8,7 +8,6 @@ $string['toc'] = 'Sumário'; $string['tocwidth'] = 'Selecione a largura do Sumário para todos os livros.'; $string['faq'] = 'Perguntas sobre Livro'; -$string['disableprinting'] = 'Desabilitar Impressão'; $string['customtitles'] = 'Títulos Personalizados'; $string['editingchapter'] = 'Edição de capítulo'; diff --git a/lang/pt_br/help/book/disableprinting.html b/lang/pt_br/help/book/disableprinting.html deleted file mode 100644 index 6e93432ea37..00000000000 --- a/lang/pt_br/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Desabilitar Impressão

                  - -

                  Esconde o ícode de impressão.

                  diff --git a/lang/pt_br/help/book/index.html b/lang/pt_br/help/book/index.html deleted file mode 100644 index 6ca4cd266db..00000000000 --- a/lang/pt_br/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Módulo Livro

                  - - diff --git a/lang/sk/book.php b/lang/sk/book.php index d9f15300215..6a3adb9e21e 100644 --- a/lang/sk/book.php +++ b/lang/sk/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Naozaj chcete odstrániť túto kapitolu?'; $string['confchapterdeleteall'] = 'Naozaj chcete odstrániť túto kapitolu včítane podkapitol?'; $string['content'] = 'Text'; $string['customtitles'] = 'Užívateľské nadpisy'; -$string['disableprinting'] = 'Zakázať tlač'; $string['doimport'] = 'Importovať'; $string['editingchapter'] = 'Úprava kapitoly'; $string['faq'] = 'Časté otázky'; diff --git a/lang/sk/help/book/disableprinting.html b/lang/sk/help/book/disableprinting.html deleted file mode 100644 index efe62146baf..00000000000 --- a/lang/sk/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Zakázať tlač

                  - -

                  Skryť ikony pre tlač.

                  diff --git a/lang/sk/help/book/index.html b/lang/sk/help/book/index.html deleted file mode 100644 index fa79f5a2934..00000000000 --- a/lang/sk/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Modul Kniha

                  - - diff --git a/lang/sl/book.php b/lang/sl/book.php index 15f8da25f13..f7ff15e2d19 100644 --- a/lang/sl/book.php +++ b/lang/sl/book.php @@ -8,7 +8,6 @@ $string['pluginname'] = 'Knjiga'; $string['toc'] = 'Kazalo vsebine'; $string['tocwidth'] = 'Izberite širino kazala vsebine za vse knjige.'; $string['faq'] = 'Knjiga - pogosta vprašanja'; -$string['disableprinting'] = 'Onemogoči tiskanje'; $string['customtitles'] = 'Ločeni naslovi'; $string['editingchapter'] = 'Urejanje poglavja'; $string['chaptertitle'] = 'Naslov poglavja'; diff --git a/lang/sl/help/book/disableprinting.html b/lang/sl/help/book/disableprinting.html deleted file mode 100644 index 59c220637b8..00000000000 --- a/lang/sl/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                  Onemogoči tiskanje

                  - -

                  Skrije ikone za printanje.

                  diff --git a/lang/sl/help/book/index.html b/lang/sl/help/book/index.html deleted file mode 100644 index b0de7ee86cd..00000000000 --- a/lang/sl/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Modul Knjiga

                  - - diff --git a/lang/sv/book.php b/lang/sv/book.php index 33aa7b53a2b..aabece36d20 100644 --- a/lang/sv/book.php +++ b/lang/sv/book.php @@ -9,7 +9,6 @@ $string['confchapterdelete'] = 'Är Du säker på att vill ta bort det här kapi $string['confchapterdeleteall'] = 'Är Du säker på att vill ta bort det här kapitlet och alla underavdelningar?'; $string['content'] = 'Innehåll'; $string['customtitles'] = 'Standardtitlar'; -$string['disableprinting'] = 'Avaktivera utskrift'; $string['doimport'] = 'Importera'; $string['editingchapter'] = 'Redigerar kapitel'; $string['faq'] = 'FAQ för Bok'; diff --git a/lang/sv/help/book/disableprinting.html b/lang/sv/help/book/disableprinting.html deleted file mode 100644 index d44f22e1a6d..00000000000 --- a/lang/sv/help/book/disableprinting.html +++ /dev/null @@ -1,2 +0,0 @@ -

                  Avaktivera utskrift

                  -

                  Dölj ikonen för utskrift.

                  \ No newline at end of file diff --git a/lang/sv/help/book/index.html b/lang/sv/help/book/index.html deleted file mode 100644 index 5b411bf5ae9..00000000000 --- a/lang/sv/help/book/index.html +++ /dev/null @@ -1,11 +0,0 @@ -

                  Modulen bok (utvecklingsmodul)

                  - \ No newline at end of file diff --git a/lib.php b/lib.php index d79904618bf..4b5c318e741 100644 --- a/lib.php +++ b/lib.php @@ -40,9 +40,6 @@ function book_add_instance($book) { if (!isset($book->customtitles)) { $book->customtitles = 0; } - if (!isset($book->disableprinting)) { - $book->disableprinting = 0; - } return $DB->insert_record('book', $book); } @@ -62,9 +59,6 @@ function book_update_instance($book) { if (!isset($book->customtitles)) { $book->customtitles = 0; } - if (!isset($book->disableprinting)) { - $book->disableprinting = 0; - } $DB->update_record('book', $book); @@ -244,18 +238,15 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig } if (has_capability('mod/book:print', $PAGE->cm->context)) { - $book = $DB->get_record('book', array('id'=>$PAGE->cm->instance)); - if (!$book->disableprinting) { - $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); - $booknode->add(get_string('printbook', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); + $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); + $booknode->add(get_string('printbook', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); - // buggy navlib - actions not supported!! - //$action = new action_link($url, get_string('printbook', 'book'), new popup_action('onclick', $url)); - //$booknode->add('', $action, navigation_node::TYPE_SETTING); + // buggy navlib - actions not supported!! + //$action = new action_link($url, get_string('printbook', 'book'), new popup_action('onclick', $url)); + //$booknode->add('', $action, navigation_node::TYPE_SETTING); - $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - $booknode->add(get_string('printchapter', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); - } + $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); + $booknode->add(get_string('printchapter', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); } if (has_capability('mod/book:import', $PAGE->cm->context)) { diff --git a/mod_form.php b/mod_form.php index 652f506170c..e25c7ae391d 100644 --- a/mod_form.php +++ b/mod_form.php @@ -52,10 +52,6 @@ class mod_book_mod_form extends moodleform_mod { $mform->addElement('select', 'numbering', get_string('numbering', 'book'), book_get_numbering_types()); $mform->addHelpButton('numbering', 'numbering', 'mod_book'); - $mform->addElement('checkbox', 'disableprinting', get_string('disableprinting', 'book')); - $mform->addHelpButton('disableprinting', 'disableprinting', 'mod_book'); - $mform->setDefault('disableprinting', 0); - $mform->addElement('checkbox', 'customtitles', get_string('customtitles', 'book')); $mform->addHelpButton('customtitles', 'customtitles', 'mod_book'); $mform->setDefault('customtitles', 0); diff --git a/print.php b/print.php index a92bdbe1f20..cc5595b9471 100644 --- a/print.php +++ b/print.php @@ -43,10 +43,6 @@ $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:read', $context); require_capability('mod/book:print', $context); -if ($book->disableprinting) { - error('Printing is disabled'); -} - //check all variables if ($chapterid) { //single chapter printing - only visible! diff --git a/version.php b/version.php index 0b5b957661e..b372ecbae85 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011011500; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011011600; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) From 1c4a973a1c1a38e449386a38a0991222303a4ebd Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:01:41 +0100 Subject: [PATCH 095/455] updated readme --- README | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README b/README index 13de725cfa7..36ea7bce324 100644 --- a/README +++ b/README @@ -107,9 +107,10 @@ CHANGELOG: * implemented user outline * fixed page title formatting == 2.0dev ============================================================ - * Moodle 2.0 conversion - no new features + * Moodle 2.0 conversion + * removed "Disable printing" option, please use capabilities instead -TODO: +Known issues, please do not file tracker reports: * upgrade imscp export code (disabled for now) * upgrade import code (disabled for now) * open print links in new windows (needs fix in navlib) From 459478b7f131b80147c9365bdbe77d6710b363bc Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:02:22 +0100 Subject: [PATCH 096/455] fix release info --- version.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version.php b/version.php index b372ecbae85..94f69eeb535 100644 --- a/version.php +++ b/version.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011011600; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2010120700; // Requires this Moodle version -$module->cron = 0; // Period for cron to check this module (secs) +$module->version = 2011011600; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2010120700; // Requires this Moodle version +$module->cron = 0; // Period for cron to check this module (secs) -$release = "2.0dev (2011011500)"; // User-friendly version number +$release = "2.0dev (20110116)"; // User-friendly version number From 23b02c4fb14199939b1421866caa0b0604efc537 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:17:51 +0100 Subject: [PATCH 097/455] improve performance when fixing book structure --- locallib.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/locallib.php b/locallib.php index 81ed766b8da..4293aaacd1e 100644 --- a/locallib.php +++ b/locallib.php @@ -59,6 +59,7 @@ function book_check_structure($bookid) { $hidesub = true; $i = 1; foreach($chapters as $ch) { + $oldch = clone($ch); if ($first and $ch->subchapter) { $ch->subchapter = 0; } @@ -69,7 +70,10 @@ function book_check_structure($bookid) { $ch->hidden = $hidesub ? true : $ch->hidden; } $ch->pagenum = $i; - $DB->update_record('book_chapters', $ch); + if ($oldch->subchpter != $ch->subchpter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) { + // update only if something changed + $DB->update_record('book_chapters', $ch); + } $i++; } } From bc953600b3c6d296c3e260bbb2004595aaec72a5 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:22:32 +0100 Subject: [PATCH 098/455] improve coding style in book structure check --- locallib.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/locallib.php b/locallib.php index 4293aaacd1e..dc425fbeb5e 100644 --- a/locallib.php +++ b/locallib.php @@ -60,14 +60,16 @@ function book_check_structure($bookid) { $i = 1; foreach($chapters as $ch) { $oldch = clone($ch); - if ($first and $ch->subchapter) { + if ($first) { + // book can not start with a subchapter $ch->subchapter = 0; + $first = false; } - $first = false; if (!$ch->subchapter) { $hidesub = $ch->hidden; - } else { - $ch->hidden = $hidesub ? true : $ch->hidden; + } else if ($hidesub) { + // all subchapters if hidden chapter are hidden too + $ch->hidden = 1; } $ch->pagenum = $i; if ($oldch->subchpter != $ch->subchpter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) { From 1cc316b762b9656b2b9cc9379a2975a629b5819c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:28:12 +0100 Subject: [PATCH 099/455] use new frankenstyle for string components --- delete.php | 4 ++-- edit.php | 2 +- edit_form.php | 6 +++--- import.php | 6 +++--- import_form.php | 2 +- index.php | 4 ++-- lib.php | 6 +++--- print.php | 12 ++++++------ settings.php | 2 +- view.php | 8 ++++---- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/delete.php b/delete.php index e2f29b8944a..b507734e175 100644 --- a/delete.php +++ b/delete.php @@ -79,9 +79,9 @@ echo $OUTPUT->header(); // the operation has not been confirmed yet so ask the user to do so if ($chapter->subchapter) { - $strconfirm = get_string('confchapterdelete','book'); + $strconfirm = get_string('confchapterdelete','mod_book'); } else { - $strconfirm = get_string('confchapterdeleteall','book'); + $strconfirm = get_string('confchapterdeleteall','mod_book'); } echo '
                  '; $continue = new moodle_url('/mod/book/delete.php', array('id'=>$cm->id, 'chapterid'=>$chapter->id, 'confirm'=>1)); diff --git a/edit.php b/edit.php index 721c6e374db..665ce81ba88 100644 --- a/edit.php +++ b/edit.php @@ -112,7 +112,7 @@ $PAGE->add_body_class('mod_book'); $PAGE->set_heading(format_string($course->fullname)); echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('editingchapter', 'book')); +echo $OUTPUT->heading(get_string('editingchapter', 'mod_book')); $mform->display(); diff --git a/edit_form.php b/edit_form.php index bf972a64b8b..dcfaebd482c 100644 --- a/edit_form.php +++ b/edit_form.php @@ -40,13 +40,13 @@ class book_chapter_edit_form extends moodleform { $mform->addElement('header', 'general', get_string('edit')); - $mform->addElement('text', 'title', get_string('chaptertitle', 'book'), array('size'=>'30')); + $mform->addElement('text', 'title', get_string('chaptertitle', 'mod_book'), array('size'=>'30')); $mform->setType('title', PARAM_RAW); $mform->addRule('title', null, 'required', null, 'client'); - $mform->addElement('advcheckbox', 'subchapter', get_string('subchapter', 'book')); + $mform->addElement('advcheckbox', 'subchapter', get_string('subchapter', 'mod_book')); - $mform->addElement('editor', 'content_editor', get_string('content', 'book'), null, $options); + $mform->addElement('editor', 'content_editor', get_string('content', 'mod_book'), null, $options); $mform->setType('content_editor', PARAM_RAW); $mform->addRule('content_editor', get_string('required'), 'required', null, 'client'); diff --git a/import.php b/import.php index 6907d47b74a..debdba8604b 100644 --- a/import.php +++ b/import.php @@ -54,8 +54,8 @@ $PAGE->add_body_class('mod_book'); $PAGE->set_heading(format_string($course->fullname)); ///prepare the page header -$strbook = get_string('modulename', 'book'); -$strbooks = get_string('modulenameplural', 'book'); +$strbook = get_string('modulename', 'mod_book'); +$strbooks = get_string('modulenameplural', 'mod_book'); $mform = new book_import_form(null, array('id'=>$id, 'chapterid'=>$chapterid)); @@ -142,7 +142,7 @@ if ($mform->is_cancelled()) { } echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('importingchapters', 'book')); +echo $OUTPUT->heading(get_string('importingchapters', 'mod_book')); $mform->display(); diff --git a/import_form.php b/import_form.php index a3a9f04c713..909f07b5fb0 100644 --- a/import_form.php +++ b/import_form.php @@ -43,7 +43,7 @@ class book_import_form extends moodleform { $mform->addElement('hidden', 'chapterid'); $mform->setType('chapterid', PARAM_INT); - $this->add_action_buttons(true, get_string('import', 'book')); + $this->add_action_buttons(true, get_string('import', 'mod_book')); $this->set_data($data); } diff --git a/index.php b/index.php index 6bebe640a37..46ef3b2bebc 100644 --- a/index.php +++ b/index.php @@ -36,8 +36,8 @@ require_course_login($course, true); $PAGE->set_pagelayout('incourse'); /// Get all required strings -$strbooks = get_string('modulenameplural', 'book'); -$strbook = get_string('modulename', 'book'); +$strbooks = get_string('modulenameplural', 'mod_book'); +$strbook = get_string('modulename', 'mod_book'); $strsectionname = get_string('sectionname', 'format_'.$course->format); $strname = get_string('name'); $strintro = get_string('moduleintro'); diff --git a/lib.php b/lib.php index 4b5c318e741..a2425fa44de 100644 --- a/lib.php +++ b/lib.php @@ -91,7 +91,7 @@ function book_get_types() { $type = new stdClass(); $type->modclass = MOD_CLASS_RESOURCE; $type->type = 'book'; - $type->typestr = get_string('modulename', 'book'); + $type->typestr = get_string('modulename', 'mod_book'); return array($type); } @@ -239,14 +239,14 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig if (has_capability('mod/book:print', $PAGE->cm->context)) { $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); - $booknode->add(get_string('printbook', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); + $booknode->add(get_string('printbook', 'mod_book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); // buggy navlib - actions not supported!! //$action = new action_link($url, get_string('printbook', 'book'), new popup_action('onclick', $url)); //$booknode->add('', $action, navigation_node::TYPE_SETTING); $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - $booknode->add(get_string('printchapter', 'book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); + $booknode->add(get_string('printchapter', 'mod_book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); } if (has_capability('mod/book:import', $PAGE->cm->context)) { diff --git a/print.php b/print.php index cc5595b9471..4b009180b55 100644 --- a/print.php +++ b/print.php @@ -57,9 +57,9 @@ unset($chapterid); // security checks END // ========================================================================= -$strbooks = get_string('modulenameplural', 'book'); -$strbook = get_string('modulename', 'book'); -$strtop = get_string('top', 'book'); +$strbooks = get_string('modulenameplural', 'mod_book'); +$strbook = get_string('modulename', 'mod_book'); +$strtop = get_string('top', 'mod_book'); @header('Cache-Control: private, pre-check=0, post-check=0, max-age=0'); @header('Pragma: no-cache'); @@ -127,13 +127,13 @@ if ($chapter) {
                  - + - + - +
                  :fullname) ?>fullname, true, array('context'=>$context)) ?>
                  :fullname) ?>fullname, true, array('context'=>$context)) ?>
                  :name) ?>name, true, array('context'=>$context)) ?>
                  :
                  : : fullname, true, array('context'=>$context)) ?>
                  :: name, true, array('context'=>$context)) ?>
                  ::
                  ::
                  diff --git a/settings.php b/settings.php index e961d6afc0c..8d978ac8cc7 100644 --- a/settings.php +++ b/settings.php @@ -28,6 +28,6 @@ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { $choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); - $settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'book'), get_string('tocwidth', 'book'), '180', $choices)); + $settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'mod_book'), get_string('tocwidth', 'book'), '180', $choices)); } \ No newline at end of file diff --git a/view.php b/view.php index 85a50805c95..fcf04c563ae 100644 --- a/view.php +++ b/view.php @@ -116,9 +116,9 @@ add_to_log($course->id, 'book', 'view', 'view.php?id='.$cm->id.'&chapterid=' ///read standard strings -$strbooks = get_string('modulenameplural', 'book'); -$strbook = get_string('modulename', 'book'); -$strtoc = get_string('toc', 'book'); +$strbooks = get_string('modulenameplural', 'mod_book'); +$strbook = get_string('modulename', 'mod_book'); +$strtoc = get_string('toc', 'mod_book'); /// prepare header $PAGE->set_title(format_string($book->name)); @@ -181,7 +181,7 @@ if ($edit) { From 56e7577e1d35631a61ab0753958cde432517ce5e Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:31:11 +0100 Subject: [PATCH 100/455] set page url --- print.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/print.php b/print.php index 4b009180b55..985a1e3eac9 100644 --- a/print.php +++ b/print.php @@ -51,6 +51,9 @@ if ($chapterid) { //complete book $chapter = false; } + +$PAGE->set_url('/mod/book/print.php', array('id'=>$id, 'chapterid'=>$chapterid)); + unset($id); unset($chapterid); // ========================================================================= From 065f5c4c3332922cb68c30239bead3daca3ef8e7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 11:34:52 +0100 Subject: [PATCH 101/455] fix recent typo --- locallib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locallib.php b/locallib.php index dc425fbeb5e..303d6591295 100644 --- a/locallib.php +++ b/locallib.php @@ -72,7 +72,7 @@ function book_check_structure($bookid) { $ch->hidden = 1; } $ch->pagenum = $i; - if ($oldch->subchpter != $ch->subchpter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) { + if ($oldch->subchapter != $ch->subchapter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) { // update only if something changed $DB->update_record('book_chapters', $ch); } From ad1c11bdfd51b75dbc15df83a2cf06c572c7c352 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 13:46:13 +0100 Subject: [PATCH 102/455] move toc to fake block, remove toc width and add new mod settings --- db/upgrade.php | 7 +++ delete.php | 4 +- edit.php | 4 +- import.php | 2 +- lang/be/book.php | 1 - lang/ca/book.php | 1 - lang/cs/book.php | 1 - lang/de/book.php | 1 - lang/en/book.php | 6 +- lang/es/book.php | 1 - lang/fi/book.php | 1 - lang/fr/book.php | 2 - lang/id/book.php | 3 - lang/it/book.php | 2 - lang/ja/book.php | 1 - lang/nl/book.php | 1 - lang/pl/book.php | 1 - lang/pt_br/book.php | 1 - lang/sk/book.php | 1 - lang/sl/book.php | 4 +- lang/sv/book.php | 1 - lib.php | 19 ++++++- locallib.php | 136 ++++++++++++++++++++++++++++++-------------- mod_form.php | 24 ++++++-- move.php | 4 +- settings.php | 13 ++++- show.php | 2 +- version.php | 2 +- view.php | 57 ++++++------------- 29 files changed, 180 insertions(+), 123 deletions(-) diff --git a/db/upgrade.php b/db/upgrade.php index 7a30e002e73..eb68470d028 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -152,6 +152,13 @@ function xmldb_book_upgrade($oldversion) { upgrade_mod_savepoint(true, 2011011600, 'book'); } + if ($oldversion < 2011011601) { + unset_config('book_tocwidth'); + + // book savepoint reached + upgrade_mod_savepoint(true, 2011011601, 'book'); + } + //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter diff --git a/delete.php b/delete.php index b507734e175..f32e66c632b 100644 --- a/delete.php +++ b/delete.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -70,7 +70,7 @@ if ($confirm) { // the operation was confirmed. add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); - book_check_structure($book->id); + book_preload_chapters($book->id); //fix structure redirect('view.php?id='.$cm->id); } diff --git a/edit.php b/edit.php index 665ce81ba88..2c16d5af898 100644 --- a/edit.php +++ b/edit.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -102,7 +102,7 @@ if ($mform->is_cancelled()) { add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); } - book_check_structure($book->id); + book_preload_chapters($book->id); // fix structure redirect("view.php?id=$cm->id&chapterid=$data->id"); } diff --git a/import.php b/import.php index debdba8604b..71f8e44cfdb 100644 --- a/import.php +++ b/import.php @@ -107,7 +107,7 @@ if ($mform->is_cancelled()) { print_box_start('generalbox boxaligncenter centerpara'); echo ''.get_string('importing', 'book').':'; echo ''; - book_check_structure($book->id); + book_preload_chapters($book->id); // fix structure foreach($refs as $ref) { $chapter = book_read_chapter($coursebase, $ref); if ($chapter) { diff --git a/lang/be/book.php b/lang/be/book.php index 654e769d290..9ea8fd00e23 100644 --- a/lang/be/book.php +++ b/lang/be/book.php @@ -36,5 +36,4 @@ $string['printedby'] = 'Надрукаваны'; $string['relinking'] = 'Перакампанаваць'; $string['subchapter'] = 'Параграф'; $string['toc'] = 'Змест'; -$string['tocwidth'] = 'Вызначыць шырыню зместу для ўсіх падручнікаў'; $string['top'] = 'наверх'; diff --git a/lang/ca/book.php b/lang/ca/book.php index 1d724bcbd58..0ed7f126c3f 100644 --- a/lang/ca/book.php +++ b/lang/ca/book.php @@ -5,7 +5,6 @@ $string['modulenameplural'] = 'Llibres'; $string['pluginname'] = 'Llibre'; $string['toc'] = 'Índex'; -$string['tocwidth'] = 'Escolliu l\'amplada de l\'índex per tots els llibres.'; $string['faq'] = 'PMF dels llibres (FAQ)'; $string['customtitles'] = 'Títols personalitzats'; diff --git a/lang/cs/book.php b/lang/cs/book.php index 87edcf35c85..1c00cdfc76d 100644 --- a/lang/cs/book.php +++ b/lang/cs/book.php @@ -36,5 +36,4 @@ $string['printedby'] = 'Vytiskl(a)'; $string['relinking'] = 'Relinkuji'; $string['subchapter'] = 'Podkapitola'; $string['toc'] = 'Obsah'; -$string['tocwidth'] = 'Vyberte šířku obsahu pro všechny knihy.'; $string['top'] = 'začátek'; diff --git a/lang/de/book.php b/lang/de/book.php index 0b3f44c47cf..79e78651b0a 100644 --- a/lang/de/book.php +++ b/lang/de/book.php @@ -5,7 +5,6 @@ $string['modulenameplural'] = 'Bücher'; $string['pluginname'] = 'Buch'; $string['toc'] = 'Inhaltsverzeichnis'; -$string['tocwidth'] = 'Wählen Sie die Breite des Inhaltsverzeichnisses für alle Bücher aus.'; $string['faq'] = 'Buch FAQ'; $string['customtitles'] = 'Angepasster Titel'; diff --git a/lang/en/book.php b/lang/en/book.php index 18985ba0c96..81cb79f5090 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -7,8 +7,6 @@ $string['pluginname'] = 'Book'; $string['pluginadministration'] = 'Book administration'; $string['toc'] = 'Table of contents'; -$string['tocwidth'] = 'Select width of the Table of Contents for all books.'; -$string['book_tocwidth'] = 'Table of Contents width'; $string['faq'] = 'Book FAQ'; $string['faq_help'] = ' *Why only two levels?* @@ -55,6 +53,8 @@ $string['numbering0'] = 'None'; $string['numbering1'] = 'Numbers'; $string['numbering2'] = 'Bullets'; $string['numbering3'] = 'Indented'; +$string['numberingoptions'] = 'Available numbering options'; +$string['numberingoptions_help'] = 'Select numbering options that should be available when creating new books.'; $string['chapterscount'] = 'Chapters'; @@ -90,3 +90,5 @@ $string['book:viewhiddenchapters'] = 'View hidden book chapters'; $string['book:import'] = 'Import chapters'; $string['book:print'] = 'Print book'; $string['book:exportimscp'] = 'Export book as IMS content package'; + +$string['errorchapter'] = 'Error reading book chapter.'; \ No newline at end of file diff --git a/lang/es/book.php b/lang/es/book.php index fa6746a4222..e25ca48e95b 100644 --- a/lang/es/book.php +++ b/lang/es/book.php @@ -27,5 +27,4 @@ $string['printedby'] = 'Imprimido por'; $string['showpreview'] = 'Mostrar TOC Preliminar'; $string['subchapter'] = 'Subcápitulo'; $string['toc'] = 'Tabla de Contenido'; -$string['tocwidth'] = 'Seleciona el Ancho de la Tabla de Contenidos de Todos los Libros.'; $string['top'] = 'arriba'; diff --git a/lang/fi/book.php b/lang/fi/book.php index ae30ebb722b..caa97ee70fc 100644 --- a/lang/fi/book.php +++ b/lang/fi/book.php @@ -37,5 +37,4 @@ $string['subchapter'] = 'Alaluku'; $string['thisdirection'] = 'ltr'; $string['thislanguage'] = 'Suomi'; $string['toc'] = 'Sisällysluettelo'; -$string['tocwidth'] = 'Valitse kaikkien kirjojen sisällysluetteloiden leveys.'; $string['top'] = 'Alkuun'; diff --git a/lang/fr/book.php b/lang/fr/book.php index 1a0ebf8f602..1222ea34132 100644 --- a/lang/fr/book.php +++ b/lang/fr/book.php @@ -32,8 +32,6 @@ $string['top'] = 'Haut'; $string['navprev'] = 'Précédent'; $string['navnext'] = 'Suivant'; -$string['tocwidth'] = 'Largeur (en pixels) de la table des matières des livres.'; - $string['import'] = 'Importation'; $string['doimport'] = 'Importer'; $string['importing'] = 'Importation'; diff --git a/lang/id/book.php b/lang/id/book.php index 4f07de44132..dd6125d2ec7 100644 --- a/lang/id/book.php +++ b/lang/id/book.php @@ -32,9 +32,6 @@ $string['top'] = 'atas'; $string['navprev'] = 'Sebelumnya'; $string['navnext'] = 'Selanjutnya'; -#$string['tocwidth'] = 'Select width of the Table of the Contents for all books.'; -$string['tocwidth'] = 'Pilih lebar Tabel untuk semua buku'; - $string['import'] = 'Import'; $string['doimport'] = 'Import'; $string['importing'] = 'Meng-Impor'; diff --git a/lang/it/book.php b/lang/it/book.php index 04fe1b49fa2..d6d2581073b 100644 --- a/lang/it/book.php +++ b/lang/it/book.php @@ -7,7 +7,6 @@ $string['book:import'] = 'Importare capitoli'; $string['book:print'] = 'Stampare libro'; $string['book:read'] = 'Leggere libro'; $string['book:viewhiddenchapters'] = 'Visualizzare capitoli nascosti'; -$string['book_tocwidth'] = 'Larghezza sommario'; $string['chapterscount'] = 'Capitoli'; $string['chaptertitle'] = 'Titolo del capitolo'; $string['confchapterdelete'] = 'Sei sicuro di eliminare questo capitolo?'; @@ -43,5 +42,4 @@ $string['printedby'] = 'Stampato da'; $string['relinking'] = 'Elaborazione dei collegamenti'; $string['subchapter'] = 'Paragrafo'; $string['toc'] = 'Sommario'; -$string['tocwidth'] = 'Larghezza in pixel del Sommario per i Libri.'; $string['top'] = 'Ritorna su'; diff --git a/lang/ja/book.php b/lang/ja/book.php index e394ddff83f..7c10713058b 100644 --- a/lang/ja/book.php +++ b/lang/ja/book.php @@ -5,7 +5,6 @@ $string['modulenameplural'] = 'ブック'; $string['pluginname'] = 'ブック'; $string['toc'] = '目次'; -$string['tocwidth'] = 'コンテンツのテーブル幅を選んでください。'; $string['faq'] = 'ブック FAQ'; $string['customtitles'] = 'カスタムタイトル'; diff --git a/lang/nl/book.php b/lang/nl/book.php index 7014e6ee72f..09c41116668 100644 --- a/lang/nl/book.php +++ b/lang/nl/book.php @@ -35,5 +35,4 @@ $string['printedby'] = 'Afgedrukt door'; $string['relinking'] = 'Opnieuw linken'; $string['subchapter'] = 'Paragraaf'; $string['toc'] = 'Inhoudstafel'; -$string['tocwidth'] = 'Kies de breedte van de inhoudstafel voor alle boeken.'; $string['top'] = 'boven'; diff --git a/lang/pl/book.php b/lang/pl/book.php index 0522b4bf992..88a18fb76da 100644 --- a/lang/pl/book.php +++ b/lang/pl/book.php @@ -36,5 +36,4 @@ $string['printedby'] = 'Wydrukowane przez użytkoniwka'; $string['relinking'] = 'Ponowne tworzenie linków'; $string['subchapter'] = 'Podrozdział'; $string['toc'] = 'Spis treści'; -$string['tocwidth'] = 'Ustaw szrokość spisu treści dla wszystkich książek'; $string['top'] = 'Góra'; diff --git a/lang/pt_br/book.php b/lang/pt_br/book.php index 22d0591146a..a4e5a804caa 100644 --- a/lang/pt_br/book.php +++ b/lang/pt_br/book.php @@ -5,7 +5,6 @@ $string['modulenameplural'] = 'Livros'; $string['pluginname'] = 'Livro'; $string['toc'] = 'Sumário'; -$string['tocwidth'] = 'Selecione a largura do Sumário para todos os livros.'; $string['faq'] = 'Perguntas sobre Livro'; $string['customtitles'] = 'Títulos Personalizados'; diff --git a/lang/sk/book.php b/lang/sk/book.php index 6a3adb9e21e..ad602ab113d 100644 --- a/lang/sk/book.php +++ b/lang/sk/book.php @@ -36,5 +36,4 @@ $string['printedby'] = 'Vytlačil(a)'; $string['relinking'] = 'Relinkujem'; $string['subchapter'] = 'Podkapitola'; $string['toc'] = 'Obsah'; -$string['tocwidth'] = 'Vyberte šírku obsahu pre všetky knihy.'; $string['top'] = 'začiatok'; diff --git a/lang/sl/book.php b/lang/sl/book.php index f7ff15e2d19..94f6dc33338 100644 --- a/lang/sl/book.php +++ b/lang/sl/book.php @@ -6,7 +6,6 @@ $string['modulename'] = 'Knjiga'; $string['modulenameplural'] = 'Knjige'; $string['pluginname'] = 'Knjiga'; $string['toc'] = 'Kazalo vsebine'; -$string['tocwidth'] = 'Izberite širino kazala vsebine za vse knjige.'; $string['faq'] = 'Knjiga - pogosta vprašanja'; $string['customtitles'] = 'Ločeni naslovi'; $string['editingchapter'] = 'Urejanje poglavja'; @@ -45,6 +44,5 @@ $string['book:import'] = 'Uvozi poglavja'; $string['book:print'] = 'Natisni knjigo'; $string['book:read'] = 'Beri knjigo'; $string['book:viewhiddenchapters'] = 'Poglej skrita poglavja'; -$string['book_tocwidth'] = 'Širina kazala vsebine'; $string['generateimscp'] = 'Generiraj IMS vsebinski paket'; -?> + diff --git a/lang/sv/book.php b/lang/sv/book.php index aabece36d20..92b9856c0fd 100644 --- a/lang/sv/book.php +++ b/lang/sv/book.php @@ -36,5 +36,4 @@ $string['printedby'] = 'Utskrivet av'; $string['relinking'] = 'Länkar tillbaka'; $string['subchapter'] = 'Underavdelning'; $string['toc'] = 'Innehållsförteckning'; -$string['tocwidth'] = 'Välj en bredd på innehållsförteckningen som gäller alla böcker.'; $string['top'] = 'Upp'; diff --git a/lib.php b/lib.php index a2425fa44de..7e777a8d5ae 100644 --- a/lib.php +++ b/lib.php @@ -19,12 +19,29 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; + +define('BOOK_NUM_NONE', '0'); +define('BOOK_NUM_NUMBERS', '1'); +define('BOOK_NUM_BULLETS', '2'); +define('BOOK_NUM_INDENTED', '3'); + +/** + * Returns list of available numbering types + * @return array + */ +function book_get_numbering_types() { + return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), + BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), + BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), + BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); +} + /** * Add book instance. * diff --git a/locallib.php b/locallib.php index 303d6591295..dde3a8d124e 100644 --- a/locallib.php +++ b/locallib.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,57 +28,88 @@ defined('MOODLE_INTERNAL') || die; require_once($CFG->dirroot.'/mod/book/lib.php'); require_once($CFG->libdir.'/filelib.php'); - -define('BOOK_NUM_NONE', '0'); -define('BOOK_NUM_NUMBERS', '1'); -define('BOOK_NUM_BULLETS', '2'); -define('BOOK_NUM_INDENTED', '3'); - /** - * Returns list of available numbering types - * @return array + * Preload book chapters and fix toc structure if necessary. + * + * Returns array of chapters with standard 'pagenum', 'id, pagenum, subchapter, title, hidden' + * and extra 'parent, number, subchapters, prev, next'. + * Please note the content/text of chapters is not included. + * + * @param $book + * @param $cm + * @return array of id=>chapter */ -function book_get_numbering_types() { - return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), - BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), - BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), - BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); -} - -/** - * Check chapter ordering and make sure subchapter is not first - * in book hidden chapter must have all subchapters hidden too - * @param int $bookid - * @return void - */ -function book_check_structure($bookid) { +function book_preload_chapters($bookid) { global $DB; + $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, subchapter, title, hidden'); + if (!$chapters) { + return array(); + } - if ($chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, subchapter, hidden')) { - $first = true; - $hidesub = true; - $i = 1; - foreach($chapters as $ch) { - $oldch = clone($ch); - if ($first) { - // book can not start with a subchapter - $ch->subchapter = 0; - $first = false; + $prev = null; + $prevsub = null; + + $first = true; + $hidesub = true; + $parent = null; + $pagenum = 0; // chapter sort + $i = 0; // main chapter num + $j = 0; // subchapter num + foreach($chapters as $id=>$ch) { + $oldch = clone($ch); + $pagenum++; + $ch->pagenum = $pagenum; + if ($first) { + // book can not start with a subchapter + $ch->subchapter = 0; + $first = false; + } + if (!$ch->subchapter) { + $ch->prev = $prev; + $ch->next = null; + if ($prev) { + $chapters[$prev]->next = $ch->id; } - if (!$ch->subchapter) { - $hidesub = $ch->hidden; - } else if ($hidesub) { - // all subchapters if hidden chapter are hidden too + if ($ch->hidden) { + $ch->number = null; + } else { + $i++; + $ch->number = $i; + } + $j = 0; + $prevsub = null; + $hidesub = $ch->hidden; + $parent = $ch->id; + $ch->parent = null; + $ch->subchpaters = array(); + } else { + $ch->prev = $prevsub; + $ch->next = null; + if ($prevsub) { + $chapters[$prevsub]->next = $ch->id; + } + $ch->parent = $parent; + $ch->subchpaters = null; + $chapters[$parent]->subchapters[$ch->id] = $ch->id; + if ($hidesub) { + // all subchapters in hidden chapter must be hidden too $ch->hidden = 1; } - $ch->pagenum = $i; - if ($oldch->subchapter != $ch->subchapter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) { - // update only if something changed - $DB->update_record('book_chapters', $ch); + if ($ch->hidden) { + $ch->number = null; + } else { + $j++; + $ch->number = $j; } - $i++; } + if ($oldch->subchapter != $ch->subchapter or $oldch->pagenum != $ch->pagenum or $oldch->hidden != $ch->hidden) { + // update only if something changed + $DB->update_record('book_chapters', $ch); + } + $chapters[$id] = $ch; } + + return $chapters; } /** @@ -102,6 +133,27 @@ function book_log($str1, $str2, $level = 0) { } } +function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { + global $OUTPUT, $PAGE; + + list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); + + if ($edit) { + $toc .= '
                  '; + $toc .= $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book')); + $toc .= '
                  '; + } + + $bc = new block_contents(); + $bc->title = get_string('toc', 'mod_book'); + $bc->attributes['class'] = 'block'; + $bc->content = $toc; + + $regions = $PAGE->blocks->get_regions(); + $firstregion = reset($regions); + $PAGE->blocks->add_fake_block($bc, $firstregion); +} + /** * Generate toc structure and titles * diff --git a/mod_form.php b/mod_form.php index e25c7ae391d..64cacce883c 100644 --- a/mod_form.php +++ b/mod_form.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -35,6 +35,8 @@ class mod_book_mod_form extends moodleform_mod { $mform = $this->_form; + $config = get_config('book'); + //------------------------------------------------------------------------------- $mform->addElement('header', 'general', get_string('general', 'form')); @@ -45,11 +47,25 @@ class mod_book_mod_form extends moodleform_mod { $mform->setType('name', PARAM_CLEANHTML); } $mform->addRule('name', null, 'required', null, 'client'); - - $this->add_intro_editor(true, get_string('summary')); + $this->add_intro_editor($config->requiremodintro, get_string('summary')); - $mform->addElement('select', 'numbering', get_string('numbering', 'book'), book_get_numbering_types()); + $alloptions = book_get_numbering_types(); + $allowed = explode(',', $config->numberingoptions); + $options = array(); + foreach ($allowed as $type) { + if (isset($alloptions[$type])) { + $options[$type] = $alloptions[$type]; + } + } + if ($this->current->instance) { + if (!isset($options[$this->current->numbering])) { + if (isset($alloptions[$this->current->numbering])) { + $options[$this->current->numbering] = $alloptions[$this->current->numbering]; + } + } + } + $mform->addElement('select', 'numbering', get_string('numbering', 'book'), $options); $mform->addHelpButton('numbering', 'numbering', 'mod_book'); $mform->addElement('checkbox', 'customtitles', get_string('customtitles', 'book')); diff --git a/move.php b/move.php index d0f28231a8b..17723db6652 100644 --- a/move.php +++ b/move.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -182,6 +182,6 @@ if (!$nothing) { add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); -book_check_structure($book->id); +book_preload_chapters($book->id); // fix structure redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); diff --git a/settings.php b/settings.php index 8d978ac8cc7..1429b99795b 100644 --- a/settings.php +++ b/settings.php @@ -19,15 +19,22 @@ * * @package mod * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { + require_once("$CFG->dirroot/mod/book/lib.php"); - $choices = array('140'=>'140', '160'=>'160', '180'=>'180', '200'=>'200', '220'=>'220', '240'=>'240', '260'=>'260', '280'=>'280', '300'=>'300'); - $settings->add(new admin_setting_configselect('book_tocwidth', get_string('book_tocwidth', 'mod_book'), get_string('tocwidth', 'book'), '180', $choices)); + $settings->add(new admin_setting_configcheckbox('book/requiremodintro', + get_string('requiremodintro', 'admin'), get_string('configrequiremodintro', 'admin'), 1)); + + $options = book_get_numbering_types(); + + $settings->add(new admin_setting_configmultiselect('book/numberingoptions', + get_string('numberingoptions', 'mod_book'), get_string('numberingoptions_help', 'mod_book'), + array_keys($options), $options)); } \ No newline at end of file diff --git a/show.php b/show.php index 0d8ee9c4040..f5893e4b375 100644 --- a/show.php +++ b/show.php @@ -69,6 +69,6 @@ if (!$chapter->subchapter) { add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); -book_check_structure($book->id); +book_preload_chapters($book->id); // fix structure redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); diff --git a/version.php b/version.php index 94f69eeb535..0959e94b1fb 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011011600; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011011601; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) diff --git a/view.php b/view.php index fcf04c563ae..62533a4e1cc 100644 --- a/view.php +++ b/view.php @@ -50,8 +50,8 @@ require_course_login($course, true, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:read', $context); -$allowedit = has_capability('mod/book:edit', $context); -$viewhidden = has_capability('mod/book:viewhiddenchapters', $context); +$allowedit = has_capability('mod/book:edit', $context); +$viewhidden = has_capability('mod/book:viewhiddenchapters', $context); if ($allowedit) { if ($edit != -1 and confirm_sesskey()) { @@ -68,16 +68,10 @@ if ($allowedit) { } /// read chapters -$select = $viewhidden ? array('bookid' => $book->id) : array('bookid' => $book->id, 'hidden' => 0); -$chapters = $DB->get_records('book_chapters', $select, 'pagenum', 'id, pagenum, subchapter, title, hidden'); +$chapters = book_preload_chapters($book->id); -if (!$chapters) { - if ($allowedit) { - redirect('edit.php?cmid='.$cm->id); //no chapters - add new one - die; - } else { - error('Error reading book chapters.'); - } +if ($allowedit and !$chapters) { + redirect('edit.php?cmid='.$cm->id); //no chapters - add new one } /// check chapterid and read chapter data if ($chapterid == '0') { // go to first chapter if no given @@ -93,20 +87,23 @@ if ($chapterid == '0') { // go to first chapter if no given } } -$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); +if (!$chapterid or !$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id))) { + print_error('errorchapter', 'mod_book', new moodle_url('/course/view.php', array('id'=>$course->id))); +} + +/// chapter is hidden for students +if ($chapter->hidden and !$viewhidden) { + print_error('errorchapter', 'mod_book', new moodle_url('/course/view.php', array('id'=>$course->id))); +} $PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chapterid'=>$chapterid)); -//check all variables +//unset all page parameters unset($id); unset($bid); unset($chapterid); -/// chapter is hidden for students -if (!$viewhidden and $chapter->hidden) { - error('Error reading book chapters.'); -} // ========================================================================= // security checks END @@ -124,6 +121,9 @@ $strtoc = get_string('toc', 'mod_book'); $PAGE->set_title(format_string($book->name)); $PAGE->add_body_class('mod_book'); $PAGE->set_heading(format_string($course->fullname)); + +book_add_fake_block($chapters, $chapter, $book, $cm, $edit); + echo $OUTPUT->header(); /// prepare chapter navigation icons @@ -164,12 +164,6 @@ if ($nextid) { // prepare $toc and $currtitle, $currsubtitle list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); -if ($edit) { - $tocwidth = $CFG->book_tocwidth + 80; -} else { - $tocwidth = $CFG->book_tocwidth; -} - // ===================================================== // Book display HTML code // ===================================================== @@ -179,11 +173,6 @@ if ($edit) { - @@ -191,18 +180,6 @@ if ($edit) { - - +
                  - -
                   
                  - box_start('generalbox'); - echo $toc; - echo $OUTPUT->box_end(); - if ($allowedit and $edit) { - echo '
                  '; - echo $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book')); - echo '
                  '; - } - ?> -
                   
                  box_start('generalbox'); From 86f6bb261222777566613a813d0320d74303a3b0 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 14:02:00 +0100 Subject: [PATCH 103/455] fix navigation links --- view.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/view.php b/view.php index 62533a4e1cc..faed9145826 100644 --- a/view.php +++ b/view.php @@ -76,7 +76,7 @@ if ($allowedit and !$chapters) { /// check chapterid and read chapter data if ($chapterid == '0') { // go to first chapter if no given foreach($chapters as $ch) { - if ($allowedit) { + if ($allowedit and !empty($USER->editing)) { $chapterid = $ch->id; break; } @@ -129,22 +129,21 @@ echo $OUTPUT->header(); /// prepare chapter navigation icons $previd = null; $nextid = null; -$found = 0; +$last = null; foreach ($chapters as $ch) { - if ($found) { - $nextid= $ch->id; + if ($allowedit and empty($USER->editing) and $ch->hidden) { + continue; + } + if ($last == $chapter->id) { + $nextid = $ch->id; break; } - if ($ch->id == $chapter->id) { - $found = 1; - } - if (!$found) { + if ($ch->id != $chapter->id) { $previd = $ch->id; } + $last = $ch->id; } -if ($ch == current($chapters)) { - $nextid = $ch->id; -} + $chnavigation = ''; if ($previd) { $chnavigation .= ''.get_string('navprev', 'book').''; From 2cdbd448b7b56eba369b1341cb373dfb77a60d00 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 14:03:54 +0100 Subject: [PATCH 104/455] fix old style pix url --- view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view.php b/view.php index faed9145826..92b4054eb4c 100644 --- a/view.php +++ b/view.php @@ -148,7 +148,7 @@ $chnavigation = ''; if ($previd) { $chnavigation .= ''.get_string('navprev', 'book').''; } else { - $chnavigation .= ''; + $chnavigation .= ''; } if ($nextid) { $chnavigation .= ''.get_string('navnext', 'book').''; From b52247a5810210d6115cdb30c808b2fad7ca8a9b Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 14:09:47 +0100 Subject: [PATCH 105/455] get rid of the table layout --- view.php | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/view.php b/view.php index 92b4054eb4c..9069b41e5c1 100644 --- a/view.php +++ b/view.php @@ -167,41 +167,25 @@ list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapte // Book display HTML code // ===================================================== -?> - +// upper nav +echo '
                  '.$chnavigation.'
                  '; - - - - +// chapter itself +echo $OUTPUT->box_start('generalbox book_content'); +if (!$book->customtitles) { + if (!$chapter->subchapter) { + echo '

                  '.$currtitle.'

                  '; + } else { + echo '

                  '.$currtitle.'
                  '.$currsubtitle.'

                  '; + } +} +$chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id); +echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); - - - - -
                  -
                  -
                   
                  - box_start('generalbox'); - echo '
                  '; - if (!$book->customtitles) { - if ($currsubtitle == ' ') { - echo '

                  '.$currtitle.'

                  '; - } else { - echo '

                  '.$currtitle.'
                  '.$currsubtitle.'

                  '; - } - } - $chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id); - echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); - echo '
                  '; - echo $OUTPUT->box_end(); - /// lower navigation - echo '
                  '.$chnavigation.'
                  '; - ?> -
                  +echo $OUTPUT->box_end(); -'.$chnavigation.''; echo $OUTPUT->footer(); From c5832d6b546cc3a3503ae820e586983191c32080 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 14:13:05 +0100 Subject: [PATCH 106/455] fix recent edit mode bug --- view.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view.php b/view.php index 9069b41e5c1..7c005098cf5 100644 --- a/view.php +++ b/view.php @@ -76,7 +76,7 @@ if ($allowedit and !$chapters) { /// check chapterid and read chapter data if ($chapterid == '0') { // go to first chapter if no given foreach($chapters as $ch) { - if ($allowedit and !empty($USER->editing)) { + if ($edit) { $chapterid = $ch->id; break; } @@ -131,7 +131,7 @@ $previd = null; $nextid = null; $last = null; foreach ($chapters as $ch) { - if ($allowedit and empty($USER->editing) and $ch->hidden) { + if (!$edit and $ch->hidden) { continue; } if ($last == $chapter->id) { From 97619eddbdea3c485be63e06653f474af76dc2d6 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 14:42:51 +0100 Subject: [PATCH 107/455] add numbering default setting --- mod_form.php | 1 + settings.php | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/mod_form.php b/mod_form.php index 64cacce883c..1a5c6ec85a5 100644 --- a/mod_form.php +++ b/mod_form.php @@ -67,6 +67,7 @@ class mod_book_mod_form extends moodleform_mod { } $mform->addElement('select', 'numbering', get_string('numbering', 'book'), $options); $mform->addHelpButton('numbering', 'numbering', 'mod_book'); + $mform->setDefault('numbering', $config->numbering); $mform->addElement('checkbox', 'customtitles', get_string('customtitles', 'book')); $mform->addHelpButton('customtitles', 'customtitles', 'mod_book'); diff --git a/settings.php b/settings.php index 1429b99795b..0ab07e29ea6 100644 --- a/settings.php +++ b/settings.php @@ -28,6 +28,8 @@ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { require_once("$CFG->dirroot/mod/book/lib.php"); + //--- general settings ----------------------------------------------------------------------------------- + $settings->add(new admin_setting_configcheckbox('book/requiremodintro', get_string('requiremodintro', 'admin'), get_string('configrequiremodintro', 'admin'), 1)); @@ -37,4 +39,11 @@ if ($ADMIN->fulltree) { get_string('numberingoptions', 'mod_book'), get_string('numberingoptions_help', 'mod_book'), array_keys($options), $options)); + + //--- modedit defaults ----------------------------------------------------------------------------------- + $settings->add(new admin_setting_heading('bookmodeditdefaults', get_string('modeditdefaults', 'admin'), get_string('condifmodeditdefaults', 'admin'))); + + $settings->add(new admin_setting_configselect('book/numbering', + get_string('numbering', 'mod_book'), '', BOOK_NUM_NUMBERS, $options)); + } \ No newline at end of file From b1a9b01ee27b121b8d2b226b7d0d9fdfc4d38de3 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 22:36:55 +0100 Subject: [PATCH 108/455] refactor chapter title proccessing --- delete.php | 2 +- edit.php | 2 +- import.php | 2 +- locallib.php | 36 ++++++++++++++++++++++++++++++++---- move.php | 2 +- show.php | 2 +- view.php | 19 ++++++++++--------- 7 files changed, 47 insertions(+), 18 deletions(-) diff --git a/delete.php b/delete.php index f32e66c632b..992de9687d3 100644 --- a/delete.php +++ b/delete.php @@ -70,7 +70,7 @@ if ($confirm) { // the operation was confirmed. add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); - book_preload_chapters($book->id); //fix structure + book_preload_chapters($book); //fix structure redirect('view.php?id='.$cm->id); } diff --git a/edit.php b/edit.php index 2c16d5af898..af563161574 100644 --- a/edit.php +++ b/edit.php @@ -102,7 +102,7 @@ if ($mform->is_cancelled()) { add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); } - book_preload_chapters($book->id); // fix structure + book_preload_chapters($book); // fix structure redirect("view.php?id=$cm->id&chapterid=$data->id"); } diff --git a/import.php b/import.php index 71f8e44cfdb..e60f2ca5389 100644 --- a/import.php +++ b/import.php @@ -107,7 +107,7 @@ if ($mform->is_cancelled()) { print_box_start('generalbox boxaligncenter centerpara'); echo ''.get_string('importing', 'book').':'; echo ''; - book_preload_chapters($book->id); // fix structure + book_preload_chapters($book); // fix structure foreach($refs as $ref) { $chapter = book_read_chapter($coursebase, $ref); if ($chapter) { diff --git a/locallib.php b/locallib.php index dde3a8d124e..b6eabfee61f 100644 --- a/locallib.php +++ b/locallib.php @@ -39,9 +39,9 @@ require_once($CFG->libdir.'/filelib.php'); * @param $cm * @return array of id=>chapter */ -function book_preload_chapters($bookid) { +function book_preload_chapters($book) { global $DB; - $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, subchapter, title, hidden'); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, pagenum, subchapter, title, hidden'); if (!$chapters) { return array(); } @@ -71,7 +71,11 @@ function book_preload_chapters($bookid) { $chapters[$prev]->next = $ch->id; } if ($ch->hidden) { - $ch->number = null; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $ch->number = 'x'; + } else { + $ch->number = null; + } } else { $i++; $ch->number = $i; @@ -96,7 +100,11 @@ function book_preload_chapters($bookid) { $ch->hidden = 1; } if ($ch->hidden) { - $ch->number = null; + if ($book->numbering == BOOK_NUM_NUMBERS) { + $ch->number = 'x'; + } else { + $ch->number = null; + } } else { $j++; $ch->number = $j; @@ -112,6 +120,26 @@ function book_preload_chapters($bookid) { return $chapters; } +function book_get_chapter_title($chid, $chapters, $book, $context) { + $ch = $chapters[$chid]; + $title = trim(format_string($ch->title, true, array('context'=>$context))); + $numbers = array(); + if ($book->numbering == BOOK_NUM_NUMBERS) { + if ($ch->parent and $chapters[$ch->parent]->number) { + $numbers[] = $chapters[$ch->parent]->number; + } + if ($ch->number) { + $numbers[] = $ch->number; + } + } + + if ($numbers) { + $title = implode('.', $numbers).' '.$title; + } + + return $title; +} + /** * General logging to table * @param string $str1 diff --git a/move.php b/move.php index 17723db6652..dd13b3a17d1 100644 --- a/move.php +++ b/move.php @@ -182,6 +182,6 @@ if (!$nothing) { add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); -book_preload_chapters($book->id); // fix structure +book_preload_chapters($book); // fix structure redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); diff --git a/show.php b/show.php index f5893e4b375..9c89128ad5b 100644 --- a/show.php +++ b/show.php @@ -69,6 +69,6 @@ if (!$chapter->subchapter) { add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); -book_preload_chapters($book->id); // fix structure +book_preload_chapters($book); // fix structure redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); diff --git a/view.php b/view.php index 7c005098cf5..3de3eb5f880 100644 --- a/view.php +++ b/view.php @@ -68,7 +68,7 @@ if ($allowedit) { } /// read chapters -$chapters = book_preload_chapters($book->id); +$chapters = book_preload_chapters($book); if ($allowedit and !$chapters) { redirect('edit.php?cmid='.$cm->id); //no chapters - add new one @@ -160,9 +160,6 @@ if ($nextid) { $chnavigation .= ''.get_string('navexit', 'book').''; } -// prepare $toc and $currtitle, $currsubtitle -list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); - // ===================================================== // Book display HTML code // ===================================================== @@ -173,11 +170,15 @@ echo '
                  '.$chnavigation.'
                  '; // chapter itself echo $OUTPUT->box_start('generalbox book_content'); if (!$book->customtitles) { - if (!$chapter->subchapter) { - echo '

                  '.$currtitle.'

                  '; - } else { - echo '

                  '.$currtitle.'
                  '.$currsubtitle.'

                  '; - } + $hidden = $chapter->hidden ? 'dimmed_text' : ''; + if (!$chapter->subchapter) { + $currtitle = book_get_chapter_title($chapter->id, $chapters, $book, $context); + echo '

                  '.$currtitle.'

                  '; + } else { + $currtitle = book_get_chapter_title($chapters[$chapter->id]->parent, $chapters, $book, $context); + $currsubtitle = book_get_chapter_title($chapter->id, $chapters, $book, $context); + echo '

                  '.$currtitle.'
                  '.$currsubtitle.'

                  '; + } } $chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id); echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); From ee952cbbb4b4116bea2b7adeea5fe1b0d8b1af6a Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 23:01:05 +0100 Subject: [PATCH 109/455] refactor chapter printing TOC --- locallib.php | 132 ++++++++++++++++++++++++++++----------------------- print.php | 35 +++++++++----- 2 files changed, 96 insertions(+), 71 deletions(-) diff --git a/locallib.php b/locallib.php index b6eabfee61f..b5d72f40a91 100644 --- a/locallib.php +++ b/locallib.php @@ -164,7 +164,7 @@ function book_log($str1, $str2, $level = 0) { function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { global $OUTPUT, $PAGE; - list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); + $toc= book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); if ($edit) { $toc .= '
                  '; @@ -193,21 +193,81 @@ function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { * @param bool $print * @return array */ -function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { +function book_get_print_toc($chapters, $book, $cm) { global $USER, $OUTPUT; - $currtitle = ''; //active chapter title (plain text) - $currsubtitle = ''; //active subchapter if any - $prevtitle = ' '; - $toc = ''; //representation of toc (HTML) - - $nch = 0; //chapter number - $ns = 0; //subchapter number - $first = 1; + $first = true; $titles = array(); $context = get_context_instance(CONTEXT_MODULE, $cm->id); + $toc = ''; //representation of toc (HTML) + + switch ($book->numbering) { + case BOOK_NUM_NONE: + $toc .= '
                  '; + break; + case BOOK_NUM_NUMBERS: + $toc .= '
                  '; + break; + case BOOK_NUM_BULLETS: + $toc .= '
                  '; + break; + case BOOK_NUM_INDENTED: + $toc .= '
                  '; + break; + } + + $toc .= ''; //representation of toc (HTML) + + if ($book->customtitles) { + $toc .= '

                  '.get_string('toc', 'book').'

                  '; + } else { + $toc .= '

                  '.get_string('toc', 'book').'

                  '; + } + $toc .= '
                    '; + foreach($chapters as $ch) { + if (!$ch->hidden) { + $title = book_get_chapter_title($ch->id, $chapters, $book, $context); + if (!$ch->subchapter) { + $toc .= $first ? '
                  • ' : '
                • '; + } else { + $toc .= $first ? '
                  • ' : '
                  • '; + } + $titles[$ch->id] = $title; + $toc .= ''.$title.''; + $toc .= (!$ch->subchapter) ? '
                      ' : ''; + $first = false; + } + } + $toc .= '
                  '; + $toc .= '
                • '; + $toc = str_replace('
                    ', '', $toc); //cleanup of invalid structures + + return array($toc, $titles); +} + +/** + * Generate toc structure + * + * @param array $chapters + * @param stdClass $chapter + * @param stdClass $book + * @param stdClass $cm + * @param bool $edit + * @param bool $print + * @return string + */ +function book_get_toc($chapters, $chapter, $book, $cm, $edit) { + global $USER, $OUTPUT; + + $toc = ''; //representation of toc (HTML) + $nch = 0; //chapter number + $ns = 0; //subchapter number + $first = 1; + + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + switch ($book->numbering) { case BOOK_NUM_NONE: $toc .= '
                    '; @@ -224,39 +284,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { } - if ($print) { ///TOC for printing - $toc .= ''; - if ($book->customtitles) { - $toc .= '

                    '.get_string('toc', 'book').'

                    '; - } else { - $toc .= '

                    '.get_string('toc', 'book').'

                    '; - } - $toc .= '
                      '; - foreach($chapters as $ch) { - $title = trim(format_string($ch->title, true, array('context'=>$context))); - if (!$ch->hidden) { - if (!$ch->subchapter) { - $nch++; - $ns = 0; - $toc .= ($first) ? '
                    • ' : '
                  • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch $title"; - } - } else { - $ns++; - $toc .= ($first) ? '
                    • ' : '
                    • '; - if ($book->numbering == BOOK_NUM_NUMBERS) { - $title = "$nch.$ns $title"; - } - } - $titles[$ch->id] = $title; - $toc .= ''.$title.''; - $toc .= (!$ch->subchapter) ? '
                        ' : ''; - $first = 0; - } - } - $toc .= '
                    '; - } else if ($edit) { ///teacher's TOC + if ($edit) { ///teacher's TOC $toc .= '
                      '; $i = 0; foreach($chapters as $ch) { @@ -276,7 +304,6 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { } $title = ''.$title.''; } - $prevtitle = $title; } else { $toc .= ($first) ? '
                      • ' : '
                      • '; if (!$ch->hidden) { @@ -294,13 +321,6 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { if ($ch->id == $chapter->id) { $toc .= ''.$title.''; - if ($ch->subchapter) { - $currtitle = $prevtitle; - $currsubtitle = $title; - } else { - $currtitle = $title; - $currsubtitle = ' '; - } } else { $toc .= ''.$title.''; } @@ -336,7 +356,6 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { if ($book->numbering == BOOK_NUM_NUMBERS) { $title = "$nch $title"; } - $prevtitle = $title; } else { $ns++; $toc .= ($first) ? '
                        • ' : '
                        • '; @@ -346,13 +365,6 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { } if ($ch->id == $chapter->id) { $toc .= ''.$title.''; - if ($ch->subchapter) { - $currtitle = $prevtitle; - $currsubtitle = $title; - } else { - $currtitle = $title; - $currsubtitle = ' '; - } } else { $toc .= ''.$title.''; } @@ -367,7 +379,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit, $print) { $toc = str_replace('
                            ', '', $toc); //cleanup of invalid structures - return array($toc, $currtitle, $currsubtitle, $titles); + return $toc; } diff --git a/print.php b/print.php index 985a1e3eac9..ff2ec39beda 100644 --- a/print.php +++ b/print.php @@ -46,7 +46,7 @@ require_capability('mod/book:print', $context); //check all variables if ($chapterid) { //single chapter printing - only visible! - $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id, 'hidden'=>0), '*', MUST_EXIST); + $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); } else { //complete book $chapter = false; @@ -60,6 +60,9 @@ unset($chapterid); // security checks END // ========================================================================= +/// read chapters +$chapters = book_preload_chapters($book); + $strbooks = get_string('modulenameplural', 'mod_book'); $strbook = get_string('modulename', 'mod_book'); $strtop = get_string('top', 'mod_book'); @@ -71,12 +74,13 @@ $strtop = get_string('top', 'mod_book'); @header('Content-type: text/html; charset=utf-8'); if ($chapter) { + + if ($chapter->hidden) { + require_capability('mod/book:viewhiddenchapters', $context); + } + add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); - $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id, 'hidden'=>0), 'pagenum, title'); - - list($toc, $currtitle, $currsubtitle, $titles) = book_get_toc($chapters, $chapter, $book, $cm, 0, 0); - /// page header ?> @@ -92,13 +96,18 @@ if ($chapter) {
                            customtitles) { - if ($currsubtitle == ' ') { - echo '

                            '.$currtitle.'

                            '; + if (!$chapter->subchapter) { + $currtitle = book_get_chapter_title($chapter->id, $chapters, $book, $context); + echo '

                            '.$currtitle.'

                            '; } else { + $currtitle = book_get_chapter_title($chapters[$chapter->id]->parent, $chapters, $book, $context); + $currsubtitle = book_get_chapter_title($chapter->id, $chapters, $book, $context); echo '

                            '.$currtitle.'
                            '.$currsubtitle.'

                            '; } } + $chaptertext = file_rewrite_pluginfile_urls($chapter->content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $chapter->id); echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); echo '
                            '; @@ -106,7 +115,7 @@ if ($chapter) { } else { add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id, $book->id, $cm->id); - $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); + $allchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); /// page header ?> @@ -142,20 +151,24 @@ if ($chapter) {
                    • wwwroot.'/mod/book/view.php?id='.$course->id.'&chapterid='; $link2 = $CFG->wwwroot.'/mod/book/view.php?id='.$course->id; foreach ($chapters as $ch) { + $chapter = $allchapters[$ch->id]; + if ($chapter->hidden) { + continue; + } echo '
                      '; if (!$book->customtitles) { echo '

                      '.$titles[$ch->id].'

                      '; } - $content = str_replace($link1, '#ch', $ch->content); + $content = str_replace($link1, '#ch', $chapter->content); $content = str_replace($link2, '#top', $content); $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $ch->id); - echo format_text($content, $ch->contentformat, array('noclean'=>true, 'context'=>$context)); + echo format_text($content, $chapter->contentformat, array('noclean'=>true, 'context'=>$context)); echo '
                      '; //echo ''.$strtop.''; } From 4cd51b08ddb79540c964495d8590a7b3e895beb7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 23:02:31 +0100 Subject: [PATCH 110/455] fix frankenstype git_string component --- locallib.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locallib.php b/locallib.php index b5d72f40a91..72c7dcdc622 100644 --- a/locallib.php +++ b/locallib.php @@ -221,9 +221,9 @@ function book_get_print_toc($chapters, $book, $cm) { $toc .= ''; //representation of toc (HTML) if ($book->customtitles) { - $toc .= '

                      '.get_string('toc', 'book').'

                      '; + $toc .= '

                      '.get_string('toc', 'mod_book').'

                      '; } else { - $toc .= '

                      '.get_string('toc', 'book').'

                      '; + $toc .= '

                      '.get_string('toc', 'mod_book').'

                      '; } $toc .= '
                        '; foreach($chapters as $ch) { @@ -338,7 +338,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { } else { $toc .= ' '.get_string('hide').''; } - $toc .= ' '.get_string('addafter', 'book').''; + $toc .= ' '.get_string('addafter', 'mod_book').''; $toc .= (!$ch->subchapter) ? '
                          ' : ''; $first = 0; From 2e9dead56de928e82bf504ff08f2c9f62886edc0 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 23:03:02 +0100 Subject: [PATCH 111/455] bump version before snapshot --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index 0959e94b1fb..51a55140eb1 100644 --- a/version.php +++ b/version.php @@ -23,7 +23,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011011601; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011011602; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) From 2890e4c1fbf9d31e84aa2bbd8c162a8988310e41 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 16 Jan 2011 23:15:56 +0100 Subject: [PATCH 112/455] implement completion tracking --- README | 8 ++++---- lib.php | 2 +- view.php | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/README b/README index 36ea7bce324..3b6bd9cd490 100644 --- a/README +++ b/README @@ -109,12 +109,12 @@ CHANGELOG: == 2.0dev ============================================================ * Moodle 2.0 conversion * removed "Disable printing" option, please use capabilities instead + * completion tracking supported Known issues, please do not file tracker reports: -* upgrade imscp export code (disabled for now) -* upgrade import code (disabled for now) -* open print links in new windows (needs fix in navlib) -* completion tracking + * upgrade imscp export code (disabled for now) + * upgrade import code (disabled for now) + * open print links in new windows (needs fix in navlib) Petr diff --git a/lib.php b/lib.php index 7e777a8d5ae..6a7173a4cf0 100644 --- a/lib.php +++ b/lib.php @@ -222,7 +222,7 @@ function book_supports($feature) { case FEATURE_GROUPINGS: return false; case FEATURE_GROUPMEMBERSONLY: return true; case FEATURE_MOD_INTRO: return true; - case FEATURE_COMPLETION_TRACKS_VIEWS: return false; //TODO + case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_BACKUP_MOODLE2: return true; default: return null; diff --git a/view.php b/view.php index 3de3eb5f880..c09becca12f 100644 --- a/view.php +++ b/view.php @@ -25,6 +25,7 @@ require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); +require_once($CFG->libdir.'/completionlib.php'); $id = optional_param('id', 0, PARAM_INT); // Course Module ID $bid = optional_param('b', 0, PARAM_INT); // Book id @@ -158,6 +159,10 @@ if ($nextid) { $sec = $section->section; } $chnavigation .= ''.get_string('navexit', 'book').''; + + // we are cheating a bit here, viewing the last page means user has viewed the whole book + $completion = new completion_info($course); + $completion->set_module_viewed($cm); } // ===================================================== From 652517cedbd86fe7b157c76162089c3db3470a95 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 23 Jan 2011 12:44:59 +0100 Subject: [PATCH 113/455] more room for edit form btw it is a sloppy hack to use admin layout just to get rid of the block on one side, ideally this should be hadnled by forms automatically!! --- edit.php | 1 + 1 file changed, 1 insertion(+) diff --git a/edit.php b/edit.php index af563161574..1f855ad0675 100644 --- a/edit.php +++ b/edit.php @@ -42,6 +42,7 @@ $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:edit', $context); $PAGE->set_url('/mod/book/edit.php', array('cmid'=>$cmid, 'id'=>$chapterid, 'pagenum'=>$pagenum, 'subchapter'=>$subchapter)); +$PAGE->set_pagelayout('admin'); //this is a bloody hack! if ($chapterid) { $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); From ffe9d57ff4b668f583dab843d23fa6096850f535 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 23 Jan 2011 15:22:20 +0100 Subject: [PATCH 114/455] tell ppl that outdate book can not be upgraded from 1.9->2.0 --- db/upgrade.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/upgrade.php b/db/upgrade.php index eb68470d028..cb707842310 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -30,6 +30,10 @@ function xmldb_book_upgrade($oldversion) { $dbman = $DB->get_manager(); + if ($oldversion < 2004081100) { + new upgrade_exception('mod_book', $oldversion, 'Can not upgrade such an old book module, sorry, you should have upgraded it long time ago in 1.9 already.'); + } + if ($oldversion < 2007052001) { /// Changing type of field importsrc on table book_chapters to char From b0333d3cf11e8e9f8de54bcc8f4777d226c4ebea Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 23 Jan 2011 15:22:40 +0100 Subject: [PATCH 115/455] new component info that helps with borked installs/upgrades --- version.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/version.php b/version.php index 51a55140eb1..1d503ddb2cd 100644 --- a/version.php +++ b/version.php @@ -23,8 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011011602; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2010120700; // Requires this Moodle version -$module->cron = 0; // Period for cron to check this module (secs) +$module->version = 2011011603; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2010120700; // Requires this Moodle version +$module->cron = 0; // Period for cron to check this module (secs) +$module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $release = "2.0dev (20110116)"; // User-friendly version number From 73491f5a6ee6164c80a6ce28e07d0636fd4919d7 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 25 Jan 2011 10:01:22 +0100 Subject: [PATCH 116/455] CONTRIB-2723 let all frontpage users view and print books --- db/access.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/access.php b/db/access.php index 5bdf05ddd9b..1a7e4dedce0 100644 --- a/db/access.php +++ b/db/access.php @@ -30,6 +30,7 @@ $capabilities = array( 'contextlevel' => CONTEXT_MODULE, 'legacy' => array( 'guest' => CAP_ALLOW, + 'frontpage' => CAP_ALLOW, 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, @@ -72,6 +73,7 @@ $capabilities = array( 'contextlevel' => CONTEXT_MODULE, 'legacy' => array( 'guest' => CAP_ALLOW, + 'frontpage' => CAP_ALLOW, 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, From 8cb50b2a87808b962240854bf7f8ee4a0098ec59 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 26 Jan 2011 12:55:40 +0100 Subject: [PATCH 117/455] CSS improvements --- locallib.php | 4 +-- styles.css | 83 ++++++++++++++++++++++------------------------------ version.php | 4 +-- view.php | 4 +-- 4 files changed, 41 insertions(+), 54 deletions(-) diff --git a/locallib.php b/locallib.php index 72c7dcdc622..c9f19319e84 100644 --- a/locallib.php +++ b/locallib.php @@ -164,10 +164,10 @@ function book_log($str1, $str2, $level = 0) { function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { global $OUTPUT, $PAGE; - $toc= book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); + $toc = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); if ($edit) { - $toc .= '
                          '; + $toc .= '
                          '; $toc .= $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book')); $toc .= '
                          '; } diff --git a/styles.css b/styles.css index 9327c878c04..d09189d15bf 100644 --- a/styles.css +++ b/styles.css @@ -1,7 +1,5 @@ -/* later should be defined in themes*/ - -.book_chapter_title { +.mod_book .book_chapter_title { font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif; text-align: left; font-size: large; @@ -11,124 +9,113 @@ margin-bottom: 20px; } -.book_content { - text-align: left; +.mod_book img.bigicon { + vertical-align: middle; + margin-right: 4px; + margin-left: 4px; + width: 24px; + height: 24px; + border: 0px; } -img.bigicon { - vertical-align:middle; - margin-right:4px; - margin-left:4px; - width:24px; - height:24px; - border:0px; +.mod_book .navtop { + text-align: right; + margin-bottom: 0.5em; } -#mod-book-view table.booktable { - border:0; +.mod_book .navbottom { + text-align: right; } -#mod-book-view .bookexport { - float:left; -} +/* == Fake toc block == */ -#mod-book-view .booknav { - float:right; -} - -#mod-book-view table.booktable tr.tocandchapter { - vertical-align:text-top; -} - -#mod-book-view div.faq { +.mod_book .book_faq { font-size: 0.7em; } -/* == TOC styles == */ - /* toc style NONE */ -.book_toc_none { +.mod_book .book_toc_none { font-size: 0.8em; } -.book_toc_none ul { +.mod_book .book_toc_none ul { margin-left: 5px; padding-left: 0px; } -.book_toc_none ul ul { +.mod_book .book_toc_none ul ul { margin-left: 0px; padding-left: 0px; } -.book_toc_none li { +.mod_book .book_toc_none li { margin-top: 5px; list-style: none; } -.book_toc_none li li { +.mod_book .book_toc_none li li { margin-top: 0px; list-style: none; } /* toc style NUMBERED */ -.book_toc_numbered { +.mod_book .book_toc_numbered { font-size: 0.8em; } -.book_toc_numbered ul { +.mod_book .book_toc_numbered ul { margin-left: 5px; padding-left: 0px; } -.book_toc_numbered ul ul { +.mod_book .book_toc_numbered ul ul { margin-left: 0px; padding-left: 0px; } -.book_toc_numbered li { +.mod_book .book_toc_numbered li { margin-top: 5px; list-style: none; } -.book_toc_numbered li li { +.mod_book .book_toc_numbered li li { margin-top: 0px; list-style: none; } /*toc style BULLETS */ -.book_toc_bullets { +.mod_book .book_toc_bullets { font-size: 0.8em; } -.book_toc_bullets ul { +.mod_book .book_toc_bullets ul { margin-left: 5px; padding-left: 0px; } -.book_toc_bullets ul ul { +.mod_book .book_toc_bullets ul ul { margin-left: 20px; padding-left: 0px; } -.book_toc_bullets li { +.mod_book .book_toc_bullets li { margin-top: 5px; list-style: none; } -.book_toc_bullets li li { +.mod_book .book_toc_bullets li li { margin-top: 0px; list-style: circle; } /* toc style INDENTED*/ -.book_toc_indented { +.mod_book .book_toc_indented { font-size: 0.8em; } -.book_toc_indented ul { +.mod_book .book_toc_indented ul { margin-left: 5px; padding-left: 0px; } -.book_toc_indented ul ul { +.mod_book .book_toc_indented ul ul { margin-left: 15px; padding-left: 0px; } -.book_toc_indented li { +.mod_book .book_toc_indented li { margin-top: 5px; list-style: none; } -.book_toc_indented li li { +.mod_book .book_toc_indented li li { margin-top: 0px; list-style: none; } diff --git a/version.php b/version.php index 1d503ddb2cd..27d14ff3d60 100644 --- a/version.php +++ b/version.php @@ -23,9 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011011603; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011012600; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$release = "2.0dev (20110116)"; // User-friendly version number +$release = "2.0dev (20110126)"; // User-friendly version number diff --git a/view.php b/view.php index c09becca12f..af958ceb5c3 100644 --- a/view.php +++ b/view.php @@ -170,7 +170,7 @@ if ($nextid) { // ===================================================== // upper nav -echo '
                          '.$chnavigation.'
                          '; +echo ''; // chapter itself echo $OUTPUT->box_start('generalbox book_content'); @@ -191,7 +191,7 @@ echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, ' echo $OUTPUT->box_end(); /// lower navigation -echo '
                          '.$chnavigation.'
                          '; +echo ''; echo $OUTPUT->footer(); From bd0945240c897b8a66e529a74468d6cd142f7be5 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 26 Jan 2011 13:15:33 +0100 Subject: [PATCH 118/455] more css cleanup --- book_print.css => print.css | 0 print.php | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename book_print.css => print.css (100%) diff --git a/book_print.css b/print.css similarity index 100% rename from book_print.css rename to print.css diff --git a/print.php b/print.php index ff2ec39beda..1e5e506b249 100644 --- a/print.php +++ b/print.php @@ -89,7 +89,7 @@ if ($chapter) { <?php echo format_string($book->name, true, array('context'=>$context)) ?> - + @@ -125,7 +125,7 @@ if ($chapter) { <?php echo format_string($book->name, true, array('context'=>$context)) ?> - + From 8c554c278451c577636a88544c2817af51b38071 Mon Sep 17 00:00:00 2001 From: John Kelsh Date: Mon, 7 Feb 2011 14:32:02 +1030 Subject: [PATCH 119/455] Fixing backup encode and restore decode rule names. --- backup/moodle2/backup_book_activity_task.class.php | 10 +++++----- backup/moodle2/restore_book_activity_task.class.php | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backup/moodle2/backup_book_activity_task.class.php b/backup/moodle2/backup_book_activity_task.class.php index 61fd1da8304..2cc91ea0898 100644 --- a/backup/moodle2/backup_book_activity_task.class.php +++ b/backup/moodle2/backup_book_activity_task.class.php @@ -67,21 +67,21 @@ class backup_book_activity_task extends backup_activity_task { // Link to the list of books $search = "/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/"; - $content = preg_replace($search, '$@bookINDEX*$2@$', $content); + $content = preg_replace($search, '$@BOOKINDEX*$2@$', $content); // Link to book view by moduleid $search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/"; - $content = preg_replace($search, '$@bookVIEWBYID*$2@$', $content); + $content = preg_replace($search, '$@BOOKVIEWBYID*$2@$', $content); $search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)&chapterid=([0-9]+)/"; - $content = preg_replace($search, '$@bookVIEWBYIDCH*$2*$3@$', $content); + $content = preg_replace($search, '$@BOOKVIEWBYIDCH*$2*$3@$', $content); // Link to book view by bookid $search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)/"; - $content = preg_replace($search, '$@bookVIEWBYB*$2@$', $content); + $content = preg_replace($search, '$@BOOKVIEWBYB*$2@$', $content); $search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)&chapterid=([0-9]+)/"; - $content = preg_replace($search, '$@bookVIEWBYBCH*$2*$3@$', $content); + $content = preg_replace($search, '$@BOOKVIEWBYBCH*$2*$3@$', $content); return $content; } diff --git a/backup/moodle2/restore_book_activity_task.class.php b/backup/moodle2/restore_book_activity_task.class.php index 4d51718417f..b37a5212eae 100644 --- a/backup/moodle2/restore_book_activity_task.class.php +++ b/backup/moodle2/restore_book_activity_task.class.php @@ -78,15 +78,15 @@ class restore_book_activity_task extends restore_activity_task { $rules = array(); // List of books in course - $rules[] = new restore_decode_rule('bookINDEX', '/mod/book/index.php?id=$1', 'course'); + $rules[] = new restore_decode_rule('BOOKINDEX', '/mod/book/index.php?id=$1', 'course'); // book by cm->id - $rules[] = new restore_decode_rule('bookVIEWBYID', '/mod/book/view.php?id=$1', 'course_module'); - $rules[] = new restore_decode_rule('bookVIEWBYIDCH', '/mod/book/view.php?id=$1&chapterid=$2', array('course_module', 'book_chapter')); + $rules[] = new restore_decode_rule('BOOKVIEWBYID', '/mod/book/view.php?id=$1', 'course_module'); + $rules[] = new restore_decode_rule('BOOKVIEWBYIDCH', '/mod/book/view.php?id=$1&chapterid=$2', array('course_module', 'book_chapter')); // book by book->id - $rules[] = new restore_decode_rule('bookVIEWBYB', '/mod/book/view.php?b=$1', 'book'); - $rules[] = new restore_decode_rule('bookVIEWBYBCH', '/mod/book/view.php?b=$1&chapterid=$2', array('book', 'book_chapter')); + $rules[] = new restore_decode_rule('BOOKVIEWBYB', '/mod/book/view.php?b=$1', 'book'); + $rules[] = new restore_decode_rule('BOOKVIEWBYBCH', '/mod/book/view.php?b=$1&chapterid=$2', array('book', 'book_chapter')); return $rules; } From 2d3a0d0f0f23a934b6d1c308df50356c51a4199c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 8 Feb 2011 23:18:53 +0100 Subject: [PATCH 120/455] version bump --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index 27d14ff3d60..d461db7a14e 100644 --- a/version.php +++ b/version.php @@ -23,9 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011012600; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011020800; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$release = "2.0dev (20110126)"; // User-friendly version number +$release = "2.0dev (20110208)"; // User-friendly version number From ed04f7c0bf46a9b373883df62c679a293655f0d1 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 14 Feb 2011 09:03:04 +0100 Subject: [PATCH 121/455] add print popups --- lib.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib.php b/lib.php index 6a7173a4cf0..a1fbd05ce94 100644 --- a/lib.php +++ b/lib.php @@ -255,15 +255,17 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig } if (has_capability('mod/book:print', $PAGE->cm->context)) { - $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); - $booknode->add(get_string('printbook', 'mod_book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); - - // buggy navlib - actions not supported!! - //$action = new action_link($url, get_string('printbook', 'book'), new popup_action('onclick', $url)); - //$booknode->add('', $action, navigation_node::TYPE_SETTING); - - $url = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - $booknode->add(get_string('printchapter', 'mod_book'), $url, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); + $url1 = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); + $url2 = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); + if ($CFG->version > 2011020900) { + $action = new action_link($url1, get_string('printbook', 'book'), new popup_action('click', $url1)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); + $action = new action_link($url2, get_string('printchapter', 'book'), new popup_action('click', $url2)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); + } else { + $booknode->add(get_string('printbook', 'mod_book'), $url1, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); + $booknode->add(get_string('printchapter', 'mod_book'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); + } } if (has_capability('mod/book:import', $PAGE->cm->context)) { From ed89ac66feef12a6bc019c98ecd56d81a8f61e41 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 19 Mar 2011 12:42:51 +0100 Subject: [PATCH 122/455] CONTRIB-2805 fix incomplete book backup --- backup/moodle2/backup_book_stepslib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/moodle2/backup_book_stepslib.php b/backup/moodle2/backup_book_stepslib.php index a0800cf8ac7..04118c0c448 100644 --- a/backup/moodle2/backup_book_stepslib.php +++ b/backup/moodle2/backup_book_stepslib.php @@ -42,7 +42,7 @@ class backup_book_activity_structure_step extends backup_activity_structure_step // Define sources $book->set_source_table('book', array('id' => backup::VAR_ACTIVITYID)); - + $chapter->set_source_table('book_chapters', array('bookid' => backup::VAR_PARENTID)); // Define file annotations $book->annotate_files('mod_book', 'intro', null); // This file area hasn't itemid From 06844f132244048b80456f2e4fec38e878275a0e Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 19 Mar 2011 12:46:24 +0100 Subject: [PATCH 123/455] fix whitespace --- backup/moodle2/restore_book_activity_task.class.php | 1 - backup/moodle2/restore_book_stepslib.php | 1 - generateimscp.php | 1 - 3 files changed, 3 deletions(-) diff --git a/backup/moodle2/restore_book_activity_task.class.php b/backup/moodle2/restore_book_activity_task.class.php index b37a5212eae..df18aed32ba 100644 --- a/backup/moodle2/restore_book_activity_task.class.php +++ b/backup/moodle2/restore_book_activity_task.class.php @@ -1,5 +1,4 @@ Date: Sat, 19 Mar 2011 12:49:38 +0100 Subject: [PATCH 124/455] legacy is not used any more --- db/access.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/db/access.php b/db/access.php index 1a7e4dedce0..a72a7b6cd9d 100644 --- a/db/access.php +++ b/db/access.php @@ -28,7 +28,7 @@ $capabilities = array( 'mod/book:read' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'legacy' => array( + 'archetypes' => array( 'guest' => CAP_ALLOW, 'frontpage' => CAP_ALLOW, 'student' => CAP_ALLOW, @@ -41,7 +41,7 @@ $capabilities = array( 'mod/book:viewhiddenchapters' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'legacy' => array( + 'archetypes' => array( 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, @@ -52,7 +52,7 @@ $capabilities = array( 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'legacy' => array( + 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, ) @@ -62,7 +62,7 @@ $capabilities = array( 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_MODULE, - 'legacy' => array( + 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW, ) @@ -71,7 +71,7 @@ $capabilities = array( 'mod/book:print' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, - 'legacy' => array( + 'archetypes' => array( 'guest' => CAP_ALLOW, 'frontpage' => CAP_ALLOW, 'student' => CAP_ALLOW, From 1d5b62b76f985a5745b74a25dcad9bd151b7e859 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 19 Mar 2011 12:53:30 +0100 Subject: [PATCH 125/455] book 2.0RC --- README | 6 ++++-- version.php | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README b/README index 3b6bd9cd490..26bfa91c305 100644 --- a/README +++ b/README @@ -15,7 +15,7 @@ GNU General Public License for more details: http:www.gnu.org/copyleft/gpl.html -Book module for Moodle - version 2.0dev +Book module for Moodle - version 2.0rc =============================================================================== Created by: Petr Skoda (skodak) - most of the coding & design @@ -110,11 +110,13 @@ CHANGELOG: * Moodle 2.0 conversion * removed "Disable printing" option, please use capabilities instead * completion tracking supported +== 2.0rc ============================================================ + * backup fixed + * print links open in new window Known issues, please do not file tracker reports: * upgrade imscp export code (disabled for now) * upgrade import code (disabled for now) - * open print links in new windows (needs fix in navlib) Petr diff --git a/version.php b/version.php index d461db7a14e..867bf1076d8 100644 --- a/version.php +++ b/version.php @@ -23,9 +23,12 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$module->version = 2011020800; // The current module version (Date: YYYYMMDDXX) +defined('MOODLE_INTERNAL') || die; + +$module->version = 2011031900; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$release = "2.0dev (20110208)"; // User-friendly version number +$maturity = 150; //MATURITY_RC +$release = "2.0rc (20110319)"; // User-friendly version number From 02f884216d11e6cade748f3952f4b5706015c2e9 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 20 Mar 2011 11:33:26 +0100 Subject: [PATCH 126/455] fix file restore --- backup/moodle2/restore_book_stepslib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/moodle2/restore_book_stepslib.php b/backup/moodle2/restore_book_stepslib.php index 89c5374bfc3..021716a8982 100644 --- a/backup/moodle2/restore_book_stepslib.php +++ b/backup/moodle2/restore_book_stepslib.php @@ -60,7 +60,7 @@ class restore_book_activity_structure_step extends restore_activity_structure_st $data->bookid = $this->get_new_parentid('book'); $newitemid = $DB->insert_record('book_chapters', $data); - $this->set_mapping('book_chapter', $oldid, $newitemid); + $this->set_mapping('book_chapter', $oldid, $newitemid, true); } protected function after_execute() { From 35b1833b2a333e076e754c84583fa54b115afeaf Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 20 Mar 2011 11:34:23 +0100 Subject: [PATCH 127/455] bump up version --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index 867bf1076d8..1752dc5b92b 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011031900; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011032000; // The current module version (Date: YYYYMMDDXX) $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $maturity = 150; //MATURITY_RC -$release = "2.0rc (20110319)"; // User-friendly version number +$release = "2.0rc (20110320)"; // User-friendly version number From 4bfe07d0884277dc0af70016233b92ceb2eb52f4 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 20 Mar 2011 19:16:10 +0100 Subject: [PATCH 128/455] legacy files TODO --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index 26bfa91c305..f922c139632 100644 --- a/README +++ b/README @@ -117,6 +117,6 @@ CHANGELOG: Known issues, please do not file tracker reports: * upgrade imscp export code (disabled for now) * upgrade import code (disabled for now) - + * legacy files were not upgraded yet Petr From 5aeca1e2ec5f8fb13f065f231d03fa50dac7352f Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 21 Mar 2011 10:09:36 +0100 Subject: [PATCH 129/455] translations are now maintained in AMOS --- lang/be/book.php | 39 ----------------- lang/be/help/book/customtitles.html | 3 -- lang/be/help/book/edit.html | 7 ---- lang/be/help/book/faq.html | 39 ----------------- lang/be/help/book/import.html | 5 --- lang/be/help/book/mods.html | 4 -- lang/be/help/book/numberingtype.html | 12 ------ lang/be/help/book/summary.html | 5 --- lang/ca/book.php | 46 -------------------- lang/ca/help/book/customtitles.html | 3 -- lang/ca/help/book/edit.html | 7 ---- lang/ca/help/book/faq.html | 39 ----------------- lang/ca/help/book/import.html | 5 --- lang/ca/help/book/mods.html | 4 -- lang/ca/help/book/numberingtype.html | 12 ------ lang/ca/help/book/summary.html | 5 --- lang/cs/book.php | 39 ----------------- lang/cs/help/book/customtitles.html | 3 -- lang/cs/help/book/edit.html | 8 ---- lang/cs/help/book/faq.html | 41 ------------------ lang/cs/help/book/import.html | 5 --- lang/cs/help/book/mods.html | 4 -- lang/cs/help/book/numberingtype.html | 14 ------- lang/cs/help/book/summary.html | 5 --- lang/de/book.php | 46 -------------------- lang/de/help/book/customtitles.html | 1 - lang/de/help/book/edit.html | 1 - lang/de/help/book/faq.html | 1 - lang/de/help/book/import.html | 1 - lang/de/help/book/mods.html | 1 - lang/de/help/book/numberingtype.html | 1 - lang/de/help/book/summary.html | 1 - lang/es/book.php | 30 ------------- lang/fi/book.php | 40 ------------------ lang/fi/help/book/customtitles.html | 3 -- lang/fi/help/book/edit.html | 7 ---- lang/fi/help/book/faq.html | 56 ------------------------- lang/fi/help/book/import.html | 5 --- lang/fi/help/book/mods.html | 4 -- lang/fi/help/book/numberingtype.html | 16 ------- lang/fi/help/book/summary.html | 5 --- lang/fr/book.php | 43 ------------------- lang/id/book.php | 43 ------------------- lang/id/help/book/faq.html | 37 ---------------- lang/id/help/book/index.html | 7 ---- lang/id/help/book/mods.html | 5 --- lang/id/help/book/numberingtype.html | 15 ------- lang/id/help/book/summary.html | 5 --- lang/it/book.php | 45 -------------------- lang/it/help/book/customtitles.html | 3 -- lang/it/help/book/edit.html | 7 ---- lang/it/help/book/faq.html | 39 ----------------- lang/it/help/book/import.html | 5 --- lang/it/help/book/mods.html | 4 -- lang/it/help/book/numberingtype.html | 12 ------ lang/it/help/book/summary.html | 5 --- lang/ja/book.php | 45 -------------------- lang/ja/help/book/customtitles.html | 3 -- lang/ja/help/book/edit.html | 7 ---- lang/ja/help/book/faq.html | 22 ---------- lang/ja/help/book/import.html | 5 --- lang/ja/help/book/mods.html | 4 -- lang/ja/help/book/numberingtype.html | 14 ------- lang/ja/help/book/summary.html | 5 --- lang/nl/book.php | 38 ----------------- lang/nl/help/book/customtitles.html | 6 --- lang/nl/help/book/edit.html | 13 ------ lang/nl/help/book/faq.html | 21 ---------- lang/nl/help/book/import.html | 10 ----- lang/nl/help/book/mods.html | 8 ---- lang/nl/help/book/numberingtype.html | 25 ----------- lang/nl/help/book/summary.html | 9 ---- lang/pl/book.php | 39 ----------------- lang/pl/help/book/customtitles.html | 3 -- lang/pl/help/book/disableprinting.html | 3 -- lang/pl/help/book/edit.html | 7 ---- lang/pl/help/book/faq.html | 47 --------------------- lang/pl/help/book/import.html | 5 --- lang/pl/help/book/mods.html | 4 -- lang/pl/help/book/numberingtype.html | 15 ------- lang/pl/help/book/summary.html | 5 --- lang/pt_br/book.php | 45 -------------------- lang/pt_br/help/book/customtitles.html | 3 -- lang/pt_br/help/book/edit.html | 7 ---- lang/pt_br/help/book/faq.html | 52 ----------------------- lang/pt_br/help/book/import.html | 6 --- lang/pt_br/help/book/mods.html | 4 -- lang/pt_br/help/book/numberingtype.html | 15 ------- lang/pt_br/help/book/summary.html | 5 --- lang/sk/book.php | 39 ----------------- lang/sk/help/book/customtitles.html | 3 -- lang/sk/help/book/edit.html | 8 ---- lang/sk/help/book/faq.html | 41 ------------------ lang/sk/help/book/import.html | 6 --- lang/sk/help/book/mods.html | 4 -- lang/sk/help/book/numberingtype.html | 14 ------- lang/sk/help/book/summary.html | 5 --- lang/sl/book.php | 48 --------------------- lang/sl/help/book/customtitles.html | 3 -- lang/sl/help/book/edit.html | 7 ---- lang/sl/help/book/faq.html | 39 ----------------- lang/sl/help/book/import.html | 5 --- lang/sl/help/book/mods.html | 4 -- lang/sl/help/book/numberingtype.html | 12 ------ lang/sl/help/book/summary.html | 5 --- lang/sv/book.php | 39 ----------------- lang/sv/help/book/customtitles.html | 2 - lang/sv/help/book/edit.html | 6 --- lang/sv/help/book/faq.html | 42 ------------------- lang/sv/help/book/import.html | 3 -- lang/sv/help/book/mods.html | 4 -- lang/sv/help/book/numberingtype.html | 9 ---- lang/sv/help/book/summary.html | 3 -- 113 files changed, 1699 deletions(-) delete mode 100644 lang/be/book.php delete mode 100644 lang/be/help/book/customtitles.html delete mode 100644 lang/be/help/book/edit.html delete mode 100644 lang/be/help/book/faq.html delete mode 100644 lang/be/help/book/import.html delete mode 100644 lang/be/help/book/mods.html delete mode 100644 lang/be/help/book/numberingtype.html delete mode 100644 lang/be/help/book/summary.html delete mode 100644 lang/ca/book.php delete mode 100644 lang/ca/help/book/customtitles.html delete mode 100644 lang/ca/help/book/edit.html delete mode 100644 lang/ca/help/book/faq.html delete mode 100644 lang/ca/help/book/import.html delete mode 100644 lang/ca/help/book/mods.html delete mode 100644 lang/ca/help/book/numberingtype.html delete mode 100644 lang/ca/help/book/summary.html delete mode 100644 lang/cs/book.php delete mode 100644 lang/cs/help/book/customtitles.html delete mode 100644 lang/cs/help/book/edit.html delete mode 100644 lang/cs/help/book/faq.html delete mode 100644 lang/cs/help/book/import.html delete mode 100644 lang/cs/help/book/mods.html delete mode 100644 lang/cs/help/book/numberingtype.html delete mode 100644 lang/cs/help/book/summary.html delete mode 100644 lang/de/book.php delete mode 100644 lang/de/help/book/customtitles.html delete mode 100644 lang/de/help/book/edit.html delete mode 100644 lang/de/help/book/faq.html delete mode 100644 lang/de/help/book/import.html delete mode 100644 lang/de/help/book/mods.html delete mode 100644 lang/de/help/book/numberingtype.html delete mode 100644 lang/de/help/book/summary.html delete mode 100644 lang/es/book.php delete mode 100644 lang/fi/book.php delete mode 100644 lang/fi/help/book/customtitles.html delete mode 100644 lang/fi/help/book/edit.html delete mode 100644 lang/fi/help/book/faq.html delete mode 100644 lang/fi/help/book/import.html delete mode 100644 lang/fi/help/book/mods.html delete mode 100644 lang/fi/help/book/numberingtype.html delete mode 100644 lang/fi/help/book/summary.html delete mode 100644 lang/fr/book.php delete mode 100644 lang/id/book.php delete mode 100644 lang/id/help/book/faq.html delete mode 100644 lang/id/help/book/index.html delete mode 100644 lang/id/help/book/mods.html delete mode 100644 lang/id/help/book/numberingtype.html delete mode 100644 lang/id/help/book/summary.html delete mode 100644 lang/it/book.php delete mode 100644 lang/it/help/book/customtitles.html delete mode 100644 lang/it/help/book/edit.html delete mode 100644 lang/it/help/book/faq.html delete mode 100644 lang/it/help/book/import.html delete mode 100644 lang/it/help/book/mods.html delete mode 100644 lang/it/help/book/numberingtype.html delete mode 100644 lang/it/help/book/summary.html delete mode 100644 lang/ja/book.php delete mode 100644 lang/ja/help/book/customtitles.html delete mode 100644 lang/ja/help/book/edit.html delete mode 100644 lang/ja/help/book/faq.html delete mode 100644 lang/ja/help/book/import.html delete mode 100644 lang/ja/help/book/mods.html delete mode 100644 lang/ja/help/book/numberingtype.html delete mode 100644 lang/ja/help/book/summary.html delete mode 100644 lang/nl/book.php delete mode 100644 lang/nl/help/book/customtitles.html delete mode 100644 lang/nl/help/book/edit.html delete mode 100644 lang/nl/help/book/faq.html delete mode 100644 lang/nl/help/book/import.html delete mode 100644 lang/nl/help/book/mods.html delete mode 100644 lang/nl/help/book/numberingtype.html delete mode 100644 lang/nl/help/book/summary.html delete mode 100644 lang/pl/book.php delete mode 100644 lang/pl/help/book/customtitles.html delete mode 100644 lang/pl/help/book/disableprinting.html delete mode 100644 lang/pl/help/book/edit.html delete mode 100644 lang/pl/help/book/faq.html delete mode 100644 lang/pl/help/book/import.html delete mode 100644 lang/pl/help/book/mods.html delete mode 100644 lang/pl/help/book/numberingtype.html delete mode 100644 lang/pl/help/book/summary.html delete mode 100644 lang/pt_br/book.php delete mode 100644 lang/pt_br/help/book/customtitles.html delete mode 100644 lang/pt_br/help/book/edit.html delete mode 100644 lang/pt_br/help/book/faq.html delete mode 100644 lang/pt_br/help/book/import.html delete mode 100644 lang/pt_br/help/book/mods.html delete mode 100644 lang/pt_br/help/book/numberingtype.html delete mode 100644 lang/pt_br/help/book/summary.html delete mode 100644 lang/sk/book.php delete mode 100644 lang/sk/help/book/customtitles.html delete mode 100644 lang/sk/help/book/edit.html delete mode 100644 lang/sk/help/book/faq.html delete mode 100644 lang/sk/help/book/import.html delete mode 100644 lang/sk/help/book/mods.html delete mode 100644 lang/sk/help/book/numberingtype.html delete mode 100644 lang/sk/help/book/summary.html delete mode 100644 lang/sl/book.php delete mode 100644 lang/sl/help/book/customtitles.html delete mode 100644 lang/sl/help/book/edit.html delete mode 100644 lang/sl/help/book/faq.html delete mode 100644 lang/sl/help/book/import.html delete mode 100644 lang/sl/help/book/mods.html delete mode 100644 lang/sl/help/book/numberingtype.html delete mode 100644 lang/sl/help/book/summary.html delete mode 100644 lang/sv/book.php delete mode 100644 lang/sv/help/book/customtitles.html delete mode 100644 lang/sv/help/book/edit.html delete mode 100644 lang/sv/help/book/faq.html delete mode 100644 lang/sv/help/book/import.html delete mode 100644 lang/sv/help/book/mods.html delete mode 100644 lang/sv/help/book/numberingtype.html delete mode 100644 lang/sv/help/book/summary.html diff --git a/lang/be/book.php b/lang/be/book.php deleted file mode 100644 index 9ea8fd00e23..00000000000 --- a/lang/be/book.php +++ /dev/null @@ -1,39 +0,0 @@ - Раздзелы адсартуюцца па алфавіту па назве файлаў.'; -$string['importing'] = 'Імпартаванне'; -$string['importingchapters'] = 'Імпартаванне радзелаў у кнігу'; -$string['maindirectory'] = 'Галоўная тэчка'; -$string['modulename'] = 'Падручнік'; -$string['modulenameplural'] = 'Падручнікі'; -$string['navexit'] = 'Выйсці з падручніка'; -$string['navnext'] = 'Далей'; -$string['navprev'] = 'Назад'; -$string['numbering'] = 'Нумарацыя раздзела'; -$string['numbering0'] = 'Няма'; -$string['numbering1'] = 'Нумары'; -$string['numbering2'] = 'Маркеры'; -$string['numbering3'] = 'Павялічыць водступ'; -$string['pluginname'] = 'Падручнік'; -$string['printbook'] = 'Друкаваць увесь падручнік'; -$string['printchapter'] = 'Друкаваць раздзел'; -$string['printdate'] = 'Дата'; -$string['printedby'] = 'Надрукаваны'; -$string['relinking'] = 'Перакампанаваць'; -$string['subchapter'] = 'Параграф'; -$string['toc'] = 'Змест'; -$string['top'] = 'наверх'; diff --git a/lang/be/help/book/customtitles.html b/lang/be/help/book/customtitles.html deleted file mode 100644 index a79febf4125..00000000000 --- a/lang/be/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Прыватныя загалоўкі

                          - -

                          Загалоўкі раздзелаў аўтаматычны адлюстроўваюцца толькі ў змесце падручніка.

                          \ No newline at end of file diff --git a/lang/be/help/book/edit.html b/lang/be/help/book/edit.html deleted file mode 100644 index 8c6efd366a8..00000000000 --- a/lang/be/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Рэдагаванне раздзела

                          - -

                          Калі ласка, прызначайце кароткі (па колькасці сімвалаў) загаловак раздзелу.

                          - -

                          Максімальная глыбіня падраздзелаў - два.

                          - -

                          Калі Вы маеце праблемы пры выкарыстанні HTML-рэдактара, лепей абярыце новы браўзэр, напрыклад Mozilla Firefox, або ў наладах уліковага запісу пазначце выкарыстанне Web-форм замест рэдактара ў полі "Падчас рэдагавання тэксту".

                          \ No newline at end of file diff --git a/lang/be/help/book/faq.html b/lang/be/help/book/faq.html deleted file mode 100644 index 129c7c63981..00000000000 --- a/lang/be/help/book/faq.html +++ /dev/null @@ -1,39 +0,0 @@ -

                          - Часта задаваемыя пытанні аб падручніку -

                          -
                          -
                          - Чаму толькі два ўзроўня (раздзел і параграф)? -
                          -
                          - Два ўзроўня звычайна дастаткова для ўсіх кніг, трэці ўзровень будзе весці да дрэнна структураваных дакументаў. Модуль "Падручнік" спраектаваны для стварэння невялічкіх шматстаронкавых навучальных матэрыялаў. Звычайна для вялікіх дакументаў лепей выкарыстоўваць файлы фармата PDF. Лёгкі шлях да стварэння PDF-файла - выкарыстанне віртуальнага прынтэра (гл. - PDFCreator, - - PDFFactory, - Adobe Acrobat, - і г.д..). -
                          -
                          -
                          -
                          - Студэнты могуць рэдагаваць падручнік? -
                          -
                          - Толькі настаўнікі могуць ствараць і рэдагваць падручнікі. Пакуль няма планаў, каб дадаць првы студэнтаў на рэдагаванне падручніка, але кожны можа стварыць нешта вельмі падобнае для студэнтаў, напрыклад, партфоліо. Галоўная прычына гэтага - пакінуць модуль "Падручнік" як мага простым. -
                          -
                          -
                          - Як праводзіць пошук падручнікаў і ў іх? -
                          -
                          - На бюягучы момант для пошуку ў падручніку лепей выкарыстоўваць сродкі пошука браўзэра і шукаць дадзеныя на старонцы, якая падрыхтавана для друку. Глабальны пошук магчымы толькі ў форумах Moodle. Было б зручна, калі б быў глабальны пошук па ўсіх рэсурсах, ўключаючы падручнікі. Ці ёсць валанцёры для напісання такога скрыпта? -
                          -
                          -
                          - Мой загаловак не змяшчаецца ў адзін радок. -
                          -
                          - Калі магчыма, дык скараціце загалоўкі або звяртайцеся да адміністратара сайта, каб змяніў шырыню радка загалоўка. Яна вызначаецца ў наладах модуля для ўсіх падручнікаў на сайце. -
                          -
                          -
                          \ No newline at end of file diff --git a/lang/be/help/book/import.html b/lang/be/help/book/import.html deleted file mode 100644 index e96dfe74d63..00000000000 --- a/lang/be/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Імпарт

                          - -

                          Вы можаце імпартаваць адзін HTML-файл або ўсе HTML-файлы, якія знаходзяцца ў тэчцы.

                          - -

                          Адносныя спасылкі паміж файламі пераўтвараюцца ў абсалютныя спасылкі паміж раздзеламі. Малюнкі, flash і Java таксама правільна імпартуюцца.

                          \ No newline at end of file diff --git a/lang/be/help/book/mods.html b/lang/be/help/book/mods.html deleted file mode 100644 index be59a96e831..00000000000 --- a/lang/be/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                          Падручнікі

                          -
                            -

                            Падручнік - гэта просты шматстаронкавы навучальны матэрыял.

                            -
                          \ No newline at end of file diff --git a/lang/be/help/book/numberingtype.html b/lang/be/help/book/numberingtype.html deleted file mode 100644 index f46d9451c5a..00000000000 --- a/lang/be/help/book/numberingtype.html +++ /dev/null @@ -1,12 +0,0 @@ -

                          Нумарацыя раздзелаў

                          - -

                          Існуе неклаькі вызначаных шляхоў нумарацыі: - -

                          Няма - усе загалоўкі раздзелаў і параграфаў не фарматуюцца. Калі жадаеца, то ў дадзеным выпадку можаце скарыстаць спецыяльныя стылі для нумарацыі. Напрыклад, выкарыстоўваць літары пры нумарацыі загалоўкаў: "А. Першы раздзел", "А.1. Першы параграф перашага раздзела", ...

                          - -

                          Лічбы - раздзелы і параграфы нумаруюцца (1, 1.1, 1.2, 2, -...)

                          - -

                          Маркеры - параграфы паказваюцца з водступам і пазначаюцца маркерамі.

                          - -

                          З водступам - параграфы паказваюцца з водступам.

                          \ No newline at end of file diff --git a/lang/be/help/book/summary.html b/lang/be/help/book/summary.html deleted file mode 100644 index 9d46653b1ec..00000000000 --- a/lang/be/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Абагульненне

                          - -

                          Абагульненне - гэта кароткія звесткі аб падручніку.

                          - -

                          Калі ласка, не спрабуйце пісаць вялізнае абагульненне!

                          \ No newline at end of file diff --git a/lang/ca/book.php b/lang/ca/book.php deleted file mode 100644 index 0ed7f126c3f..00000000000 --- a/lang/ca/book.php +++ /dev/null @@ -1,46 +0,0 @@ -Els capítols estan ordenats alfabèticament pel nom del fitxer.'; -$string['maindirectory'] = 'Directori principal'; -$string['fileordir'] = 'Fitxer o directori'; diff --git a/lang/ca/help/book/customtitles.html b/lang/ca/help/book/customtitles.html deleted file mode 100644 index 6d0ed70bf68..00000000000 --- a/lang/ca/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Títols personalitzats

                          - -

                          Els títols de capítols es mostren automàticament només a l'índex.

                          diff --git a/lang/ca/help/book/edit.html b/lang/ca/help/book/edit.html deleted file mode 100644 index 2ae442a2a22..00000000000 --- a/lang/ca/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Edició de capítol

                          - -

                          Procureu mantenir curt el títol del capítol.

                          - -

                          El nivell màxim de subcapítols és de dos.

                          - -

                          Si teniu problemes emprant l'editor HTML integrat, proveu d'usar un altre navegador (com ara el Mozilla Firefox) o bé desactivar completament l'editor en el vostre perfil.

                          diff --git a/lang/ca/help/book/faq.html b/lang/ca/help/book/faq.html deleted file mode 100644 index 2731dcc2e0f..00000000000 --- a/lang/ca/help/book/faq.html +++ /dev/null @@ -1,39 +0,0 @@ -

                          - Preguntes Més Freqüents sobre els Llibres -

                          -
                          -
                          - Per què només dos nivells? -
                          -
                          - Dos nivells acostuma a ser suficient per la majoria de llibres; tres nivells conduirien a documents amb una estructura pobra. El mòdul de llibres està dissenyat per a crear materials d'estudi multipàgina curts. Per a documents més llargs és preferible emprar el format PDF. La manera més simple de crear PDF són les impressores virtuals (vegeu - PDFCreator, - - PDFFactory, - Adobe Acrobat, - etc.). [N. del T.: A banda del mètode de les impressores virtuals, molts programes lliures (p.ex. OpenOffice) permeten exportar els documents directament a format PDF] -
                          -
                          -
                          -
                          - Els estudiants poden editar els llibres? -
                          -
                          - Només els professors poden crear i modificar els llibres. No tenim previst implementar la modificació de llibres per part d'estudiants, però algú podria crear quelcom semblant per a estudiants (portafoli?). La raó principal és la de mantenir el mòdul de Llibres el més senzill possible. -
                          -
                          -
                          - Com puc fer cerques dins dels llibres? -
                          -
                          - De moment només hi ha una manera: emprar les facilitats de cerca del navegador en una pàgina d'impressió. Les cerques globals només són possibles actualment als fòrums de Moodle. Estaria bé poder fer cerques globals en tots els recursos, llibres inclosos; algun voluntari? -
                          -
                          -
                          - Els meus títols no caben en una línia. -
                          -
                          - Mireu de reescriure els vostres títols o bé demaneu a l'administrador del lloc que un canvïi l'amplada de l'índex. Aquesta amplada és definida de forma global per a tots els llibres a la pàgina de configuració del mòdul. -
                          -
                          -
                          diff --git a/lang/ca/help/book/import.html b/lang/ca/help/book/import.html deleted file mode 100644 index a0d42aeb946..00000000000 --- a/lang/ca/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Importació

                          - -

                          Podeu importar un únic fitxer HTML o bé tots els fitxers HTML d'un directori.

                          - -

                          Els enllaços relatius seran convertits a enllaços absoluts a capítols. Les imatges i els arxius flash o java també es reenllaçaran.

                          diff --git a/lang/ca/help/book/mods.html b/lang/ca/help/book/mods.html deleted file mode 100644 index 697a995d3fa..00000000000 --- a/lang/ca/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Llibres

                          -
                            -

                            Un llibre és un material d\'estudi multipàgina senzill

                            -
                          diff --git a/lang/ca/help/book/numberingtype.html b/lang/ca/help/book/numberingtype.html deleted file mode 100644 index 28ecf7973aa..00000000000 --- a/lang/ca/help/book/numberingtype.html +++ /dev/null @@ -1,12 +0,0 @@ -

                          Numeració de capítols

                          - -

                          Hi ha uns quants tipus de numeració predefinits: - -

                          Cap - als títols de capítols i subcapítols no se'ls aplica format; useu-lo si voleu definir estils de numeració especials, com ara lletres: en aquest cas, en el títol del capítol escriviu: "A. Primer capítol", "A.1. Un subcapítol",...

                          - -

                          Nombres - els capítols i subcapítols es numeren (1, 1.1, 1.2, 2, -...)

                          - -

                          Pics - els subcapítols s'indenten i es mostren amb pics.

                          - -

                          Indentats - els subcapítols s'indenten.

                          diff --git a/lang/ca/help/book/summary.html b/lang/ca/help/book/summary.html deleted file mode 100644 index 1beb8a5f9fc..00000000000 --- a/lang/ca/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Resum

                          - -

                          El resum és una descripció molt curta del llibre.

                          - -

                          No estigueu temptats d'escriure massa coses aquí!

                          diff --git a/lang/cs/book.php b/lang/cs/book.php deleted file mode 100644 index 1c00cdfc76d..00000000000 --- a/lang/cs/book.php +++ /dev/null @@ -1,39 +0,0 @@ -Kapitoly budou seřazeny abecedně podle názvů souborů.
                          Soubory s názvem ve tvaru \'sub_*.*\' jsou vždy importovány jako podkapitoly.'; -$string['importing'] = 'Importuji'; -$string['importingchapters'] = 'Importování kapitol'; -$string['maindirectory'] = 'Hlavní složka'; -$string['modulename'] = 'Kniha'; -$string['modulenameplural'] = 'Knihy'; -$string['navnext'] = 'Následující'; -$string['navprev'] = 'Předchozí'; -$string['navexit'] = 'Zpět na přehled'; -$string['numbering'] = 'Číslování kapitol'; -$string['numbering0'] = 'Žádné'; -$string['numbering1'] = 'Čísla'; -$string['numbering2'] = 'Puntíky'; -$string['numbering3'] = 'Odsazené'; -$string['pluginname'] = 'Kniha'; -$string['printbook'] = 'Vytisknout celou knihu'; -$string['printchapter'] = 'Vytisknout jednu kapitolu'; -$string['printdate'] = 'Datum'; -$string['printedby'] = 'Vytiskl(a)'; -$string['relinking'] = 'Relinkuji'; -$string['subchapter'] = 'Podkapitola'; -$string['toc'] = 'Obsah'; -$string['top'] = 'začátek'; diff --git a/lang/cs/help/book/customtitles.html b/lang/cs/help/book/customtitles.html deleted file mode 100644 index 70879bab8be..00000000000 --- a/lang/cs/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Uživatelské nadpisy

                          - -

                          Nadpisy jsou zobrazeny pouze v obsahu knihy.

                          diff --git a/lang/cs/help/book/edit.html b/lang/cs/help/book/edit.html deleted file mode 100644 index 51eb694344b..00000000000 --- a/lang/cs/help/book/edit.html +++ /dev/null @@ -1,8 +0,0 @@ -

                          Úprava kapitol

                          - -

                          Snažte se psát pouze krátké kapitoly.

                          - -

                          Knika může mít pouze dvě úrovně nadpisů.

                          - -

                          jestliže máte problémy s HTML editorem, můžete si zkusit nainstalovat jiný prohlížeč -(napřiklad Mozilla Firefox).

                          \ No newline at end of file diff --git a/lang/cs/help/book/faq.html b/lang/cs/help/book/faq.html deleted file mode 100644 index 68d1caacfb4..00000000000 --- a/lang/cs/help/book/faq.html +++ /dev/null @@ -1,41 +0,0 @@ -

                          - Často kladené otázky -

                          -
                          -
                          - Proč pouze dvě úrovně? -
                          -
                          - Dvě úrovně nadpisu stačí, vždy se snažte psát krátce a srozumitelně. - Jestliže si myslíte, že potřebuje víc úrovní, rozdělte text do několika knih. - Pro delší texty je většinou vhodnější PDF formát. PDF soubory můžete - vytvořit pomocí následujících programů: - PDFCreator, - - PDFFactory, - Adobe Acrobat. -
                          -
                          -
                          -
                          - Mohou studenti upravovat knihy? -
                          -
                          - Knihy mohou vytvářet a upravovat pouze učitelé. -
                          -
                          -
                          - Mohu vyhledávat v knihách? -
                          -
                          - Použijte vyhledávání ve vašem prohlížeči. -
                          -
                          -
                          - Nadpisy se mi nevejdou na jeden řádek. -
                          -
                          - Buďto zkraťte nadpis, nebo požádejte vašeho správce, aby změnil šířku obsahu. -
                          -
                          -
                          diff --git a/lang/cs/help/book/import.html b/lang/cs/help/book/import.html deleted file mode 100644 index 9f4d433f97d..00000000000 --- a/lang/cs/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Import

                          - -

                          Můžete importovat jeden HTML soubor nebo všechny soubory ve složce.

                          - -

                          Relativní odkazy jsou převedeny na odkazy na kapitoly. Odkazy na obrázky, flash a Javu jsou rovněž upraveny.

                          diff --git a/lang/cs/help/book/mods.html b/lang/cs/help/book/mods.html deleted file mode 100644 index 6cbac92e3e2..00000000000 --- a/lang/cs/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Knihy

                          -
                            -

                            Kniha je jednoduchý vícestránkový studijní materiál.

                            -
                          diff --git a/lang/cs/help/book/numberingtype.html b/lang/cs/help/book/numberingtype.html deleted file mode 100644 index aa9f93e4e24..00000000000 --- a/lang/cs/help/book/numberingtype.html +++ /dev/null @@ -1,14 +0,0 @@ -

                          Číslování kapitol

                          - -

                          Existuje několik předdefinovaných typů číslování: - -

                          Žádné - kapitoly a podkapitoly nejsou formátované, používejte v přípaže, -když chcete zadat vaše vlastní číslování. Například: do pole nadpis kapitoly zadejte -"A Úvod", "A.1 Nějaké Povídání", ...

                          - -

                          Čísla - kapitoly a podkapitoly jsou číslované (1, 1.1, 1.2, 2, ...)

                          - -

                          Puntíky - podkapitoly jsou odsazené a zvýrazněné puntíky.

                          - -

                          Odsazené - podkapitoly jsou odsazené.

                          - diff --git a/lang/cs/help/book/summary.html b/lang/cs/help/book/summary.html deleted file mode 100644 index b0b86f379ba..00000000000 --- a/lang/cs/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Souhrn

                          - -

                          Stručný obsah knihy.

                          - -

                          Snažte se o opravdu krátký a výstižný popis.

                          \ No newline at end of file diff --git a/lang/de/book.php b/lang/de/book.php deleted file mode 100644 index 79e78651b0a..00000000000 --- a/lang/de/book.php +++ /dev/null @@ -1,46 +0,0 @@ -Kapitel sind alphabetisch nach den Dateinamen sortiert.'; -$string['maindirectory'] = 'Hauptordner'; -$string['fileordir'] = 'Datei oder Ordner'; diff --git a/lang/de/help/book/customtitles.html b/lang/de/help/book/customtitles.html deleted file mode 100644 index 94b0b39106d..00000000000 --- a/lang/de/help/book/customtitles.html +++ /dev/null @@ -1 +0,0 @@ -

                          Titel der Kapitel

                          Kapiteltitel werden automatisch im Inhaltsverzeichnis angezeigt.

                          \ No newline at end of file diff --git a/lang/de/help/book/edit.html b/lang/de/help/book/edit.html deleted file mode 100644 index e450b74ef32..00000000000 --- a/lang/de/help/book/edit.html +++ /dev/null @@ -1 +0,0 @@ -

                          Kapitel bearbeiten

                          Versuchen Sie die Überschriften der Kapitel knapp zu halten. Sie stehen links im Inhaltsverzeichnis. Lange Titel werden umbrochen und sehen nicht gut aus.

                          Neben der Hauptebene kann eine Unterkapitelebene angelegt werden.

                          Wenn Sie Probleme mit dem WYSIWYG HTML Editor haben, versuchen Sie einen anderen Browser z.B. Mozilla Firefox zu benutzen oder schalten Sie den Editor im Profil ab.

                          \ No newline at end of file diff --git a/lang/de/help/book/faq.html b/lang/de/help/book/faq.html deleted file mode 100644 index 602caadeb4a..00000000000 --- a/lang/de/help/book/faq.html +++ /dev/null @@ -1 +0,0 @@ -

                          Frequently Asked Questions über Bücher

                          Warum nur zwei Gliederungsebenen?
                          Zwei Stufen sind in den meisten Fällen ausreichend. Drei Stufen würden häufig zu einem schlecht strukturierten Dokument führen. Das Buch Modul wurde für die Erstellung von kurzen Inhalten entwickelt. Für größere und komplexere Dokumente macht es mehr Sinn das PDF Format zu benutzen. Am einfachsten können Sie PDF Dateien mit den folgenden Programmen erzeugen (see PDFCreator, PDFFactory, Adobe Acrobat,etc.).

                          Können Teilnehmer/innen Bücher editieren?
                          Nur Trainer/innen können Bücher erstellen und ändern. Es ist nicht geplant auch für Teilnehmer zu ermöglichen. Der Hauptgrund ist jedoch, daß das Buch Modul so simpel wie möglich bleiben soll. Mit Hilfe der Rollenfunktion kann man dieses dennoch erreichen.

                          Wie kann ich in Büchern suchen?
                          Zur Zeit gibt es nur die Möglichkeit mit der Browsersuchfunktionin einem Buch zu suchen. Eine globale Suche ist nur in Moodle Foren möglich.

                          Mein Titel passt nicht in eine Zeile.
                          Ändern Sie Ihren Titel oder bitten Sie Ihren Administrator der Webseite darum ,daß er die Breite des Inhaltsverzeichnis vergrößert. Dies ist global für alle Bücher in der Modul Konfigurationsseite einstellbar.

                          \ No newline at end of file diff --git a/lang/de/help/book/import.html b/lang/de/help/book/import.html deleted file mode 100644 index 2c72d9c0904..00000000000 --- a/lang/de/help/book/import.html +++ /dev/null @@ -1 +0,0 @@ -

                          Import

                          Sie können Buchseiten als HTML-Dateien importieren. Jede einzelne HTML-Datei wird zu einer neuen Seite des Buches. Die Anordnung erfolgt alphabetisch nach den Titeln der HTML-Dateien.

                          Relative Dateiverknüpfungen werden zu absoluten Kapitelverlinkungen konvertiert. Bilder, Flash und Java Inhalte werden ebenfalls verlinkt.

                          \ No newline at end of file diff --git a/lang/de/help/book/mods.html b/lang/de/help/book/mods.html deleted file mode 100644 index 433a63fa941..00000000000 --- a/lang/de/help/book/mods.html +++ /dev/null @@ -1 +0,0 @@ -

                           Bücher

                            Das Arbeitsmaterial Buch ermöglicht es, Lerninhalte in strukturierter und gegliederter Form zu hinterlegen. Wie in einem Buch findet man ein Inhaltsverzeichnis und kann durch die Seiten blättern.

                          \ No newline at end of file diff --git a/lang/de/help/book/numberingtype.html b/lang/de/help/book/numberingtype.html deleted file mode 100644 index c53c97c841a..00000000000 --- a/lang/de/help/book/numberingtype.html +++ /dev/null @@ -1 +0,0 @@ -

                          Nummerierung von Kapiteln

                          Es gibt verschiedene vordefinierte Nummerierungstypen:

                          Keine - Kapitel und die Titel der Unterkapitel sind nicht formatiert. Sie könnenselber eigene Styles zur Nummerierung benutzen. Zum Beispiel Buchstaben. Im Kapitel Titelgeben Sie dann folgendes ein "A Erstes Kapitel", "A.1 ein Unterkapitel",...

                          Nummern - Kapitel und Unterkapitel sind nummeriert (1, 1.1, 1.2, 2,...)

                          Punkte - Unterkapitel sind eingerückt und werden mit Auszählungspunkten angezeigt.

                          Eingerückt - Unterkapitel sind eingerückt.

                          \ No newline at end of file diff --git a/lang/de/help/book/summary.html b/lang/de/help/book/summary.html deleted file mode 100644 index 76951e70e40..00000000000 --- a/lang/de/help/book/summary.html +++ /dev/null @@ -1 +0,0 @@ -

                          Beschreibung des Buches

                          Diese Einführung ist eine sehr kurze Beschreibung des Buches.

                          Schreiben Sie hier nicht zu viel hinein! Diese Beschreibung wird in der Übersicht der Bücher eines Kurses angezeigt. Sie ist mit dem Klappentext eines Buches vergleichbar.

                          \ No newline at end of file diff --git a/lang/es/book.php b/lang/es/book.php deleted file mode 100644 index e25ca48e95b..00000000000 --- a/lang/es/book.php +++ /dev/null @@ -1,30 +0,0 @@ -Luvut aakkostetaan tiedostonimien mukaan.'; -$string['importing'] = 'Tuodaan'; -$string['importingchapters'] = 'Tuodaan kirjan lukuja'; -$string['maindirectory'] = 'Päävalikko'; -$string['modulename'] = 'Kirja'; -$string['modulenameplural'] = 'Kirjat'; -$string['navnext'] = 'Seuraava'; -$string['navprev'] = 'Edellinen'; -$string['numbering'] = 'Lukujen numerointi'; -$string['numbering0'] = 'Ei mitään'; -$string['numbering1'] = 'Numerot'; -$string['numbering2'] = 'Luettelomerkit'; -$string['numbering3'] = 'Sisennys'; -$string['pluginname'] = 'Kirja'; -$string['printbook'] = 'Tulosta koko kirja'; -$string['printchapter'] = 'Tulosta tämä luku'; -$string['printdate'] = 'Tulostettu'; -$string['printedby'] = 'Tulostanut'; -$string['relinking'] = 'Uudelleenlinkitys'; -$string['subchapter'] = 'Alaluku'; -$string['thisdirection'] = 'ltr'; -$string['thislanguage'] = 'Suomi'; -$string['toc'] = 'Sisällysluettelo'; -$string['top'] = 'Alkuun'; diff --git a/lang/fi/help/book/customtitles.html b/lang/fi/help/book/customtitles.html deleted file mode 100644 index 536cdd76e0b..00000000000 --- a/lang/fi/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Mukautetut otsikot

                          - -

                          Mukautetut otsikot näytetään automaattisesti vain sisällysluettelossa.

                          diff --git a/lang/fi/help/book/edit.html b/lang/fi/help/book/edit.html deleted file mode 100644 index 3cda15308f8..00000000000 --- a/lang/fi/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Lukujen muokkaus

                          - -

                          Pidä lukujen otsikot mahdollisimman lyhyenä.

                          - -

                          Lukuja voi olla korkeintaan kahta eri tasoa.

                          - -

                          Jos sinulla on ongelmia visuaalisen muokkaustyökalun kanssa, kokeile selaimen vaihtamista esimerkiksi Mozilla Firefoxiin, tai poista visuaalinen muokkaustyökalu (Richtext HTML -editori) käytöstä profiilin asetuksistasi.

                          \ No newline at end of file diff --git a/lang/fi/help/book/faq.html b/lang/fi/help/book/faq.html deleted file mode 100644 index bb2d71e0668..00000000000 --- a/lang/fi/help/book/faq.html +++ /dev/null @@ -1,56 +0,0 @@ -

                          - Usein kysyttyjä kysymyksiä Kirja-moduulista -

                          -
                          -
                          - Miksi tasoja on vain kaksi? -
                          -
                          - Kaksi tasoa riittää yleensä kaikille kirjoille, kolme - tasoa johtaisi huonompiin asiakirjojen rakenteisiin. Kirja-moduuli on - suunniteltu lyhyiden monisivuisten oppimateriaalien luomiseen. Pidemmät - asiakirjat kannattaa yleensä tallentaa PDF-muodossa. Helpoin tapa luoda - PDF-tiedostoja on käyttää virtuaalitulostimia (katso - PDFCreator, - - PDFFactory, - Adobe Acrobat, - ja niin edelleen). -
                          -
                          -
                          -
                          - Voivatko oppilaat muokata kirjoja? -
                          -
                          - Vain opettajat voivan luoda ja muokata kirjoja. Oppilaiden muokattavissa - olevien kirjojen toteuttaminen ei ole suunnitelmissa. On kuitenkin mahdollista, - että joku toteuttaa vastaavan toiminnallisuuden myös oppilaille, - kuten esimerkiksi oppilasportfolion. Tämä päätös on - tehty Kirja-moduulin pitämiseksi mahdollisimman yksinkertaisena. -
                          -
                          -
                          - Kuinka voin etsiä tekstiä kirjoista? -
                          -
                          - Toistaiseksi tekstiä kirjoista voi etsiä vain yhdellä tavalla: - selaimen tekstinhakutoiminnolla. Jos tulostustoiminto on käytössä, - voit valita koko kirjan tulostettavaksi ja etsiä tekstiä tältä - sivulta (älä kuitenkaan tarpeettomasti tulosta kirjaa). - Vapaa sanahaku on käytössä lähinnä vain Moodlen keskustelupalstoilla. - Muistakin Moodlen resursseista olisi mukava voida etsiä tekstiä, löytyykö - toiminnallisuuden toteuttajiksi vapaaehtoisia? -
                          -
                          -
                          - Otsikkoni eivät mahdu yhdelle riville. -
                          -
                          - Muotoile otsikkotekstit uudelleen tai levennä sisällysluettelolle - varattua tilaa. Sisällysluettelon tilaa voi leventää - moduulin asetusten määrittämissivulla. (Tämä toiminto - on vain ylläpitäjien käytettävissä). -
                          -
                          -
                          diff --git a/lang/fi/help/book/import.html b/lang/fi/help/book/import.html deleted file mode 100644 index be15342d057..00000000000 --- a/lang/fi/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Tuo

                          - -

                          Voit tuoda moduuliin yksittäisen HTML-tiedoston tai kaikki tietyn kansion HTML-tiedostot.

                          - -

                          Suhteelliset linkit muutetaan absoluuttisiksi linkeiksi. Kuvat, Flash-, ja Java-tiedostot linkitetään myös uudelleen.

                          diff --git a/lang/fi/help/book/mods.html b/lang/fi/help/book/mods.html deleted file mode 100644 index 650bfd96588..00000000000 --- a/lang/fi/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Kirjat

                          -
                            -

                            Kirja on yksinkertainen monisivuinen oppimateriaalikokonaisuus

                            -
                          diff --git a/lang/fi/help/book/numberingtype.html b/lang/fi/help/book/numberingtype.html deleted file mode 100644 index 40150a9bede..00000000000 --- a/lang/fi/help/book/numberingtype.html +++ /dev/null @@ -1,16 +0,0 @@ -

                          Lukujen numerointi

                          - -

                          Lukujen numerointiin on useita tapoja: - -

                          Ei mitään - lukujen ja alalukujen otsikoita ei muotoilla mitenkään. -Käytä tätä vaihtoehtoa, jos haluat määritellä oman, erikoisemman -numerointitapasi. Voit numeroida luvut esimerkiksi kirjaimia käyttäen: kirjoita -luvun otsikoksi "A Ensimmäinen luku", "A.1 Alaluku" ja niin edelleen. -

                          - -

                          Numerot - luvut ja alaluvut merkitään numeroin (1, 1.1, 1.2, 2 ja niin edelleen). -

                          - -

                          Luettelomerkit - alalukujen otsikot sisennetään ja niiden edessä näkyy luettelomerkki.

                          - -

                          Sisennys - alalukujen otsikot sisennetään.

                          diff --git a/lang/fi/help/book/summary.html b/lang/fi/help/book/summary.html deleted file mode 100644 index 31778fce486..00000000000 --- a/lang/fi/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Yhteenveto

                          - -

                          Yhteenveto on hyvin lyhyt kuvaus kirjasta.

                          - -

                          Älä tee kuvauksesta liian pitkää!

                          \ No newline at end of file diff --git a/lang/fr/book.php b/lang/fr/book.php deleted file mode 100644 index 1222ea34132..00000000000 --- a/lang/fr/book.php +++ /dev/null @@ -1,43 +0,0 @@ -les chapitres ont triés alphabétiquement sur la base des noms de fichiers. -

                          CETTE FONCTIONNALITÉ EST EXPÉRIMENTALE ;-)

                          '; -$string['maindirectory'] = 'Dossier principal'; -$string['selectdir'] = 'Choisir le dossier du cours'; - -$string['relinking'] = 'Mise à jour des liens'; diff --git a/lang/id/book.php b/lang/id/book.php deleted file mode 100644 index dd6125d2ec7..00000000000 --- a/lang/id/book.php +++ /dev/null @@ -1,43 +0,0 @@ -bab diurutkan secara alfabetis berdasarkan nama file. -

                          Ini adalah FEATURE UJICOBA ;-)

                          '; -$string['maindirectory'] = 'Direktori utama'; -$string['chooseafileordir'] = 'Pilih sebuah file atau direktori'; - -$string['relinking'] = 'Relinking'; diff --git a/lang/id/help/book/faq.html b/lang/id/help/book/faq.html deleted file mode 100644 index 6bd35fbce3d..00000000000 --- a/lang/id/help/book/faq.html +++ /dev/null @@ -1,37 +0,0 @@ -

                          FAQ tentang Buku

                          - -
                          -
                          Kenapa hanya dua level?
                          -
                          Dua level secara umum sudah cukup untuk seluruh buku, - tiga level jusru akan menyebabkan struktur dokumen tidak terlalu bagus. - Module buku di desain untuk membuat materi multi halaman yang pendek . - Biasanya lebih baik menggunakan format PDF untuk dokumen yang lebih panjang. - Cara termudah untuk membuat PDF adalah dengan menggunakan printer virtual - (lihat PDFCreator, PDF -Factory, Adobe Acrobat, -etc.).
                          -

                          -
                          Bisakah Mahasiswa meng-edit buku ?
                          -
                          Hanya Dosen yang dapat mebuat dan mengedit buku.Tidak ada rencana -untuk memngimplementasikan hak edit pada mahasiswa pada buku,seseorang -mungkin dapat membuat sesuatu yang persis untuk mahasiawa (Portfolio?). -Ini adalah alasan utma membuat modul buku sesederhana mungkin.

                          -
                          Bagaimana saya mencari buku?
                          -
                          Untuk sekarang hanya ada satu cara, gunakan kemampuan browser - untuk mencari pada halaman cetak.Pencarian Global sekarang memungkinkan - di forum Moodle. - Akan sangat menyenangkan memiliki kemampuan pencarian global - untuk semua resource termasuk buku, ada voluneteer ? -

                          -
                          Judul saya cukup satu baris. ?
                          -
                          Buat singkatan untuk judul anda atau tanyakan admin situs untuk - mengubah lebar daftar isi. -Ini didefinisikan secara global untuk semua buku pada kalaman konfogurasi modul. -

                          -
                          diff --git a/lang/id/help/book/index.html b/lang/id/help/book/index.html deleted file mode 100644 index 238da9a1323..00000000000 --- a/lang/id/help/book/index.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Modul buku

                          - - diff --git a/lang/id/help/book/mods.html b/lang/id/help/book/mods.html deleted file mode 100644 index c91bb2f6270..00000000000 --- a/lang/id/help/book/mods.html +++ /dev/null @@ -1,5 +0,0 @@ -

                           Buku

                          -
                            -

                            Buku adalah materi pelajaran multi-halaman sederhana

                            -
                          diff --git a/lang/id/help/book/numberingtype.html b/lang/id/help/book/numberingtype.html deleted file mode 100644 index f0eef883eb4..00000000000 --- a/lang/id/help/book/numberingtype.html +++ /dev/null @@ -1,15 +0,0 @@ -

                          Penomoran Bab

                          - -

                          Ada beberapa tipe penomoran yang telah ditentukan : - -

                          None - Jusul bab and subbab tidak diformat sama sekali, gunakan -ini jika anda ingin mendefinisikan style penomoran sendiri. -Sebagai contoh huruf: pada judul bab tulis " -tipe judul "Bab Pertama", "B.1 beberapa subbab",...

                          - -

                          Numbered - bab dan subbab diberi nomor (1, 1.1, 1.2, 2, -...)

                          - -

                          Bullets - subbab di beri indentasi dan ditampilkan dengan bullet.

                          - -

                          Indented - subbab diindent.

                          diff --git a/lang/id/help/book/summary.html b/lang/id/help/book/summary.html deleted file mode 100644 index e9f998e0bee..00000000000 --- a/lang/id/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Membaca Ringkasan

                          - -

                          Ringkasan adalah dekripsi singkat tentang buku. - -

                          Jangan terlalu banyak menulis disini! diff --git a/lang/it/book.php b/lang/it/book.php deleted file mode 100644 index d6d2581073b..00000000000 --- a/lang/it/book.php +++ /dev/null @@ -1,45 +0,0 @@ -I capitoli saranno ordinati alfabeticamente utilizzando i nomi dei file.'; -$string['importing'] = 'Importazione in corso'; -$string['importingchapters'] = 'Importazione dei capitoli'; -$string['maindirectory'] = 'Cartella principale'; -$string['modulename'] = 'Libro'; -$string['modulenameplural'] = 'Libri'; -$string['navexit'] = 'Esci'; -$string['navnext'] = 'Pagina successiva'; -$string['navprev'] = 'Pagina precedente'; -$string['numbering'] = 'Numerazione capitoli'; -$string['numbering0'] = 'Senza numerazione'; -$string['numbering1'] = 'Numeri'; -$string['numbering2'] = 'Elenco puntato'; -$string['numbering3'] = 'Elenco rientrato'; -$string['pluginname'] = 'Libro'; -$string['printbook'] = 'Stampa tutto'; -$string['printchapter'] = 'Stampa capitolo'; -$string['printdate'] = 'Data'; -$string['printedby'] = 'Stampato da'; -$string['relinking'] = 'Elaborazione dei collegamenti'; -$string['subchapter'] = 'Paragrafo'; -$string['toc'] = 'Sommario'; -$string['top'] = 'Ritorna su'; diff --git a/lang/it/help/book/customtitles.html b/lang/it/help/book/customtitles.html deleted file mode 100644 index ccb5b7513bf..00000000000 --- a/lang/it/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Titoli personalizzati

                          - -

                          I titoli dei capitoli sono mostrati automaticamente solo nel Sommario.

                          \ No newline at end of file diff --git a/lang/it/help/book/edit.html b/lang/it/help/book/edit.html deleted file mode 100644 index aa808a033ed..00000000000 --- a/lang/it/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Modifica Capitolo

                          - -

                          Cerca di definire titoli corti per i capitoli.

                          - -

                          Il massimo numero di sottocapitoli è due.

                          - -

                          Se si riscontrano problemi nell'uso dell'editor html WYSIWYG, provare a passare a un altro browser (come Mozilla Firefox) o disattivare completamente l'editor nel proprio profilo.

                          \ No newline at end of file diff --git a/lang/it/help/book/faq.html b/lang/it/help/book/faq.html deleted file mode 100644 index a716aa24d78..00000000000 --- a/lang/it/help/book/faq.html +++ /dev/null @@ -1,39 +0,0 @@ -

                          - FAQ (Frequently Asked Questions) sui Libri -

                          -
                          -
                          - Perché solo due livelli? -
                          -
                          -Due livelli di solito sono sufficienti per tutti i libri, tre livelli porterebbero a documenti mal strutturati. Il modulo Libro è stato progettato per la creazione di brevi documenti di studio a più pagine. Per documenti più lunghi di solito è meglio usare il formato PDF. Un modo per creare PDF è costituito dalle stampanti virtuali (vedi - PDFCreator, - - PDFFactory, - Adobe Acrobat, - etc.). Il più facile è usare OpenOffice salvando direttamente in formato PDF il documento creato. -
                          -
                          -
                          -
                          - Gli studenti possono modificare i libri? -
                          -
                          -Solo i docenti possono creare e modificare i libri. Per ora non è prevista la possibilità di modifica da parte degli studenti, ma qualcuno potrebbe creare qualcosa di simile per gli stessi (Portfolio?). La ragione principale è stata quella di mantenere il modulo Libro più semplice possibile. -
                          -
                          -
                          - Come posso fare una ricerca nei libri? -
                          -
                          -Al momento c'è solo un modo, quello di usare la funzione di ricerca del proprio browser nella pagina di stampa. La ricerca globale è al momento possibile solo nei forum di Moodle. Sarebbe utile avere una ricerca globale per tutte le risorse inclusi i libri. Qualche volontario? -
                          -
                          -
                          - I miei titoli non entrano su una riga. -
                          -
                          -O riscrivi i tuoi titoli o chiedi all'amministratore del tuo sito di ridimensionare la larghezza del sommario. Questa è definita globalmente per tutti i libri nella pagina di configurazione del modulo. -
                          -
                          -
                          \ No newline at end of file diff --git a/lang/it/help/book/import.html b/lang/it/help/book/import.html deleted file mode 100644 index 61830e01828..00000000000 --- a/lang/it/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Importazione

                          - -

                          Si può importare un singolo file HTML o tutti i files HTML di una cartella.

                          - -

                          I link di files di tipo relativo sono trasformati in link assoluti a capitoli. Sono anche rilinkati files Immagini, Flash e Java.

                          \ No newline at end of file diff --git a/lang/it/help/book/mods.html b/lang/it/help/book/mods.html deleted file mode 100644 index b2b212a9c4f..00000000000 --- a/lang/it/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Libro

                          -
                            -

                            Il Libro è un semplice oggetto di studio fatto di più pagine

                            -
                          \ No newline at end of file diff --git a/lang/it/help/book/numberingtype.html b/lang/it/help/book/numberingtype.html deleted file mode 100644 index 7aea1449c7f..00000000000 --- a/lang/it/help/book/numberingtype.html +++ /dev/null @@ -1,12 +0,0 @@ -

                          Numerazione dei Capitoli

                          - -

                          Sono predefiniti diversi tipi di numerazione: - -

                          Nessuna - i titoli dei capitoli e dei sottocapitoli non sono formattati, da usare se si vogliono definire stili speciali di numerazione. Per esempio lettere: nei titoli dei capitoli, tipo "A Primo Capitolo", "A.1 Qualche Sottocapitolo",...

                          - -

                          Numeri - capitoli e sottocapitoli sono numerati (1, 1.1, 1.2, 2, -...)

                          - -

                          Punti - i sottocapitoli sono indentati e mostrati con punti.

                          - -

                          Indentata - i sottocapitoli sono indentati.

                          \ No newline at end of file diff --git a/lang/it/help/book/summary.html b/lang/it/help/book/summary.html deleted file mode 100644 index 6bf878a6e61..00000000000 --- a/lang/it/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Sommario

                          - -

                          Il sommario è una descrizione molto breve del libro.

                          - -

                          Non essere tentato di scrivere troppo qui dentro!

                          \ No newline at end of file diff --git a/lang/ja/book.php b/lang/ja/book.php deleted file mode 100644 index 7c10713058b..00000000000 --- a/lang/ja/book.php +++ /dev/null @@ -1,45 +0,0 @@ -各章はファイル名順にソートされます。'; -$string['maindirectory'] = 'メインディレクトリ'; -$string['fileordir'] = 'ファイルもしくはディレクトリ'; diff --git a/lang/ja/help/book/customtitles.html b/lang/ja/help/book/customtitles.html deleted file mode 100644 index 92203bd2de8..00000000000 --- a/lang/ja/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          カスタムタイトル

                          - -

                          章の題名はTOCの中だけで自動的に表示されます。

                          diff --git a/lang/ja/help/book/edit.html b/lang/ja/help/book/edit.html deleted file mode 100644 index 4be77c2e10d..00000000000 --- a/lang/ja/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          章の編集

                          - -

                          章の題名はなるべく短くしてください

                          - -

                          各章の下にある節は2レベルまで作成できます

                          - -

                          WYSIWYG htmlエディターを利用していて何か問題があった際には、(Mozilla Firefoxのような)別のブラウザで試してみて、あなたのプロファイルで、そのエディターを使用するのを取りやめる設定にしてください。

                          \ No newline at end of file diff --git a/lang/ja/help/book/faq.html b/lang/ja/help/book/faq.html deleted file mode 100644 index 662afca5c2c..00000000000 --- a/lang/ja/help/book/faq.html +++ /dev/null @@ -1,22 +0,0 @@ -

                          ブックに関してよく聞かれる質問

                          - -
                          -
                          なぜ2レベルしか階層がないのですか?
                          -
                          ほとんどの場合、2レベルで十分だからです。3レベルになると、構造的にあまりよくない文書になってしまいます。 ブックモジュールは、複数の短い教材の作成のためにデザインされたものです。通常、長い文書にはPDFのほうが向いております。PDFを作成する簡単な方法は仮想プリンタを利用することです。(次のリンクをご覧ください。 PDFCreator, PDF -Factory, Adobe Acrobat, -etc.).
                          -

                          -
                          生徒はブックを編集できるのですか?
                          -
                          教員だけがブックを作成、もしくは編集できます。いまのところ生徒が編集できるようにする機能を実装する予定はありませんが、どなたかが似たような機能をもったもの(ポートフォリオのようなものになるでしょうか)を作成するかもしれません。先生しか編集できない理由は、ブックをできるだけシンプルなものにしておくためです。

                          -
                          どうすればブックを検索できますか?
                          -
                          いまのところ、各ページに対してブラウザの検索機能を利用するしかありません。文書全体を検索するのはフォーラムだけしかできません。全てのリソースを横断的に検索できる検索ツールがあればいいですね。ボランティアはおられませんでしょうか? -

                          -
                          題名が1行におさまらないのですが。
                          -
                          題名を変更するか、管理者に目次(TOC)の幅を変更してもらってください。目次(TOC)は、モジュールの設定によって、全てのブックに定義されています。

                          -
                          diff --git a/lang/ja/help/book/import.html b/lang/ja/help/book/import.html deleted file mode 100644 index 12ca49349a6..00000000000 --- a/lang/ja/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          インポート

                          - -

                          HTMLファイルもしくは複数のHTMLファイルを含んだディレクトリをインポートできます。

                          - -

                          相対リンクは、チャプター間の絶対リンクに変換されます。イメージファイルやフラッシュもリンクが修正されます。

                          diff --git a/lang/ja/help/book/mods.html b/lang/ja/help/book/mods.html deleted file mode 100644 index 6b99692c851..00000000000 --- a/lang/ja/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           ブック

                          -
                            -

                            ブックとは、複数のページからなる教材です。

                            -
                          diff --git a/lang/ja/help/book/numberingtype.html b/lang/ja/help/book/numberingtype.html deleted file mode 100644 index 87309d9be16..00000000000 --- a/lang/ja/help/book/numberingtype.html +++ /dev/null @@ -1,14 +0,0 @@ -

                          Numbering of Chapters

                          - -

                          There are several predefined numbering types: - -

                          None - chapter and subchapter titles are not formatted at all, use -if you want to define special numbering styles. For example letters: in chapter -title type "A First Chapter", "A.1 Some Subchapter",...

                          - -

                          Numbers - chapters and subchapters are numbered (1, 1.1, 1.2, 2, -...)

                          - -

                          Bullets - subchapters are indented and displayed with bullets.

                          - -

                          Indented - subchapters are indented.

                          diff --git a/lang/ja/help/book/summary.html b/lang/ja/help/book/summary.html deleted file mode 100644 index 148ba8dfa8f..00000000000 --- a/lang/ja/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          概要を読む

                          - -

                          概要とは、ブックの非常に短い説明です。

                          - -

                          ここにあまり多くの量を書きすぎないように!

                          \ No newline at end of file diff --git a/lang/nl/book.php b/lang/nl/book.php deleted file mode 100644 index 09c41116668..00000000000 --- a/lang/nl/book.php +++ /dev/null @@ -1,38 +0,0 @@ -De hoofdstukken worden alfabetisch gerangschikt op bestandsnaam.'; -$string['importing'] = 'Importeren'; -$string['importingchapters'] = 'Importeren van hoofdstukken in het boek'; -$string['maindirectory'] = 'Hoofdmap'; -$string['modulename'] = 'Boek'; -$string['modulenameplural'] = 'Boeken'; -$string['navnext'] = 'Volgende'; -$string['navprev'] = 'Vorige'; -$string['numbering'] = 'Hoofdstuknummering'; -$string['numbering0'] = 'Geen'; -$string['numbering1'] = 'Nummering'; -$string['numbering2'] = 'Bolletjes'; -$string['numbering3'] = 'Inspringen'; -$string['pluginname'] = 'Boek'; -$string['printbook'] = 'Druk het hele boek af'; -$string['printchapter'] = 'Druk dit hoofdstuk af'; -$string['printdate'] = 'Datum'; -$string['printedby'] = 'Afgedrukt door'; -$string['relinking'] = 'Opnieuw linken'; -$string['subchapter'] = 'Paragraaf'; -$string['toc'] = 'Inhoudstafel'; -$string['top'] = 'boven'; diff --git a/lang/nl/help/book/customtitles.html b/lang/nl/help/book/customtitles.html deleted file mode 100644 index d40ffbf57d0..00000000000 --- a/lang/nl/help/book/customtitles.html +++ /dev/null @@ -1,6 +0,0 @@ -

                          Titels alleen in inhoudstafel

                          - - - -

                          Indien ja worden de titels van de hoofdstukken automatisch alleen in de inhoudstafel getoond.

                          - diff --git a/lang/nl/help/book/edit.html b/lang/nl/help/book/edit.html deleted file mode 100644 index 02c8097a417..00000000000 --- a/lang/nl/help/book/edit.html +++ /dev/null @@ -1,13 +0,0 @@ -

                          Hoofdstuk bewerken

                          - - - -

                          Probeer de titel van een hoofdstuk kort te houden.

                          - - - -

                          Paragrafen maximum twee niveaus diep.

                          - - - -

                          Als je problemen ondervindt met de WYSIWYG HTML-editor, probeer dan een andere browser (zoals Mozilla Firefox) of zet de editor af in je gebruikersprofiel.

                          \ No newline at end of file diff --git a/lang/nl/help/book/faq.html b/lang/nl/help/book/faq.html deleted file mode 100644 index 9ba3c3458e5..00000000000 --- a/lang/nl/help/book/faq.html +++ /dev/null @@ -1,21 +0,0 @@ -

                          Frequently Asked Questions over boeken

                          - -
                          -
                          Waarom slechts twee niveaus diep?
                          -
                          Twee niveaus zijn genoeg voor de meeste boeken, drie niveaus zou tot slecht gestructureerde documenten leiden. De boekmodule is ontworpen voor kort, uit meerdere pagina's bestaand studiemateriaal. Het is beter PDF te gebruiken voor grotere documenten. De gemakkelijkste manier om PDF's te maken is met virtuele printers (zie PDFCreator, PDF -Factory, Adobe Acrobat, -enz.).
                          -

                          -
                          Kunnen leerlingen boeken bewerken?
                          -
                          Alleen leraren kunnen boeken maken en bewerken. Er zijn geen plannen voor het implementeren van bewerken voor leerlingen, maar misschien maakt iemand anders iets gelijkaardigs voor leerlingen (Portfolio?). De belangrijkste reden is om de boekmodule zo eenvoudig mogelijk te houden.

                          -
                          Hoe kan ik de boeken doorzoeken?
                          -
                          Op dit ogenblik is er maar één manier, namelijk de zoekfunctie van de browser op de afdrukpagina. Zoeken is op dit ogenblik enkel mogelijk in de Moodle forums.

                          -
                          Mijn titels passen niet op deze lijn.
                          -
                          Probeer je titel anders te verwoorden of vraag je sitebeheerder om de breedte van de inhoudstafel aan te passen. Deze wordt voor alle boeken gedefinieerd op de configuratiepagina van de module.

                          -
                          diff --git a/lang/nl/help/book/import.html b/lang/nl/help/book/import.html deleted file mode 100644 index 0a71f9a99c8..00000000000 --- a/lang/nl/help/book/import.html +++ /dev/null @@ -1,10 +0,0 @@ -

                          Importeren

                          - - - -

                          Je kunt een enkel HTML-bestand of alle HTML-bestanden van een map importeren.

                          - - - -

                          Relatieve links naar bestanden worden geconverteerd in absolute hoofdstuklinks. De links naar bestanden, flash en java worden ook herwerkt.

                          - diff --git a/lang/nl/help/book/mods.html b/lang/nl/help/book/mods.html deleted file mode 100644 index d69f273b1a3..00000000000 --- a/lang/nl/help/book/mods.html +++ /dev/null @@ -1,8 +0,0 @@ -

                           Boeken

                          - -
                            - -

                            Met de boekmodule maak je eenvoudig studiemateriaal op meerdere pagina's.

                            - -
                          - diff --git a/lang/nl/help/book/numberingtype.html b/lang/nl/help/book/numberingtype.html deleted file mode 100644 index a982b976b59..00000000000 --- a/lang/nl/help/book/numberingtype.html +++ /dev/null @@ -1,25 +0,0 @@ -

                          Hoofdstuknummering

                          - - - -

                          Er zijn verschillende voorgedefinieerde nummeringstypes: - - - -

                          Geen - hoofdstukken en ondertitels krijgen geen opmaak. Gebruik deze instelling als je speciale nummeringsstijlen, zoals letters, wil gebruiken. Bijvoorbeeld: "A Eerste hoofdstuk", "A.1 Eerste paragraaf", .... -

                          - - - -

                          Getallen - hoofdstukken en paragrafen worden genummerd(1, 1.1, 1.2, 2, - -...)

                          - - - -

                          Bolletjes - paragrafen springen in en worden met bolletjes getoond.

                          - - - -

                          Indented - paragrafen springen in.

                          - diff --git a/lang/nl/help/book/summary.html b/lang/nl/help/book/summary.html deleted file mode 100644 index 61de4ebc709..00000000000 --- a/lang/nl/help/book/summary.html +++ /dev/null @@ -1,9 +0,0 @@ -

                          Samenvatting

                          - - - -

                          De samenvatting is een heel korte beschrijving van het boek.

                          - - - -

                          Kom niet in de verleiding hier teveel te schrijven!

                          \ No newline at end of file diff --git a/lang/pl/book.php b/lang/pl/book.php deleted file mode 100644 index 88a18fb76da..00000000000 --- a/lang/pl/book.php +++ /dev/null @@ -1,39 +0,0 @@ -Rozdziały są sortowane alfabetycznie wg. nazw plików.'; -$string['importing'] = 'Importowanie'; -$string['importingchapters'] = 'Importowanie rozdziałów do książki'; -$string['maindirectory'] = 'Główny katalog'; -$string['modulename'] = 'Książka'; -$string['modulenameplural'] = 'Książki'; -$string['navexit'] = 'Zamknij książkę'; -$string['navnext'] = 'Następny'; -$string['navprev'] = 'Poprzedni'; -$string['numbering'] = 'Numerowanie rodziałów'; -$string['numbering0'] = 'żaden'; -$string['numbering1'] = 'Liczby'; -$string['numbering2'] = 'Wypunktowanie'; -$string['numbering3'] = 'Wcięte'; -$string['pluginname'] = 'Książka'; -$string['printbook'] = 'Drukuj kopletną książkę'; -$string['printchapter'] = 'Drukuj ten rozdział'; -$string['printdate'] = 'Data'; -$string['printedby'] = 'Wydrukowane przez użytkoniwka'; -$string['relinking'] = 'Ponowne tworzenie linków'; -$string['subchapter'] = 'Podrozdział'; -$string['toc'] = 'Spis treści'; -$string['top'] = 'Góra'; diff --git a/lang/pl/help/book/customtitles.html b/lang/pl/help/book/customtitles.html deleted file mode 100644 index 1f742246943..00000000000 --- a/lang/pl/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Tytuły użytkownika

                          - -

                          Tytuły rozdziałów są automatycznie wyświetlane tylko w Spisie Treści.

                          \ No newline at end of file diff --git a/lang/pl/help/book/disableprinting.html b/lang/pl/help/book/disableprinting.html deleted file mode 100644 index 5254fff096c..00000000000 --- a/lang/pl/help/book/disableprinting.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Wyłącz drukowanie

                          - -

                          Ukryj ikonki wydruku.

                          \ No newline at end of file diff --git a/lang/pl/help/book/edit.html b/lang/pl/help/book/edit.html deleted file mode 100644 index ef2cd5327d9..00000000000 --- a/lang/pl/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Edycja rozdziału

                          - -

                          Staraj się używać krótkich tytułów rozdziałów

                          - -

                          Maksymalna liczba poziomów podrozdziałów to dwa.

                          - -

                          Jeśli zauważysz problemy używając edytora html WYSIWYG, spróbuj przejść na inną przeglądarkę (taką jak Mozilla Firefox) lub całkowicie wyłącz edytor w swoim profilu.

                          \ No newline at end of file diff --git a/lang/pl/help/book/faq.html b/lang/pl/help/book/faq.html deleted file mode 100644 index a57dcc62943..00000000000 --- a/lang/pl/help/book/faq.html +++ /dev/null @@ -1,47 +0,0 @@ -

                          - Często Zadawane Pytania dotyczace książek -

                          -
                          -
                          - Dlaczego tylko dwa poziomy? -
                          -
                          - Dwa poziomy są zasadniczno wystarczające dla wszystkich książęk, trzy i więcej mogłyby prowadzić do źle ustruturyzowanych dokumentów. Moduł książka jest zaprojektowany do tworzenia krótkich, kilkustronicowych materiałów. Dla długich dokumentów lepiej użyć formtu PDF. Najprostszy sposób tworzenia plików PDF to wykorzystanie wirtualnych drukarek (zobacz - PDFCreator, - - PDFFactory, - Adobe Acrobat, - itp.). -
                          -
                          -
                          -
                          - Czy studenci mogą edytowac książki? -
                          -
                          - Tylko nauczyciele mogą tworzyć i edytować książki. Nie ma planów implementacji takiej - funkcjonalności, ale ktoś może stworzyć coś podobnego dla studnetów (Portfolio?). - Główny powód to utrzymanie modułu tak prostym jak to tylko możliwe. -
                          -
                          -
                          -
                          - Jak mogę przeszukiwać książki? -
                          -
                          - Obecnie jest tylko jeden sposób, użyj funkcji przeglądarki w widoku wydruku. Globalne - przeszukiwanie jest możliwe tylko w forach Moodla. - Byłoby dobrze posiadać globalne wyszukiwanie we wszystkich zasobach włączając książki, są - chętni? -
                          -
                          -
                          -
                          - Moje tytuły nie mieszczą się. -
                          -
                          - Przeformułuj swoje tytuły lub poproś admina, żeby zmienił szerokość spisu treści. Jest ona - definiowalna globalnie dla wszystkich książek na stronie konfiguracji Moodla. -
                          -
                          -
                          \ No newline at end of file diff --git a/lang/pl/help/book/import.html b/lang/pl/help/book/import.html deleted file mode 100644 index ed09f9af7ff..00000000000 --- a/lang/pl/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Import

                          - -

                          Możesz zaimportować plik HTML lub wszystkie pliki HTML z katalogu.

                          - -

                          Względne linki do plików są przekształcane w bezwzględne linki do rozdziałów. Obrazy, Fleshe i Java są również ponownie linkowane.

                          \ No newline at end of file diff --git a/lang/pl/help/book/mods.html b/lang/pl/help/book/mods.html deleted file mode 100644 index c49b244aa22..00000000000 --- a/lang/pl/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                          Książki

                          -
                            -

                            Książka jest prostym kilkustronicowym materiałem do studiowania.

                            -
                          \ No newline at end of file diff --git a/lang/pl/help/book/numberingtype.html b/lang/pl/help/book/numberingtype.html deleted file mode 100644 index cae0cf1b811..00000000000 --- a/lang/pl/help/book/numberingtype.html +++ /dev/null @@ -1,15 +0,0 @@ -

                          Numerownie rodziałów

                          - -

                          Jest kilka predefiniowanych typów numerowania: - -

                          żaden - tytuły rodziałów i podrozdziałów nie są w żaden sposób formatwane, użyj go jeśli chcesz zdefiniować specjalny styl numerowania. -
                          Na przykład litery: w tytule rozdziału typu -
                          "A Pierwszy rozdział", -
                          "A.1 Jakiś podrozdział",...

                          - -

                          Liczby - rozdziały i podrozdziały są numerowane (1, 1.1, 1.2, 2, -...)

                          - -

                          Wypunktowanie - podrozdziały sa wcięte i wyświetlane ze znakami wypunktowania.

                          - -

                          Wcięty - podrozdziały są wcięte.

                          \ No newline at end of file diff --git a/lang/pl/help/book/summary.html b/lang/pl/help/book/summary.html deleted file mode 100644 index 0227b5363bc..00000000000 --- a/lang/pl/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Streszczenie

                          - -

                          Streszczenie jest bardzo krótkim opisem książki.

                          - -

                          Niech cię nie kusi pisać tu zbyt dużo!

                          \ No newline at end of file diff --git a/lang/pt_br/book.php b/lang/pt_br/book.php deleted file mode 100644 index a4e5a804caa..00000000000 --- a/lang/pt_br/book.php +++ /dev/null @@ -1,45 +0,0 @@ -Os capítulos são ordenados alfabeticamente usando os nomes dos arquivos.'; -$string['maindirectory'] = 'Diretório principal'; -$string['fileordir'] = 'Arquivo ou diretório'; diff --git a/lang/pt_br/help/book/customtitles.html b/lang/pt_br/help/book/customtitles.html deleted file mode 100644 index 01988d7cd57..00000000000 --- a/lang/pt_br/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Títulos personalizados

                          - -

                          Os títulos dos capítulos são mostrados automaticamente só no sumário.

                          diff --git a/lang/pt_br/help/book/edit.html b/lang/pt_br/help/book/edit.html deleted file mode 100644 index 0ec3298dcd8..00000000000 --- a/lang/pt_br/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Edução de capítulo

                          - -

                          Tente manter o título do capítulo breve.

                          - -

                          O nível máximo de sub-capítulos é dois.

                          - -

                          Se encontrar problemas com o editor HTML interno, tente mudar para outro navegador (como, por exemplo, Mozilla Firefox) ou desabilite de vez o editor em suas preferências.

                          diff --git a/lang/pt_br/help/book/faq.html b/lang/pt_br/help/book/faq.html deleted file mode 100644 index 0a8250d4688..00000000000 --- a/lang/pt_br/help/book/faq.html +++ /dev/null @@ -1,52 +0,0 @@ -

                          - Perguntas sobre "Livro" -

                          -
                          -
                          - Porque só dois níveis? -
                          -
                          - Dois níveis são em geral suficiente para todos os livros. Três níveis - levariam a documentos pobremente estruturados. O módulo Livro foi - desenhado para a criação de materiais de estudo com várias páginas - curtos. Normalmente seria melhor usar o formato PDF para documentos - maiores. A forma mais fácil de criar PDFs é usar as impressoras virtuais - (veja - PDFCreator, - - PDFFactory, - Adobe Acrobat, - etc.). -
                          -
                          -
                          -
                          - Os alunos podem editar livros? -
                          -
                          - Só professores podem criar e editar livros. Não há previsão de implementar - edição de livros por estudantes, mas alguém poderia criar algo similar - para estudantes (portfólios?). O principal motivo é para manter o módulo - Livro tão simples quanto possível. -
                          -
                          -
                          - Como faço uma busca nos livros? -
                          -
                          - Atualmente só há uma forma, use o mecanismo de busca de seu navegador - na página que é mostrada. A busca global só é possível atualmente nos - fóruns do Moodle. Seria ótimo ter uma busca global em todos os recursos, - incluindo os livros. Algum voluntário? -
                          -
                          -
                          - Meus títulos não cabem numa linha. -
                          -
                          - Veja uma alternativa menor para seus títulos, ou peça para o administrador - do sistema mudar a largura máxima do sumário. Ela é definida globalmente - para todos os livros no módulo de configuração. -
                          -
                          -
                          diff --git a/lang/pt_br/help/book/import.html b/lang/pt_br/help/book/import.html deleted file mode 100644 index 5f95e9348e7..00000000000 --- a/lang/pt_br/help/book/import.html +++ /dev/null @@ -1,6 +0,0 @@ -

                          Importação

                          - -

                          Você pode importar um arquivo HTML ou todos os arquivos HTML num diretório.

                          - -

                          As referências relativas (links) são convertidos para referências absolutas de capítulos. Imagens, flash e Java também são - re-referenciados.

                          diff --git a/lang/pt_br/help/book/mods.html b/lang/pt_br/help/book/mods.html deleted file mode 100644 index c256fc8ce2e..00000000000 --- a/lang/pt_br/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Livros

                          -
                            -

                            Livro é simplesmente um material de estudo com várias páginas

                            -
                          diff --git a/lang/pt_br/help/book/numberingtype.html b/lang/pt_br/help/book/numberingtype.html deleted file mode 100644 index a12ceaca2f8..00000000000 --- a/lang/pt_br/help/book/numberingtype.html +++ /dev/null @@ -1,15 +0,0 @@ -

                          Numeração de capítulos

                          - -

                          Há várias maneiras pré-definidas de numerar capítulos:

                          - -

                          Nada - títulos de capítulos e sub-capítulos não são formatados. Use -se quiser definir um estilo especial de numeração. Por exemplo, letras: no -título do capítulo escreva "A Primeiro capítulo", "A.1 Algum sub-capítulo",... -

                          - -

                          Números - capítulos e sub-capítulos são numerados (1, 1.1, 1.2, 2, -...)

                          - -

                          Bolinhas - sub-capítulos são indentados, tendo uma bolinha na frente.

                          - -

                          Indentado - sub-capítulos são indentados.

                          diff --git a/lang/pt_br/help/book/summary.html b/lang/pt_br/help/book/summary.html deleted file mode 100644 index a193ed5df6a..00000000000 --- a/lang/pt_br/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Sumário de Leitura

                          - -

                          Este sumário é uma descrição muito breve do livro.

                          - -

                          Não caia na tentação de escrever demasiado aqui!

                          diff --git a/lang/sk/book.php b/lang/sk/book.php deleted file mode 100644 index ad602ab113d..00000000000 --- a/lang/sk/book.php +++ /dev/null @@ -1,39 +0,0 @@ -Kapitoly budú striedené abecedne podľa názvov súborov.'; -$string['importing'] = 'Importujej'; -$string['importingchapters'] = 'Importovanie kapitol'; -$string['maindirectory'] = 'Hlavná zložka'; -$string['modulename'] = 'Kniha'; -$string['modulenameplural'] = 'Knihy'; -$string['navnext'] = 'Následujúci'; -$string['navprev'] = 'Predchádzajúci'; -$string['navexit'] = 'Späť na prehľad'; -$string['numbering'] = 'Číslovanie kapitol'; -$string['numbering0'] = 'Žiadne'; -$string['numbering1'] = 'Čísla'; -$string['numbering2'] = 'Odrážky'; -$string['numbering3'] = 'Odsadené'; -$string['pluginname'] = 'Kniha'; -$string['printbook'] = 'Vytlačiť celú knihu'; -$string['printchapter'] = 'Vytlačiť jednu kapitolu'; -$string['printdate'] = 'Dátum'; -$string['printedby'] = 'Vytlačil(a)'; -$string['relinking'] = 'Relinkujem'; -$string['subchapter'] = 'Podkapitola'; -$string['toc'] = 'Obsah'; -$string['top'] = 'začiatok'; diff --git a/lang/sk/help/book/customtitles.html b/lang/sk/help/book/customtitles.html deleted file mode 100644 index 6fb24c43556..00000000000 --- a/lang/sk/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Užívateľské nadpisy

                          - -

                          Nadpisy sú zobrazené iba v obsahu knihy.

                          diff --git a/lang/sk/help/book/edit.html b/lang/sk/help/book/edit.html deleted file mode 100644 index 3305aeaeda3..00000000000 --- a/lang/sk/help/book/edit.html +++ /dev/null @@ -1,8 +0,0 @@ -

                          Úprava kapitol

                          - -

                          Snažte sa písať iba krátke kapitoly.

                          - -

                          Knika môže mať iba dve úrovne nadpisov.

                          - -

                          ak máte problémy s HTML editorom, môžete si skúsiť nainštalovať iný prohliadač -(napríklad Mozilla Firefox).

                          \ No newline at end of file diff --git a/lang/sk/help/book/faq.html b/lang/sk/help/book/faq.html deleted file mode 100644 index e1a9dda165b..00000000000 --- a/lang/sk/help/book/faq.html +++ /dev/null @@ -1,41 +0,0 @@ -

                          - Často kladené otázky -

                          -
                          -
                          - Prečo iba dve úrovne? -
                          -
                          - Dve úrovne nadpisu stačia, vždy se snažte písať krátko a zrozumiteľne. - Ak si myslíte, že potrebujete viac úrovní, rozdeľte text do niekoľkých kníh. - Pre dlhšie texty je väčšinou vhodnejší PDF formát. PDF súbory môžete - vytvoriť pomocou nasledujúcich programov: - PDFCreator, - - PDFFactory, - Adobe Acrobat. -
                          -
                          -
                          -
                          - Môžu študenti upravovať knihy? -
                          -
                          - Knihy môžu vytvárať a upravovať iba učitelia. -
                          -
                          -
                          - Môžem vyhľadávať v knihách? -
                          -
                          - Použite vyhľadávanie vo vašom prehliadači. -
                          -
                          -
                          - Nadpisy sa mi nevojdu na jeden riadok. -
                          -
                          - Alebo skráťte nadpis, alebo požiadajte vášho správce, aby zmenil šírku obsahu. -
                          -
                          -
                          diff --git a/lang/sk/help/book/import.html b/lang/sk/help/book/import.html deleted file mode 100644 index 7440b308cb0..00000000000 --- a/lang/sk/help/book/import.html +++ /dev/null @@ -1,6 +0,0 @@ -

                          Import

                          - -

                          Môžete importovať jeden HTML súbor alebo všetky súbory v zložke.

                          - -

                          Relatívne odkazy sú prevedené na odkazy na kapitoly. Odkazy na -obrázky, flash a Javu sú tiež upravené.

                          diff --git a/lang/sk/help/book/mods.html b/lang/sk/help/book/mods.html deleted file mode 100644 index 5a1c46e41e9..00000000000 --- a/lang/sk/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Knihy

                          -
                            -

                            Kniha je jednoduchý viacstránkový študijný materiál.

                            -
                          diff --git a/lang/sk/help/book/numberingtype.html b/lang/sk/help/book/numberingtype.html deleted file mode 100644 index 5639f4a099a..00000000000 --- a/lang/sk/help/book/numberingtype.html +++ /dev/null @@ -1,14 +0,0 @@ -

                          Číslovanie kapitol

                          - -

                          Existuje niekoľko preddefinovaných typov číslovania: - -

                          Žiadne - kapitoly a podkapitoly nie sú formátované, používajte v prípade, -ak chcete zadať vaše vlastné číslovánie. Napríklad: do poľa nadpis kapitoly zadajte -"A Úvod", "A.1 Nejaké Rozprávanie", ...

                          - -

                          Čísla - kapitoly a podkapitoly sú číslované (1, 1.1, 1.2, 2, ...)

                          - -

                          Odrážky - podkapitoly sú odsadené a zvýraznené odrážkami.

                          - -

                          Odsadené - podkapitoly sú odsadené.

                          - diff --git a/lang/sk/help/book/summary.html b/lang/sk/help/book/summary.html deleted file mode 100644 index 2f065470f25..00000000000 --- a/lang/sk/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Súhrn

                          - -

                          Stručný obsah knihy.

                          - -

                          Snažte sa o skutočne krátky a výstižný opis.

                          \ No newline at end of file diff --git a/lang/sl/book.php b/lang/sl/book.php deleted file mode 100644 index 94f6dc33338..00000000000 --- a/lang/sl/book.php +++ /dev/null @@ -1,48 +0,0 @@ -Poglavja bodo razvrščena po abecedi glede na imena datotek.
                          Datoteke imenovane \'sub_*.*\' bodo vedno uvožene kod podpoglavja.'; -$string['maindirectory'] = 'Glavna mapa'; -$string['fileordir'] = 'Datoteka ali mapa'; -$string['book:edit'] = 'Uredi poglavja knjige'; -$string['book:exportimscp'] = 'Izvozi knjigo kot IMS vsebinski paket'; -$string['book:import'] = 'Uvozi poglavja'; -$string['book:print'] = 'Natisni knjigo'; -$string['book:read'] = 'Beri knjigo'; -$string['book:viewhiddenchapters'] = 'Poglej skrita poglavja'; -$string['generateimscp'] = 'Generiraj IMS vsebinski paket'; - diff --git a/lang/sl/help/book/customtitles.html b/lang/sl/help/book/customtitles.html deleted file mode 100644 index fe18c5c0c2c..00000000000 --- a/lang/sl/help/book/customtitles.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Ločeni naslovi

                          - -

                          Naslov poglavja se običajno izpiše v kazalu vsebine in pri ogledu poglavja. Če odkljukate to možnost se bo naslov poglavja izpisal le v kazalu. Ta možnost je koristna, če hočete ob ogledu poglavja prikazati drugačen naslov oz. ga sploh nočete prikazati.

                          diff --git a/lang/sl/help/book/edit.html b/lang/sl/help/book/edit.html deleted file mode 100644 index 4704cb1f3b5..00000000000 --- a/lang/sl/help/book/edit.html +++ /dev/null @@ -1,7 +0,0 @@ -

                          Urejanje poglavja

                          - -

                          Skušajte uporabljati kratke naslove.

                          - -

                          Mogoča sta samo dva (2) nivoja poglavij.

                          - -

                          Če med uporabo html urejevalnika tekstov (WYSIWYG) naletite na težave, skušajte uporabiti drug brskalnik (npr. Mozilla Firefox) ali izključite urejevalnik v vašem profilu.

                          \ No newline at end of file diff --git a/lang/sl/help/book/faq.html b/lang/sl/help/book/faq.html deleted file mode 100644 index 93bca047156..00000000000 --- a/lang/sl/help/book/faq.html +++ /dev/null @@ -1,39 +0,0 @@ -

                          - Pogosta vprašanja o modulu Knjiga -

                          -
                          -
                          - Zakaj samo dva nivoja? -
                          -
                          - Dva nivoja sta običajno dovolj za vse knjige, trije nivoji pa bi že vodili k slabo strukturiranim dokumentom. Modul Knjiga je bil zasnovan za izdelavo kratkih večstranskih študijskih gradiv. Za daljše dokumente pa je ponavadi bolje uporabiti PDF format. Najlažji način za izdelavo PDF formatov je uporaba virtualnega tiskalnika (glej - PDFCreator, - - PDFFactory, - Adobe Acrobat, - idr.). -
                          -
                          -
                          -
                          - Ali lahko študentje urejajo knjigo? -
                          -
                          - Knjigo lahko ustvarijo in urejajo samo učitelji. Zaenkrat ni nobenih načrtov za izdelavo tovrstne funkcije, vendar bo lahko izdelal nekaj podobnega tudi za študente (Portfolio?). Glavni razlog za to je, da bi bil modul Knjiga čim bolj enostaven. -
                          -
                          -
                          - Kako naj iščem po knjigah? -
                          -
                          - Trenutno je mogoč samo en način in sicer uporaba brskalnikove funkcije "najdi" na strani knjige za tiskanje. Globalno iskanje je trenutno možno le v Moodle forumih. Lepo bi bilo, če bi ta možnost obstajala za vse aktivnosti, vključno s Knjigo. Kak prostovoljec? -
                          -
                          -
                          - Moji naslovi se ne prilegajo v eno vrstico. -
                          -
                          - Spremenite naslov ali pa prosite administratorja, da spremeni širino kazala. Ta nastavitev je definirana globalno in velja za vse knjige. -
                          -
                          -
                          diff --git a/lang/sl/help/book/import.html b/lang/sl/help/book/import.html deleted file mode 100644 index 434b5e9df59..00000000000 --- a/lang/sl/help/book/import.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Uvoz

                          - -

                          Uvozite lahko eno HTML datoteko ali vse HTML datoteke v mapi.

                          - -

                          Relativne povezave na datoteke so spremenjene v absolutne povezave na poglavja. Spremenjene so tudi povezave na grafike, flash animacije in Java skripte.

                          diff --git a/lang/sl/help/book/mods.html b/lang/sl/help/book/mods.html deleted file mode 100644 index aad38c64c16..00000000000 --- a/lang/sl/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Knjiga

                          -
                            -

                            Knjiga je enostavno večstransko študijsko gradivo

                            -
                          diff --git a/lang/sl/help/book/numberingtype.html b/lang/sl/help/book/numberingtype.html deleted file mode 100644 index 950efb3007e..00000000000 --- a/lang/sl/help/book/numberingtype.html +++ /dev/null @@ -1,12 +0,0 @@ -

                          Označevanje poglavij

                          - -

                          Na voljo je več prednastavljenih načinov označevanja: - -

                          Brez - naslovi poglavij in podpoglavij niso oblikovani. To možnost izberite, če želite uporabiti poseben način označevanja. Na primer črke: v naslovu poglavja zapišete "A Prvo poglavje!, "A.1 Neko podpoglavje", ...

                          - -

                          Številke - naslovi poglavij in podpoglavij bodo oštevilčeni (1, 1.1, 1.2, 2, -...)

                          - -

                          Vrstične oznake - naslovi podpoglavij so zamaknjeni in označeni z vrstično oznako (pika, kvadratek,...).

                          - -

                          Zamik - naslovi podpoglavij so zamaknjeni.

                          diff --git a/lang/sl/help/book/summary.html b/lang/sl/help/book/summary.html deleted file mode 100644 index fd5ef10ce8c..00000000000 --- a/lang/sl/help/book/summary.html +++ /dev/null @@ -1,5 +0,0 @@ -

                          Povzetek knjige

                          - -

                          Povzetek je zelo kratek opis knjige.

                          - -

                          Naj vas ne premami, da bi napisali preveč!p> \ No newline at end of file diff --git a/lang/sv/book.php b/lang/sv/book.php deleted file mode 100644 index 92b9856c0fd..00000000000 --- a/lang/sv/book.php +++ /dev/null @@ -1,39 +0,0 @@ -Kapitel sorteras alfabetiskt utifrån filnamn.'; -$string['importing'] = 'Importerar'; -$string['importingchapters'] = 'Importerar kapitel till bok'; -$string['maindirectory'] = 'Huvudkatalog'; -$string['modulename'] = 'Bok'; -$string['modulenameplural'] = 'Böcker'; -$string['navexit'] = 'Exit Book'; -$string['navnext'] = 'Nästa'; -$string['navprev'] = 'Föregående'; -$string['numbering'] = 'Numrering av kapitel'; -$string['numbering0'] = 'Ingen'; -$string['numbering1'] = 'Tal'; -$string['numbering2'] = 'Bullets'; -$string['numbering3'] = 'Indragen'; -$string['pluginname'] = 'Bok'; -$string['printbook'] = 'Skriv ut hela boken'; -$string['printchapter'] = 'Skriv ut det här kapitlet'; -$string['printdate'] = 'Datum'; -$string['printedby'] = 'Utskrivet av'; -$string['relinking'] = 'Länkar tillbaka'; -$string['subchapter'] = 'Underavdelning'; -$string['toc'] = 'Innehållsförteckning'; -$string['top'] = 'Upp'; diff --git a/lang/sv/help/book/customtitles.html b/lang/sv/help/book/customtitles.html deleted file mode 100644 index 9ebe5dfde98..00000000000 --- a/lang/sv/help/book/customtitles.html +++ /dev/null @@ -1,2 +0,0 @@ -

                          Standardiserade titlar

                          -

                          Titlar på kapitel visas automatiskt bara i innehållsförteckningen.

                          \ No newline at end of file diff --git a/lang/sv/help/book/edit.html b/lang/sv/help/book/edit.html deleted file mode 100644 index 2b626ac5085..00000000000 --- a/lang/sv/help/book/edit.html +++ /dev/null @@ -1,6 +0,0 @@ -

                          Att redigera ett kapitel

                          -

                          Försök att använda korta titlar på kapitel.

                          -

                          Den maximala nivån på underkapitel är två.

                          -

                          Om Du stöter på problem när Du använder WYSIWYG HTML-redigeraren, -så kan Du försöka att byta till en annan webbläsare -(som Mozilla Firefox) eller stänga av redigeraren helt och hållet i Din profil.

                          \ No newline at end of file diff --git a/lang/sv/help/book/faq.html b/lang/sv/help/book/faq.html deleted file mode 100644 index fe7fc6cf9d2..00000000000 --- a/lang/sv/help/book/faq.html +++ /dev/null @@ -1,42 +0,0 @@ -

                          Vanligt förekommande frågor om Modulen bok

                          -
                          -
                          - Varför bara två nivåer? -
                          -
                          - Två nivåer räcker vanligtvis för alla böcker, tre nivåer skulle leda till - illa strukturerade dokument. Modulen bok är utformad för att skapa korta - studiematerial som består av ett antal sidor. För längre dokument är det normalt - sett bättre med Pdf-format. Det enklaste sättet att skapa Pdf-filer är - virtuella skrivare (se - PDFCreator, - - PDFFactory, - Adobe Acrobat, - etc.). -

                          -
                          -
                          Kan studenter/elever/deltagare/lärande redigera böcker?
                          -
                          Endast lärare kan skapa och redigera böcker. - Det finns inga planer på att utvidga detta, men någon kan kanske - skapa någonting liknande för studenter/elever/deltagare/lärande - (Portfolio?). Den viktigaste orsaken är att den här modulen ska vara så enkel som möjligt.

                          -
                          -
                          - Hur söker jag i böckerna? -
                          -
                          - F.n. finns det bara ett sätt, nämligen att använda webbläsarens - sökfunktion i "Skriv ut". Global sökning går bara att göra i Moodles forum. - Det vore trevligt med global sökning för alla resurser inklusive böcker, - några frivilliga?

                          -
                          -
                          - Min titlar passar inte in på raden. -
                          -
                          - Formulera antingen om dina titlar eller be din systemadministratör - att öka vidden på innehållsförteckningen. Den är globalt definierad - på sidan för konfiguration av modulen. -
                          -
                          \ No newline at end of file diff --git a/lang/sv/help/book/import.html b/lang/sv/help/book/import.html deleted file mode 100644 index afb75010eac..00000000000 --- a/lang/sv/help/book/import.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Att importera

                          -

                          Du kan importera en enskild HTML-fil eller varje HTML-fil i en katalog.

                          -

                          Relativa länkar konverteras till absoluta länkar för kapitel. Bilder, Flash och Java länkas också om.

                          \ No newline at end of file diff --git a/lang/sv/help/book/mods.html b/lang/sv/help/book/mods.html deleted file mode 100644 index d3246f505be..00000000000 --- a/lang/sv/help/book/mods.html +++ /dev/null @@ -1,4 +0,0 @@ -

                           Böcker

                          -
                            -
                          • Bok är ett enkelt studiematerial bestående av ett antal sidor
                          • -
                          \ No newline at end of file diff --git a/lang/sv/help/book/numberingtype.html b/lang/sv/help/book/numberingtype.html deleted file mode 100644 index 5b4c5ff9675..00000000000 --- a/lang/sv/help/book/numberingtype.html +++ /dev/null @@ -1,9 +0,0 @@ -

                          Att numrera kapitel

                          -

                          Det finns ett antal fördefinierade sätt att numrera:

                          -

                          Inget - kapitel och undertitlar formatteras inte alls, använd det om Du vill -definiera Dina egna sätt att numrera. T.ex. bokstäver: I titlar på kapitel av typen -"Första kapitlet", "A.1 några underavdelningar",...

                          -

                          Siffror - kapitel och undertitlar numreras (1, 1.1, 1.2, 2, -...)

                          -

                          Punkter - undertitlar har indrag och visas med punkter.

                          -

                          Indrag - undertitlar har indrag.

                          \ No newline at end of file diff --git a/lang/sv/help/book/summary.html b/lang/sv/help/book/summary.html deleted file mode 100644 index ea4eec17084..00000000000 --- a/lang/sv/help/book/summary.html +++ /dev/null @@ -1,3 +0,0 @@ -

                          Sammanfattning av läsningen

                          -

                          Sammanfattningen är en mycket kort beskrivning av boken.

                          -

                          Låt Dig inte frestas att skriva för mycket här!

                          \ No newline at end of file From 33b8e0f06dcfcfecd271e753182cd8517393b1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mudr=C3=A1k?= Date: Sun, 24 Apr 2011 07:31:20 +0800 Subject: [PATCH 130/455] Fixed missing 'throw' keyword --- db/upgrade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/upgrade.php b/db/upgrade.php index cb707842310..8b0c245c79d 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -31,7 +31,7 @@ function xmldb_book_upgrade($oldversion) { $dbman = $DB->get_manager(); if ($oldversion < 2004081100) { - new upgrade_exception('mod_book', $oldversion, 'Can not upgrade such an old book module, sorry, you should have upgraded it long time ago in 1.9 already.'); + throw new upgrade_exception('mod_book', $oldversion, 'Can not upgrade such an old book module, sorry, you should have upgraded it long time ago in 1.9 already.'); } if ($oldversion < 2007052001) { From 49ed0a269793dac1cb17bf792013d8ea0c52b7e2 Mon Sep 17 00:00:00 2001 From: Myles Carrick Date: Thu, 28 Apr 2011 07:02:03 +0800 Subject: [PATCH 131/455] MDL-26708 fix typo - custom titles --- lang/en/book.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/en/book.php b/lang/en/book.php index 81cb79f5090..d543b6323f3 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -35,7 +35,7 @@ Either rephrase your titles or ask your site admin to change TOC width. It is defined globally for all books in module configuration page.'; -$string['customtitles'] = 'Custom citles'; +$string['customtitles'] = 'Custom titles'; $string['customtitles_help'] = 'Chapter titles are displayed automatically only in TOC.'; $string['editingchapter'] = 'Editing chapter'; From 4b76ec61c07401bfa784cf1e62c622cad6cb1ce6 Mon Sep 17 00:00:00 2001 From: Myles Carrick Date: Thu, 5 May 2011 14:40:21 +1000 Subject: [PATCH 132/455] backup - fixed typo to correctly backup contentformat setting --- backup/moodle2/backup_book_stepslib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/moodle2/backup_book_stepslib.php b/backup/moodle2/backup_book_stepslib.php index 04118c0c448..e10e3426e62 100644 --- a/backup/moodle2/backup_book_stepslib.php +++ b/backup/moodle2/backup_book_stepslib.php @@ -35,7 +35,7 @@ class backup_book_activity_structure_step extends backup_activity_structure_step // Define each element separated $book = new backup_nested_element('book', array('id'), array('name', 'intro', 'introformat', 'numbering', 'customtitles', 'timecreated', 'timemodified')); $chapters = new backup_nested_element('chapters'); - $chapter = new backup_nested_element('chapter', array('id'), array('pagenum', 'subchapter', 'title', 'content', 'contentormat', 'hidden', 'timemcreated', 'timemodified', 'importsrc',)); + $chapter = new backup_nested_element('chapter', array('id'), array('pagenum', 'subchapter', 'title', 'content', 'contentformat', 'hidden', 'timemcreated', 'timemodified', 'importsrc',)); $book->add_child($chapters); $chapters->add_child($chapter); From 337b43a7f86bbf835f324ee6ac00a191ffa536ab Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 27 Jun 2011 11:28:17 +0200 Subject: [PATCH 133/455] CONTRIB-2970 header printed too early Credit goes to Sam Chaffee. --- view.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/view.php b/view.php index af958ceb5c3..9a0d904bd7b 100644 --- a/view.php +++ b/view.php @@ -125,8 +125,6 @@ $PAGE->set_heading(format_string($course->fullname)); book_add_fake_block($chapters, $chapter, $book, $cm, $edit); -echo $OUTPUT->header(); - /// prepare chapter navigation icons $previd = null; $nextid = null; @@ -169,6 +167,8 @@ if ($nextid) { // Book display HTML code // ===================================================== +echo $OUTPUT->header(); + // upper nav echo ''; From 8c5ff185df98a1d50f6f643a4cb6f1f61509f802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B5nis=20Tartes?= Date: Mon, 11 Jul 2011 17:52:32 +0200 Subject: [PATCH 134/455] CONTRIB-3023 basic 1.x restore support for 2.x --- backup/moodle1/lib.php | 140 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100755 backup/moodle1/lib.php diff --git a/backup/moodle1/lib.php b/backup/moodle1/lib.php new file mode 100755 index 00000000000..5126c7fbf85 --- /dev/null +++ b/backup/moodle1/lib.php @@ -0,0 +1,140 @@ +. + +/** + * Provides support for the conversion of moodle1 backup to the moodle2 format + * + * @package mod + * @subpackage book + * @copyright 2011 Tõnis Tartes + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Book conversion handler + */ +class moodle1_mod_book_handler extends moodle1_mod_handler { + + /** @var array in-memory cache for the course module information for the current book */ + protected $currentcminfo = null; + + /** + * Declare the paths in moodle.xml we are able to convert + * + * The method returns list of {@link convert_path} instances. For each path returned, + * at least one of on_xxx_start(), process_xxx() and on_xxx_end() methods must be + * defined. The method process_xxx() is not executed if the associated path element is + * empty (i.e. it contains none elements or sub-paths only). + * + * Note that the path /MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK does not + * actually exist in the file. The last element with the module name was + * appended by the moodle1_converter class. + * + * @return array of {@link convert_path} instances + */ + public function get_paths() { + return array( + new convert_path('book', '/MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK', + array( + 'renamefields' => array( + 'summary' => 'intro', + ), + 'newfields' => array( + 'introformat' => 0, + ), + 'dropfields' => array( + 'disableprinting' + ), + ) + ), + new convert_path('book_chapters', '/MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK/CHAPTERS/CHAPTER', + array( + 'newfields' => array( + 'contentformat' => 1, + ), + ) + ), + ); + } + + /** + * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK + * data available + */ + public function process_book($data) { + + // get the course module id and context id + $instanceid = $data['id']; + $this->currentcminfo = $this->get_cminfo($instanceid); + $moduleid = $this->currentcminfo['id']; + $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $moduleid); + + // we now have all information needed to start writing into the file + $this->open_xml_writer("activities/book_{$moduleid}/book.xml"); + $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $moduleid, + 'modulename' => 'book', 'contextid' => $contextid)); + $this->xmlwriter->begin_tag('book', array('id' => $instanceid)); + + unset($data['id']); // we already write it as attribute, do not repeat it as child element + foreach ($data as $field => $value) { + $this->xmlwriter->full_tag($field, $value); + } + + } + + /** + * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK/CHAPTERS/CHAPTER + * data available + */ + public function process_book_chapters($data) { + + $this->write_xml('chapter', $data, array('/chapter/id')); + + } + + /** + * This is executed when the parser reaches the opening element + */ + public function on_book_chapters_start() { + + $this->xmlwriter->begin_tag('chapters'); + + } + + /** + * This is executed when the parser reaches the closing element + */ + public function on_book_chapters_end() { + + $this->xmlwriter->end_tag('chapters'); + + } + + /** + * This is executed when we reach the closing tag of our 'book' path + */ + public function on_book_end() { + + // close book.xml + $this->xmlwriter->end_tag('book'); + $this->xmlwriter->end_tag('activity'); + $this->close_xml_writer(); + + } + +} From 252256fe3f6603500213553053eab382c40f2597 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 11 Jul 2011 18:02:43 +0200 Subject: [PATCH 135/455] use the same intro upgrade logic as the rest of modules --- db/upgrade.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/db/upgrade.php b/db/upgrade.php index 8b0c245c79d..33a516a60c1 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -84,7 +84,18 @@ function xmldb_book_upgrade($oldversion) { $dbman->add_field($table, $field); } - $DB->set_field('book', 'introformat', FORMAT_HTML, array()); + // conditionally migrate to html format in intro + if ($CFG->texteditors !== 'textarea') { + $rs = $DB->get_recordset('book', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat'); + foreach ($rs as $b) { + $b->intro = text_to_html($b->intro, false, false, true); + $b->introformat = FORMAT_HTML; + $DB->update_record('book', $b); + upgrade_set_timeout(); + } + unset($b); + $rs->close(); + } // book savepoint reached upgrade_mod_savepoint(true, 2010120803, 'book'); From f6aa1830f1c2993bf25d0e3fb00694f13f32d6ca Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Mon, 11 Jul 2011 18:15:29 +0200 Subject: [PATCH 136/455] copying more restore logic from glossary --- backup/moodle1/lib.php | 67 +++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/backup/moodle1/lib.php b/backup/moodle1/lib.php index 5126c7fbf85..20abcb3df10 100755 --- a/backup/moodle1/lib.php +++ b/backup/moodle1/lib.php @@ -30,8 +30,11 @@ defined('MOODLE_INTERNAL') || die(); */ class moodle1_mod_book_handler extends moodle1_mod_handler { - /** @var array in-memory cache for the course module information for the current book */ - protected $currentcminfo = null; + /** @var moodle1_file_manager */ + protected $fileman = null; + + /** @var int cmid */ + protected $moduleid = null; /** * Declare the paths in moodle.xml we are able to convert @@ -55,7 +58,7 @@ class moodle1_mod_book_handler extends moodle1_mod_handler { 'summary' => 'intro', ), 'newfields' => array( - 'introformat' => 0, + 'introformat' => FORMAT_MOODLE, ), 'dropfields' => array( 'disableprinting' @@ -65,7 +68,7 @@ class moodle1_mod_book_handler extends moodle1_mod_handler { new convert_path('book_chapters', '/MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK/CHAPTERS/CHAPTER', array( 'newfields' => array( - 'contentformat' => 1, + 'contentformat' => FORMAT_HTML, ), ) ), @@ -77,24 +80,39 @@ class moodle1_mod_book_handler extends moodle1_mod_handler { * data available */ public function process_book($data) { + global $CFG; // get the course module id and context id - $instanceid = $data['id']; - $this->currentcminfo = $this->get_cminfo($instanceid); - $moduleid = $this->currentcminfo['id']; - $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $moduleid); + $instanceid = $data['id']; + $cminfo = $this->get_cminfo($instanceid); + $this->moduleid = $cminfo['id']; + $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $this->moduleid); - // we now have all information needed to start writing into the file - $this->open_xml_writer("activities/book_{$moduleid}/book.xml"); - $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $moduleid, + // replay the upgrade step 2009042006 + if ($CFG->texteditors !== 'textarea') { + $data['intro'] = text_to_html($data['intro'], false, false, true); + $data['introformat'] = FORMAT_HTML; + } + + // get a fresh new file manager for this instance + $this->fileman = $this->converter->get_file_manager($contextid, 'mod_book'); + + // convert course files embedded into the intro + $this->fileman->filearea = 'intro'; + $this->fileman->itemid = 0; + $data['intro'] = moodle1_converter::migrate_referenced_files($data['intro'], $this->fileman); + + // start writing book.xml + $this->open_xml_writer("activities/book_{$this->moduleid}/book.xml"); + $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $this->moduleid, 'modulename' => 'book', 'contextid' => $contextid)); $this->xmlwriter->begin_tag('book', array('id' => $instanceid)); - unset($data['id']); // we already write it as attribute, do not repeat it as child element foreach ($data as $field => $value) { - $this->xmlwriter->full_tag($field, $value); + if ($field <> 'id') { + $this->xmlwriter->full_tag($field, $value); + } } - } /** @@ -102,39 +120,42 @@ class moodle1_mod_book_handler extends moodle1_mod_handler { * data available */ public function process_book_chapters($data) { - $this->write_xml('chapter', $data, array('/chapter/id')); - + //TODO: convert chapter files } /** * This is executed when the parser reaches the opening element */ public function on_book_chapters_start() { - $this->xmlwriter->begin_tag('chapters'); - } /** * This is executed when the parser reaches the closing element */ public function on_book_chapters_end() { - $this->xmlwriter->end_tag('chapters'); - } /** * This is executed when we reach the closing tag of our 'book' path */ public function on_book_end() { - - // close book.xml + // finalize book.xml $this->xmlwriter->end_tag('book'); $this->xmlwriter->end_tag('activity'); $this->close_xml_writer(); + // write inforef.xml + $this->open_xml_writer("activities/book_{$this->moduleid}/inforef.xml"); + $this->xmlwriter->begin_tag('inforef'); + $this->xmlwriter->begin_tag('fileref'); + foreach ($this->fileman->get_fileids() as $fileid) { + $this->write_xml('file', array('id' => $fileid)); + } + $this->xmlwriter->end_tag('fileref'); + $this->xmlwriter->end_tag('inforef'); + $this->close_xml_writer(); } - } From 61e36b964985d4baa2e86b383d1d4c1ccb257819 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 25 Sep 2011 20:36:27 +0200 Subject: [PATCH 137/455] fix maturity info --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index 1752dc5b92b..7d14f4012cf 100644 --- a/version.php +++ b/version.php @@ -30,5 +30,5 @@ $module->requires = 2010120700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$maturity = 150; //MATURITY_RC -$release = "2.0rc (20110320)"; // User-friendly version number +$module->maturity = MATURITY_RC; +$module->release = "2.0rc (20110320)"; // User-friendly version number From 389392486d6ec808e0c9523a23c6e9e4a4d5d7b6 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 25 Sep 2011 20:38:59 +0200 Subject: [PATCH 138/455] remove deprecated enum info --- db/install.xml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/db/install.xml b/db/install.xml index d01db999547..7aef3c27574 100644 --- a/db/install.xml +++ b/db/install.xml @@ -6,15 +6,15 @@ - - - + + + - - - - + + + + @@ -22,17 +22,17 @@
                          - - - - - - + + + + + + - - - - + + + + From b2617f0b993175ec7d7560faceca416311031205 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 10:00:22 +0200 Subject: [PATCH 139/455] future versions of mod_book are going to require at least Moodle 2.1.0 --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index 7d14f4012cf..99010f9b4be 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die; $module->version = 2011032000; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2010120700; // Requires this Moodle version +$module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From 3c6239ee581fdd32b8c2d0dedc7e8b79da235c17 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 10:08:30 +0200 Subject: [PATCH 140/455] use plugin_supports for module resource type information closes #10 --- lib.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib.php b/lib.php index a1fbd05ce94..a1cd4cca9d9 100644 --- a/lib.php +++ b/lib.php @@ -104,15 +104,6 @@ function book_delete_instance($id) { return true; } -function book_get_types() { - $type = new stdClass(); - $type->modclass = MOD_CLASS_RESOURCE; - $type->type = 'book'; - $type->typestr = get_string('modulename', 'mod_book'); - - return array($type); -} - /** * Return use outline * @param object $course @@ -218,11 +209,14 @@ function book_get_post_actions() { */ function book_supports($feature) { switch($feature) { + case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE; case FEATURE_GROUPS: return false; case FEATURE_GROUPINGS: return false; case FEATURE_GROUPMEMBERSONLY: return true; case FEATURE_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return true; + case FEATURE_GRADE_HAS_GRADE: return false; + case FEATURE_GRADE_OUTCOMES: return false; case FEATURE_BACKUP_MOODLE2: return true; default: return null; From 7927cab1b1f69e3a338347511ed4d52573fab28c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 10:47:16 +0200 Subject: [PATCH 141/455] convert printing support to new booktool plugin fixed #6 AMOS BEGIN MOV [pluginname,mod_book],[pluginname,booktool_print] MOV [printbook,mod_book],[printbook,booktool_print] MOV [printchapter,mod_book],[printchapter,booktool_print] MOV [printdate,mod_book],[printdate,booktool_print] MOV [printedby,mod_book],[printedby,booktool_print] MOV [book:print,mod_book],[print:print,booktool_print] AMOS END --- db/access.php | 13 ---- db/log.php | 1 - db/subplugins.php | 30 +++++++++ lang/en/book.php | 30 +++++++-- lib.php | 19 +++--- tool/print/db/access.php | 39 ++++++++++++ print.php => tool/print/index.php | 16 ++--- tool/print/lang/en/booktool_print.php | 33 ++++++++++ tool/print/lib.php | 60 ++++++++++++++++++ pix/print_book.gif => tool/print/pix/book.gif | Bin .../print/pix/chapter.gif | Bin print.css => tool/print/print.css | 0 tool/print/version.php | 29 +++++++++ version.php | 2 +- 14 files changed, 233 insertions(+), 39 deletions(-) create mode 100644 db/subplugins.php create mode 100644 tool/print/db/access.php rename print.php => tool/print/index.php (92%) create mode 100644 tool/print/lang/en/booktool_print.php create mode 100644 tool/print/lib.php rename pix/print_book.gif => tool/print/pix/book.gif (100%) rename pix/print_chapter.gif => tool/print/pix/chapter.gif (100%) rename print.css => tool/print/print.css (100%) create mode 100644 tool/print/version.php diff --git a/db/access.php b/db/access.php index a72a7b6cd9d..11d26c0edea 100644 --- a/db/access.php +++ b/db/access.php @@ -68,19 +68,6 @@ $capabilities = array( ) ), - 'mod/book:print' => array( - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'guest' => CAP_ALLOW, - 'frontpage' => CAP_ALLOW, - 'student' => CAP_ALLOW, - 'teacher' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW, - ) - ), - 'mod/book:exportimscp' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE diff --git a/db/log.php b/db/log.php index a829c262912..c83481abe80 100644 --- a/db/log.php +++ b/db/log.php @@ -29,5 +29,4 @@ $logs = array( array('module'=>'book', 'action'=>'update', 'mtable'=>'book', 'field'=>'name'), array('module'=>'book', 'action'=>'view', 'mtable'=>'book', 'field'=>'name'), array('module'=>'book', 'action'=>'view all', 'mtable'=>'book', 'field'=>'name'), - array('module'=>'book', 'action'=>'print', 'mtable'=>'book', 'field'=>'name'), ); diff --git a/db/subplugins.php b/db/subplugins.php new file mode 100644 index 00000000000..71c251bb527 --- /dev/null +++ b/db/subplugins.php @@ -0,0 +1,30 @@ +. + +/** + * Book subplugin types declaration + * + * @package mod + * @subpackage book + * @copyright 2011 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$subplugins = array( + 'booktool' => 'mod/book/tool', + ); diff --git a/lang/en/book.php b/lang/en/book.php index d543b6323f3..7451ef19958 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -1,4 +1,29 @@ . + +/** + * Book module language strings + * + * @package mod + * @subpackage book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; $string['modulename'] = 'Book'; $string['modulenameplural'] = 'Books'; @@ -63,10 +88,6 @@ $string['confchapterdelete'] = 'Do you really want to delete this chapter?'; $string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?'; $string['generateimscp'] = 'Generate IMS content package'; -$string['printbook'] = 'Print book'; -$string['printchapter'] = 'Print this chapter'; -$string['printdate'] = 'Date'; -$string['printedby'] = 'Printed by'; $string['top'] = 'top'; $string['navprev'] = 'Previous'; @@ -88,7 +109,6 @@ $string['book:read'] = 'Read book'; $string['book:edit'] = 'Edit book chapters'; $string['book:viewhiddenchapters'] = 'View hidden book chapters'; $string['book:import'] = 'Import chapters'; -$string['book:print'] = 'Print book'; $string['book:exportimscp'] = 'Export book as IMS content package'; $string['errorchapter'] = 'Error reading book chapter.'; \ No newline at end of file diff --git a/lib.php b/lib.php index a1cd4cca9d9..4770cbc5d21 100644 --- a/lib.php +++ b/lib.php @@ -248,17 +248,14 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig return; } - if (has_capability('mod/book:print', $PAGE->cm->context)) { - $url1 = new moodle_url('/mod/book/print.php', array('id'=>$params['id'])); - $url2 = new moodle_url('/mod/book/print.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - if ($CFG->version > 2011020900) { - $action = new action_link($url1, get_string('printbook', 'book'), new popup_action('click', $url1)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); - $action = new action_link($url2, get_string('printchapter', 'book'), new popup_action('click', $url2)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); - } else { - $booknode->add(get_string('printbook', 'mod_book'), $url1, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'mod_book', array('class'=>'icon'))); - $booknode->add(get_string('printchapter', 'mod_book'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'mod_book', array('class'=>'icon'))); + $plugins = get_plugin_list('booktool'); + foreach($plugins as $plugin=>$dir) { + if (file_exists("$dir/lib.php")) { + require_once("$dir/lib.php"); + } + $function = 'booktool_'.$plugin.'_extend_settings_navigation'; + if (function_exists($function)) { + $function($settingsnav, $booknode); } } diff --git a/tool/print/db/access.php b/tool/print/db/access.php new file mode 100644 index 00000000000..fe57fb2229f --- /dev/null +++ b/tool/print/db/access.php @@ -0,0 +1,39 @@ +. + +/** + * Book module capability definition + * + * @package booktool + * @subpackage print + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$capabilities = array( + 'booktool/print:print' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'guest' => CAP_ALLOW, + 'frontpage' => CAP_ALLOW, + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ) + ), +); diff --git a/print.php b/tool/print/index.php similarity index 92% rename from print.php rename to tool/print/index.php index 1e5e506b249..91542ec90ab 100644 --- a/print.php +++ b/tool/print/index.php @@ -17,13 +17,13 @@ /** * Book printing * - * @package mod - * @subpackage book + * @package booktool + * @subpackage print * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); +require(dirname(__FILE__).'/../../../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID @@ -41,7 +41,7 @@ require_course_login($course, true, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:read', $context); -require_capability('mod/book:print', $context); +require_capability('booktool/print:print', $context); //check all variables if ($chapterid) { @@ -79,7 +79,7 @@ if ($chapter) { require_capability('mod/book:viewhiddenchapters', $context); } - add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); + add_to_log($course->id, 'book', 'print', 'tool/print/index.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); /// page header ?> @@ -114,7 +114,7 @@ if ($chapter) { echo ' '; } else { - add_to_log($course->id, 'book', 'print', 'print.php?id='.$cm->id, $book->id, $cm->id); + add_to_log($course->id, 'book', 'print', 'tool/print/index.php?id='.$cm->id, $book->id, $cm->id); $allchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); /// page header @@ -142,10 +142,10 @@ if ($chapter) { - + - +
                          : name, true, array('context'=>$context)) ?>
                          ::
                          ::
                          diff --git a/tool/print/lang/en/booktool_print.php b/tool/print/lang/en/booktool_print.php new file mode 100644 index 00000000000..ef87324614f --- /dev/null +++ b/tool/print/lang/en/booktool_print.php @@ -0,0 +1,33 @@ +. + +/** + * Book module language strings + * + * @package booktool + * @subpackage print + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +$string['pluginname'] = 'Book printing'; +$string['printbook'] = 'Print book'; +$string['printchapter'] = 'Print this chapter'; +$string['printdate'] = 'Date'; +$string['printedby'] = 'Printed by'; +$string['print:print'] = 'Print book'; diff --git a/tool/print/lib.php b/tool/print/lib.php new file mode 100644 index 00000000000..c519ec87607 --- /dev/null +++ b/tool/print/lib.php @@ -0,0 +1,60 @@ +. + +/** + * Print lib + * + * @package booktool + * @subpackage print + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +function booktool_print_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { + global $USER, $PAGE, $CFG, $DB, $OUTPUT; + + if ($PAGE->cm->modname !== 'book') { + return; + } + + if (empty($PAGE->cm->context)) { + $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); + } + + + $params = $PAGE->url->params(); + + if (empty($params['id']) or empty($params['chapterid'])) { + return; + } + + + if (has_capability('booktool/print:print', $PAGE->cm->context)) { + $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'])); + $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); + if ($CFG->version > 2011020900) { + $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); + $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); + } else { + $booknode->add(get_string('printbook', 'booktool_print'), $url1, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'booktool_print', array('class'=>'icon'))); + $booknode->add(get_string('printchapter', 'booktool_print'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'booktool_print', array('class'=>'icon'))); + } + } +} \ No newline at end of file diff --git a/pix/print_book.gif b/tool/print/pix/book.gif similarity index 100% rename from pix/print_book.gif rename to tool/print/pix/book.gif diff --git a/pix/print_chapter.gif b/tool/print/pix/chapter.gif similarity index 100% rename from pix/print_chapter.gif rename to tool/print/pix/chapter.gif diff --git a/print.css b/tool/print/print.css similarity index 100% rename from print.css rename to tool/print/print.css diff --git a/tool/print/version.php b/tool/print/version.php new file mode 100644 index 00000000000..3de5f9c85eb --- /dev/null +++ b/tool/print/version.php @@ -0,0 +1,29 @@ +. + +/** + * Book print plugin version info + * + * @package booktool + * @subpackage print + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +$plugin->version = 2011090800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->component = 'booktool_print'; // Full name of the plugin (used for diagnostics) diff --git a/version.php b/version.php index 99010f9b4be..cddf04a774c 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011032000; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011032001; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From 4bc75ecc3ff14f735f4a5a5ca37a09831b58f02d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 11:17:00 +0200 Subject: [PATCH 142/455] convert imscp export to new booktool plugin fixed #4 AMOS BEGIN MOV [book:exportimscp,mod_book],[exportimscp:export,booktool_exportimscp] MOV [generateimscp,mod_book],[generateimscp,booktool_exportimscp] AMOS END --- db/access.php | 5 -- lang/en/book.php | 2 - lib.php | 6 --- tool/exportimscp/db/access.php | 31 +++++++++++ .../exportimscp/imscp.css | 0 .../exportimscp/index.php | 3 +- .../lang/en/booktool_exportimscp.php | 30 +++++++++++ tool/exportimscp/lib.php | 51 ++++++++++++++++++ .../exportimscp/pix}/generateimscp.gif | Bin tool/exportimscp/version.php | 29 ++++++++++ version.php | 2 +- 11 files changed, 144 insertions(+), 15 deletions(-) create mode 100644 tool/exportimscp/db/access.php rename generateimscp.css => tool/exportimscp/imscp.css (100%) rename generateimscp.php => tool/exportimscp/index.php (99%) create mode 100644 tool/exportimscp/lang/en/booktool_exportimscp.php create mode 100644 tool/exportimscp/lib.php rename {pix => tool/exportimscp/pix}/generateimscp.gif (100%) create mode 100644 tool/exportimscp/version.php diff --git a/db/access.php b/db/access.php index 11d26c0edea..b5da08ff5c0 100644 --- a/db/access.php +++ b/db/access.php @@ -68,9 +68,4 @@ $capabilities = array( ) ), - 'mod/book:exportimscp' => array( - 'captype' => 'read', - 'contextlevel' => CONTEXT_MODULE - ), - ); diff --git a/lang/en/book.php b/lang/en/book.php index 7451ef19958..b89ee75cf52 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -87,7 +87,6 @@ $string['addafter'] = 'Add new chapter'; $string['confchapterdelete'] = 'Do you really want to delete this chapter?'; $string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?'; -$string['generateimscp'] = 'Generate IMS content package'; $string['top'] = 'top'; $string['navprev'] = 'Previous'; @@ -109,6 +108,5 @@ $string['book:read'] = 'Read book'; $string['book:edit'] = 'Edit book chapters'; $string['book:viewhiddenchapters'] = 'View hidden book chapters'; $string['book:import'] = 'Import chapters'; -$string['book:exportimscp'] = 'Export book as IMS content package'; $string['errorchapter'] = 'Error reading book chapter.'; \ No newline at end of file diff --git a/lib.php b/lib.php index 4770cbc5d21..cd3b495f70d 100644 --- a/lib.php +++ b/lib.php @@ -264,12 +264,6 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig //$doimport = ($allowimport and $edit) ? '' : ''; } - if (has_capability('mod/book:exportimscp', $PAGE->cm->context)) { - //TODO - /// Enable the IMS CP button - //$generateimscp = ($allowexport) ? ''.get_string('generateimscp', 'book').'' : ''; - } - if (has_capability('mod/book:edit', $PAGE->cm->context)) { if (!empty($USER->editing)) { $string = get_string("turneditingoff"); diff --git a/tool/exportimscp/db/access.php b/tool/exportimscp/db/access.php new file mode 100644 index 00000000000..9e4396d8e9d --- /dev/null +++ b/tool/exportimscp/db/access.php @@ -0,0 +1,31 @@ +. + +/** + * Book module capability definition + * + * @package booktool + * @subpackage exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$capabilities = array( + 'booktool/exportimscp:export' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE + ), +); diff --git a/generateimscp.css b/tool/exportimscp/imscp.css similarity index 100% rename from generateimscp.css rename to tool/exportimscp/imscp.css diff --git a/generateimscp.php b/tool/exportimscp/index.php similarity index 99% rename from generateimscp.php rename to tool/exportimscp/index.php index 36703056c1f..574c03d2239 100644 --- a/generateimscp.php +++ b/tool/exportimscp/index.php @@ -23,6 +23,8 @@ // // /////////////////////////////////////////////////////////////////////////// +die('Not converted to 2.0 yet, sorry'); + require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once($CFG->dirroot.'/backup/lib.php'); @@ -30,7 +32,6 @@ require_once($CFG->libdir.'/filelib.php'); $id = required_param('id', PARAM_INT); // Course Module ID -die('Not converted to 2.0 yet, sorry'); if (!$cm = get_coursemodule_from_id('book', $id)) { error('Course Module ID was incorrect'); diff --git a/tool/exportimscp/lang/en/booktool_exportimscp.php b/tool/exportimscp/lang/en/booktool_exportimscp.php new file mode 100644 index 00000000000..f717f638ce7 --- /dev/null +++ b/tool/exportimscp/lang/en/booktool_exportimscp.php @@ -0,0 +1,30 @@ +. + +/** + * Book module language strings + * + * @package booktool + * @subpackage exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +$string['exportimscp:export'] = 'Export book as IMS content package'; +$string['generateimscp'] = 'Generate IMS content package'; +$string['pluginname'] = 'Book IMSCP export'; diff --git a/tool/exportimscp/lib.php b/tool/exportimscp/lib.php new file mode 100644 index 00000000000..e1d924db987 --- /dev/null +++ b/tool/exportimscp/lib.php @@ -0,0 +1,51 @@ +. + +/** + * IMSCP export lib + * + * @package booktool + * @subpackage print + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +function booktool_exportimscp_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { + global $USER, $PAGE, $CFG, $DB, $OUTPUT; + + if ($PAGE->cm->modname !== 'book') { + return; + } + + if (empty($PAGE->cm->context)) { + $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); + } + + + $params = $PAGE->url->params(); + + if (empty($params['id']) or empty($params['chapterid'])) { + return; + } + + if (has_capability('booktool/exportimscp:export', $PAGE->cm->context)) { + //TODO + /// Enable the IMS CP button + //$generateimscp = ($allowexport) ? ''.get_string('generateimscp', 'book').'' : ''; + } +} \ No newline at end of file diff --git a/pix/generateimscp.gif b/tool/exportimscp/pix/generateimscp.gif similarity index 100% rename from pix/generateimscp.gif rename to tool/exportimscp/pix/generateimscp.gif diff --git a/tool/exportimscp/version.php b/tool/exportimscp/version.php new file mode 100644 index 00000000000..4afe31092bb --- /dev/null +++ b/tool/exportimscp/version.php @@ -0,0 +1,29 @@ +. + +/** + * Book print plugin version info + * + * @package booktool + * @subpackage exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +$plugin->version = 2011090800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->component = 'booktool_exportimscp'; // Full name of the plugin (used for diagnostics) diff --git a/version.php b/version.php index cddf04a774c..01a484ff951 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011032001; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011032002; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From 3325a1891f748ec893b2f8431e417c0fe99b0bc0 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 11:41:13 +0200 Subject: [PATCH 143/455] convert html import to new booktool plugin fixes #5 AMOS BEGIN MOV [doimport,mod_book],[doimport,booktool_importhtml] MOV [import,mod_book],[import,booktool_importhtml] MOV [book:importhtml,mod_book],[importhtml:import,booktool_importhtml] MOV [importinfo,mod_book],[importinfo,booktool_importhtml] MOV [importing,mod_book],[importing,booktool_importhtml] MOV [importingchapters,mod_book],[importingchapters,booktool_importhtml] MOV [import_help,mod_book],[import_help,booktool_importhtml] MOV [maindirectory,mod_book],[maindirectory,booktool_importhtml] MOV [relinking,mod_book],[relinking,booktool_importhtml] AMOS END --- db/access.php | 11 ---- edit_form.php | 6 --- lang/en/book.php | 12 ----- lib.php | 5 -- tool/importhtml/db/access.php | 36 +++++++++++++ .../importhtml/import_form.php | 6 ++- import.php => tool/importhtml/index.php | 8 +-- .../lang/en/booktool_importhtml.php | 37 ++++++++++++++ tool/importhtml/lib.php | 51 +++++++++++++++++++ tool/importhtml/version.php | 29 +++++++++++ version.php | 2 +- 11 files changed, 163 insertions(+), 40 deletions(-) create mode 100644 tool/importhtml/db/access.php rename import_form.php => tool/importhtml/import_form.php (95%) rename import.php => tool/importhtml/index.php (98%) create mode 100644 tool/importhtml/lang/en/booktool_importhtml.php create mode 100644 tool/importhtml/lib.php create mode 100644 tool/importhtml/version.php diff --git a/db/access.php b/db/access.php index b5da08ff5c0..7f42897505c 100644 --- a/db/access.php +++ b/db/access.php @@ -57,15 +57,4 @@ $capabilities = array( 'manager' => CAP_ALLOW, ) ), - - 'mod/book:import' => array( - 'riskbitmask' => RISK_XSS, - 'captype' => 'write', - 'contextlevel' => CONTEXT_MODULE, - 'archetypes' => array( - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW, - ) - ), - ); diff --git a/edit_form.php b/edit_form.php index dcfaebd482c..5ccda8bebfc 100644 --- a/edit_form.php +++ b/edit_form.php @@ -50,12 +50,6 @@ class book_chapter_edit_form extends moodleform { $mform->setType('content_editor', PARAM_RAW); $mform->addRule('content_editor', get_string('required'), 'required', null, 'client'); - if ($chapter->id and has_capability('mod/book:import', $context)) { - //TODO: after files - //$mform->addElement('static', 'doimport', get_string('importingchapters', 'book').':', ''.get_string('doimport', 'book').''); - } - - $mform->addElement('hidden', 'id'); $mform->setType('id', PARAM_INT); diff --git a/lang/en/book.php b/lang/en/book.php index b89ee75cf52..0b866583288 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -93,20 +93,8 @@ $string['navprev'] = 'Previous'; $string['navnext'] = 'Next'; $string['navexit'] = 'Exit book'; -$string['importingchapters'] = 'Importing chapters into book'; -$string['import'] = 'Import'; -$string['import_help'] = 'You can import a single HTML file or every HTML file in a direcory. Relative file links are converted to absolute chapter links. Images, flash and Java are relinked too.'; -$string['doimport'] = 'Import'; -$string['doexport'] = 'Export'; -$string['importing'] = 'Importing'; -$string['relinking'] = 'Relinking'; -$string['importinfo'] = 'Import selected HTML file or directory.
                          Chapters are sorted alphabetically using file names.
                          Files named \'sub_*.*\' are always imported as subchapters.'; -$string['maindirectory'] = 'Main directory'; -$string['fileordir'] = 'File or directory'; - $string['book:read'] = 'Read book'; $string['book:edit'] = 'Edit book chapters'; $string['book:viewhiddenchapters'] = 'View hidden book chapters'; -$string['book:import'] = 'Import chapters'; $string['errorchapter'] = 'Error reading book chapter.'; \ No newline at end of file diff --git a/lib.php b/lib.php index cd3b495f70d..127edf617b9 100644 --- a/lib.php +++ b/lib.php @@ -259,11 +259,6 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig } } - if (has_capability('mod/book:import', $PAGE->cm->context)) { - //TODO - //$doimport = ($allowimport and $edit) ? '' : ''; - } - if (has_capability('mod/book:edit', $PAGE->cm->context)) { if (!empty($USER->editing)) { $string = get_string("turneditingoff"); diff --git a/tool/importhtml/db/access.php b/tool/importhtml/db/access.php new file mode 100644 index 00000000000..cf87c1fddba --- /dev/null +++ b/tool/importhtml/db/access.php @@ -0,0 +1,36 @@ +. + +/** + * Book import capability definition + * + * @package booktool + * @subpackage importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$capabilities = array( + 'booktool/importhtml:import' => array( + 'riskbitmask' => RISK_XSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'archetypes' => array( + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW, + ) + ), +); diff --git a/import_form.php b/tool/importhtml/import_form.php similarity index 95% rename from import_form.php rename to tool/importhtml/import_form.php index 909f07b5fb0..23ec250f646 100644 --- a/import_form.php +++ b/tool/importhtml/import_form.php @@ -17,12 +17,14 @@ /** * Book import form * - * @package mod - * @subpackage book + * @package booktool + * @subpackage importhtml * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die; + require_once($CFG->libdir.'/formslib.php'); class book_import_form extends moodleform { diff --git a/import.php b/tool/importhtml/index.php similarity index 98% rename from import.php rename to tool/importhtml/index.php index e60f2ca5389..6532189d9a5 100644 --- a/import.php +++ b/tool/importhtml/index.php @@ -17,12 +17,14 @@ /** * Book import * - * @package mod - * @subpackage book + * @package booktool + * @subpackage importhtml * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +die('TODO'); + require('../../config.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once('import_form.php'); @@ -70,7 +72,7 @@ if ($mform->is_cancelled()) { } else if ($data = $mform->get_data()) { - die('TODO'); + /* $coursebase = $CFG->dataroot.'/'.$book->course; diff --git a/tool/importhtml/lang/en/booktool_importhtml.php b/tool/importhtml/lang/en/booktool_importhtml.php new file mode 100644 index 00000000000..fc8ff1f95ae --- /dev/null +++ b/tool/importhtml/lang/en/booktool_importhtml.php @@ -0,0 +1,37 @@ +. + +/** + * Book import language strings + * + * @package booktool + * @subpackage importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +$string['doimport'] = 'Import'; +$string['import'] = 'Import'; +$string['importhtml:import'] = 'Import chapters'; +$string['importinfo'] = 'Import selected HTML file or directory.
                          Chapters are sorted alphabetically using file names.
                          Files named \'sub_*.*\' are always imported as subchapters.'; +$string['importing'] = 'Importing'; +$string['importingchapters'] = 'Importing chapters into book'; +$string['import_help'] = 'You can import a single HTML file or every HTML file in a direcory. Relative file links are converted to absolute chapter links. Images, flash and Java are relinked too.'; +$string['maindirectory'] = 'Main directory'; +$string['pluginname'] = 'Book HTML import'; +$string['relinking'] = 'Relinking'; diff --git a/tool/importhtml/lib.php b/tool/importhtml/lib.php new file mode 100644 index 00000000000..7723c197fdb --- /dev/null +++ b/tool/importhtml/lib.php @@ -0,0 +1,51 @@ +. + +/** + * HTML import lib + * + * @package booktool + * @subpackage importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +function booktool_importhtml_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { + global $USER, $PAGE, $CFG, $DB, $OUTPUT; + + if ($PAGE->cm->modname !== 'book') { + return; + } + + if (empty($PAGE->cm->context)) { + $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); + } + + + $params = $PAGE->url->params(); + + if (empty($params['id'])) { + return; + } + + + if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) { + //TODO + //$doimport = ($allowimport and $edit) ? '' : ''; + } +} \ No newline at end of file diff --git a/tool/importhtml/version.php b/tool/importhtml/version.php new file mode 100644 index 00000000000..ca37b8a58cd --- /dev/null +++ b/tool/importhtml/version.php @@ -0,0 +1,29 @@ +. + +/** + * Book import plugin version info + * + * @package booktool + * @subpackage importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +$plugin->version = 2011090800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->component = 'booktool_importhtml'; // Full name of the plugin (used for diagnostics) diff --git a/version.php b/version.php index 01a484ff951..fc28ee6529f 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011032002; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011032003; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From b6931b14bdf2cf385e47beac4ba88c5a9cf27a2c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 11:58:15 +0200 Subject: [PATCH 144/455] use png instead of legacy gif format fixes #11 --- pix/add.gif | Bin 68 -> 0 bytes pix/add.png | Bin 0 -> 141 bytes pix/chapter.gif | Bin 112 -> 0 bytes pix/chapter.png | Bin 0 -> 209 bytes pix/icon.gif | Bin 111 -> 0 bytes pix/icon.png | Bin 0 -> 211 bytes pix/nav_exit.gif | Bin 248 -> 0 bytes pix/nav_exit.png | Bin 0 -> 470 bytes pix/nav_next.gif | Bin 246 -> 0 bytes pix/nav_next.png | Bin 0 -> 472 bytes pix/nav_prev.gif | Bin 247 -> 0 bytes pix/nav_prev.png | Bin 0 -> 466 bytes pix/nav_prev_dis.gif | Bin 209 -> 0 bytes pix/nav_prev_dis.png | Bin 0 -> 483 bytes pix/nav_sep.gif | Bin 41 -> 0 bytes pix/nav_sep.png | Bin 0 -> 100 bytes tool/print/pix/book.gif | Bin 204 -> 0 bytes tool/print/pix/book.png | Bin 0 -> 363 bytes tool/print/pix/chapter.gif | Bin 158 -> 0 bytes tool/print/pix/chapter.png | Bin 0 -> 339 bytes 20 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 pix/add.gif create mode 100644 pix/add.png delete mode 100644 pix/chapter.gif create mode 100644 pix/chapter.png delete mode 100644 pix/icon.gif create mode 100644 pix/icon.png delete mode 100644 pix/nav_exit.gif create mode 100644 pix/nav_exit.png delete mode 100644 pix/nav_next.gif create mode 100644 pix/nav_next.png delete mode 100644 pix/nav_prev.gif create mode 100644 pix/nav_prev.png delete mode 100644 pix/nav_prev_dis.gif create mode 100644 pix/nav_prev_dis.png delete mode 100644 pix/nav_sep.gif create mode 100644 pix/nav_sep.png delete mode 100644 tool/print/pix/book.gif create mode 100644 tool/print/pix/book.png delete mode 100644 tool/print/pix/chapter.gif create mode 100644 tool/print/pix/chapter.png diff --git a/pix/add.gif b/pix/add.gif deleted file mode 100644 index 3a0de01034f7619f568f9f6684e225b73a5651b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmZ?wbhEHbv%%&c@?yOU^ z5kI&8OIkO)y%0KR9@LcNnYMQtAt~XYf4USyW+VR-zruK=`nRQDzE*e{EN^>$; F0|2NBBmMvY diff --git a/pix/chapter.png b/pix/chapter.png new file mode 100644 index 0000000000000000000000000000000000000000..d84cac04025beab07cd7429404d6d9cca082290b GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_Wt4 z#WBP}@NJMIUxNaV^pWn{rX zf0TFl@{6x6d5*8s@mH_I8jR!aZ}!g3zhTxRxR%$hT;f^Bvc!Er=P-D>`njxgN@xNA D1RY4= literal 0 HcmV?d00001 diff --git a/pix/icon.gif b/pix/icon.gif deleted file mode 100644 index bcdde5ac1dcbc217ca7282abe6e0b1771177862d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111 zcmZ?wbhEHb6krfwSj7MW4Gs+d|Nn1jXaMt|gyK&YMg|5J1|1L|q?Uo%#ADZ;bqoi# zKa!X@NyB9d|8qvh7d3$aK`ATOExdJT`JY+7){lGYHk(OaQ0)<{w3Xh}UZujoU=08) CEg|Lr diff --git a/pix/icon.png b/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..41095ef128528fcb01367b49eacca12f113600e5 GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP_Wh0 z#WBP}@a^P_ybT5%E-MQS+>=erR~PUuTjG96{=Z7#lLxW0S1HN6o7eAGdX}D{Yo(GL z5qhyJ$2G~1X&1|m?;8`cJ3UWKToo7)p>LEKw3T^g_}YZ+Db@n)OkHmd>#SguUbE%? zf(q`djfS<60O_nuw&lcC_CSUiVkr5Mmb44$rjF6*2U FngGG8NnQW| literal 0 HcmV?d00001 diff --git a/pix/nav_exit.gif b/pix/nav_exit.gif deleted file mode 100644 index 6177c8e7c3b95bb151e03f8770ce3075da1a5832..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmZ?wbhEHblwgox*v$X}|NsAg`t)gGVd3}h-=|NXZf+1`a!9pnhWMO1r;9$@J z$$`vZU|A|~va^fPVz%>d9e1-H=Q5FdAxy3h_T@G5W?CNjkzM{tR)8g(jX`^%8pC~m z3zb(4TFbR>oH;N_RBWA9%}Jdgwd-1YG>#^}d?n*Cnfdjd)w847pO#1*)XU!=Uv11( zo@v3tq$=JVl3dl!z!uNc+^Ro0o-zF3*@0Nwwulw2%0&QP*VQe{BH>{e#D_DEqpZD% zYnsOOeV^q?A{-BrZXxu}kmJk3h_wkXSrCr-zou&wC>QKR!;j;*Flatkx`l6zB9TS3 z%$J6v_zq67l88{@P}wF^fUweR>yQ_j&hgP;&RGd+_jRpiI=<&Rfxd;jTeA)`awGfi zI66rG9ni*EhnbK4<&(Z@KX-KBND{89^rG5$k{lOug7Z9c@sIX2O9Vb5Jtz`^eczo{ z#^bQ#0WUDX660&SZCkjxPcN4T;AKe+wHRO_4)&|-x*#^svxBldNeDjtVLezdvgK0& zWqXpO#mqu?&3ez~JqSYl37brMB9w#kf)Oe+zaL1*i4bOIolAIR30oW{SP=~=`MOqs zIfscpcA=9Jko!D2@?&j+P49jTq3COW`dS`ByeH_;4#eUKbXns60$ka4;m+djdH?_b M07*qoM6N<$f;H>W4gdfE literal 0 HcmV?d00001 diff --git a/pix/nav_next.gif b/pix/nav_next.gif deleted file mode 100644 index 17b42333ed7f18f9576ec1ac87b3491c4dceec70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmZ?wbhEHblwgox*v-K3|Nnmm28O3kpB5Gte*gY``t<4M=H|Y>zCb~&K=CIFBLf2m zgAPa*WCjDvVu6#LeVi7voqp@MoAo%C70e4^V|}nMuaP&?^1zSm@=tUBt4>jQ@SBl& z@+83tCj|vJO*0fe;HvMfCMv!|q&|cv=PU2*qk2Yfa;}}_&@a2;s&F{=lkNgL;X8AS ztC>{A>saawtJ;}j1DV=le4Cg8IaK>6bcVLG^!qzA&uF*o?pGDDT{LI)3`beB85=iQ c%W1Q2nqf3wQ$a~Z%}G;;RXkBzQ;@+L09sH_^#A|> diff --git a/pix/nav_next.png b/pix/nav_next.png new file mode 100644 index 0000000000000000000000000000000000000000..1e11bd93e633a22e71e1b7ea2249dc9e58dbde47 GIT binary patch literal 472 zcmV;}0Vn>6P)K)j2$w^pp50JPKTeh&{dGa!r zNuBn6c$QKddpzT$d_s6(_xt^*>-rFgyHFd30kxu4UIk6_JcntTwA^)_#t8bp*J~Lh zG))s8kB7^rKm0wodT6ZhA4JTfom33wtr_75q# zR#oqx8QTcF3}jO=zCC3wPN=}X@0U?qE)}?pJtI(@)3KRCdp#@lpR zmSfvCUDDv1H0p!Km_YV}3pH@x+P0NAgmE0BGS%&FBB1aiFA|TcYqvm@azRfUlmYF7Lx?Qvzg?%XWjPj0VAn;zCQr44J0XfizRvDQf>_h$VDtk zDYm^z=mi8yEq>5Tgv@j2z^C35t^2}3)4zT6tvrPIoM6Iyp;kQaMDz(RX7_IlN08?L O0000zCb~&K=CIFBLf2m zgAPa*WCjDv5`mMQU7QxPoqy}NoAo%CiQEfeV|}nMuaP&?^1zSm@=tUBt6oug@SBl& zm4jX~i-5LHj9ccE$QA1~zlrY=#@!3C>%amv}LuO@SU@6 zEKI86b@joPEL}{oVN7*}J_g-PVH~RcT?Lb>oBI8QT>9HO=QVrCFPb@P&0 dTgz#)ZeDD(KvO|UMa@Z5UObBJkcc3IH2~b)QW^jN diff --git a/pix/nav_prev.png b/pix/nav_prev.png new file mode 100644 index 0000000000000000000000000000000000000000..b08bbda83e1ccabfd8b4d87bd5eba653d7c050c4 GIT binary patch literal 466 zcmV;@0WJQCP)-F=>)7XZLV*BbTEtR=Trj{=<7>Js%du^n z9R^?xyl^lUde*{&g*vcbP1BgU$T*Hx`R-0^k^AA!QHuckKaF#mHFSUv)DkxPQ9it7DZbnw+E= zj8s_JE~u?JQsvY-OO{(?SJi&z1xqflHoLY8Nha8}UlKZWYp<4o*{7Y`<2HC(uoR^R zXw^3A@-^0`ge$i-+Hy5?W%re}Gx2CNR(5yKF_veXvt;SQS%phyOq3J%kyZ-uKRF@NN+V+pR9 z&1bHvbH6LFw%=?19BSXwHND^O*8kPqvXa18#KPjVMYr26v~3&ex(@sOKFss%E+bYl zs)r?u9q6j!RD1700%&BN*5VVh(sjCCuTdFwC4MTReAe=Vg~6`)hBJ|3jQl-R(K`_f z*IHOGVW+R@Fbofzhr>a6@l1H(Ts-sORF6R4_mQ1$k-AWO0CiaECLe7MbHQQBQU^Hf zhtGDRx6Bg|Sos!???nJ7oiN&iw{5S*ayWUe00B%}_W$NT5%$2! Z{srTC7e8b?yN&<=002ovPDHLkV1iGQ-4p-- literal 0 HcmV?d00001 diff --git a/pix/nav_sep.gif b/pix/nav_sep.gif deleted file mode 100644 index 821ac1eb5613688eb46d9ba0f40e49f765aa604b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 scmZ?wbh9u|WMVL2=wM(lHa2EpV9)_#29O8?6Guz`%F}Q8leHME0gB!StpET3 diff --git a/pix/nav_sep.png b/pix/nav_sep.png new file mode 100644 index 0000000000000000000000000000000000000000..35139a0b2bdcdff93301fa56194e15163bb2807b GIT binary patch literal 100 zcmeAS@N?(olHy`uVBq!ia0vp^Oh9bF0V21g*<1xuoCO|{#S9GG!XV7ZFl&wkP*BX% t#W6%eGTFq;EG;1+f$33T7ndUg1N&cwpZS|Q)PX7(JYD@<);T3K0RU-Z6&L^j literal 0 HcmV?d00001 diff --git a/tool/print/pix/book.gif b/tool/print/pix/book.gif deleted file mode 100644 index 19311922071ab9833a006fe5b4e8552bbdea4b26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204 zcmZ?wbhEHblwgox*v$X}4Gs(k4jlOZ|G%-Z@&Df+{{Lr~Hf>r%Ljzb6olyMA!pOkD z$)E$00GYwSQfY9~bM;<}*JpRzyJ+;Wh|4*zTK1G}Pl3%ADSL4B2#VrqFQTTgwSbFCpqrfFC66upW1a&yE48LR=|5lLDA diff --git a/tool/print/pix/book.png b/tool/print/pix/book.png new file mode 100644 index 0000000000000000000000000000000000000000..a5c90804b756a0d0f74bc21f9265ad571eec0db9 GIT binary patch literal 363 zcmV-x0hIoUP)2j96ldfwk|Kn%kLPv+ana8B`CY_4cL#RNtRUT0IJh z0bKPkAlVrb1I&K9g=hlEKugP-c-8Ia8|4DN`XK(wWHGI0Gse@lX-ZQCmDC12VA zU=bjZFu4@OF+iYH2qN`&067LBFny@QZlb!HrrF?f1{(tu;Y}S!??RAx$hl{F_mu<| zmoWx2s~S!|lg|{R{vA002ov JPDHLkV1l{dnv?(l literal 0 HcmV?d00001 diff --git a/tool/print/pix/chapter.gif b/tool/print/pix/chapter.gif deleted file mode 100644 index b98dde903756da8aa13b333b8375fa03012e7d05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmZ?wbhEHblwgoxSj7MW|Ns9#aNxj$2M_-L{_y`lLqkIYP*CwF3nK#qJA)2L1xPIe zb8^M5JO2z$d9L0o_~NW1tD{Dj9BW^)<=l)FRWDs) diff --git a/tool/print/pix/chapter.png b/tool/print/pix/chapter.png new file mode 100644 index 0000000000000000000000000000000000000000..99ecd29853b87422550e6d593b0cda1f8f425b6c GIT binary patch literal 339 zcmV-Z0j&OsP)wC9tDbwb4*jkt<<+@f^Xw4PjJ+tt{-jrk(QxquL6_)t< zt8TY#bK7Wf?TV%jy^w2+t-!GD92GZaAW#Dz**wn)74SO3;C`sQjX?!Pkm4d0s47nh zl$t>~%+7MoIwL*&@ZlkMVR-K5d}&GWYS=l3_orI4EX%t+Omeih{~$DID92+!dx{zM lh+EG&2$e*QaZ$`QaWAst(BW&&f;s>I002ovPDHLkV1f`}kW2so literal 0 HcmV?d00001 From e08764150aabb5b325e1b9c48cb4484e5ee3c2be Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 12:23:08 +0200 Subject: [PATCH 145/455] add missing extra caps --- lib.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib.php b/lib.php index 127edf617b9..4e8396fdc26 100644 --- a/lib.php +++ b/lib.php @@ -42,6 +42,15 @@ function book_get_numbering_types() { BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); } +/** + * Returns all other caps used in module + * @return array + */ +function book_get_extra_capabilities() { + // used for group-members-only + return array('moodle/site:accessallgroups'); +} + /** * Add book instance. * From 3f24450df285cde3ddf9dc8f742a58205d41ffa2 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 12:33:28 +0200 Subject: [PATCH 146/455] fix php docs, abstract view and post actions --- lib.php | 131 +++++++++++++++++++++++++++++++++------------ tool/print/lib.php | 10 +++- 2 files changed, 105 insertions(+), 36 deletions(-) diff --git a/lib.php b/lib.php index 4e8396fdc26..99c5150cef2 100644 --- a/lib.php +++ b/lib.php @@ -58,16 +58,16 @@ function book_get_extra_capabilities() { * @param stdClass $mform * @return int new book instance id */ -function book_add_instance($book) { +function book_add_instance($data, $mform) { global $DB; - $book->timecreated = time(); - $book->timemodified = $book->timecreated; - if (!isset($book->customtitles)) { - $book->customtitles = 0; + $data->timecreated = time(); + $data->timemodified = $data->timecreated; + if (!isset($data->customtitles)) { + $data->customtitles = 0; } - return $DB->insert_record('book', $book); + return $DB->insert_record('book', $data); } /** @@ -77,16 +77,16 @@ function book_add_instance($book) { * @param stdClass $mform * @return bool true */ -function book_update_instance($book) { +function book_update_instance($data, $mform) { global $DB; - $book->timemodified = time(); - $book->id = $book->instance; - if (!isset($book->customtitles)) { - $book->customtitles = 0; + $data->timemodified = time(); + $data->id = $data->instance; + if (!isset($data->customtitles)) { + $data->customtitles = 0; } - $DB->update_record('book', $book); + $DB->update_record('book', $data); return true; } @@ -115,10 +115,11 @@ function book_delete_instance($id) { /** * Return use outline - * @param object $course - * @param object $user - * @param object $mod - * @param object $page + * + * @param stdClass $course + * @param stdClass $user + * @param stdClass $mod + * @param object $book * @return object|null */ function book_user_outline($course, $user, $mod, $book) { @@ -139,31 +140,49 @@ function book_user_outline($course, $user, $mod, $book) { return NULL; } +/** + * Print a detailed representation of what a user has done with + * a given particular instance of this module, for user activity reports. + * + * @param $course + * @param $user + * @param $mod + * @param $book + * @return bool + */ function book_user_complete($course, $user, $mod, $book) { - // Print a detailed representation of what a user has done with - // a given particular instance of this module, for user activity reports. - return true; } +/** + * Given a course and a time, this module should find recent activity + * that has occurred in book activities and print it out. + * Return true if there was output, or false is there was none. + * @param $course + * @param $isteacher + * @param $timestart + * @return bool + */ function book_print_recent_activity($course, $isteacher, $timestart) { - // Given a course and a time, this module should find recent activity - // that has occurred in book activities and print it out. - // Return true if there was output, or false is there was none. return false; // True if anything was printed, otherwise false } +/** + * No cron in book. + * + * @return bool + */ function book_cron () { - // Function to be run periodically according to the moodle cron - // This function searches for things that need to be done, such - // as sending out mail, toggling flags etc ... return true; } +/** + * No grading in book. + * + * @param $bookid + * @return null + */ function book_grades($bookid) { - // Must return an array of grades for a given instance of this module, - // indexed by user. It also returns a maximum allowed grade. - return null; } @@ -202,12 +221,54 @@ function book_scale_used_anywhere($scaleid) { return false; } +/** + * Return read actions. + * @return array + */ function book_get_view_actions() { - return array('view', 'view all', 'print'); + global $CFG; // necessary for includes + + $return = array('view', 'view all'); + + $plugins = get_plugin_list('booktool'); + foreach($plugins as $plugin=>$dir) { + if (file_exists("$dir/lib.php")) { + require_once("$dir/lib.php"); + } + $function = 'booktool_'.$plugin.'_get_view_actions'; + if (function_exists($function)) { + if ($actions = $function($settingsnav, $booknode)) { + $return = array_merge($return, $actions); + } + } + } + + return $return; } +/** + * Return write actions. + * @return array + */ function book_get_post_actions() { - return array('update'); + global $CFG; // necessary for includes + + $return = array('update'); + + $plugins = get_plugin_list('booktool'); + foreach($plugins as $plugin=>$dir) { + if (file_exists("$dir/lib.php")) { + require_once("$dir/lib.php"); + } + $function = 'booktool_'.$plugin.'_get_post_actions'; + if (function_exists($function)) { + if ($actions = $function($settingsnav, $booknode)) { + $return = array_merge($return, $actions); + } + } + } + + return $return; } /** @@ -235,7 +296,7 @@ function book_supports($feature) { /** * Adds module specific settings to the settings block * - * @param settings_navigation $settings The settings navigation object + * @param settings_navigation $settingsnav The settings navigation object * @param navigation_node $booknode The node to add module settings to * @return void */ @@ -253,7 +314,7 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig $params = $PAGE->url->params(); - if (empty($params['id']) or empty($params['chapterid'])) { + if (empty($params['id'])) { return; } @@ -268,7 +329,7 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig } } - if (has_capability('mod/book:edit', $PAGE->cm->context)) { + if (!empty($params['chapterid']) and has_capability('mod/book:edit', $PAGE->cm->context)) { if (!empty($USER->editing)) { $string = get_string("turneditingoff"); $edit = '0'; @@ -290,10 +351,10 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig * @param string $filearea * @param array $args * @param bool $forcedownload - * @return bool false if file not found, does not return if found - justsend the file + * @return bool false if file not found, does not return if found - just send the file */ function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { - global $CFG, $DB; + global $DB; if ($context->contextlevel != CONTEXT_MODULE) { return false; diff --git a/tool/print/lib.php b/tool/print/lib.php index c519ec87607..affd262bfc3 100644 --- a/tool/print/lib.php +++ b/tool/print/lib.php @@ -57,4 +57,12 @@ function booktool_print_extend_settings_navigation(settings_navigation $settings $booknode->add(get_string('printchapter', 'booktool_print'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'booktool_print', array('class'=>'icon'))); } } -} \ No newline at end of file +} + +/** + * Return read actions. + * @return array + */ +function booktool_print_get_view_actions() { + return array('print'); +} From 45573d5ad14136d0f0a3d940c2cc8dcb629927cd Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 12:35:59 +0200 Subject: [PATCH 147/455] move book specific stuff to locallib.php --- lib.php | 9 +++------ locallib.php | 5 +++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib.php b/lib.php index 99c5150cef2..6b9aed9d7ca 100644 --- a/lib.php +++ b/lib.php @@ -25,17 +25,14 @@ defined('MOODLE_INTERNAL') || die; - -define('BOOK_NUM_NONE', '0'); -define('BOOK_NUM_NUMBERS', '1'); -define('BOOK_NUM_BULLETS', '2'); -define('BOOK_NUM_INDENTED', '3'); - /** * Returns list of available numbering types * @return array */ function book_get_numbering_types() { + global $CFG; // required for the include + require_once(dirname(__FILE__).'/locallib.php'); + return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), diff --git a/locallib.php b/locallib.php index c9f19319e84..3d8135b2705 100644 --- a/locallib.php +++ b/locallib.php @@ -28,6 +28,11 @@ defined('MOODLE_INTERNAL') || die; require_once($CFG->dirroot.'/mod/book/lib.php'); require_once($CFG->libdir.'/filelib.php'); +define('BOOK_NUM_NONE', '0'); +define('BOOK_NUM_NUMBERS', '1'); +define('BOOK_NUM_BULLETS', '2'); +define('BOOK_NUM_INDENTED', '3'); + /** * Preload book chapters and fix toc structure if necessary. * From b962f03009010acd9917b91417f86df43b970ca8 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 8 Oct 2011 12:55:04 +0200 Subject: [PATCH 148/455] more refactoring --- locallib.php | 280 +---------------------------------- tool/importhtml/locallib.php | 235 +++++++++++++++++++++++++++++ tool/print/index.php | 4 +- tool/print/locallib.php | 89 +++++++++++ 4 files changed, 327 insertions(+), 281 deletions(-) create mode 100644 tool/importhtml/locallib.php create mode 100644 tool/print/locallib.php diff --git a/locallib.php b/locallib.php index 3d8135b2705..24c76b5d82c 100644 --- a/locallib.php +++ b/locallib.php @@ -40,8 +40,7 @@ define('BOOK_NUM_INDENTED', '3'); * and extra 'parent, number, subchapters, prev, next'. * Please note the content/text of chapters is not included. * - * @param $book - * @param $cm + * @param stdClass $book * @return array of id=>chapter */ function book_preload_chapters($book) { @@ -187,71 +186,6 @@ function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { $PAGE->blocks->add_fake_block($bc, $firstregion); } -/** - * Generate toc structure and titles - * - * @param array $chapters - * @param stdClass $chapter - * @param stdClass $book - * @param stdClass $cm - * @param bool $edit - * @param bool $print - * @return array - */ -function book_get_print_toc($chapters, $book, $cm) { - global $USER, $OUTPUT; - - $first = true; - $titles = array(); - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - $toc = ''; //representation of toc (HTML) - - switch ($book->numbering) { - case BOOK_NUM_NONE: - $toc .= '
                          '; - break; - case BOOK_NUM_NUMBERS: - $toc .= '
                          '; - break; - case BOOK_NUM_BULLETS: - $toc .= '
                          '; - break; - case BOOK_NUM_INDENTED: - $toc .= '
                          '; - break; - } - - $toc .= ''; //representation of toc (HTML) - - if ($book->customtitles) { - $toc .= '

                          '.get_string('toc', 'mod_book').'

                          '; - } else { - $toc .= '

                          '.get_string('toc', 'mod_book').'

                          '; - } - $toc .= '
                            '; - foreach($chapters as $ch) { - if (!$ch->hidden) { - $title = book_get_chapter_title($ch->id, $chapters, $book, $context); - if (!$ch->subchapter) { - $toc .= $first ? '
                          • ' : '
                        • '; - } else { - $toc .= $first ? '
                          • ' : '
                          • '; - } - $titles[$ch->id] = $title; - $toc .= ''.$title.''; - $toc .= (!$ch->subchapter) ? '
                              ' : ''; - $first = false; - } - } - $toc .= '
                          '; - $toc .= '
                        • '; - $toc = str_replace('
                            ', '', $toc); //cleanup of invalid structures - - return array($toc, $titles); -} - /** * Generate toc structure * @@ -260,7 +194,6 @@ function book_get_print_toc($chapters, $book, $cm) { * @param stdClass $book * @param stdClass $cm * @param bool $edit - * @param bool $print * @return string */ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { @@ -386,214 +319,3 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { return $toc; } - - -//================================================= -// import functions - not converted yet! -//================================================= - -/// normalize relative links (= remove ..) -function book_prepare_link($ref) { - if ($ref == '') { - return ''; - } - $ref = str_replace('\\','/',$ref); //anti MS hack - $cnt = substr_count($ref, '..'); - for($i=0; $i<$cnt; $i++) { - $ref = ereg_replace('[^/]+/\.\./', '', $ref); - } - //still any '..' left?? == error! error! - if (substr_count($ref, '..') > 0) { - return ''; - } - if (ereg('[\|\`]', $ref)) { // check for other bad characters - return ''; - } - return $ref; -} - -/// read chapter content from file -function book_read_chapter($base, $ref) { - $file = $base.'/'.$ref; - if (filesize($file) <= 0 or !is_readable($file)) { - book_log($ref, get_string('error'), 2); - return; - } - //first read data - $handle = fopen($file, "rb"); - $contents = fread($handle, filesize($file)); - fclose($handle); - //extract title - $chapter = new object(); - if (preg_match('/([^<]+)<\/title>/i', $contents, $matches)) { - $chapter->title = $matches[1]; - } else { - $chapter->title = $ref; - } - //extract page body - if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { - $chapter->content = $matches[1]; - } else { - book_log($ref, get_string('error'), 2); - return; - } - book_log($ref, get_string('ok')); - $chapter->importsrc = $ref; - //extract page head - if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { - $head = $matches[1]; - if (preg_match('/charset=([^"]+)/is', $head, $matches)) { - $enc = $matches[1]; - $textlib = textlib_get_instance(); - $chapter->content = $textlib->convert($chapter->content, $enc, 'utf-8'); - $chapter->title = $textlib->convert($chapter->title, $enc, 'utf-8'); - } - if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css - for($i=0; $i<count($matches[0]); $i++){ - $chapter->content = $matches[0][$i]."\n".$chapter->content; - } - } - } - return $chapter; -} - -///relink images and relative links -function book_relink($id, $bookid, $courseid) { - global $CFG, $DB; - - if ($CFG->slasharguments) { - $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; - } else { - $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; - } - $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, title, content, importsrc'); - $originals = array(); - foreach($chapters as $ch) { - $originals[$ch->importsrc] = $ch; - } - foreach($chapters as $ch) { - $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); - $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) - $modified = false; - //image relinking - if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { - for($i = 0; $i<count($images[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link - $link = book_prepare_link($base.$images[2][$i]); - if ($link == '') { - continue; - } - $origtag = $images[0][$i]; - $newtag = $images[1][$i].$link.$images[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $images[2][$i].' --> '.$link); - } - } - } - //css relinking (dlnsk) - if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { - for($i = 0; $i<count($csslinks[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link - $link = book_prepare_link($base.$csslinks[2][$i]); - if ($link == '') { - continue; - } - $origtag = $csslinks[0][$i]; - $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $csslinks[2][$i].' --> '.$link); - } - } - } - //general embed relinking - flash and others?? - if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { - for($i = 0; $i<count($embeds[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link - $link = book_prepare_link($base.$embeds[2][$i]); - if ($link == '') { - continue; - } - $origtag = $embeds[0][$i]; - $newtag = $embeds[1][$i].$link.$embeds[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $embeds[2][$i].' --> '.$link); - } - } - } - //flash in IE <param name=movie value="something" - I do hate IE! - if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { - for($i = 0; $i<count($params[0]); $i++) { - if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { - if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link - $link = book_prepare_link($base.$values[2]); - if ($link == '') { - continue; - } - $newvalue = $values[1].$link.$values[3]; - $newparam = str_replace($values[0], $newvalue, $params[0][$i]); - $ch->content = str_replace($params[0][$i], $newparam, $ch->content); - $modified = true; - book_log($ch->title, $values[2].' --> '.$link); - } - } - } - } - //java applet - add code bases if not present!!!! - if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { - for($i = 0; $i<count($applets[0]); $i++) { - if (!stripos($applets[0][$i], 'codebase')) { - $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); - $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); - $modified = true; - } - } - } - //relink java applet code bases - if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { - for($i = 0; $i<count($codebases[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link - $link = book_prepare_link($base.$codebases[2][$i]); - if ($link == '') { - continue; - } - $origtag = $codebases[0][$i]; - $newtag = $codebases[1][$i].$link.$codebases[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $codebases[2][$i].' --> '.$link); - } - } - } - //relative link conversion - if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { - for($i = 0; $i<count($links[0]); $i++) { - if ($links[2][$i] != '' //check for inner anchor links - && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link - $origtag = $links[0][$i]; - $target = book_prepare_link($rel.$links[2][$i]); //target chapter - if ($target != '' && array_key_exists($target, $originals)) { - $o = $originals[$target]; - $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; - $newtag = preg_replace('/target=[^\s>]/i','', $newtag); - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); - } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links - $target = book_prepare_link($base.$links[2][$i]); - $origtag = $links[0][$i]; - $newtag = $links[1][$i].$target.$links[4][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $links[2][$i].' --> '.$target); - } - } - } - } - if ($modified) { - $DB->update_record('book_chapters', $ch); - } - } -} diff --git a/tool/importhtml/locallib.php b/tool/importhtml/locallib.php new file mode 100644 index 00000000000..110acc1ce6f --- /dev/null +++ b/tool/importhtml/locallib.php @@ -0,0 +1,235 @@ +<?php +// This file is part of Book plugin for 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/>. + +/** + * HTML import lib + * + * @package booktool + * @subpackage importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + + +//TODO: not converted yet! + +/// normalize relative links (= remove ..) +function book_prepare_link($ref) { + if ($ref == '') { + return ''; + } + $ref = str_replace('\\','/',$ref); //anti MS hack + $cnt = substr_count($ref, '..'); + for($i=0; $i<$cnt; $i++) { + $ref = ereg_replace('[^/]+/\.\./', '', $ref); + } + //still any '..' left?? == error! error! + if (substr_count($ref, '..') > 0) { + return ''; + } + if (ereg('[\|\`]', $ref)) { // check for other bad characters + return ''; + } + return $ref; +} + +/// read chapter content from file +function book_read_chapter($base, $ref) { + $file = $base.'/'.$ref; + if (filesize($file) <= 0 or !is_readable($file)) { + book_log($ref, get_string('error'), 2); + return; + } + //first read data + $handle = fopen($file, "rb"); + $contents = fread($handle, filesize($file)); + fclose($handle); + //extract title + $chapter = new object(); + if (preg_match('/<title>([^<]+)<\/title>/i', $contents, $matches)) { + $chapter->title = $matches[1]; + } else { + $chapter->title = $ref; + } + //extract page body + if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { + $chapter->content = $matches[1]; + } else { + book_log($ref, get_string('error'), 2); + return; + } + book_log($ref, get_string('ok')); + $chapter->importsrc = $ref; + //extract page head + if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { + $head = $matches[1]; + if (preg_match('/charset=([^"]+)/is', $head, $matches)) { + $enc = $matches[1]; + $textlib = textlib_get_instance(); + $chapter->content = $textlib->convert($chapter->content, $enc, 'utf-8'); + $chapter->title = $textlib->convert($chapter->title, $enc, 'utf-8'); + } + if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css + for($i=0; $i<count($matches[0]); $i++){ + $chapter->content = $matches[0][$i]."\n".$chapter->content; + } + } + } + return $chapter; +} + +///relink images and relative links +function book_relink($id, $bookid, $courseid) { + global $CFG, $DB; + + if ($CFG->slasharguments) { + $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; + } else { + $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; + } + $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, title, content, importsrc'); + $originals = array(); + foreach($chapters as $ch) { + $originals[$ch->importsrc] = $ch; + } + foreach($chapters as $ch) { + $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); + $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) + $modified = false; + //image relinking + if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { + for($i = 0; $i<count($images[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link + $link = book_prepare_link($base.$images[2][$i]); + if ($link == '') { + continue; + } + $origtag = $images[0][$i]; + $newtag = $images[1][$i].$link.$images[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $images[2][$i].' --> '.$link); + } + } + } + //css relinking (dlnsk) + if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { + for($i = 0; $i<count($csslinks[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link + $link = book_prepare_link($base.$csslinks[2][$i]); + if ($link == '') { + continue; + } + $origtag = $csslinks[0][$i]; + $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $csslinks[2][$i].' --> '.$link); + } + } + } + //general embed relinking - flash and others?? + if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { + for($i = 0; $i<count($embeds[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link + $link = book_prepare_link($base.$embeds[2][$i]); + if ($link == '') { + continue; + } + $origtag = $embeds[0][$i]; + $newtag = $embeds[1][$i].$link.$embeds[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $embeds[2][$i].' --> '.$link); + } + } + } + //flash in IE <param name=movie value="something" - I do hate IE! + if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { + for($i = 0; $i<count($params[0]); $i++) { + if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { + if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link + $link = book_prepare_link($base.$values[2]); + if ($link == '') { + continue; + } + $newvalue = $values[1].$link.$values[3]; + $newparam = str_replace($values[0], $newvalue, $params[0][$i]); + $ch->content = str_replace($params[0][$i], $newparam, $ch->content); + $modified = true; + book_log($ch->title, $values[2].' --> '.$link); + } + } + } + } + //java applet - add code bases if not present!!!! + if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { + for($i = 0; $i<count($applets[0]); $i++) { + if (!stripos($applets[0][$i], 'codebase')) { + $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); + $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); + $modified = true; + } + } + } + //relink java applet code bases + if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { + for($i = 0; $i<count($codebases[0]); $i++) { + if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link + $link = book_prepare_link($base.$codebases[2][$i]); + if ($link == '') { + continue; + } + $origtag = $codebases[0][$i]; + $newtag = $codebases[1][$i].$link.$codebases[3][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $codebases[2][$i].' --> '.$link); + } + } + } + //relative link conversion + if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { + for($i = 0; $i<count($links[0]); $i++) { + if ($links[2][$i] != '' //check for inner anchor links + && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link + $origtag = $links[0][$i]; + $target = book_prepare_link($rel.$links[2][$i]); //target chapter + if ($target != '' && array_key_exists($target, $originals)) { + $o = $originals[$target]; + $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; + $newtag = preg_replace('/target=[^\s>]/i','', $newtag); + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); + } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links + $target = book_prepare_link($base.$links[2][$i]); + $origtag = $links[0][$i]; + $newtag = $links[1][$i].$target.$links[4][$i]; + $ch->content = str_replace($origtag, $newtag, $ch->content); + $modified = true; + book_log($ch->title, $links[2][$i].' --> '.$target); + } + } + } + } + if ($modified) { + $DB->update_record('book_chapters', $ch); + } + } +} diff --git a/tool/print/index.php b/tool/print/index.php index 91542ec90ab..b1949dd7731 100644 --- a/tool/print/index.php +++ b/tool/print/index.php @@ -24,7 +24,7 @@ */ require(dirname(__FILE__).'/../../../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); +require_once(dirname(__FILE__).'/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID @@ -151,7 +151,7 @@ if ($chapter) { </table></div> <?php - list($toc, $titles) = book_get_print_toc($chapters, $book, $cm); + list($toc, $titles) = booktool_print_get_toc($chapters, $book, $cm); echo $toc; // chapters $link1 = $CFG->wwwroot.'/mod/book/view.php?id='.$course->id.'&chapterid='; diff --git a/tool/print/locallib.php b/tool/print/locallib.php new file mode 100644 index 00000000000..c3b716432db --- /dev/null +++ b/tool/print/locallib.php @@ -0,0 +1,89 @@ +<?php +// This file is part of Book plugin for 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/>. + +/** + * HTML import lib + * + * @package booktool + * @subpackage print + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +require_once(dirname(__FILE__).'/lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); + +/** + * Generate toc structure and titles + * + * @param array $chapters + * @param stdClass $book + * @param stdClass $cm + * @return array + */ +function booktool_print_get_toc($chapters, $book, $cm) { + $first = true; + $titles = array(); + + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + $toc = ''; //representation of toc (HTML) + + switch ($book->numbering) { + case BOOK_NUM_NONE: + $toc .= '<div class="book_toc_none">'; + break; + case BOOK_NUM_NUMBERS: + $toc .= '<div class="book_toc_numbered">'; + break; + case BOOK_NUM_BULLETS: + $toc .= '<div class="book_toc_bullets">'; + break; + case BOOK_NUM_INDENTED: + $toc .= '<div class="book_toc_indented">'; + break; + } + + $toc .= '<a name="toc"></a>'; //representation of toc (HTML) + + if ($book->customtitles) { + $toc .= '<h1>'.get_string('toc', 'mod_book').'</h1>'; + } else { + $toc .= '<p class="book_chapter_title">'.get_string('toc', 'mod_book').'</p>'; + } + $toc .= '<ul>'; + foreach($chapters as $ch) { + if (!$ch->hidden) { + $title = book_get_chapter_title($ch->id, $chapters, $book, $context); + if (!$ch->subchapter) { + $toc .= $first ? '<li>' : '</ul></li><li>'; + } else { + $toc .= $first ? '<li><ul><li>' : '<li>'; + } + $titles[$ch->id] = $title; + $toc .= '<a title="'.s($title).'" href="#ch'.$ch->id.'">'.$title.'</a>'; + $toc .= (!$ch->subchapter) ? '<ul>' : '</li>'; + $first = false; + } + } + $toc .= '</ul></li></ul>'; + $toc .= '</div>'; + $toc = str_replace('<ul></ul>', '', $toc); //cleanup of invalid structures + + return array($toc, $titles); +} From 920fd2c6a4bf0241932e9573c3673f4fee949eeb Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 12:59:39 +0200 Subject: [PATCH 149/455] add support for page types --- lang/en/book.php | 4 +++- lib.php | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lang/en/book.php b/lang/en/book.php index 0b866583288..2a56180de51 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -97,4 +97,6 @@ $string['book:read'] = 'Read book'; $string['book:edit'] = 'Edit book chapters'; $string['book:viewhiddenchapters'] = 'View hidden book chapters'; -$string['errorchapter'] = 'Error reading book chapter.'; \ No newline at end of file +$string['errorchapter'] = 'Error reading book chapter.'; + +$string['page-mod-book-x'] = 'Any book module page'; diff --git a/lib.php b/lib.php index 6b9aed9d7ca..09a89d2e66f 100644 --- a/lib.php +++ b/lib.php @@ -390,4 +390,17 @@ function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa // finally send the file send_stored_file($file, 360, 0, false); -} \ No newline at end of file +} + +/** + * Return a list of page types + * + * @param string $pagetype current page type + * @param stdClass $parentcontext Block's parent context + * @param stdClass $currentcontext Current context of block + * @return array + */ +function book_page_type_list($pagetype, $parentcontext, $currentcontext) { + $module_pagetype = array('mod-book-*'=>get_string('page-mod-book-x', 'mod_book')); + return $module_pagetype; +} From dd9b772bb603bdd1a0b2eb1bc9eed9be8125c023 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 13:25:55 +0200 Subject: [PATCH 150/455] add file browser support closes #14 --- lang/en/book.php | 1 + lib.php | 63 ++++++++++++++++++++++++++++++++++++ locallib.php | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) diff --git a/lang/en/book.php b/lang/en/book.php index 2a56180de51..984b9fb90e2 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -63,6 +63,7 @@ page.'; $string['customtitles'] = 'Custom titles'; $string['customtitles_help'] = 'Chapter titles are displayed automatically only in TOC.'; +$string['chapters'] = 'Chapters'; $string['editingchapter'] = 'Editing chapter'; $string['chaptertitle'] = 'Chapter title'; $string['content'] = 'Content'; diff --git a/lib.php b/lib.php index 09a89d2e66f..2bedf3cb0f0 100644 --- a/lib.php +++ b/lib.php @@ -339,6 +339,69 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig } } + +/** + * Lists all browsable file areas + * @param object $course + * @param object $cm + * @param object $context + * @return array + */ +function book_get_file_areas($course, $cm, $context) { + $areas = array(); + $areas['chapter'] = get_string('chapters', 'mod_book'); + return $areas; +} + +/** + * File browsing support for book module ontent area. + * @param object $browser + * @param object $areas + * @param object $course + * @param object $cm + * @param object $context + * @param string $filearea + * @param int $itemid + * @param string $filepath + * @param string $filename + * @return object file_info instance or null if not found + */ +function book_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { + global $CFG, $DB; + + // note: book_intro handled in file_browser automatically + + if (!has_capability('mod/book:read', $context)) { + return null; + } + + if ($filearea !== 'chapter') { + return null; + } + + require_once("$CFG->dirroot/mod/book/locallib.php"); + + if (is_null($itemid)) { + return new book_file_info($browser, $course, $cm, $context, $areas, $filearea, $itemid); + } + + $fs = get_file_storage(); + $filepath = is_null($filepath) ? '/' : $filepath; + $filename = is_null($filename) ? '.' : $filename; + if (!$storedfile = $fs->get_file($context->id, 'mod_book', $filearea, $itemid, $filepath, $filename)) { + return null; + } + + // modifications may be tricky - may cause caching problems + $canwrite = has_capability('mod/book:edit', $context); + + $chaptername = $DB->get_field('book_chapters', 'title', array('bookid'=>$cm->instance, 'id'=>$itemid)); + $chaptername = format_string($chaptername, true, array('context'=>$context)); + + $urlbase = $CFG->wwwroot.'/pluginfile.php'; + return new file_info_stored($browser, $context, $storedfile, $urlbase, $chaptername, true, true, $canwrite, false); +} + /** * Serves the book attachments. Implements needed access control ;-) * diff --git a/locallib.php b/locallib.php index 24c76b5d82c..5cfc7bc0816 100644 --- a/locallib.php +++ b/locallib.php @@ -319,3 +319,86 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { return $toc; } + + +/** + * File browsing support class + */ +class book_file_info extends file_info { + protected $course; + protected $cm; + protected $areas; + protected $filearea; + + public function __construct($browser, $course, $cm, $context, $areas, $filearea) { + parent::__construct($browser, $context); + $this->course = $course; + $this->cm = $cm; + $this->areas = $areas; + $this->filearea = $filearea; + } + + /** + * Returns list of standard virtual file/directory identification. + * The difference from stored_file parameters is that null values + * are allowed in all fields + * @return array with keys contextid, filearea, itemid, filepath and filename + */ + public function get_params() { + return array('contextid'=>$this->context->id, + 'component'=>'mod_book', + 'filearea' =>$this->filearea, + 'itemid' =>null, + 'filepath' =>null, + 'filename' =>null); + } + + /** + * Returns localised visible name. + * @return string + */ + public function get_visible_name() { + return $this->areas[$this->filearea]; + } + + /** + * Can I add new files or directories? + * @return bool + */ + public function is_writable() { + return false; + } + + /** + * Is directory? + * @return bool + */ + public function is_directory() { + return true; + } + + /** + * Returns list of children. + * @return array of file_info instances + */ + public function get_children() { + global $DB; + + $children = array(); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$this->cm->instance), 'pagenum', 'id, pagenum'); + foreach ($chapters as $itemid=>$unused) { + if ($child = $this->browser->get_file_info($this->context, 'mod_book', $this->filearea, $itemid)) { + $children[] = $child; + } + } + return $children; + } + + /** + * Returns parent file_info instance + * @return file_info or null for root + */ + public function get_parent() { + return $this->browser->get_file_info($this->context); + } +} From 21496cd86b2cbdba6ee48808ef7669f75a72f2f5 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 14:08:38 +0200 Subject: [PATCH 151/455] new markdown formatted readme release notes will be released separately --- README | 122 ------------------------------------------------------ README.md | 49 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 122 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index f922c139632..00000000000 --- a/README +++ /dev/null @@ -1,122 +0,0 @@ -Book module for Moodle -Copyright (C) 2004-2011 Petr Skoda (http://skodak.org) - - -This program 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. - -This program 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: - -http:www.gnu.org/copyleft/gpl.html - - -Book module for Moodle - version 2.0rc -=============================================================================== -Created by: - Petr Skoda (skodak) - most of the coding & design - Mojmir Volf - CSS formatted printer friendly format - -Developed for Technical University of Liberec (Czech Republic). -Many ideas and code were taken from other Moodle modules and Moodle itself - -Installation: - * see http://docs.moodle.org/en/Installing_contributed_modules_or_plugins - -List of features - version 2.0: - * easy to use - new teachers can quickly create multipage study materials - * two levels - only chapters and subchapters - * possible automatic chapter numbering - * chapters authored in build-in HTML editor (html stored in database, - images in course data) - * printing support - all chapters can be displayed on one CSS formatted page - * backup/restore with internal link preservation - * support for global searching in study materials (see contrib/search) - * import from html files (relinking of images, flash, Java applets and - relative links) - * works with all supported databases - - -Intentionally omitted features: - * more chapter levels - it would encourage teachers to write too much - complex and long books, better use standard standalone HTML editor and - import it as Resource. DocBook format is another suitable solution. - * TOC hiding in normal view - instead use printer friendly view - * PDF export - there is no elegant way AFAIK to convert HTML to PDF, - use virtual PDF printer or better use DocBook format for authoring - * detailed student tracking (postponed till officially supported) - * export as zipped set of HTML pages - instead use browser command - Save page as... in print view - -Future: - * I like eXe editor, I would like to improve Book in this direction ... - -CHANGELOG: -== 1.1RC1 - 2004/11/15 ======================================================= - * compatible ONLY with 1.4.2 and later !!! - * added sesskey for enhanced security - * navigation links do not enter hidden chapters - * import - correct linking when slasharguments are off - * removed coursefiles.php -== 1.1 - 2005/01/01 ======================================================= - * compatible ONLY with 1.4.3 and later! - * removed some unused searching stuff - * fixed headers in print.php -== 1.2RC - 2005/07/13 ========================================================== - * compatible with 1.5.1 + only - * improved restore - * fixed selection of directories for import - * html editor for summary - * fixed postgresql upgrade - * no need to move language packs -== 1.2 - 2006/03/11 ========================================================== - * removed 64kB page content limit in mysql - * exit button now goes to course section anchor - * chater title now in browser title bar - * added translations be and sv - * during import chapters with names "*_sub.htm?" are imported as subchapters - * deleting in import selection windows now works - * last version before transition to 1.6 -== 1.3alpha - 2006/03/12 ====================================================== - * compatible with 1.6dev only, use previous version for 1.5.x - * unicode upgrade supported - not much tested - * backup fixes - from Penny Leach, thanks! - * all languages converted to utf-8 - * moved to contrib/book_16 directory - * added proper content encoding conversion during import -== 1.4alpha - 2007/05/20 ==================================================== - * compatible with 1.8 - * export link enabled - thanks Eloy! - * no new features -== 1.5beta - 2008/08/14 ==================================================== - * compatible with 1.9.1 and above - * xhtml strict and css improvements - * formslib conversion - * capabilities implemented - * no new features -== 1.5 2009/11/11 ============================================================ - * minor cleanup - * new Slovenian language pack - thanks Mitja Podreka - * updated German Language pack - thanks Ralf Hilgenstock -== 1.9 2011/01/15 ============================================================ - * fixed print icons - * implemented user outline - * fixed page title formatting -== 2.0dev ============================================================ - * Moodle 2.0 conversion - * removed "Disable printing" option, please use capabilities instead - * completion tracking supported -== 2.0rc ============================================================ - * backup fixed - * print links open in new window - -Known issues, please do not file tracker reports: - * upgrade imscp export code (disabled for now) - * upgrade import code (disabled for now) - * legacy files were not upgraded yet - -Petr diff --git a/README.md b/README.md new file mode 100644 index 00000000000..31ded76eb90 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +Book module for Moodle - Copyright (C) 2004-2011 Petr Skoda (http://skodak.org) + +The Book module makes it easy to create multi-page resources with a book-like format. This module can be used to build complete book-like websites inside of your Moodle course. +This module was developed for Technical University of Liberec (Czech Republic). Many ideas and code were taken from other Moodle modules and Moodle itself + +This program 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. + +This program 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: http://www.gnu.org/copyleft/gpl.html + + +Created by: + +* Petr Skoda (skodak) - most of the coding & design +* Mojmir Volf - CSS formatted printer friendly format + + +Project page: + +* https://github.com/skodak/moodle-mod_book + + +Installation: + +* http://docs.moodle.org/en/Installing_contributed_modules_or_plugins + + +Issue tracker: + +* https://github.com/skodak/moodle-mod_book/issues?milestone=&labels= + + +Intentionally omitted features: + +* more chapter levels - it would encourage teachers to write too much complex and long books, better use standard standalone HTML editor and import it as Resource. DocBook format is another suitable solution. +* TOC hiding in normal view - instead use printer friendly view +* PDF export - there is no elegant way AFAIK to convert HTML to PDF, use virtual PDF printer or better use DocBook format for authoring +* detailed student tracking (postponed till officially supported) +* export as zipped set of HTML pages - instead use browser command Save page as... in print view + + +Future: + +* I like eXe editor, I would like to improve Book in this direction ... From bd4a960f36e595dc108ef1f24e6d84dcd5f1b84c Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 14:40:42 +0200 Subject: [PATCH 152/455] add full 1.9 restore support #15 --- backup/moodle1/lib.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backup/moodle1/lib.php b/backup/moodle1/lib.php index 20abcb3df10..9d4dcc9ab93 100755 --- a/backup/moodle1/lib.php +++ b/backup/moodle1/lib.php @@ -78,6 +78,7 @@ class moodle1_mod_book_handler extends moodle1_mod_handler { /** * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK * data available + * @param array $data */ public function process_book($data) { global $CFG; @@ -118,10 +119,15 @@ class moodle1_mod_book_handler extends moodle1_mod_handler { /** * This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/BOOK/CHAPTERS/CHAPTER * data available + * @param array $data */ public function process_book_chapters($data) { $this->write_xml('chapter', $data, array('/chapter/id')); - //TODO: convert chapter files + + // convert chapter files + $this->fileman->filearea = 'chapter'; + $this->fileman->itemid = $data['id']; + $data['content'] = moodle1_converter::migrate_referenced_files($data['content'], $this->fileman); } /** From 00328eb344dcafa6eaa9802bef24804e365fb480 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 15:44:02 +0200 Subject: [PATCH 153/455] fix borked backup and restore credit for the amp problem discovery goes to Davo Smith, closes #16 --- .../backup_book_activity_task.class.php | 26 +++++++++---------- .../restore_book_activity_task.class.php | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/backup/moodle2/backup_book_activity_task.class.php b/backup/moodle2/backup_book_activity_task.class.php index 2cc91ea0898..04b78098a11 100644 --- a/backup/moodle2/backup_book_activity_task.class.php +++ b/backup/moodle2/backup_book_activity_task.class.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -50,7 +50,7 @@ class backup_book_activity_task extends backup_activity_task { */ protected function define_my_steps() { // book only has one structure step - $this->add_step(new backup_book_activity_structure_step('book structure', 'book.xml')); + $this->add_step(new backup_book_activity_structure_step('book_structure', 'book.xml')); } /** @@ -58,30 +58,30 @@ class backup_book_activity_task extends backup_activity_task { * order to get transportable (encoded) links * * @param string $content - * @return $string encoded content + * @return string encoded content */ static public function encode_content_links($content) { global $CFG; - $base = preg_quote($CFG->wwwroot,"/"); + $base = preg_quote($CFG->wwwroot, "/"); // Link to the list of books - $search = "/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/"; + $search = "/($base\/mod\/book\/index.php\?id=)([0-9]+)/"; $content = preg_replace($search, '$@BOOKINDEX*$2@$', $content); // Link to book view by moduleid - $search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/"; + $search = "/($base\/mod\/book\/view.php\?id=)([0-9]+)(&|&)chapterid=([0-9]+)/"; + $content = preg_replace($search, '$@BOOKVIEWBYIDCH*$2*$4@$', $content); + + $search = "/($base\/mod\/book\/view.php\?id=)([0-9]+)/"; $content = preg_replace($search, '$@BOOKVIEWBYID*$2@$', $content); - $search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)&chapterid=([0-9]+)/"; - $content = preg_replace($search, '$@BOOKVIEWBYIDCH*$2*$3@$', $content); - // Link to book view by bookid - $search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)/"; - $content = preg_replace($search, '$@BOOKVIEWBYB*$2@$', $content); + $search = "/($base\/mod\/book\/view.php\?b=)([0-9]+)(&|&)chapterid=([0-9]+)/"; + $content = preg_replace($search, '$@BOOKVIEWBYBCH*$2*$4@$', $content); - $search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)&chapterid=([0-9]+)/"; - $content = preg_replace($search, '$@BOOKVIEWBYBCH*$2*$3@$', $content); + $search = "/($base\/mod\/book\/view.php\?b=)([0-9]+)/"; + $content = preg_replace($search, '$@BOOKVIEWBYB*$2@$', $content); return $content; } diff --git a/backup/moodle2/restore_book_activity_task.class.php b/backup/moodle2/restore_book_activity_task.class.php index df18aed32ba..180615e2fcc 100644 --- a/backup/moodle2/restore_book_activity_task.class.php +++ b/backup/moodle2/restore_book_activity_task.class.php @@ -81,11 +81,11 @@ class restore_book_activity_task extends restore_activity_task { // book by cm->id $rules[] = new restore_decode_rule('BOOKVIEWBYID', '/mod/book/view.php?id=$1', 'course_module'); - $rules[] = new restore_decode_rule('BOOKVIEWBYIDCH', '/mod/book/view.php?id=$1&chapterid=$2', array('course_module', 'book_chapter')); + $rules[] = new restore_decode_rule('BOOKVIEWBYIDCH', '/mod/book/view.php?id=$1&chapterid=$2', array('course_module', 'book_chapter')); // book by book->id $rules[] = new restore_decode_rule('BOOKVIEWBYB', '/mod/book/view.php?b=$1', 'book'); - $rules[] = new restore_decode_rule('BOOKVIEWBYBCH', '/mod/book/view.php?b=$1&chapterid=$2', array('book', 'book_chapter')); + $rules[] = new restore_decode_rule('BOOKVIEWBYBCH', '/mod/book/view.php?b=$1&chapterid=$2', array('book', 'book_chapter')); return $rules; } From a22a82822d856fc9c3abffdcb4f05722fc14ff77 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 19:03:03 +0200 Subject: [PATCH 154/455] migrate all legacy book files - yay! closes #7 --- db/upgrade.php | 9 +++++-- db/upgradelib.php | 65 ++++++++++++++++++++++++++++++++++++++++++++++- lib.php | 2 +- version.php | 4 +-- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/db/upgrade.php b/db/upgrade.php index 33a516a60c1..5c93777ccde 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -138,7 +138,7 @@ function xmldb_book_upgrade($oldversion) { $context = get_context_instance(CONTEXT_MODULE, $book->cmid); - book_migrate_moddata_dir_to_legacy($book, $context, '/'); + mod_book_migrate_moddata_dir_to_legacy($book, $context, '/'); // remove dirs if empty @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id/"); @@ -174,8 +174,13 @@ function xmldb_book_upgrade($oldversion) { upgrade_mod_savepoint(true, 2011011601, 'book'); } + if ($oldversion < 2011090800) { + require_once("$CFG->dirroot/mod/book/db/upgradelib.php"); - //TODO: migrate the legacy file.php links to new pluginfile.php and file areas per chapter + mod_book_migrate_all_areas(); + + upgrade_mod_savepoint(true, 2011090800, 'book'); + } return true; diff --git a/db/upgradelib.php b/db/upgradelib.php index 952cb82c5bf..cda0c9cc269 100644 --- a/db/upgradelib.php +++ b/db/upgradelib.php @@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die; * @param string $path * @return void */ -function book_migrate_moddata_dir_to_legacy($book, $context, $path) { +function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) { global $OUTPUT, $CFG; $base = "$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id"; @@ -103,4 +103,67 @@ function book_migrate_moddata_dir_to_legacy($book, $context, $path) { } } unset($items); //release file handles +} + +/** + * Migrate legacy files in intro and chapters + * @return void + */ +function mod_book_migrate_all_areas() { + global $DB; + + $rsbooks = $DB->get_recordset('book'); + foreach($rsbooks as $book) { + upgrade_set_timeout(360); // set up timeout, may also abort execution + $cm = get_coursemodule_from_instance('book', $book->id); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + mod_book_migrate_area($book, 'intro', 'book', $book->course, $context, 'mod_book', 'intro', 0); + + $rschapters = $DB->get_recordset('book_chapters', array('bookid'=>$book->id)); + foreach ($rschapters as $chapter) { + mod_book_migrate_area($chapter, 'content', 'book_chapters', $book->course, $context, 'mod_book', 'chapter', $chapter->id); + } + $rschapters->close(); + } + $rsbooks->close(); +} + +/** + * Migrate one area, this should be probably part of moodle core... + * @param $record + * @param $field + * @param $table + * @param $courseid + * @param $context + * @param $component + * @param $filearea + * @param $itemid + * @return void + */ +function mod_book_migrate_area($record, $field, $table, $courseid, $context, $component, $filearea, $itemid) { + global $CFG, $DB; + + $fs = get_file_storage(); + + foreach(array(get_site()->id, $courseid) as $cid) { + $matches = null; + $ooldcontext = get_context_instance(CONTEXT_COURSE, $cid); + if (preg_match_all("|$CFG->wwwroot/file.php(\?file=)?/$cid(/[^\s'\"&\?#]+)|", $record->$field, $matches)) { + $file_record = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid); + foreach ($matches[2] as $i=>$filepath) { + if (!$file = $fs->get_file_by_hash(sha1("/$ooldcontext->id/course/legacy/0".$filepath))) { + continue; + } + try { + if (!$newfile = $fs->get_file_by_hash(sha1("/$context->id/$component/$filearea/$itemid".$filepath))) { + $fs->create_file_from_storedfile($file_record, $file); + } + $record->$field = str_replace($matches[0][$i], '@@PLUGINFILE@@'.$filepath, $record->$field); + } catch (Exception $ex) { + // ignore problems + } + $DB->set_field($table, $field, $record->$field, array('id'=>$record->id)); + } + } + } } \ No newline at end of file diff --git a/lib.php b/lib.php index 2bedf3cb0f0..2aa65be1206 100644 --- a/lib.php +++ b/lib.php @@ -369,7 +369,7 @@ function book_get_file_areas($course, $cm, $context) { function book_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { global $CFG, $DB; - // note: book_intro handled in file_browser automatically + // note: 'intro' area is handled in file_browser automatically if (!has_capability('mod/book:read', $context)) { return null; diff --git a/version.php b/version.php index fc28ee6529f..469a36ae2f9 100644 --- a/version.php +++ b/version.php @@ -25,8 +25,8 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011032003; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2011070101; // Requires this Moodle version +$module->version = 2011090800; // The current module version (Date: YYYYMMDDXX) +$module->requires = 2011070100; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From e145338300d37aaadacad1fba7802cc51070f0b0 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 20:44:13 +0200 Subject: [PATCH 155/455] fix indentation --- tool/print/lib.php | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/tool/print/lib.php b/tool/print/lib.php index affd262bfc3..8cc6a83609f 100644 --- a/tool/print/lib.php +++ b/tool/print/lib.php @@ -26,37 +26,37 @@ defined('MOODLE_INTERNAL') || die; function booktool_print_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { - global $USER, $PAGE, $CFG, $DB, $OUTPUT; + global $USER, $PAGE, $CFG, $DB, $OUTPUT; - if ($PAGE->cm->modname !== 'book') { - return; - } + if ($PAGE->cm->modname !== 'book') { + return; + } - if (empty($PAGE->cm->context)) { - $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); - } + if (empty($PAGE->cm->context)) { + $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); + } - $params = $PAGE->url->params(); + $params = $PAGE->url->params(); - if (empty($params['id']) or empty($params['chapterid'])) { - return; - } + if (empty($params['id']) or empty($params['chapterid'])) { + return; + } - if (has_capability('booktool/print:print', $PAGE->cm->context)) { - $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'])); - $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - if ($CFG->version > 2011020900) { - $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); - $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); - } else { - $booknode->add(get_string('printbook', 'booktool_print'), $url1, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'booktool_print', array('class'=>'icon'))); - $booknode->add(get_string('printchapter', 'booktool_print'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'booktool_print', array('class'=>'icon'))); - } - } + if (has_capability('booktool/print:print', $PAGE->cm->context)) { + $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'])); + $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); + if ($CFG->version > 2011020900) { + $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); + $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); + } else { + $booknode->add(get_string('printbook', 'booktool_print'), $url1, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'booktool_print', array('class'=>'icon'))); + $booknode->add(get_string('printchapter', 'booktool_print'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'booktool_print', array('class'=>'icon'))); + } + } } /** From df78099aeeac38bc28811ff1393202102db989a9 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 20:45:34 +0200 Subject: [PATCH 156/455] remove old hack --- tool/print/lib.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tool/print/lib.php b/tool/print/lib.php index 8cc6a83609f..6171f367434 100644 --- a/tool/print/lib.php +++ b/tool/print/lib.php @@ -47,15 +47,10 @@ function booktool_print_extend_settings_navigation(settings_navigation $settings if (has_capability('booktool/print:print', $PAGE->cm->context)) { $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'])); $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - if ($CFG->version > 2011020900) { - $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); - $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); - } else { - $booknode->add(get_string('printbook', 'booktool_print'), $url1, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_book', '', 'booktool_print', array('class'=>'icon'))); - $booknode->add(get_string('printchapter', 'booktool_print'), $url2, navigation_node::TYPE_SETTING, null, null, new pix_icon('print_chapter', '', 'booktool_print', array('class'=>'icon'))); - } + $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); + $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); + $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); } } From 2ecc0ff5d0f7ba8bff263192812d6b10841936e4 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 22:13:12 +0200 Subject: [PATCH 157/455] add proper deleting of chapter files --- delete.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/delete.php b/delete.php index 992de9687d3..98d9f5a08c6 100644 --- a/delete.php +++ b/delete.php @@ -52,6 +52,7 @@ $PAGE->set_heading(format_string($course->fullname)); ///form processing if ($confirm) { // the operation was confirmed. + $fs = get_file_storage(); if (!$chapter->subchapter) { //delete all its subchapters if any $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter'); $found = false; @@ -59,12 +60,14 @@ if ($confirm) { // the operation was confirmed. if ($ch->id == $chapter->id) { $found = true; } else if ($found and $ch->subchapter) { + $fs->delete_area_files($context->id, 'mod_book', 'chapter', $ch->id); $DB->delete_records('book_chapters', array('id'=>$ch->id)); } else if ($found) { break; } } } + $fs->delete_area_files($context->id, 'mod_book', 'chapter', $chapter->id); $DB->delete_records('book_chapters', array('id'=>$chapter->id)); add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); From 22d3a77a5262e2d66c656bea0275ecb336d8223d Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sat, 8 Oct 2011 22:24:23 +0200 Subject: [PATCH 158/455] oops, it is 10th month already --- tool/exportimscp/version.php | 2 +- tool/importhtml/version.php | 2 +- tool/print/version.php | 2 +- version.php | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tool/exportimscp/version.php b/tool/exportimscp/version.php index 4afe31092bb..b946c71cd16 100644 --- a/tool/exportimscp/version.php +++ b/tool/exportimscp/version.php @@ -25,5 +25,5 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2011090800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2011100800; // The current plugin version (Date: YYYYMMDDXX) $plugin->component = 'booktool_exportimscp'; // Full name of the plugin (used for diagnostics) diff --git a/tool/importhtml/version.php b/tool/importhtml/version.php index ca37b8a58cd..2b73b8bb41e 100644 --- a/tool/importhtml/version.php +++ b/tool/importhtml/version.php @@ -25,5 +25,5 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2011090800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2011100800; // The current plugin version (Date: YYYYMMDDXX) $plugin->component = 'booktool_importhtml'; // Full name of the plugin (used for diagnostics) diff --git a/tool/print/version.php b/tool/print/version.php index 3de5f9c85eb..778a12d18e4 100644 --- a/tool/print/version.php +++ b/tool/print/version.php @@ -25,5 +25,5 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2011090800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2011100800; // The current plugin version (Date: YYYYMMDDXX) $plugin->component = 'booktool_print'; // Full name of the plugin (used for diagnostics) diff --git a/version.php b/version.php index 469a36ae2f9..86a45f3e09a 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011090800; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011100800; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070100; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$module->maturity = MATURITY_RC; -$module->release = "2.0rc (20110320)"; // User-friendly version number +$module->maturity = MATURITY_BETA; +$module->release = "2.1dev (20111008)"; // User-friendly version number From 34660c5979863c9b45038853bdb356c66d6d60da Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sun, 9 Oct 2011 12:55:54 +0200 Subject: [PATCH 159/455] rewritten html import hopefully there are not many bugs, closes #13 --- lib.php | 11 +- tool/importhtml/import_form.php | 38 +- tool/importhtml/index.php | 94 +--- .../lang/en/booktool_importhtml.php | 10 +- tool/importhtml/lib.php | 12 +- tool/importhtml/locallib.php | 429 ++++++++++-------- 6 files changed, 302 insertions(+), 292 deletions(-) diff --git a/lib.php b/lib.php index 2aa65be1206..9cf8faaa6dc 100644 --- a/lib.php +++ b/lib.php @@ -308,13 +308,6 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); } - - $params = $PAGE->url->params(); - - if (empty($params['id'])) { - return; - } - $plugins = get_plugin_list('booktool'); foreach($plugins as $plugin=>$dir) { if (file_exists("$dir/lib.php")) { @@ -326,7 +319,9 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig } } - if (!empty($params['chapterid']) and has_capability('mod/book:edit', $PAGE->cm->context)) { + $params = $PAGE->url->params(); + + if (!empty($params['id']) and !empty($params['chapterid']) and has_capability('mod/book:edit', $PAGE->cm->context)) { if (!empty($USER->editing)) { $string = get_string("turneditingoff"); $edit = '0'; diff --git a/tool/importhtml/import_form.php b/tool/importhtml/import_form.php index 23ec250f646..7d4a383c7e7 100644 --- a/tool/importhtml/import_form.php +++ b/tool/importhtml/import_form.php @@ -27,15 +27,22 @@ defined('MOODLE_INTERNAL') || die; require_once($CFG->libdir.'/formslib.php'); -class book_import_form extends moodleform { +class booktool_importhtml_form extends moodleform { function definition() { - global $CFG; $mform = $this->_form; $data = $this->_customdata; $mform->addElement('header', 'general', get_string('import')); + $options = array( + //'0'=>get_string('typeonefile', 'booktool_importhtml'), + '1'=>get_string('typezipdirs', 'booktool_importhtml'), + '2'=>get_string('typezipfiles', 'booktool_importhtml'), + ); + $mform->addElement('select', 'type', get_string('type', 'booktool_importhtml'), $options); + $mform->setDefault('type', 2); + $mform->addElement('filepicker', 'importfile', get_string('file')); $mform->addRule('importfile', null, 'required'); @@ -45,17 +52,36 @@ class book_import_form extends moodleform { $mform->addElement('hidden', 'chapterid'); $mform->setType('chapterid', PARAM_INT); - $this->add_action_buttons(true, get_string('import', 'mod_book')); + $this->add_action_buttons(true, get_string('doimport', 'booktool_importhtml')); $this->set_data($data); } function validation($data, $files) { - global $CFG; + global $USER; - $errors = parent::validation($data, $files); + if ($errors = parent::validation($data, $files)) { + return $errors; + } - //TODO: validate package + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $fs = get_file_storage(); + + if (!$files = $fs->get_area_files($usercontext->id, 'user', 'draft', $data['importfile'], 'id', false)) { + $errors['importfile'] = get_string('required'); + return $errors; + } else { + $file = reset($files); + if ($file->get_mimetype() != 'application/zip') { + $errors['importfile'] = get_string('invalidfiletype', 'error', $file->get_filename()); + // better delete current file, it is not usable anyway + $fs->delete_area_files($usercontext->id, 'user', 'draft', $data['importfile']); + } else { + if (!$chpterfiles = toolbook_importhtml_get_chapter_files($file, $data['type'])) { + $errors['importfile'] = get_string('errornochapters', 'booktool_importhtml'); + } + } + } return $errors; } diff --git a/tool/importhtml/index.php b/tool/importhtml/index.php index 6532189d9a5..9e557ca8eac 100644 --- a/tool/importhtml/index.php +++ b/tool/importhtml/index.php @@ -23,11 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -die('TODO'); - -require('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); -require_once('import_form.php'); +require(dirname(__FILE__).'/../../../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); +require_once(dirname(__FILE__).'/import_form.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = optional_param('chapterid', 0, PARAM_INT); // Chapter ID @@ -39,9 +37,9 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); -require_capability('mod/book:import', $context); +require_capability('booktool/importhtml:import', $context); -$PAGE->set_url('/mod/book/import.php', array('id'=>$id, 'chapterid'=>$chapterid)); +$PAGE->set_url('/mod/book/tool/importhtml/index.php', array('id'=>$id, 'chapterid'=>$chapterid)); if ($chapterid) { if (!$chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id))) { @@ -59,7 +57,7 @@ $PAGE->set_heading(format_string($course->fullname)); $strbook = get_string('modulename', 'mod_book'); $strbooks = get_string('modulenameplural', 'mod_book'); -$mform = new book_import_form(null, array('id'=>$id, 'chapterid'=>$chapterid)); +$mform = new booktool_importhtml_form(null, array('id'=>$id, 'chapterid'=>$chapterid)); /// If data submitted, then process and store. if ($mform->is_cancelled()) { @@ -70,81 +68,25 @@ if ($mform->is_cancelled()) { } } else if ($data = $mform->get_data()) { + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('importingchapters', 'booktool_importhtml')); - - -/* - - $coursebase = $CFG->dataroot.'/'.$book->course; - - $reference = book_prepare_link($data->reference); - - if ($reference == '') { - $base = $coursebase; - } else { - $base = $coursebase.'/'.$reference; + // this is a bloody hack - children do not try this at home! + $fs = get_file_storage(); + $draftid = file_get_submitted_draft_itemid('importfile'); + if (!$files = $fs->get_area_files(get_context_instance(CONTEXT_USER, $USER->id)->id, 'user', 'draft', $draftid, 'id DESC', false)) { + redirect($PAGE->url); } + $file = reset($files); + toolbook_importhtml_import_chapters($file, $data->type, $book, $context); - //prepare list of html files in $refs - $refs = array(); - $htmlpat = '/\.html$|\.htm$/i'; - if (is_dir($base)) { //import whole directory - $basedir = opendir($base); - while ($file = readdir($basedir)) { - $path = $base.'/'.$file; - if (filetype($path) == 'file' and preg_match($htmlpat, $file)) { - $refs[] = str_replace($coursebase, '', $path); - } - } - asort($refs); - } else if (is_file($base)) { //import single file - $refs[] = '/'.$reference; - } else { //what is it??? - error('Incorrect file/directory specified!'); - } - - print_header("$course->shortname: $book->name", $course->fullname, $navigation); - - //import files - print_box_start('generalbox boxaligncenter centerpara'); - echo '<strong>'.get_string('importing', 'book').':</strong>'; - echo '<table cellpadding="2" cellspacing="2" border="1">'; - book_preload_chapters($book); // fix structure - foreach($refs as $ref) { - $chapter = book_read_chapter($coursebase, $ref); - if ($chapter) { - $chapter->bookid = $book->id; - $chapter->pagenum = $DB->count_records('book_chapters', array('bookid'=>$book->id)+1); - $chapter->timecreated = time(); - $chapter->timemodified = time(); - echo "imsrc:".$chapter->importsrc; - if (($data->subchapter) || preg_match('/_sub\.htm/i', $chapter->importsrc)) { //if filename or directory starts with sub_* treat as subdirecotories - $chapter->subchapter = 1; - } else { - $chapter->subchapter = 0; - } - $chapter->id = $DB->insert_record('book_chapters', $chapter); - - add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); - add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id); - } - } - echo '</table><br />'; - echo '<strong>'.get_string('relinking', 'book').':</strong>'; - echo '<table cellpadding="2" cellspacing="2" border="1">'; - //relink whole book = all chapters - book_relink($cm->id, $book->id, $course->id); - echo '</table><br />'; - print_box_end(); - print_continue('view.php?id='.$cm->id); - print_footer($course); + echo $OUTPUT->continue_button(new moodle_url('/mod/book/view.php', array('id'=>$id))); + echo $OUTPUT->footer(); die; - - */ } echo $OUTPUT->header(); -echo $OUTPUT->heading(get_string('importingchapters', 'mod_book')); +echo $OUTPUT->heading(get_string('import', 'booktool_importhtml')); $mform->display(); diff --git a/tool/importhtml/lang/en/booktool_importhtml.php b/tool/importhtml/lang/en/booktool_importhtml.php index fc8ff1f95ae..ff6ceae1a4c 100644 --- a/tool/importhtml/lang/en/booktool_importhtml.php +++ b/tool/importhtml/lang/en/booktool_importhtml.php @@ -26,12 +26,14 @@ defined('MOODLE_INTERNAL') || die; $string['doimport'] = 'Import'; -$string['import'] = 'Import'; +$string['errornochapters'] = 'Can not find chapters in selected file'; +$string['import'] = 'Import from HTML'; $string['importhtml:import'] = 'Import chapters'; -$string['importinfo'] = 'Import selected HTML file or directory.<br />Chapters are sorted alphabetically using file names.<br />Files named \'sub_*.*\' are always imported as subchapters.'; $string['importing'] = 'Importing'; $string['importingchapters'] = 'Importing chapters into book'; -$string['import_help'] = 'You can import a single HTML file or every HTML file in a direcory. Relative file links are converted to absolute chapter links. Images, flash and Java are relinked too.'; -$string['maindirectory'] = 'Main directory'; $string['pluginname'] = 'Book HTML import'; $string['relinking'] = 'Relinking'; +$string['type'] = 'Type'; +$string['typeonefile'] = 'One HTML file with headings as chapters'; +$string['typezipfiles'] = 'Each HTML file represents one chapter'; +$string['typezipdirs'] = 'Each directory represents one chapter'; diff --git a/tool/importhtml/lib.php b/tool/importhtml/lib.php index 7723c197fdb..59eb547c30e 100644 --- a/tool/importhtml/lib.php +++ b/tool/importhtml/lib.php @@ -36,16 +36,8 @@ function booktool_importhtml_extend_settings_navigation(settings_navigation $set $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); } - - $params = $PAGE->url->params(); - - if (empty($params['id'])) { - return; - } - - if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) { - //TODO - //$doimport = ($allowimport and $edit) ? '<div>(<a href="import.php?id='.$cm->id.'">'.get_string('doimport', 'book').'</a>)</div>' : ''; + $url = new moodle_url('/mod/book/tool/importhtml/index.php', array('id'=>$PAGE->cm->id)); + $booknode->add(get_string('import', 'booktool_importhtml'), $url, navigation_node::TYPE_SETTING, null, null, null); } } \ No newline at end of file diff --git a/tool/importhtml/locallib.php b/tool/importhtml/locallib.php index 110acc1ce6f..6a41d98f4d1 100644 --- a/tool/importhtml/locallib.php +++ b/tool/importhtml/locallib.php @@ -25,211 +25,264 @@ defined('MOODLE_INTERNAL') || die; +require_once(dirname(__FILE__).'/lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); -//TODO: not converted yet! +function toolbook_importhtml_import_chapters($package, $type, $book, $context, $verbose = true) { + global $DB, $OUTPUT; -/// normalize relative links (= remove ..) -function book_prepare_link($ref) { - if ($ref == '') { - return ''; + $fs = get_file_storage(); + $chapterfiles = toolbook_importhtml_get_chapter_files($package, $type); + $packer = get_file_packer('application/zip'); + $fs->delete_area_files($context->id, 'mod_book', 'importhtmltemp', 0); + $package->extract_to_storage($packer, $context->id, 'mod_book', 'importhtmltemp', 0, '/'); + //$datafiles = $fs->get_area_files($context->id, 'mod_book', 'importhtmltemp', 0, 'id', false); + //echo "<pre>";p(var_export($datafiles, true)); + + $chapters = array(); + + if ($verbose) { + echo $OUTPUT->notification(get_string('importing', 'booktool_importhtml'), 'notifysuccess'); } - $ref = str_replace('\\','/',$ref); //anti MS hack - $cnt = substr_count($ref, '..'); - for($i=0; $i<$cnt; $i++) { - $ref = ereg_replace('[^/]+/\.\./', '', $ref); + if ($type == 0) { + $chapterfile = reset($chapterfiles); + if ($file = $fs->get_file_by_hash("$context->id/mod_book/importhtmltemp/0/$chapterfile->pathname")) { + $htmlcontent = toolbook_importhtml_fix_encoding($file->get_content()); + $htmlchapters = toolbook_importhtml_parse_headings(toolbook_importhtml_parse_body($htmlcontent)); + //TODO: process h1 as main chapter and h2 as subchapters + } + } else { + foreach ($chapterfiles as $chapterfile) { + if ($file = $fs->get_file_by_hash(sha1("/$context->id/mod_book/importhtmltemp/0/$chapterfile->pathname"))) { + $chapter = new stdClass(); + $htmlcontent = toolbook_importhtml_fix_encoding($file->get_content()); + + $chapter->bookid = $book->id; + $chapter->pagenum = $DB->get_field_sql('SELECT MAX(pagenum) FROM {book_chapters} WHERE bookid = ?', array($book->id)) + 1; + $chapter->importsrc = '/'.$chapterfile->pathname; + $chapter->content = toolbook_importhtml_parse_styles($htmlcontent); + $chapter->content .= toolbook_importhtml_parse_body($htmlcontent); + $chapter->title = toolbook_importhtml_parse_title($htmlcontent, $chapterfile->pathname); + $chapter->contentformat = FORMAT_HTML; + $chapter->hidden = 0; + $chapter->timecreated = time(); + $chapter->timemodified = time(); + if (preg_match('/_sub(\/|\.htm)/i', $chapter->importsrc)) { //if filename or directory ends with sub_* treat as subchapters + $chapter->subchapter = 1; + } else { + $chapter->subchapter = 0; + } + + $chapter->id = $DB->insert_record('book_chapters', $chapter); + $chapters[$chapter->id] = $chapter; + + add_to_log($book->course, 'book', 'update', 'view.php?id='.$context->instanceid.'&chapterid='.$chapter->id, $book->id, $context->instanceid); + } + } } - //still any '..' left?? == error! error! - if (substr_count($ref, '..') > 0) { - return ''; + + if ($verbose) { + echo $OUTPUT->notification(get_string('relinking', 'booktool_importhtml'), 'notifysuccess'); } - if (ereg('[\|\`]', $ref)) { // check for other bad characters - return ''; + $allchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); + foreach ($chapters as $chapter) { + // find references to all files and copy them + relink them + $matches = null; + if (preg_match_all('/(src|codebase|name|href)\s*=\s*"([^"]+)"/i', $chapter->content, $matches)) { + $file_record = array('contextid'=>$context->id, 'component'=>'mod_book', 'filearea'=>'chapter', 'itemid'=>$chapter->id); + foreach ($matches[0] as $i=>$match) { + $filepath = dirname($chapter->importsrc).'/'.$matches[2][$i]; + $filepath = toolbook_importhtml_fix_path($filepath); + + if (strtolower($matches[1][$i]) === 'href') { + // skip linked html files, we will try chapter relinking later + foreach ($allchapters as $target) { + if ($target->importsrc === $filepath) { + continue 2; + } + } + } + + if ($file = $fs->get_file_by_hash(sha1("/$context->id/mod_book/importhtmltemp/0$filepath"))) { + if (!$oldfile = $fs->get_file_by_hash(sha1("/$context->id/mod_book/chapter/$chapter->id$filepath"))) { + $fs->create_file_from_storedfile($file_record, $file); + } + $chapter->content = str_replace($match, $matches[1][$i].'="@@PLUGINFILE@@'.$filepath.'"', $chapter->content); + } + } + $DB->set_field('book_chapters', 'content', $chapter->content, array('id'=>$chapter->id)); + } } - return $ref; + unset($chapters); + + $allchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); + foreach ($allchapters as $chapter) { + $newcontent = $chapter->content; + $matches = null; + if (preg_match_all('/(href)\s*=\s*"([^"]+)"/i', $chapter->content, $matches)) { + foreach ($matches[0] as $i=>$match) { + if (strpos($matches[2][$i], ':') !== false or strpos($matches[2][$i], '@') !== false) { + // it is either absolute or pluginfile link + continue; + } + $chapterpath = dirname($chapter->importsrc).'/'.$matches[2][$i]; + $chapterpath = toolbook_importhtml_fix_path($chapterpath); + foreach ($allchapters as $target) { + if ($target->importsrc === $chapterpath) { + $newcontent = str_replace($match, 'href="'.new moodle_url('/mod/book/view.php', array('id'=>$context->instanceid, 'chapter'=>$target->id)).'"', $newcontent); + } + } + } + } + if ($newcontent !== $chapter->content) { + $DB->set_field('book_chapters', 'content', $newcontent, array('id'=>$chapter->id)); + } + } + + add_to_log($book->course, 'course', 'update mod', '../mod/book/view.php?id='.$context->instanceid, 'book '.$book->id); + $fs->delete_area_files($context->id, 'mod_book', 'importhtmltemp', 0); } -/// read chapter content from file -function book_read_chapter($base, $ref) { - $file = $base.'/'.$ref; - if (filesize($file) <= 0 or !is_readable($file)) { - book_log($ref, get_string('error'), 2); - return; +function toolbook_importhtml_parse_headings($html) { + //TODO +} + +function toolbook_importhtml_parse_styles($html) { + $styles = ''; + if (preg_match('/<head[^>]*>(.+)<\/head>/is', $html, $matches)) { + $head = $matches[1]; + if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css + for($i=0; $i<count($matches[0]); $i++) { + $styles .= $matches[0][$i]."\n"; + } + } } - //first read data - $handle = fopen($file, "rb"); - $contents = fread($handle, filesize($file)); - fclose($handle); - //extract title - $chapter = new object(); - if (preg_match('/<title>([^<]+)<\/title>/i', $contents, $matches)) { - $chapter->title = $matches[1]; - } else { - $chapter->title = $ref; + return $styles; +} + +function toolbook_importhtml_fix_path($path) { + $path = str_replace('\\', '/', $path); //anti MS hack + $path = '/'.ltrim($path, './'); // dirname() produces . for top level files + our paths start with / + + $cnt = substr_count($path, '..'); + for($i=0; $i<$cnt; $i++) { + $path = preg_replace('|[^/]+/\.\./|', '', $path, 1); } - //extract page body - if (preg_match('/<body[^>]*>(.+)<\/body>/is', $contents, $matches)) { - $chapter->content = $matches[1]; - } else { - book_log($ref, get_string('error'), 2); - return; - } - book_log($ref, get_string('ok')); - $chapter->importsrc = $ref; - //extract page head - if (preg_match('/<head[^>]*>(.+)<\/head>/is', $contents, $matches)) { + + $path = clean_param($path, PARAM_PATH); + return $path; +} + +function toolbook_importhtml_fix_encoding($html) { + if (preg_match('/<head[^>]*>(.+)<\/head>/is', $html, $matches)) { $head = $matches[1]; if (preg_match('/charset=([^"]+)/is', $head, $matches)) { $enc = $matches[1]; - $textlib = textlib_get_instance(); - $chapter->content = $textlib->convert($chapter->content, $enc, 'utf-8'); - $chapter->title = $textlib->convert($chapter->title, $enc, 'utf-8'); - } - if (preg_match_all('/<link[^>]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css - for($i=0; $i<count($matches[0]); $i++){ - $chapter->content = $matches[0][$i]."\n".$chapter->content; - } + return textlib_get_instance()->convert($html, $enc, 'utf-8'); } } - return $chapter; + return iconv('UTF-8', 'UTF-8//IGNORE', $html); } -///relink images and relative links -function book_relink($id, $bookid, $courseid) { - global $CFG, $DB; - - if ($CFG->slasharguments) { - $coursebase = $CFG->wwwroot.'/file.php/'.$courseid; +function toolbook_importhtml_parse_body($html) { + $matches = null; + if (preg_match('/<body[^>]*>(.+)<\/body>/is', $html, $matches)) { + return $matches[1]; } else { - $coursebase = $CFG->wwwroot.'/file.php?file=/'.$courseid; - } - $chapters = $DB->get_records('book_chapters', array('bookid'=>$bookid), 'pagenum', 'id, pagenum, title, content, importsrc'); - $originals = array(); - foreach($chapters as $ch) { - $originals[$ch->importsrc] = $ch; - } - foreach($chapters as $ch) { - $rel = substr($ch->importsrc, 0, strrpos($ch->importsrc, '/')+1); - $base = $coursebase.strtr(urlencode($rel), array("%2F" => "/")); //for better internationalization (dlnsk) - $modified = false; - //image relinking - if ($ch->importsrc && preg_match_all('/(<img[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $images)) { - for($i = 0; $i<count($images[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $images[2][$i])) { // not absolute link - $link = book_prepare_link($base.$images[2][$i]); - if ($link == '') { - continue; - } - $origtag = $images[0][$i]; - $newtag = $images[1][$i].$link.$images[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $images[2][$i].' --> '.$link); - } - } - } - //css relinking (dlnsk) - if ($ch->importsrc && preg_match_all('/(<link[^>]+href=")([^"]+)("[^>]*>)/i', $ch->content, $csslinks)) { - for($i = 0; $i<count($csslinks[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $csslinks[2][$i])) { // not absolute link - $link = book_prepare_link($base.$csslinks[2][$i]); - if ($link == '') { - continue; - } - $origtag = $csslinks[0][$i]; - $newtag = $csslinks[1][$i].$link.$csslinks[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $csslinks[2][$i].' --> '.$link); - } - } - } - //general embed relinking - flash and others?? - if ($ch->importsrc && preg_match_all('/(<embed[^>]+src=")([^"]+)("[^>]*>)/i', $ch->content, $embeds)) { - for($i = 0; $i<count($embeds[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $embeds[2][$i])) { // not absolute link - $link = book_prepare_link($base.$embeds[2][$i]); - if ($link == '') { - continue; - } - $origtag = $embeds[0][$i]; - $newtag = $embeds[1][$i].$link.$embeds[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $embeds[2][$i].' --> '.$link); - } - } - } - //flash in IE <param name=movie value="something" - I do hate IE! - if ($ch->importsrc && preg_match_all('/<param[^>]+name\s*=\s*"?movie"?[^>]*>/i', $ch->content, $params)) { - for($i = 0; $i<count($params[0]); $i++) { - if (preg_match('/(value=\s*")([^"]+)(")/i', $params[0][$i], $values)) { - if (!preg_match('/[a-z]+:/i', $values[2])) { // not absolute link - $link = book_prepare_link($base.$values[2]); - if ($link == '') { - continue; - } - $newvalue = $values[1].$link.$values[3]; - $newparam = str_replace($values[0], $newvalue, $params[0][$i]); - $ch->content = str_replace($params[0][$i], $newparam, $ch->content); - $modified = true; - book_log($ch->title, $values[2].' --> '.$link); - } - } - } - } - //java applet - add code bases if not present!!!! - if ($ch->importsrc && preg_match_all('/<applet[^>]*>/i', $ch->content, $applets)) { - for($i = 0; $i<count($applets[0]); $i++) { - if (!stripos($applets[0][$i], 'codebase')) { - $newapplet = str_ireplace('<applet', '<applet codebase="."', $applets[0][$i]); - $ch->content = str_replace($applets[0][$i], $newapplet, $ch->content); - $modified = true; - } - } - } - //relink java applet code bases - if ($ch->importsrc && preg_match_all('/(<applet[^>]+codebase=")([^"]+)("[^>]*>)/i', $ch->content, $codebases)) { - for($i = 0; $i<count($codebases[0]); $i++) { - if (!preg_match('/[a-z]+:/i', $codebases[2][$i])) { // not absolute link - $link = book_prepare_link($base.$codebases[2][$i]); - if ($link == '') { - continue; - } - $origtag = $codebases[0][$i]; - $newtag = $codebases[1][$i].$link.$codebases[3][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $codebases[2][$i].' --> '.$link); - } - } - } - //relative link conversion - if ($ch->importsrc && preg_match_all('/(<a\s[^>]*href=")([^"^#]*)(#[^"]*)?("[^>]*>)/i', $ch->content, $links)) { - for($i = 0; $i<count($links[0]); $i++) { - if ($links[2][$i] != '' //check for inner anchor links - && !preg_match('/[a-z]+:/i', $links[2][$i])) { //not absolute link - $origtag = $links[0][$i]; - $target = book_prepare_link($rel.$links[2][$i]); //target chapter - if ($target != '' && array_key_exists($target, $originals)) { - $o = $originals[$target]; - $newtag = $links[1][$i].$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i].$links[4][$i]; - $newtag = preg_replace('/target=[^\s>]/i','', $newtag); - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $links[2][$i].$links[3][$i].' --> '.$CFG->wwwroot.'/mod/book/view.php?id='.$id.'&chapterid='.$o->id.$links[3][$i]); - } else if ($target!='' && (!preg_match('/\.html$|\.htm$/i', $links[2][$i]))) { // other relative non html links converted to download links - $target = book_prepare_link($base.$links[2][$i]); - $origtag = $links[0][$i]; - $newtag = $links[1][$i].$target.$links[4][$i]; - $ch->content = str_replace($origtag, $newtag, $ch->content); - $modified = true; - book_log($ch->title, $links[2][$i].' --> '.$target); - } - } - } - } - if ($modified) { - $DB->update_record('book_chapters', $ch); - } + return ''; } } + +function toolbook_importhtml_parse_title($html, $default) { + $matches = null; + if (preg_match('/<title>([^<]+)<\/title>/i', $html, $matches)) { + return $matches[1]; + } else { + return $default; + } +} + +function toolbook_importhtml_get_chapter_files($package, $type) { + $packer = get_file_packer('application/zip'); + $files = $package->list_files($packer); + $tophtmlfiles = array(); + $subhtmlfiles = array(); + $topdirs = array(); + + foreach ($files as $file) { + if (empty($file->pathname)) { + continue; + } + if (substr($file->pathname, -1) === '/') { + if (substr_count($file->pathname, '/') !== 1) { + // skip subdirs + continue; + } + if (!isset($topdirs[$file->pathname])) { + $topdirs[$file->pathname] = array(); + } + + } else { + $mime = mimeinfo('icon', $file->pathname); + if ($mime !== 'html') { + continue; + } + $level = substr_count($file->pathname, '/'); + if ($level === 0) { + $tophtmlfiles[$file->pathname] = $file; + } else if ($level === 1) { + $subhtmlfiles[$file->pathname] = $file; + $dir = preg_replace('|/.*$|', '', $file->pathname); + $topdirs[$dir][$file->pathname] = $file; + } else { + // lower levels are not interesting + continue; + } + } + } + // TODO: natural dir sorting would be nice here... + textlib_get_instance()->asort($tophtmlfiles); + textlib_get_instance()->asort($subhtmlfiles); + textlib_get_instance()->asort($topdirs); + + $chapterfiles = array(); + + if ($type == 2) { + $chapterfiles = $tophtmlfiles; + + } else if ($type == 1) { + foreach ($topdirs as $dir=>$htmlfiles) { + if (empty($htmlfiles)) { + continue; + } + textlib_get_instance()->asort($htmlfiles); + if (isset($htmlfiles[$dir.'/index.html'])) { + $htmlfile = $htmlfiles[$dir.'/index.html']; + } else if (isset($htmlfiles[$dir.'/index.htm'])) { + $htmlfile = $htmlfiles[$dir.'/index.htm']; + } else if (isset($htmlfiles[$dir.'/Default.htm'])) { + $htmlfile = $htmlfiles[$dir.'/Default.htm']; + } else { + $htmlfile = reset($htmlfiles); + } + $chapterfiles[$htmlfile->pathname] = $htmlfile; + } + } else if ($type == 0) { + if ($tophtmlfiles) { + if (isset($tophtmlfiles['index.html'])) { + $htmlfile = $tophtmlfiles['index.html']; + } else if (isset($tophtmlfiles['index.htm'])) { + $htmlfile = $tophtmlfiles['index.htm']; + } else if (isset($tophtmlfiles['Default.htm'])) { + $htmlfile = $tophtmlfiles['Default.htm']; + } else { + $htmlfile = reset($tophtmlfiles); + } + } else { + $htmlfile = reset($subhtmlfiles); + } + $chapterfiles[$htmlfile->pathname] = $htmlfile; + } + + return $chapterfiles; +} From 0c9f18642ff6b1cab616f419cbd940d233f11367 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sun, 9 Oct 2011 13:40:20 +0200 Subject: [PATCH 160/455] add basic revision tracking support --- db/install.xml | 7 ++++--- db/upgrade.php | 14 ++++++++++++++ delete.php | 3 ++- edit.php | 1 + lib.php | 3 +++ move.php | 2 ++ show.php | 2 ++ tool/importhtml/locallib.php | 4 ++++ version.php | 4 ++-- 9 files changed, 34 insertions(+), 6 deletions(-) diff --git a/db/install.xml b/db/install.xml index 7aef3c27574..217f0f1d821 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<XMLDB PATH="mod/book/db" VERSION="20110116" COMMENT="XMLDB file for Moodle mod_book" +<XMLDB PATH="mod/book/db" VERSION="20111009" COMMENT="XMLDB file for Moodle mod_book" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd" > @@ -12,8 +12,9 @@ <FIELD NAME="intro" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/> <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="intro" NEXT="numbering"/> <FIELD NAME="numbering" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="introformat" NEXT="customtitles"/> - <FIELD NAME="customtitles" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="numbering" NEXT="timecreated"/> - <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="customtitles" NEXT="timemodified"/> + <FIELD NAME="customtitles" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="numbering" NEXT="revision"/> + <FIELD NAME="revision" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="customtitles" NEXT="timecreated"/> + <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="revision" NEXT="timemodified"/> <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated"/> </FIELDS> <KEYS> diff --git a/db/upgrade.php b/db/upgrade.php index 5c93777ccde..d1314998e9d 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -182,6 +182,20 @@ function xmldb_book_upgrade($oldversion) { upgrade_mod_savepoint(true, 2011090800, 'book'); } + if ($oldversion < 2011100900) { + + // Define field revision to be added to book + $table = new xmldb_table('book'); + $field = new xmldb_field('revision', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'customtitles'); + + // Conditionally launch add field revision + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // book savepoint reached + upgrade_mod_savepoint(true, 2011100900, 'book'); + } return true; } diff --git a/delete.php b/delete.php index 98d9f5a08c6..c56b6ae814f 100644 --- a/delete.php +++ b/delete.php @@ -74,8 +74,9 @@ if ($confirm) { // the operation was confirmed. add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); book_preload_chapters($book); //fix structure - redirect('view.php?id='.$cm->id); + $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); + redirect('view.php?id='.$cm->id); } echo $OUTPUT->header(); diff --git a/edit.php b/edit.php index 1f855ad0675..69612ea8eae 100644 --- a/edit.php +++ b/edit.php @@ -98,6 +98,7 @@ if ($mform->is_cancelled()) { // store the files $data = file_postupdate_standard_editor($data, 'content', $options, $context, 'mod_book', 'chapter', $data->id); $DB->update_record('book_chapters', $data); + $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); diff --git a/lib.php b/lib.php index 9cf8faaa6dc..b707dc6f8ad 100644 --- a/lib.php +++ b/lib.php @@ -85,6 +85,9 @@ function book_update_instance($data, $mform) { $DB->update_record('book', $data); + $book = $DB->get_record('book', array('id'=>$data->id)); + $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); + return true; } diff --git a/move.php b/move.php index dd13b3a17d1..85ffd47dbd8 100644 --- a/move.php +++ b/move.php @@ -183,5 +183,7 @@ add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm-> add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); book_preload_chapters($book); // fix structure +$DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); + redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); diff --git a/show.php b/show.php index 9c89128ad5b..067da556073 100644 --- a/show.php +++ b/show.php @@ -70,5 +70,7 @@ add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm-> add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); book_preload_chapters($book); // fix structure +$DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); + redirect('view.php?id='.$cm->id.'&chapterid='.$chapter->id); diff --git a/tool/importhtml/locallib.php b/tool/importhtml/locallib.php index 6a41d98f4d1..70c3705dc3f 100644 --- a/tool/importhtml/locallib.php +++ b/tool/importhtml/locallib.php @@ -141,6 +141,10 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $ add_to_log($book->course, 'course', 'update mod', '../mod/book/view.php?id='.$context->instanceid, 'book '.$book->id); $fs->delete_area_files($context->id, 'mod_book', 'importhtmltemp', 0); + + // update the revision flag - this takes a long time, better to refetch the current value + $book = $DB->get_record('book', array('id'=>$book->id)); + $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); } function toolbook_importhtml_parse_headings($html) { diff --git a/version.php b/version.php index 86a45f3e09a..99350604f13 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011100800; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011100900; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070100; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $module->maturity = MATURITY_BETA; -$module->release = "2.1dev (20111008)"; // User-friendly version number +$module->release = "2.1dev (20111009)"; // User-friendly version number From f3d91d521f7db70ae53393db78e1440c109ea5e3 Mon Sep 17 00:00:00 2001 From: Petr Skoda <commits@skodak.org> Date: Sun, 9 Oct 2011 15:18:15 +0200 Subject: [PATCH 161/455] fixed imscp export support closes #12 --- tool/exportimscp/index.php | 270 +++--------------- .../lang/en/booktool_exportimscp.php | 4 +- tool/exportimscp/lib.php | 15 +- tool/exportimscp/locallib.php | 228 +++++++++++++++ tool/exportimscp/pix/generate.png | Bin 0 -> 1180 bytes tool/exportimscp/pix/generateimscp.gif | Bin 803 -> 0 bytes tool/exportimscp/version.php | 2 +- 7 files changed, 270 insertions(+), 249 deletions(-) create mode 100644 tool/exportimscp/locallib.php create mode 100644 tool/exportimscp/pix/generate.png delete mode 100644 tool/exportimscp/pix/generateimscp.gif diff --git a/tool/exportimscp/index.php b/tool/exportimscp/index.php index 574c03d2239..fcb6861c707 100644 --- a/tool/exportimscp/index.php +++ b/tool/exportimscp/index.php @@ -1,256 +1,56 @@ <?php -/////////////////////////////////////////////////////////////////////////// -// // -// NOTICE OF COPYRIGHT // -// // -// Moodle - Modular Object-Oriented Dynamic Learning Environment // -// http://moodle.com // -// // -// Copyright (C) 2001-3001 Antonio Vicent http://ludens.es // -// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com // -// // -// This program 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 2 of the License, or // -// (at your option) any later version. // -// // -// This program 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: // -// // -// http://www.gnu.org/copyleft/gpl.html // -// // -/////////////////////////////////////////////////////////////////////////// +// This file is part of Book plugin for 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/>. -die('Not converted to 2.0 yet, sorry'); +/** + * Book IMSCP export plugin + * + * @package booktool + * @subpackage exportimscp + * @copyright 2001-3001 Antonio Vicent {@link http://ludens.es} + * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com} + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ -require('../../config.php'); +require(dirname(__FILE__).'/../../../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); require_once($CFG->dirroot.'/backup/lib.php'); require_once($CFG->libdir.'/filelib.php'); $id = required_param('id', PARAM_INT); // Course Module ID +$cm = get_coursemodule_from_id('book', $id, 0, false, MUST_EXIST); +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); +$book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST); -if (!$cm = get_coursemodule_from_id('book', $id)) { - error('Course Module ID was incorrect'); -} +$PAGE->set_url('/mod/book/tool/exportimscp/index.php', array('id'=>$id)); -if (!$course = get_record('course', 'id', $cm->course)) { - error('Course is misconfigured'); -} - -require_login($course, true, $cm); +require_login($course, false, $cm); $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:read', $context); -require_capability('mod/book:exportimscp', $context); - -if (!$book = get_record('book', 'id', $cm->instance)) { - error('Course module is incorrect'); -} +require_capability('booktool/exportimscp:export', $context); $strbooks = get_string('modulenameplural', 'book'); $strbook = get_string('modulename', 'book'); $strtop = get_string('top', 'book'); -add_to_log($course->id, 'book', 'generateimscp', 'generateimscp.php?id='.$cm->id, $book->id, $cm->id); +add_to_log($course->id, 'book', 'generateimscp', 'tool/generateimscp/index.php?id='.$cm->id, $book->id, $cm->id); -/// Get all the chapters - $chapters = get_records('book_chapters', 'bookid', $book->id, 'pagenum'); +$file = booktool_exportimscp_build_package($book, $context); -/// Generate the manifest and all the contents - chapters2imsmanifest($chapters, $book, $cm); - -/// Now zip everything - make_upload_directory('temp'); - $zipfile = $CFG->dataroot . "/temp/". time() . '.zip'; - $files = get_directory_list($CFG->dataroot . "/$cm->course/moddata/book/$book->id", basename($zipfile), false, true, true); - foreach ($files as $key => $value) { - $files[$key] = $CFG->dataroot . "/$cm->course/moddata/book/$book->id/" . $value; - } - zip_files($files, $zipfile); -/// Now delete all the temp dirs - delete_dir_contents($CFG->dataroot . "/$cm->course/moddata/book/$book->id"); -/// Now serve the file - send_temp_file($zipfile, clean_filename($book->name) . '.zip'); - -/** - * This function will create the default imsmanifest plus contents for the book chapters passed as array - * Everything will be created under the book moddata file area * - */ -function chapters2imsmanifest ($chapters, $book, $cm) { - - global $CFG; - -/// Init imsmanifest and others - $imsmanifest = ''; - $imsitems = ''; - $imsresources = ''; - -/// Moodle and Book version - $moodle_release = $CFG->release; - $moodle_version = $CFG->version; - $book_version = get_field('modules', 'version', 'name', 'book'); - -/// Load manifest header - $imsmanifest .= '<?xml version="1.0" encoding="UTF-8"?> -<!-- This package has been created with Moodle ' . $moodle_release . ' (' . $moodle_version . '), Book module version ' . $book_version . ' - http://moodle.org --> -<!-- One idea and implementation by Eloy Lafuente (stronk7) and Antonio Vicent (C) 2001-3001 --> -<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:imsmd="http://www.imsglobal.org/xsd/imsmd_v1p2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" identifier="MANIFEST-' . md5($CFG->wwwroot . '-' . $book->course . '-' . $book->id) . '" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p2.xsd"> - <organizations default="MOODLE-' . $book->course . '-' . $book->id . '"> - <organization identifier="MOODLE-' . $book->course . '-' . $book->id . '" structure="hierarchical"> - <title>' . htmlspecialchars($book->name) . ''; - -/// Create the temp directory - $moddir = "$cm->course/moddata/book/$book->id"; - make_upload_directory($moddir); - -/// For each chapter, create the corresponding directory and save contents there - -/// To store the prev level (book only have 0 and 1) - $prevlevel = null; - foreach ($chapters as $chapter) { - /// Calculate current level ((book only have 0 and 1) - $currlevel = empty($chapter->subchapter) ? 0 : 1; - /// Based upon prevlevel and current one, decide what to close - if ($prevlevel !== null) { - /// Calculate the number of spaces (for visual xml-text formating) - $prevspaces = substr(' ', 0, $currlevel * 2); - - /// Same level, simply close the item - if ($prevlevel == $currlevel) { - $imsitems .= $prevspaces . ' ' . "\n"; - } - /// Bigger currlevel, nothing to close - /// Smaller currlevel, close both the current item and the parent one - if ($prevlevel > $currlevel) { - $imsitems .= ' ' . "\n"; - $imsitems .= ' ' . "\n"; - } - } - /// Update prevlevel - $prevlevel = $currlevel; - - /// Calculate the number of spaces (for visual xml-text formating) - $currspaces = substr(' ', 0, $currlevel * 2); - - /// Create the static html file + local attachments (images...) - $chapterdir = "$moddir/$chapter->pagenum"; - make_upload_directory($chapterdir); - $chaptercontent = chapter2html($chapter, $book->course, $book->id); - file_put_contents($CFG->dataroot . "/" . $chapterdir . "/index.html", $chaptercontent->content); - /// Add the imsitems - $imsitems .= $currspaces .' - ' . $currspaces . ' ' . htmlspecialchars($chapter->title) . '' . "\n"; - - /// Add the imsresources - /// First, check if we have localfiles - $localfiles = ''; - if ($chaptercontent->localfiles) { - foreach ($chaptercontent->localfiles as $localfile) { - $localfiles .= "\n" . ' '; - } - } - /// Now add the dependency to css - $cssdependency = "\n" . ' '; - /// Now build the resources section - $imsresources .= ' - ' . $localfiles . $cssdependency . ' - ' . "\n"; - } - -/// Close items (the latest chapter) -/// Level 1, close 1 - if ($currlevel == 0) { - $imsitems .= ' ' . "\n"; - } -/// Level 2, close 2 - if ($currlevel == 1) { - $imsitems .= ' ' . "\n"; - $imsitems .= ' ' . "\n"; - } - -/// Define the css common resource -$cssresource = ' - - ' . "\n"; - -/// Add imsitems to manifest - $imsmanifest .= "\n" . $imsitems; -/// Close the organization - $imsmanifest .= " - "; -/// Add resources to manifest - $imsmanifest .= "\n \n" . $imsresources . $cssresource . " "; -/// Close manifest - $imsmanifest .= "\n\n"; - - file_put_contents($CFG->dataroot . "/" . $moddir . '/imsmanifest.xml', $imsmanifest ); - -/// Now send the css resource - make_upload_directory("$moddir/css"); - file_put_contents($CFG->dataroot . "/" . $moddir . "/css/styles.css", file_get_contents("$CFG->dirroot/mod/book/generateimscp.css")); -} - -/** - * This function will create one chaptercontent object, with the contents converted to html and - * one array of local images to be included - */ -function chapter2html($chapter, $courseid, $bookid) { - - global $CFG; - - $content = ''; - $content .= '' . "\n"; - $content .= '' . "\n"; - $content .= '' . "\n"; - $content .= '' . "\n"; - $content .= '' . "\n"; - $content .= '' . $chapter->title . '' . "\n"; - $content .= '' . "\n"; - $content .= '' . "\n"; - $content .= '

                            ' . $chapter->title . '

                            ' ."\n"; - $options = new object(); - $options->noclean = true; - $content .= format_text($chapter->content, '', $options, $courseid) . "\n"; - $content .= '' . "\n"; - $content .= '' . "\n"; - -/// Now look for course-files in contents - $search = array($CFG->wwwroot.'/file.php/'.$courseid, - $CFG->wwwroot.'/file.php?file=/'.$courseid); - $replace = array('$@FILEPHP@$','$@FILEPHP@$'); - $content = str_replace($search, $replace, $content); - - $regexp = '/\$@FILEPHP@\$(.*?)"/is'; - $localfiles = array(); - $basefiles = array(); - preg_match_all($regexp, $content, $list); - - if ($list) { - /// Build the array of local files - foreach (array_unique($list[1]) as $key => $value) { - $localfiles['<#'. $key . '#>'] = $value; - $basefiles['<#'. $key . '#>'] = basename($value); - /// Copy files to current chapter directory - if (file_exists($CFG->dataroot . '/' . $courseid . '/' . $value)) { - copy($CFG->dataroot . '/' . $courseid . '/' . $value, $CFG->dataroot . '/' . $courseid . '/moddata/book/' . $bookid . '/' . $chapter->pagenum . '/' . basename ($value)); - } - } - /// Replace contents by keys - $content = str_replace($localfiles, array_keys($localfiles), $content); - /// Replace keys by basefiles - $content = str_replace(array_keys($basefiles), $basefiles, $content); - /// Delete $@FILEPHP@$ - $content = str_replace('$@FILEPHP@$', '', $content); - } - -/// Build the final object needed to have all the info in order to create the manifest - $object = new object(); - $object->content = $content; - $object->localfiles = $basefiles; - - return $object; -} +send_stored_file($file, 10, 0, true, clean_filename($book->name).'.zip'); diff --git a/tool/exportimscp/lang/en/booktool_exportimscp.php b/tool/exportimscp/lang/en/booktool_exportimscp.php index f717f638ce7..2d3f12358d2 100644 --- a/tool/exportimscp/lang/en/booktool_exportimscp.php +++ b/tool/exportimscp/lang/en/booktool_exportimscp.php @@ -26,5 +26,5 @@ defined('MOODLE_INTERNAL') || die; $string['exportimscp:export'] = 'Export book as IMS content package'; -$string['generateimscp'] = 'Generate IMS content package'; -$string['pluginname'] = 'Book IMSCP export'; +$string['generateimscp'] = 'Generate IMS CP'; +$string['pluginname'] = 'Book IMS CP export'; diff --git a/tool/exportimscp/lib.php b/tool/exportimscp/lib.php index e1d924db987..6316768c395 100644 --- a/tool/exportimscp/lib.php +++ b/tool/exportimscp/lib.php @@ -18,7 +18,7 @@ * IMSCP export lib * * @package booktool - * @subpackage print + * @subpackage exportimscp * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -36,16 +36,9 @@ function booktool_exportimscp_extend_settings_navigation(settings_navigation $se $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); } - - $params = $PAGE->url->params(); - - if (empty($params['id']) or empty($params['chapterid'])) { - return; - } - if (has_capability('booktool/exportimscp:export', $PAGE->cm->context)) { - //TODO - /// Enable the IMS CP button - //$generateimscp = ($allowexport) ? ''.get_string('generateimscp', 'book').'' : ''; + $url = new moodle_url('/mod/book/tool/exportimscp/index.php', array('id'=>$PAGE->cm->id)); + $icon = new pix_icon('generate', '', 'booktool_exportimscp', array('class'=>'icon')); + $booknode->add(get_string('generateimscp', 'booktool_exportimscp'), $url, navigation_node::TYPE_SETTING, null, null, $icon); } } \ No newline at end of file diff --git a/tool/exportimscp/locallib.php b/tool/exportimscp/locallib.php new file mode 100644 index 00000000000..f897c353a68 --- /dev/null +++ b/tool/exportimscp/locallib.php @@ -0,0 +1,228 @@ +. + +/** + * Book imscp export lib + * + * @package booktool + * @subpackage exportimscp + * @copyright 2001-3001 Antonio Vicent {@link http://ludens.es} + * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com} + * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +require_once(dirname(__FILE__).'/lib.php'); +require_once($CFG->dirroot.'/mod/book/locallib.php'); + + +function booktool_exportimscp_build_package($book, $context) { + global $DB; + + $fs = get_file_storage(); + + if ($packagefile = $fs->get_file($context->id, 'booktool_exportimscp', 'package', $book->revision, '/', 'imscp.zip')) { + return $packagefile; + } + + book_preload_chapters($book); //fix structure + + // prepare temp area with package contents + booktool_exportimscp_prepare_files($book, $context); + + $packer = get_file_packer('application/zip'); + $areafiles = $fs->get_area_files($context->id, 'booktool_exportimscp', 'temp', $book->revision, "sortorder, itemid, filepath, filename", false); + $files = array(); + foreach ($areafiles as $file) { + $path = $file->get_filepath().$file->get_filename(); + $path = ltrim($path, '/'); + $files[$path] = $file; + } + unset($areafiles); + $packagefile = $packer->archive_to_storage($files, $context->id, 'booktool_exportimscp', 'package', $book->revision, '/', 'imscp.zip'); + + // drop temp area + $fs->delete_area_files($context->id, 'booktool_exportimscp', 'temp', $book->revision); + + // delete older versions + $sql = "SELECT DISTINCT itemid + FROM {files} + WHERE contextid = :contextid AND component = 'booktool_exportimscp' AND itemid < :revision"; + $params = array('contextid'=>$context->id, 'revision'=>$book->revision); + $revisions = $DB->get_records_sql($sql, $params); + foreach ($revisions as $rev=>$unused) { + $fs->delete_area_files($context->id, 'booktool_exportimscp', 'temp', $rev); + $fs->delete_area_files($context->id, 'booktool_exportimscp', 'package', $rev); + } + + return $packagefile; +} + + +function booktool_exportimscp_prepare_files($book, $context) { + global $CFG, $DB; + + $fs = get_file_storage(); + + $temp_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision); + $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum'); + $chapterresources = array(); + foreach ($chapters as $chapter) { + $chapterresources[$chapter->id] = array(); + $files = $fs->get_area_files($context->id, 'mod_book', 'chapter', $chapter->id, "sortorder, itemid, filepath, filename", false); + foreach ($files as $file) { + $temp_file_record['filepath'] = '/'.$chapter->pagenum.$file->get_filepath(); + $fs->create_file_from_storedfile($temp_file_record, $file); + $chapterresources[$chapter->id][] = $chapter->pagenum.$file->get_filepath().$file->get_filename(); + } + if ($file = $fs->get_file($context->id, 'booktool_exportimscp', 'temp', $book->revision, "/$chapter->pagenum/", 'index.html')) { + // this should not exist + $file->delete(); + } + $content = booktool_exportimscp_chapter_content($chapter, $context); + $index_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision, 'filepath'=>"/$chapter->pagenum/", 'filename'=>'index.html'); + $fs->create_file_from_string($index_file_record, $content); + } + + $css_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision, 'filepath'=>"/css/", 'filename'=>'styles.css'); + $fs->create_file_from_pathname($css_file_record, dirname(__FILE__).'/imscp.css'); + + // Init imsmanifest and others + $imsmanifest = ''; + $imsitems = ''; + $imsresources = ''; + + // Moodle and Book version + $moodle_release = $CFG->release; + $moodle_version = $CFG->version; + $book_version = $DB->get_field('modules', 'version', array('name'=>'book')); + $bookname = format_string($book->name, true, array('context'=>$context)); + + // Load manifest header + $imsmanifest .= ' + + + + + + ' . htmlspecialchars($bookname) . ''; + + // To store the prev level (book only have 0 and 1) + $prevlevel = null; + foreach ($chapters as $chapter) { + // Calculate current level ((book only have 0 and 1) + $currlevel = empty($chapter->subchapter) ? 0 : 1; + // Based upon prevlevel and current one, decide what to close + if ($prevlevel !== null) { + // Calculate the number of spaces (for visual xml-text formating) + $prevspaces = substr(' ', 0, $currlevel * 2); + + // Same level, simply close the item + if ($prevlevel == $currlevel) { + $imsitems .= $prevspaces . ' ' . "\n"; + } + // Bigger currlevel, nothing to close + // Smaller currlevel, close both the current item and the parent one + if ($prevlevel > $currlevel) { + $imsitems .= ' ' . "\n"; + $imsitems .= ' ' . "\n"; + } + } + // Update prevlevel + $prevlevel = $currlevel; + + // Calculate the number of spaces (for visual xml-text formating) + $currspaces = substr(' ', 0, $currlevel * 2); + + $chaptertitle = format_string($chapter->title, true, array('context'=>$context)); + + // Add the imsitems + $imsitems .= $currspaces .' + ' . $currspaces . ' ' . htmlspecialchars($chaptertitle) . '' . "\n"; + + // Add the imsresources + // First, check if we have localfiles + $localfiles = array(); + foreach ($chapterresources[$chapter->id] as $localfile) { + $localfiles[] = "\n" . ' '; + } + // Now add the dependency to css + $cssdependency = "\n" . ' '; + // Now build the resources section + $imsresources .= ' + ' . implode($localfiles) . $cssdependency . ' + ' . "\n"; + } + + // Close items (the latest chapter) + // Level 1, close 1 + if ($currlevel == 0) { + $imsitems .= ' ' . "\n"; + } + // Level 2, close 2 + if ($currlevel == 1) { + $imsitems .= ' ' . "\n"; + $imsitems .= ' ' . "\n"; + } + + // Define the css common resource + $cssresource = ' + + ' . "\n"; + + // Add imsitems to manifest + $imsmanifest .= "\n" . $imsitems; + // Close the organization + $imsmanifest .= " + "; + // Add resources to manifest + $imsmanifest .= "\n \n" . $imsresources . $cssresource . " "; + // Close manifest + $imsmanifest .= "\n\n"; + + $manifest_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision, 'filepath'=>"/", 'filename'=>'imsmanifest.xml'); + $fs->create_file_from_string($manifest_file_record, $imsmanifest); +} + +function booktool_exportimscp_chapter_content($chapter, $context) { + + $options = new object(); + $options->noclean = true; + $options->context = $context; + + $chaptercontent = str_replace('@@PLUGINFILE@@/', '', $chapter->content); + $chaptercontent = format_text($chaptercontent, $chapter->contentformat, $options); + + $chaptertitle = format_string($chapter->title, true, array('context'=>$context)); + + $content = ''; + $content .= '' . "\n"; + $content .= '' . "\n"; + $content .= '' . "\n"; + $content .= '' . "\n"; + $content .= '' . "\n"; + $content .= '' . $chaptertitle . '' . "\n"; + $content .= '' . "\n"; + $content .= '' . "\n"; + $content .= '

                            ' . $chaptertitle . '

                            ' ."\n"; + $content .= $chaptercontent . "\n"; + $content .= '' . "\n"; + $content .= '' . "\n"; + + return $content; +} diff --git a/tool/exportimscp/pix/generate.png b/tool/exportimscp/pix/generate.png new file mode 100644 index 0000000000000000000000000000000000000000..de7090a5a543b18dffaa6283c28280e4834adda9 GIT binary patch literal 1180 zcmV;N1Y`S&P)HsIq%pnO;6ENWd)RB;w zk=^L7Ow3}knJrtE$c@S3Nn!)(Y$B zFy7mX&yOERkmiq1Pa~d4z?+?o#_ik9;dQxCN5wwv>cTHWLwK9>>6sZN2AUwb zvVsI3D@;bCcod1Clv;gv!1THJou!Mk z#R4mlRP_R_R1ihFPMkovstUzS00kXnDWF_d?A*P37-l8gm?3uh)NQ$}9tlx^_oWa$ zRHSEM0JFDm?Hmwr$Ac zSHWSo<8)`Ix%5|7qL8(+NQ=|yw7T+wpgb7N3N|ztl1U0#eC%db=4{-E@UC5mJ${To z`}*()v&EU4ix{o_jQ!}1mKMCbdpEwKdzKkPiHnb&Kta36nQ05^z{q4siosu8T0$Tc zGKa+GIg2X6LTo>F%yfzLAHgzHRI=zz_NR*(K|08lH8p0&NU+q%k|1XaPzq6o_}{~p zQn6!)?pdjfGA;@qVncj~u2#?l6>I|rePg%mzq0|h?%av@ z>+5xw)&w8z+Xo-}j4FBaC4ZEwWUWYKp636Ag4BX%{dzRj*5c#lW-VOKbquOXO3VZK zUpU>}jq7Z10!dRv;-p0i$}O_)y?GN~96gE;o0?V$morTu3qf0Lt-jP5i5NdHb9ygb zf{Pv0N+7P1fJWHPTbO095-#$zFj>3~R;%pnuu?1eOx0)XppA8P=sJA(U&(o${8jrM u7cLlEj~p>Vt*yofr%t^L#Hw5WfKo&wm z7DGc8L_`-wMHfd$8B9zWO-&k4Pa05A8&OdkQ&SvNR2)`T9amQ#T3R1nT_9j!Az@)7 zV`C;}W+!K7D{5*iYiliRY%XnWFK%uyZ*MVha5HgnG;(q^b8|LybU1c)I(T?Hd3im0 zdOmx5KYV;aeSJcHenWqMM}vb&goI3nhER%%Qj3dKjg3~0j#!Y8TauDtmzQLjnP!@r zXPcX8ot;qC3{@$vuv|NsC0|NsC0|NsC0|NsC0A^8LW6aaq!EC2ui z02lxm000O6fPaF6goTEOgLr67K|@SdWO8QuG1quKpOkcKJRAGciOHNcyQ%4sQHd#|YC>0ewWNKK1F+9>qG!6O;L@UamevbL}gpa6svH-nVPkfFkrDLx2kNWoTx z2nm5PLMR}xfCK{@TPFM>Drf{-wjva?C^;jA2VYbsNRd*7P!JN3AtTUQ(#NkUdV#PZ z1jVS)6bDqO(CWj96Dbpfh$&RZg@(@tM2~LK!?cqSUl6$|@. /** - * Book print plugin version info + * Book IMSCP export plugin version info * * @package booktool * @subpackage exportimscp From 890e146f45cfff9ca7e8be1b5c17623875a3b7ea Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 15:20:09 +0200 Subject: [PATCH 162/455] add missing moodle.org link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31ded76eb90..1ab422059c2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Book module for Moodle - Copyright (C) 2004-2011 Petr Skoda (http://skodak.org) +Book module for Moodle (http://moodle.org/) - Copyright (C) 2004-2011 Petr Skoda (http://skodak.org/) The Book module makes it easy to create multi-page resources with a book-like format. This module can be used to build complete book-like websites inside of your Moodle course. This module was developed for Technical University of Liberec (Czech Republic). Many ideas and code were taken from other Moodle modules and Moodle itself From d4f56420575302b5e2c6e6a94c60c29a2519b93c Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 15:21:48 +0200 Subject: [PATCH 163/455] highlight more authors --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ab422059c2..5c684f14634 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,8 @@ GNU General Public License for more details: http://www.gnu.org/copyleft/gpl.htm Created by: * Petr Skoda (skodak) - most of the coding & design -* Mojmir Volf - CSS formatted printer friendly format +* Mojmir Volf, Eloy Lafuente, Antonio Vicent and others + Project page: From 74979715a4447535ae009690e331fc2f4e24cb5d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 15:26:33 +0200 Subject: [PATCH 164/455] standardised includes --- delete.php | 4 ++-- edit.php | 6 +++--- index.php | 4 ++-- move.php | 4 ++-- show.php | 4 ++-- view.php | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/delete.php b/delete.php index c56b6ae814f..7fb9b978a86 100644 --- a/delete.php +++ b/delete.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); +require(dirname(__FILE__).'/../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = required_param('chapterid', PARAM_INT); // Chapter ID diff --git a/edit.php b/edit.php index 69612ea8eae..4c6f522fa57 100644 --- a/edit.php +++ b/edit.php @@ -23,9 +23,9 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); -require_once($CFG->dirroot.'/mod/book/edit_form.php'); +require(dirname(__FILE__).'/../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); +require_once(dirname(__FILE__).'/edit_form.php'); $cmid = required_param('cmid', PARAM_INT); // Book Course Module ID $chapterid = optional_param('id', 0, PARAM_INT); // Chapter ID diff --git a/index.php b/index.php index 46ef3b2bebc..64d23dae27d 100644 --- a/index.php +++ b/index.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); +require(dirname(__FILE__).'/../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID diff --git a/move.php b/move.php index 85ffd47dbd8..6a2011dc715 100644 --- a/move.php +++ b/move.php @@ -24,8 +24,8 @@ */ -require('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); +require(dirname(__FILE__).'/../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = required_param('chapterid', PARAM_INT); // Chapter ID diff --git a/show.php b/show.php index 067da556073..fdda808b5b4 100644 --- a/show.php +++ b/show.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); +require(dirname(__FILE__).'/../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); $id = required_param('id', PARAM_INT); // Course Module ID $chapterid = required_param('chapterid', PARAM_INT); // Chapter ID diff --git a/view.php b/view.php index 9a0d904bd7b..2530b8da255 100644 --- a/view.php +++ b/view.php @@ -23,8 +23,8 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require('../../config.php'); -require_once($CFG->dirroot.'/mod/book/locallib.php'); +require(dirname(__FILE__).'/../../config.php'); +require_once(dirname(__FILE__).'/locallib.php'); require_once($CFG->libdir.'/completionlib.php'); $id = optional_param('id', 0, PARAM_INT); // Course Module ID From 6992de4fdad9fe854041061f2ae2694e1dc79edc Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 15:29:20 +0200 Subject: [PATCH 165/455] normalise copyright links --- db/subplugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/subplugins.php b/db/subplugins.php index 71c251bb527..7a0979d09e6 100644 --- a/db/subplugins.php +++ b/db/subplugins.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2011 Petr Skoda (http://skodak.org) + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From d816304377c4f96f5f89438c33de9628001d0c9a Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 15:53:53 +0200 Subject: [PATCH 166/455] annoy users with MDL-28019 closes #17, it should be no ready for beta testing --- edit.php | 2 ++ lang/en/book.php | 2 ++ version.php | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/edit.php b/edit.php index 4c6f522fa57..abc2d205177 100644 --- a/edit.php +++ b/edit.php @@ -116,6 +116,8 @@ $PAGE->set_heading(format_string($course->fullname)); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('editingchapter', 'mod_book')); +echo $OUTPUT->box($OUTPUT->notification(get_string('missingfilemanagement', 'mod_book', html_writer::link('http://tracker.moodle.org/browse/MDL-28019', 'MDL-28019')))); + $mform->display(); echo $OUTPUT->footer(); diff --git a/lang/en/book.php b/lang/en/book.php index 984b9fb90e2..2a5bf768ba2 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -101,3 +101,5 @@ $string['book:viewhiddenchapters'] = 'View hidden book chapters'; $string['errorchapter'] = 'Error reading book chapter.'; $string['page-mod-book-x'] = 'Any book module page'; + +$string['missingfilemanagement'] = 'Dear users of Book module, I supposed you have already notised that it is not possible to delete or manage files used in Book chapters. Please vote in {$a} to get this fixed, thanks. Petr Škoda'; \ No newline at end of file diff --git a/version.php b/version.php index 99350604f13..b1e395cbda6 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011100900; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011100901; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070100; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $module->maturity = MATURITY_BETA; -$module->release = "2.1dev (20111009)"; // User-friendly version number +$module->release = "2.1beta1 (20111009)"; // User-friendly version number From bc66f1c0e3651a2bf2834c648d2b3fd950bd5126 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 16:05:44 +0200 Subject: [PATCH 167/455] fix readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c684f14634..32da86bc69c 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,12 @@ Created by: Project page: * https://github.com/skodak/moodle-mod_book +* http://moodle.org/plugins/view.php?plugin=mod_book Installation: -* http://docs.moodle.org/en/Installing_contributed_modules_or_plugins +* http://docs.moodle.org/20/en/Installing_contributed_modules_or_plugins Issue tracker: From fe9820e8a76a4811660b4a829b3ad281c557d3e3 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 9 Oct 2011 16:27:42 +0200 Subject: [PATCH 168/455] fix required Moodle version --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index b1e395cbda6..f08030f4381 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die; $module->version = 2011100901; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2011070100; // Requires this Moodle version +$module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From 8ad39e4f38582533d8a504fb4db76eb6abce5392 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 14 Oct 2011 19:36:08 +0200 Subject: [PATCH 169/455] explain zip archive is required when importing html closes #19 --- tool/importhtml/import_form.php | 3 ++- tool/importhtml/lang/en/booktool_importhtml.php | 2 ++ tool/importhtml/locallib.php | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tool/importhtml/import_form.php b/tool/importhtml/import_form.php index 7d4a383c7e7..55e9c90c4df 100644 --- a/tool/importhtml/import_form.php +++ b/tool/importhtml/import_form.php @@ -43,7 +43,8 @@ class booktool_importhtml_form extends moodleform { $mform->addElement('select', 'type', get_string('type', 'booktool_importhtml'), $options); $mform->setDefault('type', 2); - $mform->addElement('filepicker', 'importfile', get_string('file')); + $mform->addElement('filepicker', 'importfile', get_string('ziparchive', 'booktool_importhtml')); + $mform->addHelpButton('importfile', 'ziparchive', 'booktool_importhtml'); $mform->addRule('importfile', null, 'required'); $mform->addElement('hidden', 'id'); diff --git a/tool/importhtml/lang/en/booktool_importhtml.php b/tool/importhtml/lang/en/booktool_importhtml.php index ff6ceae1a4c..f58616e5910 100644 --- a/tool/importhtml/lang/en/booktool_importhtml.php +++ b/tool/importhtml/lang/en/booktool_importhtml.php @@ -37,3 +37,5 @@ $string['type'] = 'Type'; $string['typeonefile'] = 'One HTML file with headings as chapters'; $string['typezipfiles'] = 'Each HTML file represents one chapter'; $string['typezipdirs'] = 'Each directory represents one chapter'; +$string['ziparchive'] = 'Zip archive'; +$string['ziparchive_help'] = 'Select a ZIP archive that contains HTML files and other media. File or directory names ending with "_sub" indicate subchapters. You can use copy and paste in text editor for simple HML files without embedded media.'; \ No newline at end of file diff --git a/tool/importhtml/locallib.php b/tool/importhtml/locallib.php index 70c3705dc3f..37d87b54373 100644 --- a/tool/importhtml/locallib.php +++ b/tool/importhtml/locallib.php @@ -67,7 +67,7 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $ $chapter->hidden = 0; $chapter->timecreated = time(); $chapter->timemodified = time(); - if (preg_match('/_sub(\/|\.htm)/i', $chapter->importsrc)) { //if filename or directory ends with sub_* treat as subchapters + if (preg_match('/_sub(\/|\.htm)/i', $chapter->importsrc)) { //if filename or directory ends with *_sub treat as subchapters $chapter->subchapter = 1; } else { $chapter->subchapter = 0; From 327f9184c59ad2ca7786b9916bcb14819fb08a99 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 14 Oct 2011 19:45:37 +0200 Subject: [PATCH 170/455] fix return link on the frontpage credit goes to mauno, closes #18 --- view.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/view.php b/view.php index 2530b8da255..afec9da20da 100644 --- a/view.php +++ b/view.php @@ -156,7 +156,12 @@ if ($nextid) { if ($section = $DB->get_record('course_sections', array('id'=>$cm->section))) { $sec = $section->section; } - $chnavigation .= ''.get_string('navexit', 'book').''; + if ($course->id == $SITE->id) { + $returnurl = "$CFG->wwwroot/"; + } else { + $returnurl = "$CFG->wwwroot/course/view.php?id=$course->id#section-$sec"; + } + $chnavigation .= ''.get_string('navexit', 'book').''; // we are cheating a bit here, viewing the last page means user has viewed the whole book $completion = new completion_info($course); From 26c6ba6c7281c0b6bc8aa6eb4bf0139df5e5d7c1 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 14 Oct 2011 19:50:36 +0200 Subject: [PATCH 171/455] do not try to export when no chapters present yet --- tool/exportimscp/lang/en/booktool_exportimscp.php | 1 + tool/exportimscp/locallib.php | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tool/exportimscp/lang/en/booktool_exportimscp.php b/tool/exportimscp/lang/en/booktool_exportimscp.php index 2d3f12358d2..2aa40818a92 100644 --- a/tool/exportimscp/lang/en/booktool_exportimscp.php +++ b/tool/exportimscp/lang/en/booktool_exportimscp.php @@ -27,4 +27,5 @@ defined('MOODLE_INTERNAL') || die; $string['exportimscp:export'] = 'Export book as IMS content package'; $string['generateimscp'] = 'Generate IMS CP'; +$string['nochapters'] = 'No book chapters found, can not export to IMS CP.'; $string['pluginname'] = 'Book IMS CP export'; diff --git a/tool/exportimscp/locallib.php b/tool/exportimscp/locallib.php index f897c353a68..c80f2e9ac8f 100644 --- a/tool/exportimscp/locallib.php +++ b/tool/exportimscp/locallib.php @@ -40,7 +40,10 @@ function booktool_exportimscp_build_package($book, $context) { return $packagefile; } - book_preload_chapters($book); //fix structure + // fix structure and test if chapters present + if (!book_preload_chapters($book)) { + print_error('nochapters', 'booktool_exportimscp'); + } // prepare temp area with package contents booktool_exportimscp_prepare_files($book, $context); From 82ebcbc855b5d96144a8725d0df32f895446c393 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 14 Oct 2011 19:52:57 +0200 Subject: [PATCH 172/455] bump up version --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index f08030f4381..179a42d9047 100644 --- a/version.php +++ b/version.php @@ -31,4 +31,4 @@ $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $module->maturity = MATURITY_BETA; -$module->release = "2.1beta1 (20111009)"; // User-friendly version number +$module->release = "2.1beta1 (20111014)"; // User-friendly version number From e2ddc5318f21f06cbb20db169b16f3a1e3b8a6d6 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 14 Oct 2011 19:54:06 +0200 Subject: [PATCH 173/455] bump up subplugins too and mark as beta2 --- tool/exportimscp/version.php | 2 +- tool/importhtml/version.php | 2 +- tool/print/version.php | 2 +- version.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tool/exportimscp/version.php b/tool/exportimscp/version.php index f6dbe2e75b4..4a7ce6779a9 100644 --- a/tool/exportimscp/version.php +++ b/tool/exportimscp/version.php @@ -25,5 +25,5 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2011100800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2011101400; // The current plugin version (Date: YYYYMMDDXX) $plugin->component = 'booktool_exportimscp'; // Full name of the plugin (used for diagnostics) diff --git a/tool/importhtml/version.php b/tool/importhtml/version.php index 2b73b8bb41e..2a96e4bf801 100644 --- a/tool/importhtml/version.php +++ b/tool/importhtml/version.php @@ -25,5 +25,5 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2011100800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2011101400; // The current plugin version (Date: YYYYMMDDXX) $plugin->component = 'booktool_importhtml'; // Full name of the plugin (used for diagnostics) diff --git a/tool/print/version.php b/tool/print/version.php index 778a12d18e4..e566b67fa28 100644 --- a/tool/print/version.php +++ b/tool/print/version.php @@ -25,5 +25,5 @@ defined('MOODLE_INTERNAL') || die; -$plugin->version = 2011100800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2011101400; // The current plugin version (Date: YYYYMMDDXX) $plugin->component = 'booktool_print'; // Full name of the plugin (used for diagnostics) diff --git a/version.php b/version.php index 179a42d9047..2eb60d7fe4c 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011100901; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011101400; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $module->maturity = MATURITY_BETA; -$module->release = "2.1beta1 (20111014)"; // User-friendly version number +$module->release = "2.1beta2 (20111014)"; // User-friendly version number From 0b7fc76a9c08bf61b85ab91d47815a7b38c884f1 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Thu, 3 Nov 2011 11:38:39 +0100 Subject: [PATCH 174/455] Fix errors in book module during stats execution closes skodak/moodle-mod_book#20 --- lib.php | 2 +- version.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib.php b/lib.php index b707dc6f8ad..5e89cfe34f6 100644 --- a/lib.php +++ b/lib.php @@ -237,7 +237,7 @@ function book_get_view_actions() { } $function = 'booktool_'.$plugin.'_get_view_actions'; if (function_exists($function)) { - if ($actions = $function($settingsnav, $booknode)) { + if ($actions = $function()) { $return = array_merge($return, $actions); } } diff --git a/version.php b/version.php index 2eb60d7fe4c..a11c9470029 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011101400; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011110300; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) $module->maturity = MATURITY_BETA; -$module->release = "2.1beta2 (20111014)"; // User-friendly version number +$module->release = "2.1beta3 (20111103)"; // User-friendly version number From 61d821821aa8acb200d36ebf3b08c23734cc68e6 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 5 Nov 2011 12:54:31 +0100 Subject: [PATCH 175/455] stable mod_book release for Moodle 2.1 No more development planned, I am looking for a new maintainer. --- README.md | 2 +- edit.php | 4 +++- edit_form.php | 1 - version.php | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 32da86bc69c..c4161c14b29 100644 --- a/README.md +++ b/README.md @@ -48,4 +48,4 @@ Intentionally omitted features: Future: -* I like eXe editor, I would like to improve Book in this direction ... +* No more development planned diff --git a/edit.php b/edit.php index abc2d205177..1957003bccb 100644 --- a/edit.php +++ b/edit.php @@ -116,7 +116,9 @@ $PAGE->set_heading(format_string($course->fullname)); echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('editingchapter', 'mod_book')); -echo $OUTPUT->box($OUTPUT->notification(get_string('missingfilemanagement', 'mod_book', html_writer::link('http://tracker.moodle.org/browse/MDL-28019', 'MDL-28019')))); +if (debugging()) { + echo $OUTPUT->box($OUTPUT->notification(get_string('missingfilemanagement', 'mod_book', html_writer::link('http://tracker.moodle.org/browse/MDL-28019', 'MDL-28019')))); +} $mform->display(); diff --git a/edit_form.php b/edit_form.php index 5ccda8bebfc..ffa942da4d5 100644 --- a/edit_form.php +++ b/edit_form.php @@ -36,7 +36,6 @@ class book_chapter_edit_form extends moodleform { $options = $this->_customdata['options']; $mform = $this->_form; - $context = $options['context']; $mform->addElement('header', 'general', get_string('edit')); diff --git a/version.php b/version.php index a11c9470029..16603ec0022 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,10 @@ defined('MOODLE_INTERNAL') || die; -$module->version = 2011110300; // The current module version (Date: YYYYMMDDXX) +$module->version = 2011110500; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070101; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$module->maturity = MATURITY_BETA; -$module->release = "2.1beta3 (20111103)"; // User-friendly version number +$module->maturity = MATURITY_STABLE; +$module->release = "2.1 (20111105)"; // User-friendly version number From d4fa91564d164fce22acb6e58bd9dac220ac0f57 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 5 Nov 2011 12:59:33 +0100 Subject: [PATCH 176/455] fix requires, originally plugins database did not allow proper version there --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index 16603ec0022..b1879eec6a0 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die; $module->version = 2011110500; // The current module version (Date: YYYYMMDDXX) -$module->requires = 2011070101; // Requires this Moodle version +$module->requires = 2011070100; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From 0e83167422f7d938320db85f3c8de7d7ac861b5a Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 21 Apr 2012 09:39:25 +0200 Subject: [PATCH 177/455] addinstance support in book --- db/access.php | 14 +++++++++++++- lang/en/book.php | 3 ++- version.php | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/db/access.php b/db/access.php index 7f42897505c..378b3c5d5c8 100644 --- a/db/access.php +++ b/db/access.php @@ -19,12 +19,24 @@ * * @package mod * @subpackage book - * @copyright 2009-2010 Petr Skoda {@link http://skodak.org} + * @copyright 2009-2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $capabilities = array( + 'mod/book:addinstance' => array( + 'riskbitmask' => RISK_XSS, + + 'captype' => 'write', + 'contextlevel' => CONTEXT_COURSE, + 'archetypes' => array( + 'editingteacher' => CAP_ALLOW, + 'manager' => CAP_ALLOW + ), + 'clonepermissionsfrom' => 'moodle/course:manageactivities' + ), + 'mod/book:read' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, diff --git a/lang/en/book.php b/lang/en/book.php index 2a5bf768ba2..a6a246c0c7c 100644 --- a/lang/en/book.php +++ b/lang/en/book.php @@ -19,7 +19,7 @@ * * @package mod * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -94,6 +94,7 @@ $string['navprev'] = 'Previous'; $string['navnext'] = 'Next'; $string['navexit'] = 'Exit book'; +$string['book:addinstance'] = 'Add a new book'; $string['book:read'] = 'Read book'; $string['book:edit'] = 'Edit book chapters'; $string['book:viewhiddenchapters'] = 'View hidden book chapters'; diff --git a/version.php b/version.php index b1879eec6a0..45fceaea8b4 100644 --- a/version.php +++ b/version.php @@ -19,13 +19,13 @@ * * @package mod * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @copyright 2004-2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; -$module->version = 2011110500; // The current module version (Date: YYYYMMDDXX) +$module->version = 2012042100; // The current module version (Date: YYYYMMDDXX) $module->requires = 2011070100; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) From bcb4958e2a08a3c4ec40bbe096bb33938fe84c63 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Tue, 24 Apr 2012 17:53:29 +0200 Subject: [PATCH 178/455] fix invalid function name in legacy file migration Credit goes to t6nis. Closes issue #25. --- db/upgradelib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/upgradelib.php b/db/upgradelib.php index cda0c9cc269..dcf49d6e917 100644 --- a/db/upgradelib.php +++ b/db/upgradelib.php @@ -98,7 +98,7 @@ function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) { $oldpathname = $base.$item->getFilename().'/'; $subpath = $path.$item->getFilename().'/'; unset($item); // release file handle - book_migrate_moddata_dir_to_legacy($book, $context, $subpath); + mod_book_migrate_moddata_dir_to_legacy($book, $context, $subpath); @rmdir($oldpathname); // deletes dir if empty } } From 2975523afba69475d5f9cecba3bb1fb63b1c5f9d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 27 Apr 2012 10:49:59 +0200 Subject: [PATCH 179/455] CONTRIB-3616 Book module do not display icon for book and chapter print Credit goes to Peter Svec, thanks. --- tool/print/lib.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tool/print/lib.php b/tool/print/lib.php index 6171f367434..54e801218af 100644 --- a/tool/print/lib.php +++ b/tool/print/lib.php @@ -26,32 +26,32 @@ defined('MOODLE_INTERNAL') || die; function booktool_print_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { - global $USER, $PAGE, $CFG, $DB, $OUTPUT; + global $USER, $PAGE, $CFG, $DB, $OUTPUT; - if ($PAGE->cm->modname !== 'book') { - return; - } + if ($PAGE->cm->modname !== 'book') { + return; + } - if (empty($PAGE->cm->context)) { + if (empty($PAGE->cm->context)) { $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); - } + } - $params = $PAGE->url->params(); + $params = $PAGE->url->params(); - if (empty($params['id']) or empty($params['chapterid'])) { - return; - } + if (empty($params['id']) or empty($params['chapterid'])) { + return; + } - if (has_capability('booktool/print:print', $PAGE->cm->context)) { - $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'])); - $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); - $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); - $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); - $booknode->add('', $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); - } + if (has_capability('booktool/print:print', $PAGE->cm->context)) { + $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'])); + $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'])); + $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1)); + $booknode->add(get_string('printbook', 'booktool_print'), $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon'))); + $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2)); + $booknode->add(get_string('printchapter', 'booktool_print'), $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon'))); + } } /** From 41ee480a9b51cda7f804e4a40377ce25f63d359f Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 27 Apr 2012 10:51:47 +0200 Subject: [PATCH 180/455] fix bogus post action params --- lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib.php b/lib.php index 5e89cfe34f6..759105129af 100644 --- a/lib.php +++ b/lib.php @@ -262,7 +262,7 @@ function book_get_post_actions() { } $function = 'booktool_'.$plugin.'_get_post_actions'; if (function_exists($function)) { - if ($actions = $function($settingsnav, $booknode)) { + if ($actions = $function()) { $return = array_merge($return, $actions); } } From dcb83c348f6fc07c922ad8871ce3eb8b1b5d25d6 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 27 Apr 2012 11:09:53 +0200 Subject: [PATCH 181/455] fix use of legacy object class --- tool/exportimscp/locallib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/exportimscp/locallib.php b/tool/exportimscp/locallib.php index c80f2e9ac8f..37b5a68781e 100644 --- a/tool/exportimscp/locallib.php +++ b/tool/exportimscp/locallib.php @@ -204,7 +204,7 @@ function booktool_exportimscp_prepare_files($book, $context) { function booktool_exportimscp_chapter_content($chapter, $context) { - $options = new object(); + $options = new stdClass(); $options->noclean = true; $options->context = $context; From dbfcf440fa7725badeeffc0fe721a3f5a5fc0853 Mon Sep 17 00:00:00 2001 From: Aaron Barnes Date: Wed, 28 Mar 2012 10:53:09 +1300 Subject: [PATCH 182/455] MDL-32203 completion: Fix issues with data object where clauses --- course/completion.php | 36 ++++---- lib/completion/completion_aggregation.php | 20 ++++- lib/completion/completion_completion.php | 18 ++-- lib/completion/completion_criteria.php | 4 +- .../completion_criteria_activity.php | 3 +- .../completion_criteria_completion.php | 3 + lib/completion/completion_criteria_course.php | 4 +- lib/completion/completion_criteria_date.php | 4 +- .../completion_criteria_duration.php | 3 +- lib/completion/completion_criteria_grade.php | 4 +- lib/completion/cron.php | 2 +- lib/completion/data_object.php | 82 +++++++++++++++---- lib/completionlib.php | 5 +- 13 files changed, 130 insertions(+), 58 deletions(-) diff --git a/course/completion.php b/course/completion.php index 2bd3ed9ee2c..3d4e17b1398 100644 --- a/course/completion.php +++ b/course/completion.php @@ -103,44 +103,43 @@ if ($form->is_cancelled()){ // Handle aggregation methods // Overall aggregation - $aggregation = new completion_aggregation(); - $aggregation->course = $data->id; - $aggregation->criteriatype = null; + $aggdata = array( + 'course' => $data->id, + 'criteriatype' => null + ); + $aggregation = new completion_aggregation($aggdata); $aggregation->setMethod($data->overall_aggregation); - $aggregation->insert(); + $aggregation->save(); // Activity aggregation if (empty($data->activity_aggregation)) { $data->activity_aggregation = 0; } - $aggregation = new completion_aggregation(); - $aggregation->course = $data->id; - $aggregation->criteriatype = COMPLETION_CRITERIA_TYPE_ACTIVITY; + $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ACTIVITY; + $aggregation = new completion_aggregation($aggdata); $aggregation->setMethod($data->activity_aggregation); - $aggregation->insert(); + $aggregation->save(); // Course aggregation if (empty($data->course_aggregation)) { $data->course_aggregation = 0; } - $aggregation = new completion_aggregation(); - $aggregation->course = $data->id; - $aggregation->criteriatype = COMPLETION_CRITERIA_TYPE_COURSE; + $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_COURSE; + $aggregation = new completion_aggregation($aggdata); $aggregation->setMethod($data->course_aggregation); - $aggregation->insert(); + $aggregation->save(); // Role aggregation if (empty($data->role_aggregation)) { $data->role_aggregation = 0; } - $aggregation = new completion_aggregation(); - $aggregation->course = $data->id; - $aggregation->criteriatype = COMPLETION_CRITERIA_TYPE_ROLE; + $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ROLE; + $aggregation = new completion_aggregation($aggdata); $aggregation->setMethod($data->role_aggregation); - $aggregation->insert(); + $aggregation->save(); // Update course total passing grade if (!empty($data->criteria_grade)) { @@ -152,7 +151,10 @@ if ($form->is_cancelled()){ } } - redirect($CFG->wwwroot."/course/view.php?id=$course->id", get_string('changessaved')); + add_to_log($course->id, 'course', 'completion updated', 'completion.php?id='.$course->id); + + $url = new moodle_url('/course/view.php', array('id' => $course->id)); + redirect($url); } diff --git a/lib/completion/completion_aggregation.php b/lib/completion/completion_aggregation.php index e7a07863781..e6e626a4de9 100644 --- a/lib/completion/completion_aggregation.php +++ b/lib/completion/completion_aggregation.php @@ -49,13 +49,16 @@ class completion_aggregation extends data_object { */ public $required_fields = array('id', 'course', 'criteriatype', 'method', 'value'); + /* @var array Array of unique fields, used in where clauses */ + public $unique_fields = array('course', 'criteriatype'); + /* @var int Course id */ public $course; /* @var int Criteria type this aggregation method applies to, or NULL for overall course aggregation */ public $criteriatype; - /* @var int Aggregation method (COMPLETION_AGGREGATION_* constant)*/ + /* @var int Aggregation method (COMPLETION_AGGREGATION_* constant) */ public $method; /* @var mixed Method value */ @@ -98,4 +101,19 @@ class completion_aggregation extends data_object { $this->method = COMPLETION_AGGREGATION_ALL; } } + + + /** + * Save aggregation method to database + * + * @access public + * @return boolean + */ + public function save() { + if ($this->id) { + return $this->update(); + } else { + return $this->insert(); + } + } } diff --git a/lib/completion/completion_completion.php b/lib/completion/completion_completion.php index 2b5d8bf4bad..e6523eadf26 100644 --- a/lib/completion/completion_completion.php +++ b/lib/completion/completion_completion.php @@ -111,7 +111,7 @@ class completion_completion extends data_object { $this->timeenrolled = $timeenrolled; } - $this->_save(); + return $this->_save(); } /** @@ -137,7 +137,7 @@ class completion_completion extends data_object { $this->timestarted = $timestarted; } - $this->_save(); + return $this->_save(); } /** @@ -165,24 +165,24 @@ class completion_completion extends data_object { $this->timecompleted = $timecomplete; // Save record - $this->_save(); + return $this->_save(); } /** * Save course completion status * * This method creates a course_completions record if none exists + * @access private + * @return bool */ private function _save() { - global $DB; - if ($this->timeenrolled === null) { $this->timeenrolled = 0; } // Save record if ($this->id) { - $this->update(); + return $this->update(); } else { // Make sure reaggregate field is not null if (!$this->reaggregate) { @@ -191,10 +191,10 @@ class completion_completion extends data_object { // Make sure timestarted is not null if (!$this->timestarted) { - $this->timestarted = 0; + $this->timestarted = 0; } - - $this->insert(); + + return $this->insert(); } } } diff --git a/lib/completion/completion_criteria.php b/lib/completion/completion_criteria.php index d93e9a043a2..31f5187edcb 100644 --- a/lib/completion/completion_criteria.php +++ b/lib/completion/completion_criteria.php @@ -167,11 +167,11 @@ abstract class completion_criteria extends data_object { public static function factory($params) { global $CFG, $COMPLETION_CRITERIA_TYPES; - if (!isset($params->criteriatype) || !isset($COMPLETION_CRITERIA_TYPES[$params->criteriatype])) { + if (!isset($params['criteriatype']) || !isset($COMPLETION_CRITERIA_TYPES[$params['criteriatype']])) { error('invalidcriteriatype', 'completion'); } - $class = 'completion_criteria_'.$COMPLETION_CRITERIA_TYPES[$params->criteriatype]; + $class = 'completion_criteria_'.$COMPLETION_CRITERIA_TYPES[$params['criteriatype']]; require_once($CFG->libdir.'/completion/'.$class.'.php'); return new $class($params, false); diff --git a/lib/completion/completion_criteria_activity.php b/lib/completion/completion_criteria_activity.php index 409bf42c08f..ba275468723 100644 --- a/lib/completion/completion_criteria_activity.php +++ b/lib/completion/completion_criteria_activity.php @@ -235,8 +235,7 @@ class completion_criteria_activity extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { - - $completion = new completion_criteria_completion((array)$record); + $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record->timecompleted); } $rs->close(); diff --git a/lib/completion/completion_criteria_completion.php b/lib/completion/completion_criteria_completion.php index f4d700d0772..7f448001d20 100644 --- a/lib/completion/completion_criteria_completion.php +++ b/lib/completion/completion_criteria_completion.php @@ -44,6 +44,9 @@ class completion_criteria_completion extends data_object { /* @var array Array of required table fields, must start with 'id'. */ public $required_fields = array('id', 'userid', 'course', 'criteriaid', 'gradefinal', 'rpl', 'deleted', 'unenroled', 'timecompleted'); + /* @var array Array of unique fields, used in where clauses */ + public $unique_fields = array('userid', 'course', 'criteriaid'); + /* @var int User ID */ public $userid; diff --git a/lib/completion/completion_criteria_course.php b/lib/completion/completion_criteria_course.php index 882ee6365c2..04be448241e 100644 --- a/lib/completion/completion_criteria_course.php +++ b/lib/completion/completion_criteria_course.php @@ -193,8 +193,8 @@ class completion_criteria_course extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { - $completion = new completion_criteria_completion((array)$record); - $completion->mark_complete($record->timecompleted); + $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion->mark_complete($record['timecompleted']); } $rs->close(); } diff --git a/lib/completion/completion_criteria_date.php b/lib/completion/completion_criteria_date.php index e6e81c09148..bacc144955d 100644 --- a/lib/completion/completion_criteria_date.php +++ b/lib/completion/completion_criteria_date.php @@ -179,8 +179,8 @@ class completion_criteria_date extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql, array(time())); foreach ($rs as $record) { - $completion = new completion_criteria_completion((array)$record); - $completion->mark_complete($record->timeend); + $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion->mark_complete($record['timeend']); } $rs->close(); } diff --git a/lib/completion/completion_criteria_duration.php b/lib/completion/completion_criteria_duration.php index 97bcb923b00..962b052fe4e 100644 --- a/lib/completion/completion_criteria_duration.php +++ b/lib/completion/completion_criteria_duration.php @@ -229,8 +229,7 @@ class completion_criteria_duration extends completion_criteria { $now = time(); $rs = $DB->get_recordset_sql($sql, array($now, $now)); foreach ($rs as $record) { - - $completion = new completion_criteria_completion((array)$record); + $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); // Use time start if not 0, otherwise use timeenrolled if ($record->otimestart) { diff --git a/lib/completion/completion_criteria_grade.php b/lib/completion/completion_criteria_grade.php index e452454d080..3e0da11715f 100644 --- a/lib/completion/completion_criteria_grade.php +++ b/lib/completion/completion_criteria_grade.php @@ -215,8 +215,8 @@ class completion_criteria_grade extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { - $completion = new completion_criteria_completion((array)$record); - $completion->mark_complete($record->timecompleted); + $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion->mark_complete($record['timecompleted']); } $rs->close(); } diff --git a/lib/completion/cron.php b/lib/completion/cron.php index be480d47a21..3645c0618d6 100644 --- a/lib/completion/cron.php +++ b/lib/completion/cron.php @@ -317,7 +317,7 @@ function completion_cron_completions() { foreach ($completions as $params) { $timecompleted = max($timecompleted, $params->timecompleted); - $completion = new completion_criteria_completion($params, false); + $completion = new completion_criteria_completion((array)$params, false); // Handle aggregation special cases if ($params->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) { diff --git a/lib/completion/data_object.php b/lib/completion/data_object.php index 01345ee0cc9..9d862ba914a 100644 --- a/lib/completion/data_object.php +++ b/lib/completion/data_object.php @@ -26,6 +26,14 @@ defined('MOODLE_INTERNAL') || die(); + +/** + * Trigger for the new data_object api. + * + * See data_object::__constructor + */ +define('DATA_OBJECT_FETCH_BY_KEY', 2); + /** * A data abstraction object that holds methods and attributes * @@ -50,32 +58,74 @@ abstract class data_object { */ public $optional_fields = array(); + /* @var Array of unique fields, used in where clauses and constructor */ + public $unique_fields = array(); + /* @var int The primary key */ public $id; + /** * Constructor. Optionally (and by default) attempts to fetch corresponding row from DB. * - * @param array $params an array with required parameters for this data object. - * @param bool $fetch Whether to fetch corresponding row from DB or not, - * optional fields might not be defined if false used + * If $fetch is not false, there are a few different things that can happen: + * - true: + * load corresponding row from the database, using $params as the WHERE clause + * + * - DATA_OBJECT_FETCH_BY_KEY: + * load corresponding row from the database, using only the $id in the WHERE clause (if set), + * otherwise using the columns listed in $this->unique_fields. + * + * - array(): + * load corresponding row from the database, using the columns listed in this array + * in the WHERE clause + * + * @param array $params required parameters and their values for this data object + * @param mixed $fetch if false, do not attempt to fetch from the database, otherwise see notes */ public function __construct($params = null, $fetch = true) { - if (!empty($params) and (is_array($params) or is_object($params))) { - if ($fetch) { - if ($data = $this->fetch($params)) { - self::set_properties($this, $data); - } else { - self::set_properties($this, $this->optional_fields);//apply defaults for optional fields - self::set_properties($this, $params); - } - } else { - self::set_properties($this, $params); + if (is_object($params)) { + throw new coding_exception('data_object params should be in the form of an array, not an object'); + } + + // If no params given, apply defaults for optional fields + if (empty($params) || !is_array($params)) { + self::set_properties($this, $this->optional_fields); + return; + } + + // If fetch is false, do not load from database + if ($fetch === false) { + self::set_properties($this, $params); + return; + } + + // Compose where clause only from fields in unique_fields + if ($fetch === DATA_OBJECT_FETCH_BY_KEY && !empty($this->unique_fields)) { + if (empty($params['id'])) { + $where = array_intersect_key($params, array_flip($this->unique_fields)); } - + else { + $where = array('id' => $params['id']); + } + // Compose where clause from given field names + } else if (is_array($fetch) && !empty($fetch)) { + $where = array_intersect_key($params, array_flip($fetch)); + // Use entire params array for where clause } else { - self::set_properties($this, $this->optional_fields);//apply defaults for optional fields + $where = $params; + } + + // Attempt to load from database + if ($data = $this->fetch($where)) { + // Apply data from database, then data sent to constructor + self::set_properties($this, $data); + self::set_properties($this, $params); + } else { + // Apply defaults for optional fields, then data from constructor + self::set_properties($this, $this->optional_fields); + self::set_properties($this, $params); } } @@ -339,4 +389,4 @@ abstract class data_object { */ public function notify_changed($deleted) { } -} \ No newline at end of file +} diff --git a/lib/completionlib.php b/lib/completionlib.php index a47a1f89ee2..2034af148f5 100644 --- a/lib/completionlib.php +++ b/lib/completionlib.php @@ -322,8 +322,9 @@ class completion_info { */ public function get_user_completion($user_id, $criteria) { $params = array( + 'course' => $this->course_id, + 'userid' => $user_id, 'criteriaid' => $criteria->id, - 'userid' => $user_id ); $completion = new completion_criteria_completion($params); @@ -362,7 +363,7 @@ class completion_info { // Build array of criteria objects $this->criteria = array(); foreach ($records as $record) { - $this->criteria[$record->id] = completion_criteria::factory($record); + $this->criteria[$record->id] = completion_criteria::factory((array)$record); } } From fd87d0bf7891c8c93219217a432d2433da3e5055 Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Fri, 4 May 2012 11:25:42 +0800 Subject: [PATCH 183/455] MDL-32338 Libraries : made pluginlib.php cron_execute handle the exceptions it faces. --- lib/pluginlib.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pluginlib.php b/lib/pluginlib.php index 150d42c69c6..6c9021ebc59 100644 --- a/lib/pluginlib.php +++ b/lib/pluginlib.php @@ -1100,12 +1100,12 @@ class available_update_checker { */ protected function cron_execute() { - $this->restore_response(); - $previous = $this->recentresponse; - $this->fetch(); - $this->restore_response(true); - $current = $this->recentresponse; try { + $this->restore_response(); + $previous = $this->recentresponse; + $this->fetch(); + $this->restore_response(true); + $current = $this->recentresponse; $changes = $this->compare_responses($previous, $current); $notifications = $this->cron_notifications($changes); $this->cron_notify($notifications); From 96e0e914ce57a966f271a7ba1255611bb7ea0ae5 Mon Sep 17 00:00:00 2001 From: Mary Evans Date: Sat, 12 May 2012 02:09:31 +0100 Subject: [PATCH 184/455] MDL-32879 changes default region from side-post to side-pre for most CORE themes (Afterburner,Anomally, Arialist, Base, Boxxie, Canvas, Formal White, Formfactor, Leatherbound, Magazine,Splash and Standard Old) --- theme/afterburner/config.php | 12 ++++----- theme/anomaly/config.php | 14 +++++------ theme/arialist/config.php | 46 +++++++++++++++++------------------ theme/base/config.php | 14 +++++------ theme/boxxie/config.php | 16 ++++++------ theme/canvas/config.php | 16 ++++++------ theme/formal_white/config.php | 16 ++++++------ theme/formfactor/config.php | 16 ++++++------ theme/leatherbound/config.php | 16 ++++++------ theme/magazine/config.php | 16 ++++++------ theme/splash/config.php | 14 +++++------ theme/standardold/config.php | 14 +++++------ 12 files changed, 105 insertions(+), 105 deletions(-) diff --git a/theme/afterburner/config.php b/theme/afterburner/config.php index f1b5859ca2e..12e25a02bef 100644 --- a/theme/afterburner/config.php +++ b/theme/afterburner/config.php @@ -34,31 +34,31 @@ $THEME->layouts = array( 'standard' => array( 'file' => 'default.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // Main course page 'course' => array( 'file' => 'default.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'coursecategory' => array( 'file' => 'default.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // part of course, typical for modules - default page layout if $cm specified in require_login() 'incourse' => array( 'file' => 'default.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // The site home page. 'frontpage' => array( 'file' => 'default.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), // Server administration scripts. @@ -71,7 +71,7 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'default.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), // My public page diff --git a/theme/anomaly/config.php b/theme/anomaly/config.php index 8b6746d0124..6fcbaee386c 100644 --- a/theme/anomaly/config.php +++ b/theme/anomaly/config.php @@ -32,33 +32,33 @@ $THEME->layouts = array( 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), // Course page 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), // Course page 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), 'frontpage' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), 'admin' => array( @@ -70,13 +70,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu' => true) ), 'login' => array( diff --git a/theme/arialist/config.php b/theme/arialist/config.php index 751523c85fb..86bbf3a6518 100644 --- a/theme/arialist/config.php +++ b/theme/arialist/config.php @@ -38,8 +38,8 @@ $THEME->name = 'arialist'; $THEME->parents = array( - 'canvas', - 'base', + 'canvas', + 'base', ); ///////////////////////////////////////////////////// @@ -55,8 +55,8 @@ $THEME->parents = array( $THEME->sheets = array( 'pagelayout', - 'core', - 'settings', + 'core', + 'settings', ); //////////////////////////////////////////////////// @@ -65,12 +65,12 @@ $THEME->sheets = array( //////////////////////////////////////////////////// $THEME->parents_exclude_sheets = array( - 'base'=>array( - 'pagelayout', - ), - 'canvas'=>array( - 'pagelayout', - ), + 'base'=>array( + 'pagelayout', + ), + 'canvas'=>array( + 'pagelayout', + ), ); @@ -92,48 +92,48 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'standard' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'admin' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', @@ -156,7 +156,7 @@ $THEME->layouts = array( 'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true), ), 'embedded' => array( - 'theme' => 'canvas', + 'theme' => 'canvas', 'file' => 'embedded.php', 'regions' => array(), 'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true), @@ -170,7 +170,7 @@ $THEME->layouts = array( 'report' => array( 'file' => 'report.php', 'regions' => array('side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), ); @@ -209,14 +209,14 @@ $THEME->csspostprocess = 'arialist_process_css'; // As above but will be included in the page footer. //////////////////////////////////////////////////// -$THEME->larrow = '⟨'; +$THEME->larrow = '⟨'; //////////////////////////////////////////////////// // Overrides the left arrow image used throughout // Moodle //////////////////////////////////////////////////// -$THEME->rarrow = '⟩'; +$THEME->rarrow = '⟩'; //////////////////////////////////////////////////// // Overrides the right arrow image used throughout Moodle diff --git a/theme/base/config.php b/theme/base/config.php index 561fb1ddbaf..aba35fdd7ed 100644 --- a/theme/base/config.php +++ b/theme/base/config.php @@ -63,31 +63,31 @@ $THEME->layouts = array( 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // Main course page 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // part of course, typical for modules - default page layout if $cm specified in require_login() 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // The site home page. 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // Server administration scripts. 'admin' => array( @@ -99,14 +99,14 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), // My public page 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/boxxie/config.php b/theme/boxxie/config.php index 7aff519cec6..8c91ce3510c 100644 --- a/theme/boxxie/config.php +++ b/theme/boxxie/config.php @@ -69,32 +69,32 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'admin' => array( 'file' => 'general.php', @@ -104,13 +104,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/canvas/config.php b/theme/canvas/config.php index 1fdd5961e19..925a72b0701 100644 --- a/theme/canvas/config.php +++ b/theme/canvas/config.php @@ -89,32 +89,32 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'admin' => array( 'file' => 'general.php', @@ -124,13 +124,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/formal_white/config.php b/theme/formal_white/config.php index 6c0ba87c9b1..64ab73f85ad 100644 --- a/theme/formal_white/config.php +++ b/theme/formal_white/config.php @@ -91,33 +91,33 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'general' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'admin' => array( @@ -128,13 +128,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/formfactor/config.php b/theme/formfactor/config.php index 25814bd6f30..ddc32e8c6d2 100644 --- a/theme/formfactor/config.php +++ b/theme/formfactor/config.php @@ -76,32 +76,32 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'admin' => array( 'file' => 'general.php', @@ -111,13 +111,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/leatherbound/config.php b/theme/leatherbound/config.php index 823f923add5..992a3388c01 100644 --- a/theme/leatherbound/config.php +++ b/theme/leatherbound/config.php @@ -80,32 +80,32 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'admin' => array( 'file' => 'general.php', @@ -115,13 +115,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/magazine/config.php b/theme/magazine/config.php index cc138f2f770..3c9b925f932 100644 --- a/theme/magazine/config.php +++ b/theme/magazine/config.php @@ -52,32 +52,32 @@ $THEME->layouts = array( 'base' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'general' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'admin' => array( 'file' => 'general.php', @@ -87,13 +87,13 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', diff --git a/theme/splash/config.php b/theme/splash/config.php index 41ba3bcd107..f9bca28d4b8 100644 --- a/theme/splash/config.php +++ b/theme/splash/config.php @@ -53,29 +53,29 @@ $THEME->layouts = array( 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), // Course page 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), // Course page 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'frontpage' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'admin' => array( 'file' => 'general.php', @@ -85,12 +85,12 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post' + 'defaultregion' => 'side-pre' ), 'login' => array( 'file' => 'general.php', diff --git a/theme/standardold/config.php b/theme/standardold/config.php index 30d43198153..0d81929b9db 100644 --- a/theme/standardold/config.php +++ b/theme/standardold/config.php @@ -54,31 +54,31 @@ $THEME->layouts = array( 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // Main course page 'course' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), 'coursecategory' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // part of course, typical for modules - default page layout if $cm specified in require_login() 'incourse' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // The site home page. 'frontpage' => array( 'file' => 'frontpage.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), // Server administration scripts. 'admin' => array( @@ -90,14 +90,14 @@ $THEME->layouts = array( 'mydashboard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', 'options' => array('langmenu'=>true), ), // My public page 'mypublic' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), - 'defaultregion' => 'side-post', + 'defaultregion' => 'side-pre', ), 'login' => array( 'file' => 'general.php', From 5b12114476e42f16b8dc0ee535687ad40b8bc252 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Thu, 10 May 2012 11:54:46 +0800 Subject: [PATCH 185/455] MDL-32895: Improvements to assignment upgrade tool for large numbers of assignments. * Form to control the perpage variable for the upgradable assignments table. * Set timeout and increase memory limit for batch upgrades * Output/renderer pages to the upgrade progress is progressively displayed * Cleanup of relative includes in assignmentupgrade tool * More verbose errors reported for failed upgrades --- admin/tool/assignmentupgrade/batchupgrade.php | 36 +++++++++-- admin/tool/assignmentupgrade/index.php | 4 +- .../lang/en/tool_assignmentupgrade.php | 3 + .../assignmentupgrade/listnotupgraded.php | 21 +++++-- admin/tool/assignmentupgrade/locallib.php | 61 ++++++------------- admin/tool/assignmentupgrade/module.js | 5 ++ .../tool/assignmentupgrade/paginationform.php | 59 ++++++++++++++++++ admin/tool/assignmentupgrade/renderer.php | 59 ++++-------------- admin/tool/assignmentupgrade/styles.css | 2 +- .../upgradableassignmentstable.php | 3 +- .../tool/assignmentupgrade/upgradesingle.php | 16 +++-- .../upgradesingleconfirm.php | 2 +- mod/assign/upgradelib.php | 13 +++- 13 files changed, 168 insertions(+), 116 deletions(-) create mode 100644 admin/tool/assignmentupgrade/paginationform.php diff --git a/admin/tool/assignmentupgrade/batchupgrade.php b/admin/tool/assignmentupgrade/batchupgrade.php index 20ebf5c9958..a8d8ec39a0d 100644 --- a/admin/tool/assignmentupgrade/batchupgrade.php +++ b/admin/tool/assignmentupgrade/batchupgrade.php @@ -22,16 +22,21 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +define('NO_OUTPUT_BUFFERING', true); + require_once(dirname(__FILE__) . '/../../../config.php'); -require_once(dirname(__FILE__) . '/locallib.php'); -require_once(dirname(__FILE__) . '/upgradableassignmentstable.php'); -require_once(dirname(__FILE__) . '/upgradableassignmentsbatchform.php'); require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentstable.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php'); require_sesskey(); // admin_externalpage_setup calls require_login and checks moodle/site:config admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('batchupgrade')); + + +$PAGE->set_pagelayout('maintenance'); $PAGE->navbar->add(get_string('batchupgrade', 'tool_assignmentupgrade')); $renderer = $PAGE->get_renderer('tool_assignmentupgrade'); @@ -41,7 +46,26 @@ if (!$confirm) { print_error('invalidrequest'); die(); } -$result = tool_assignmentupgrade_upgrade_multiple_assignments(optional_param('upgradeall', 0, PARAM_BOOL), - explode(',', optional_param('selected', '', PARAM_TEXT))); +raise_memory_limit(MEMORY_EXTRA); +session_get_instance()->write_close(); // release session -echo $renderer->convert_multiple_assignments_result($result); +echo $renderer->header(); +echo $renderer->heading(get_string('batchupgrade', 'tool_assignmentupgrade')); + +$current = 0; +if (optional_param('upgradeall', false, PARAM_BOOL)) { + $assignmentids = tool_assignmentupgrade_load_all_upgradable_assignmentids(); +} else { + $assignmentids = explode(',', optional_param('selected', '', PARAM_TEXT)); +} +$total = count($assignmentids); + +foreach ($assignmentids as $assignmentid) { + list($summary, $success, $log) = tool_assignmentupgrade_upgrade_assignment($assignmentid); + $current += 1; + echo $renderer->heading(get_string('upgradeprogress', 'tool_assignmentupgrade', array('current'=>$current, 'total'=>$total)), 3); + echo $renderer->convert_assignment_result($summary, $success, $log); +} + +echo $renderer->continue_button(tool_assignmentupgrade_url('listnotupgraded')); +echo $renderer->footer(); diff --git a/admin/tool/assignmentupgrade/index.php b/admin/tool/assignmentupgrade/index.php index bb7ff493b10..f4cd1797d73 100644 --- a/admin/tool/assignmentupgrade/index.php +++ b/admin/tool/assignmentupgrade/index.php @@ -34,8 +34,8 @@ */ require_once(dirname(__FILE__) . '/../../../config.php'); -require_once(dirname(__FILE__) . '/locallib.php'); require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php'); // admin_externalpage_setup calls require_login and checks moodle/site:config admin_externalpage_setup('assignmentupgrade'); @@ -47,4 +47,4 @@ $actions = array(); $header = get_string('pluginname', 'tool_assignmentupgrade'); $actions[] = tool_assignmentupgrade_action::make('listnotupgraded'); -echo $renderer->index_page($header, $actions); \ No newline at end of file +echo $renderer->index_page($header, $actions); diff --git a/admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php b/admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php index 3b3734bc247..e9a61dcb381 100644 --- a/admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php +++ b/admin/tool/assignmentupgrade/lang/en/tool_assignmentupgrade.php @@ -26,6 +26,7 @@ $string['areyousure'] = 'Are you sure?'; $string['areyousuremessage'] = 'Are you sure you want to upgrade the assignment "{$a->name}"?'; $string['assignmentid'] = 'Assignment ID'; $string['assignmentnotfound'] = 'Assignment could not be found (id={$a})'; +$string['assignmentsperpage'] = 'Assignments per page'; $string['assignmenttype'] = 'Assignment type'; $string['backtoindex'] = 'Back to index'; $string['batchoperations'] = 'Batch operations'; @@ -43,6 +44,7 @@ $string['pluginname'] = 'Assignment upgrade helper'; $string['select'] = 'Select'; $string['submissions'] = 'Submissions'; $string['supported'] = 'Upgrade'; +$string['updatetable'] = 'Update table'; $string['unknown'] = 'Unknown'; $string['upgradeassignmentsummary'] = 'Upgrade assignment: {$a->name} (Course: {$a->shortname})'; $string['upgradeassignmentsuccess'] = 'Result: Upgrade successful'; @@ -52,5 +54,6 @@ $string['upgradeselected'] = 'Upgrade selected assignments'; $string['upgradeselectedcount'] = 'Upgrade {$a} selected assignments?'; $string['upgradeall'] = 'Upgrade all assignments'; $string['upgradeallconfirm'] = 'Upgrade all assignments?'; +$string['upgradeprogress'] = 'Upgrade assignment {$a->current} of {$a->total}'; $string['upgradesingle'] = 'Upgrade single assignment'; $string['viewcourse'] = 'View the course with the converted assignment'; diff --git a/admin/tool/assignmentupgrade/listnotupgraded.php b/admin/tool/assignmentupgrade/listnotupgraded.php index 37605a5d36a..b03883adf4a 100644 --- a/admin/tool/assignmentupgrade/listnotupgraded.php +++ b/admin/tool/assignmentupgrade/listnotupgraded.php @@ -23,10 +23,11 @@ */ require_once(dirname(__FILE__) . '/../../../config.php'); -require_once(dirname(__FILE__) . '/locallib.php'); -require_once(dirname(__FILE__) . '/upgradableassignmentstable.php'); -require_once(dirname(__FILE__) . '/upgradableassignmentsbatchform.php'); require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentstable.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/upgradableassignmentsbatchform.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/paginationform.php'); // admin_externalpage_setup calls require_login and checks moodle/site:config admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrade_url('listnotupgraded')); @@ -34,16 +35,26 @@ $PAGE->navbar->add(get_string('listnotupgraded', 'tool_assignmentupgrade')); $renderer = $PAGE->get_renderer('tool_assignmentupgrade'); -$perpage = get_user_preferences('tool_assignmentupgrade_perpage', 5); +$perpage = optional_param('perpage', 0, PARAM_INT); +if (!$perpage) { + $perpage = get_user_preferences('tool_assignmentupgrade_perpage', 100); +} else { + set_user_preference('tool_assignmentupgrade_perpage', $perpage); +} $assignments = new tool_assignmentupgrade_assignments_table($perpage); $batchform = new tool_assignmentupgrade_batchoperations_form(); $data = $batchform->get_data(); + if ($data && $data->selectedassignments != '' || $data && isset($data->upgradeall)) { require_sesskey(); echo $renderer->confirm_batch_operation_page($data); } else { - echo $renderer->assignment_list_page($assignments, $batchform); + $paginationform = new tool_assignmentupgrade_pagination_form(); + $pagedata = new stdClass(); + $pagedata->perpage = $perpage; + $paginationform->set_data($pagedata); + echo $renderer->assignment_list_page($assignments, $batchform, $paginationform); } diff --git a/admin/tool/assignmentupgrade/locallib.php b/admin/tool/assignmentupgrade/locallib.php index 5b814859fc3..6ea1883a4d3 100644 --- a/admin/tool/assignmentupgrade/locallib.php +++ b/admin/tool/assignmentupgrade/locallib.php @@ -170,54 +170,33 @@ function tool_assignmentupgrade_load_all_upgradable_assignmentids() { /** - * Convert a list of assignments from the old format to the new one. - * @param bool $upgradeall - Upgrade all possible assignments - * @param array $assignmentids An array of assignment ids to upgrade - * @return array of $entry['assignmentsummary' => (result from tool_assignmentupgrade_get_assignment) - * $entry['success'] => boolean - * $entry['log'] => string - upgrade log + * Upgrade a single assignment. This is used by both upgrade single and upgrade batch + * + * @param int $assignmentid - The assignment id to upgrade + * @return array(string, boolean, string) - + * The array contains + * - the assignment summary (returned by tool_assignmentupgrade_get_assignment) + * - success + * - the upgrade log */ -function tool_assignmentupgrade_upgrade_multiple_assignments($upgradeall, $assignmentids) { +function tool_assignmentupgrade_upgrade_assignment($assignmentid) { global $CFG; - require_once($CFG->dirroot . '/mod/assign/locallib.php'); require_once($CFG->dirroot . '/mod/assign/upgradelib.php'); - $upgrades = array(); - - if ($upgradeall) { - $assignmentids = tool_assignmentupgrade_load_all_upgradable_assignmentids(); - } $assignment_upgrader = new assign_upgrade_manager(); - foreach ($assignmentids as $assignmentid) { - $info = tool_assignmentupgrade_get_assignment($assignmentid); - if ($info) { - $log = ''; - $success = $assignment_upgrader->upgrade_assignment($assignmentid, $log); - } else { - $success = false; - $log = get_string('assignmentnotfound', 'tool_assignmentupgrade', $assignmentid); - $info = new stdClass(); - $info->name = get_string('unknown', 'tool_assignmentupgrade'); - $info->shortname = get_string('unknown', 'tool_assignmentupgrade'); - } - - $upgrades[] = array('assignmentsummary'=>$info, 'success'=>$success, 'log'=>$log); + $info = tool_assignmentupgrade_get_assignment($assignmentid); + if ($info) { + $log = ''; + $success = $assignment_upgrader->upgrade_assignment($assignmentid, $log); + } else { + $success = false; + $log = get_string('assignmentnotfound', 'tool_assignmentupgrade', $assignmentid); + $info = new stdClass(); + $info->name = get_string('unknown', 'tool_assignmentupgrade'); + $info->shortname = get_string('unknown', 'tool_assignmentupgrade'); } - return $upgrades; -} -/** - * Convert a single assignment from the old format to the new one. - * @param stdClass $assignmentinfo An object containing information about this class - * @param string $log This gets appended to with the details of the conversion process - * @return boolean This is the overall result (true/false) - */ -function tool_assignmentupgrade_upgrade_assignment($assignmentinfo, &$log) { - global $CFG; - require_once($CFG->dirroot . '/mod/assign/locallib.php'); - require_once($CFG->dirroot . '/mod/assign/upgradelib.php'); - $assignment_upgrader = new assign_upgrade_manager(); - return $assignment_upgrader->upgrade_assignment($assignmentinfo->id, $log); + return array($info, $success, $log); } /** diff --git a/admin/tool/assignmentupgrade/module.js b/admin/tool/assignmentupgrade/module.js index 829f99a34ad..edee839835f 100644 --- a/admin/tool/assignmentupgrade/module.js +++ b/admin/tool/assignmentupgrade/module.js @@ -61,6 +61,11 @@ M.tool_assignmentupgrade = { } }); + var perpage = Y.one('#id_perpage'); + perpage.on('change', function(e) { + window.onbeforeunload = null; + Y.one('.tool_assignmentupgrade_paginationform form').submit(); + }); } } diff --git a/admin/tool/assignmentupgrade/paginationform.php b/admin/tool/assignmentupgrade/paginationform.php new file mode 100644 index 00000000000..3efb8d4d508 --- /dev/null +++ b/admin/tool/assignmentupgrade/paginationform.php @@ -0,0 +1,59 @@ +. + +/** + * This file contains the forms to create and edit an instance of this module + * + * @package tool_assignmentupgrade + * @copyright 2012 NetSpot {@link http://www.netspot.com.au} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); + + +/** Include formslib.php */ +require_once ($CFG->libdir.'/formslib.php'); + +/** + * Assignment upgrade table display options + * + * @package tool_assignmentupgrade + * @copyright 2012 NetSpot {@link http://www.netspot.com.au} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_assignmentupgrade_pagination_form extends moodleform { + /** + * Define this form - called from the parent constructor + */ + function definition() { + $mform = $this->_form; + $instance = $this->_customdata; + + $mform->addElement('header', 'general', get_string('assignmentsperpage', 'tool_assignmentupgrade')); + // visible elements + $options = array(10=>'10', 20=>'20', 50=>'50', 100=>'100'); + $mform->addElement('select', 'perpage', get_string('assignmentsperpage', 'assign'), $options); + + // hidden params + $mform->addElement('hidden', 'action', 'saveoptions'); + $mform->setType('action', PARAM_ALPHA); + + // buttons + $this->add_action_buttons(false, get_string('updatetable', 'tool_assignmentupgrade')); + } +} + diff --git a/admin/tool/assignmentupgrade/renderer.php b/admin/tool/assignmentupgrade/renderer.php index 16c013c9108..7c64f7f8306 100644 --- a/admin/tool/assignmentupgrade/renderer.php +++ b/admin/tool/assignmentupgrade/renderer.php @@ -112,9 +112,10 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base { * Render the list of assignments that still need to be upgraded page. * @param tool_assignmentupgrade_assignments_table $assignments of data about assignments. * @param tool_assignmentupgrade_batchoperations_form $batchform Submitted form with list of assignments to upgrade + * @param tool_assignmentupgrade_pagination_form $paginationform Form which contains the preferences for paginating the table * @return string html to output. */ - public function assignment_list_page(tool_assignmentupgrade_assignments_table $assignments, tool_assignmentupgrade_batchoperations_form $batchform) { + public function assignment_list_page(tool_assignmentupgrade_assignments_table $assignments, tool_assignmentupgrade_batchoperations_form $batchform, tool_assignmentupgrade_pagination_form $paginationform) { $output = ''; $output .= $this->header(); $this->page->requires->js_init_call('M.tool_assignmentupgrade.init_upgrade_table', array()); @@ -126,6 +127,10 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base { $output .= $this->container_start('tool_assignmentupgrade_upgradetable'); + $output .= $this->container_start('tool_assignmentupgrade_paginationform'); + $output .= $this->moodleform($paginationform); + $output .= $this->container_end(); + $output .= $this->flexible_table($assignments, $assignments->get_rows_per_page(), true); $output .= $this->container_end(); @@ -140,43 +145,6 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base { return $output; } - /** - * Render the result of an assignment conversion - * @param array $assignments - An array of arrays with keys $entry['assignmentsummary', 'success', 'log'] - * See convert_assignment_result for more description of these keys. - * @return string html to output. - */ - public function convert_multiple_assignments_result($assignments) { - $output = ''; - $output .= $this->header(); - $output .= $this->heading(get_string('batchupgrade', 'tool_assignmentupgrade')); - - foreach ($assignments as $assignment) { - $assignmentsummary = $assignment['assignmentsummary']; - $success = $assignment['success']; - $log = $assignment['log']; - - $output .= $this->heading(get_string('upgradeassignmentsummary', 'tool_assignmentupgrade', $assignmentsummary), 5); - if ($success) { - $output .= $this->container(get_string('upgradeassignmentsuccess', 'tool_assignmentupgrade')); - - } else { - $output .= $this->container(get_string('upgradeassignmentfailed', 'tool_assignmentupgrade', $assignment)); - } - if (isset($assignmentsummary->courseid)) { - $output .= html_writer::link(new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid)) ,get_string('viewcourse', 'tool_assignmentupgrade')); - } - - - } - - $output .= $this->continue_button(tool_assignmentupgrade_url('listnotupgraded')); - - - $output .= $this->footer(); - return $output; - } - /** * Render the result of an assignment conversion * @param stdClass $assignmentsummary data about the assignment to upgrade. @@ -186,19 +154,18 @@ class tool_assignmentupgrade_renderer extends plugin_renderer_base { */ public function convert_assignment_result($assignmentsummary, $success, $log) { $output = ''; - $output .= $this->header(); - $output .= $this->heading(get_string('conversioncomplete', 'tool_assignmentupgrade')); + $output .= $this->container_start('tool_assignmentupgrade_result'); + $output .= $this->container(get_string('upgradeassignmentsummary', 'tool_assignmentupgrade', $assignmentsummary)); if (!$success) { - $output .= get_string('conversionfailed', 'tool_assignmentupgrade', $log); + $output .= $this->container(get_string('conversionfailed', 'tool_assignmentupgrade', $log)); } else { - $output .= html_writer::link(new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid)) ,get_string('viewcourse', 'tool_assignmentupgrade')); + $output .= $this->container(get_string('upgradeassignmentsuccess', 'tool_assignmentupgrade')); + + $output .= $this->container(html_writer::link(new moodle_url('/course/view.php', array('id'=>$assignmentsummary->courseid)) ,get_string('viewcourse', 'tool_assignmentupgrade'))); } + $output .= $this->container_end(); - $output .= $this->continue_button(tool_assignmentupgrade_url('listnotupgraded')); - - - $output .= $this->footer(); return $output; } diff --git a/admin/tool/assignmentupgrade/styles.css b/admin/tool/assignmentupgrade/styles.css index 0188dc416eb..277400bded1 100644 --- a/admin/tool/assignmentupgrade/styles.css +++ b/admin/tool/assignmentupgrade/styles.css @@ -8,4 +8,4 @@ #page-admin-tool-assignmentupgrade-listnotupgraded .tool_assignmentupgrade_upgradetable tr.selectedrow td { background-color: #ffeecc; } #page-admin-tool-assignmentupgrade-listnotupgraded .tool_assignmentupgrade_upgradetable tr.unselectedrow td { background-color: white; } - +#page-admin-tool-assignmentupgrade-listnotupgraded .tool_assignmentupgrade_paginationform .hidden { display: none; } diff --git a/admin/tool/assignmentupgrade/upgradableassignmentstable.php b/admin/tool/assignmentupgrade/upgradableassignmentstable.php index 0e4830ba602..307a8c95f61 100644 --- a/admin/tool/assignmentupgrade/upgradableassignmentstable.php +++ b/admin/tool/assignmentupgrade/upgradableassignmentstable.php @@ -70,12 +70,11 @@ class tool_assignmentupgrade_assignments_table extends table_sql implements rend $from = '{assignment} a JOIN {course} c ON a.course = c.id ' . ' LEFT JOIN {assignment_submissions} s ON a.id = s.assignment'; - $where = '1 = 1'; $where .= ' GROUP BY a.id, a.name, a.assignmenttype, c.shortname, c.id '; $this->set_sql($fields, $from, $where, array()); - $this->set_count_sql('SELECT COUNT(*) FROM ' . $from, array()); + $this->set_count_sql('SELECT COUNT(*) FROM {assignment} a JOIN {course} c ON a.course = c.id', array()); $columns = array(); $headers = array(); diff --git a/admin/tool/assignmentupgrade/upgradesingle.php b/admin/tool/assignmentupgrade/upgradesingle.php index 2464ebea56c..5125bbbfa66 100644 --- a/admin/tool/assignmentupgrade/upgradesingle.php +++ b/admin/tool/assignmentupgrade/upgradesingle.php @@ -23,8 +23,8 @@ */ require_once(dirname(__FILE__) . '/../../../config.php'); -require_once(dirname(__FILE__) . '/locallib.php'); require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php'); require_sesskey(); @@ -36,13 +36,11 @@ admin_externalpage_setup('assignmentupgrade', '', array(), tool_assignmentupgrad $PAGE->navbar->add(get_string('upgradesingle', 'tool_assignmentupgrade')); $renderer = $PAGE->get_renderer('tool_assignmentupgrade'); -$assignmentinfo = tool_assignmentupgrade_get_assignment($assignmentid); -if (!$assignmentinfo) { - print_error('invalidrequest'); - die(); -} - $log = ''; -$result = tool_assignmentupgrade_upgrade_assignment($assignmentinfo, $log); +list($summary, $success, $log) = tool_assignmentupgrade_upgrade_assignment($assignmentid); -echo $renderer->convert_assignment_result($assignmentinfo, $result, $log); +echo $renderer->header(); +echo $renderer->heading(get_string('conversioncomplete', 'tool_assignmentupgrade')); +echo $renderer->convert_assignment_result($summary, $success, $log); +echo $renderer->continue_button(tool_assignmentupgrade_url('listnotupgraded')); +echo $renderer->footer(); diff --git a/admin/tool/assignmentupgrade/upgradesingleconfirm.php b/admin/tool/assignmentupgrade/upgradesingleconfirm.php index 0325b4a09d4..b7ec24c52e9 100644 --- a/admin/tool/assignmentupgrade/upgradesingleconfirm.php +++ b/admin/tool/assignmentupgrade/upgradesingleconfirm.php @@ -23,8 +23,8 @@ */ require_once(dirname(__FILE__) . '/../../../config.php'); -require_once(dirname(__FILE__) . '/locallib.php'); require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->dirroot . '/admin/tool/assignmentupgrade/locallib.php'); require_sesskey(); diff --git a/mod/assign/upgradelib.php b/mod/assign/upgradelib.php index d17dc66f20e..cb9a767d0cd 100644 --- a/mod/assign/upgradelib.php +++ b/mod/assign/upgradelib.php @@ -29,6 +29,12 @@ require_once($CFG->dirroot.'/mod/assign/locallib.php'); /** Include accesslib.php */ require_once($CFG->libdir.'/accesslib.php'); +/** + * The maximum amount of time to spend upgrading a single assignment. + * This is intentionally generous (5 mins) as the effect of a timeout + * for a legitimate upgrade would be quite harsh (roll back code will not run) + */ +define('ASSIGN_MAX_UPGRADE_TIME_SECS', 300); /** * Class to manage upgrades from mod_assignment to mod_assign @@ -48,9 +54,7 @@ class assign_upgrade_manager { * @return bool true or false */ public function upgrade_assignment($oldassignmentid, & $log) { - global $DB, $CFG; // steps to upgrade an assignment - global $DB, $CFG, $USER; // steps to upgrade an assignment @@ -59,6 +63,9 @@ class assign_upgrade_manager { return false; } + // should we use a shutdown handler to rollback on timeout? + @set_time_limit(ASSIGN_MAX_UPGRADE_TIME_SECS); + // get the module details $oldmodule = $DB->get_record('modules', array('name'=>'assignment'), '*', MUST_EXIST); @@ -217,7 +224,7 @@ class assign_upgrade_manager { } catch (Exception $exception) { $rollback = true; - $log .= get_string('conversionexception', 'mod_assign', $exception->getMessage()); + $log .= get_string('conversionexception', 'mod_assign', $exception->error); } if ($rollback) { From fc6b4c1b4d9c2ac4d66921d86fe742f859ce3acd Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 4 May 2012 18:43:13 +0100 Subject: [PATCH 186/455] MDL-31393 qtype_essay upgrade: save old question_answers.feebdack --- question/type/essay/db/upgrade.php | 80 ++++++++++++++++++++++++++++++ question/type/essay/version.php | 2 +- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/question/type/essay/db/upgrade.php b/question/type/essay/db/upgrade.php index 7a80f4dba34..6d60323c623 100644 --- a/question/type/essay/db/upgrade.php +++ b/question/type/essay/db/upgrade.php @@ -40,5 +40,85 @@ function xmldb_qtype_essay_upgrade($oldversion) { // Moodle v2.2.0 release upgrade line // Put any upgrade step following this + if ($oldversion < 2011102701) { + // In Moodle <= 2.0 essay had both question.generalfeedback and question_answers.feedback. + // This was silly, and in Moodel >= 2.1 only question.generalfeedback. To avoid + // dataloss, we concatenate question_answers.feedback onto the end of question.generalfeedback. + $toupdate = $DB->get_recordset_sql(" + SELECT q.id, + q.generalfeedback, + q.generalfeedbackformat, + qa.feedback, + qa.feedbackformat + + FROM {question} q + JOIN {question_answers} qa ON qa.question = q.id + + WHERE q.qtype = 'essay' + AND " . $DB->sql_isnotempty('question_answers', 'feedback', false, true)); + + foreach ($toupdate as $data) { + upgrade_set_timeout(60); + if ($data->generalfeedbackformat == $data->feedbackformat) { + $DB->set_field('question', 'generalfeedback', + $data->generalfeedback . $data->feedback, + array('id' => $data->id)); + + } else { + $newdata = new stdClass(); + $newdata->id = $data->id; + $newdata->generalfeedback = + qtype_essay_convert_to_html($data->generalfeedback, $data->generalfeedbackformat) . + qtype_essay_convert_to_html($data->feedback, $data->feedbackformat); + $newdata->generalfeedbackformat = FORMAT_HTML; + $DB->update_record('question', $newdata); + } + } + + $toupdate->close(); + + // Essay savepoint reached. + upgrade_plugin_savepoint(true, 2011102701, 'qtype', 'essay'); + } + + if ($oldversion < 2011102702) { + // Then we delete the old question_answers rows for essay questions. + $DB->delete_records_select('question_answers', + "question IN (SELECT id FROM {question} WHERE qtype = 'essay')"); + + // Essay savepoint reached. + upgrade_plugin_savepoint(true, 2011102702, 'qtype', 'essay'); + } + return true; } + +/** + * Convert some content to HTML. + * @param string $text the content to convert to HTML + * @param int $oldformat One of the FORMAT_... constants. + */ +function qtype_essay_convert_to_html($text, $oldformat) { + switch ($oldformat) { + // Similar to format_text. + + case FORMAT_PLAIN: + $text = s($text); + $text = str_replace(' ', '  ', $text); + $text = nl2br($text); + return $text; + + case FORMAT_MARKDOWN: + return markdown_to_html($text); + + case FORMAT_MOODLE: + return text_to_html($text); + + case FORMAT_HTML: + return $text; + + default: + throw new coding_exception( + 'Unexpected text format when upgrading essay questions.'); + } +} diff --git a/question/type/essay/version.php b/question/type/essay/version.php index fec288963ce..0b44d4b6631 100644 --- a/question/type/essay/version.php +++ b/question/type/essay/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'qtype_essay'; -$plugin->version = 2011102700; +$plugin->version = 2011102702; $plugin->requires = 2011102700; From a769a00157717262deae4a63f1dc3696f18b777e Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Fri, 11 May 2012 14:28:03 +0800 Subject: [PATCH 187/455] MDL-32933: Add outcomes to mod_assign and upgrade tool --- mod/assign/gradingtable.php | 30 +++++++++++++++-- mod/assign/locallib.php | 64 +++++++++++++++++++++++++++++++++++-- mod/assign/upgradelib.php | 51 ++++++----------------------- 3 files changed, 100 insertions(+), 45 deletions(-) diff --git a/mod/assign/gradingtable.php b/mod/assign/gradingtable.php index 03b11f1592d..3ab2e07701f 100644 --- a/mod/assign/gradingtable.php +++ b/mod/assign/gradingtable.php @@ -171,6 +171,13 @@ class assign_grading_table extends table_sql implements renderable { $columns[] = 'finalgrade'; $headers[] = get_string('finalgrade', 'grades'); + // load the grading info for all users + $this->gradinginfo = grade_get_grades($this->assignment->get_course()->id, 'mod', 'assign', $this->assignment->get_instance()->id, $users); + + if (!empty($CFG->enableoutcomes) && !empty($this->gradinginfo->outcomes)) { + $columns[] = 'outcomes'; + $headers[] = get_string('outcomes', 'grades'); + } // set the columns @@ -179,6 +186,8 @@ class assign_grading_table extends table_sql implements renderable { $this->no_sorting('finalgrade'); $this->no_sorting('edit'); $this->no_sorting('select'); + $this->no_sorting('outcomes'); + foreach ($this->assignment->get_submission_plugins() as $plugin) { if ($plugin->is_visible() && $plugin->is_enabled()) { $this->no_sorting('assignsubmission_' . $plugin->get_type()); @@ -190,8 +199,6 @@ class assign_grading_table extends table_sql implements renderable { } } - // load the grading info for all users - $this->gradinginfo = grade_get_grades($this->assignment->get_course()->id, 'mod', 'assign', $this->assignment->get_instance()->id, $users); } /** @@ -228,6 +235,25 @@ class assign_grading_table extends table_sql implements renderable { return $o; } + /** + * Format a list of outcomes + * + * @param stdClass $row + * @return string + */ + function col_outcomes(stdClass $row) { + $outcomes = ''; + foreach($this->gradinginfo->outcomes as $index=>$outcome) { + $options = make_grades_menu(-$outcome->scaleid); + + $options[0] = get_string('nooutcome', 'grades'); + $outcomes .= $this->output->container($outcome->name . ': ' . $options[$outcome->grades[$row->userid]->grade], 'outcome'); + } + + return $outcomes; + } + + /** * Format a user picture for display (and update rownum as a sideeffect) * diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index d694b0b9f3d..9cd960d92cf 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -560,7 +560,7 @@ class assign { if ($this->adminconfig) { return $this->adminconfig; } - $this->adminconfig = get_config('mod_assign'); + $this->adminconfig = get_config('assign'); return $this->adminconfig; } @@ -2487,8 +2487,30 @@ class assign { } } } - $mform->addElement('static', 'progress', '', get_string('gradingstudentprogress', 'assign', array('index'=>$rownum+1, 'count'=>count($useridlist)))); + $gradinginfo = grade_get_grades($this->get_course()->id, + 'mod', + 'assign', + $this->get_instance()->id, + $userid); + if (!empty($CFG->enableoutcomes)) { + foreach($gradinginfo->outcomes as $index=>$outcome) { + $options = make_grades_menu(-$outcome->scaleid); + if ($outcome->grades[$userid]->locked) { + $options[0] = get_string('nooutcome', 'grades'); + $mform->addElement('static', 'outcome_'.$index.'['.$userid.']', $outcome->name.':', + $options[$outcome->grades[$userid]->grade]); + } else { + $options[''] = get_string('nooutcome', 'grades'); + $attributes = array('id' => 'menuoutcome_'.$index ); + $mform->addElement('select', 'outcome_'.$index.'['.$userid.']', $outcome->name.':', $options, $attributes ); + $mform->setType('outcome_'.$index.'['.$userid.']', PARAM_INT); + $mform->setDefault('outcome_'.$index.'['.$userid.']', $outcome->grades[$userid]->grade ); + } + } + } + + $mform->addElement('static', 'progress', '', get_string('gradingstudentprogress', 'assign', array('index'=>$rownum+1, 'count'=>count($useridlist)))); // plugins $this->add_plugin_grade_elements($grade, $mform, $data); @@ -2701,6 +2723,43 @@ class assign { $this->add_to_log('unlock submission', get_string('unlocksubmissionforstudent', 'assign', array('id'=>$user->id, 'fullname'=>fullname($user)))); } + /** + * save outcomes submitted from grading form + * + * @param int $userid + * @param stdClass $formdata + */ + private function process_outcomes($userid, $formdata) { + global $CFG, $USER; + + if (empty($CFG->enableoutcomes)) { + return; + } + + require_once($CFG->libdir.'/gradelib.php'); + + $data = array(); + $gradinginfo = grade_get_grades($this->get_course()->id, + 'mod', + 'assign', + $this->get_instance()->id, + $userid); + + if (!empty($gradinginfo->outcomes)) { + foreach($gradinginfo->outcomes as $index=>$oldoutcome) { + $name = 'outcome_'.$index; + if (isset($formdata->{$name}[$userid]) and $oldoutcome->grades[$userid]->grade != $formdata->{$name}[$userid]) { + $data[$index] = $formdata->{$name}[$userid]; + } + } + } + if (count($data) > 0) { + grade_update_outcomes('mod/assign', $this->course->id, 'mod', 'assign', $this->get_instance()->id, $userid, $data); + } + + } + + /** * save grade * @@ -2763,6 +2822,7 @@ class assign { } } } + $this->process_outcomes($userid, $formdata); $this->update_grade($grade); $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); diff --git a/mod/assign/upgradelib.php b/mod/assign/upgradelib.php index d17dc66f20e..36b203671a8 100644 --- a/mod/assign/upgradelib.php +++ b/mod/assign/upgradelib.php @@ -105,6 +105,7 @@ class assign_upgrade_manager { $gradingdefinitions = null; $gradeidmap = array(); $completiondone = false; + $gradesdone = false; // from this point we want to rollback on failure $rollback = false; @@ -213,7 +214,9 @@ class assign_upgrade_manager { $newassignment->update_gradebook(false,$newcoursemodule->id); // copy the grades from the old assignment to the new one - $this->copy_grades_for_upgrade($oldassignment, $newassignment); + $DB->set_field('grade_items', 'itemmodule', 'assign', array('iteminstance'=>$oldassignment->id)); + $DB->set_field('grade_items', 'iteminstance', $newassignment->get_instance()->id, array('iteminstance'=>$oldassignment->id)); + $gradesdone = true; } catch (Exception $exception) { $rollback = true; @@ -221,6 +224,12 @@ class assign_upgrade_manager { } if ($rollback) { + // roll back the grades changes + if ($gradesdone) { + // copy the grades from the old assignment to the new one + $DB->set_field('grade_items', 'itemmodule', 'assignment', array('iteminstance'=>$newassignment->get_instance()->id)); + $DB->set_field('grade_items', 'iteminstance', $oldassignment->id, array('iteminstance'=>$newassignment->get_instance()->id)); + } // roll back the completion changes if ($completiondone) { $DB->set_field('course_modules_completion', 'coursemoduleid', $oldcoursemodule->id, array('coursemoduleid'=>$newcoursemodule->id)); @@ -363,44 +372,4 @@ class assign_upgrade_manager { return true; } - /** - * This function copies the grades from the old assignment module to this one. - * - * @param stdClass $oldassignment old assignment data record - * @param assign $newassignment the new assign class - * @return bool true or false - */ - public function copy_grades_for_upgrade($oldassignment, $newassignment) { - global $CFG; - - require_once($CFG->libdir.'/gradelib.php'); - - // get the old and new grade items - $oldgradeitems = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>'assignment', 'iteminstance'=>$oldassignment->id)); - if (!$oldgradeitems) { - return false; - } - $oldgradeitem = array_pop($oldgradeitems); - if (!$oldgradeitem) { - return false; - } - $newgradeitems = grade_item::fetch_all(array('itemtype'=>'mod', 'itemmodule'=>'assign', 'iteminstance'=>$newassignment->get_instance()->id)); - if (!$newgradeitems) { - return false; - } - $newgradeitem = array_pop($newgradeitems); - if (!$newgradeitem) { - return false; - } - - $gradegrades = grade_grade::fetch_all(array('itemid'=>$oldgradeitem->id)); - if ($gradegrades) { - foreach ($gradegrades as $gradeid=>$grade) { - $grade->itemid = $newgradeitem->id; - grade_update('mod/assign', $newassignment->get_course()->id, 'mod', 'assign', $newassignment->get_instance()->id, 0, $grade, NULL); - } - } - return true; - } - } From bf78ebd650779231fc16bb0c50c9e2d80fd47bc9 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Tue, 15 May 2012 13:33:59 +0800 Subject: [PATCH 188/455] MDL-32932: Add quickgrading support to mod_assign --- mod/assign/gradingbatchoperationsform.php | 2 +- mod/assign/gradingoptionsform.php | 12 +- mod/assign/gradingtable.php | 39 ++-- mod/assign/lang/en/assign.php | 7 + mod/assign/locallib.php | 214 +++++++++++++++++++--- mod/assign/module.js | 100 ++++++++-- mod/assign/quickgradingform.php | 62 +++++++ mod/assign/renderable.php | 34 +++- mod/assign/renderer.php | 21 +++ mod/assign/styles.css | 4 + 10 files changed, 437 insertions(+), 58 deletions(-) create mode 100644 mod/assign/quickgradingform.php diff --git a/mod/assign/gradingbatchoperationsform.php b/mod/assign/gradingbatchoperationsform.php index 82d08b286cd..626a7cc6a18 100644 --- a/mod/assign/gradingbatchoperationsform.php +++ b/mod/assign/gradingbatchoperationsform.php @@ -53,7 +53,7 @@ class mod_assign_grading_batch_operations_form extends moodleform { if ($instance['submissiondrafts']) { $options['reverttodraft'] = get_string('reverttodraft', 'assign'); } - $mform->addElement('select', 'operation', get_string('batchoperationsdescription', 'assign'), $options, array('class'=>'operation')); + $mform->addElement('select', 'operation', get_string('batchoperationsdescription', 'assign'), $options, array('class'=>'operation ignoredirty')); $mform->addHelpButton('operation', 'batchoperationsdescription', 'assign'); $mform->addElement('hidden', 'action', 'batchgradingoperation'); $mform->addElement('hidden', 'id', $instance['cm']); diff --git a/mod/assign/gradingoptionsform.php b/mod/assign/gradingoptionsform.php index 5d3883402a1..d9abe0fb35a 100644 --- a/mod/assign/gradingoptionsform.php +++ b/mod/assign/gradingoptionsform.php @@ -48,10 +48,16 @@ class mod_assign_grading_options_form extends moodleform { $mform->addElement('header', 'general', get_string('gradingoptions', 'assign')); // visible elements $options = array(-1=>'All',10=>'10', 20=>'20', 50=>'50', 100=>'100'); - $autosubmit = array('onchange'=>'form.submit();'); - $mform->addElement('select', 'perpage', get_string('assignmentsperpage', 'assign'), $options, $autosubmit); + $mform->addElement('select', 'perpage', get_string('assignmentsperpage', 'assign'), $options, array('class'=>'ignoredirty')); $options = array(''=>get_string('filternone', 'assign'), ASSIGN_FILTER_SUBMITTED=>get_string('filtersubmitted', 'assign'), ASSIGN_FILTER_REQUIRE_GRADING=>get_string('filterrequiregrading', 'assign')); - $mform->addElement('select', 'filter', get_string('filter', 'assign'), $options, $autosubmit); + $mform->addElement('select', 'filter', get_string('filter', 'assign'), $options, array('class'=>'ignoredirty')); + + // quickgrading + if ($instance['showquickgrading']) { + $mform->addElement('checkbox', 'quickgrading', get_string('quickgrading', 'assign'), '', array('class'=>'ignoredirty')); + $mform->addHelpButton('quickgrading', 'quickgrading', 'assign'); + $mform->setDefault('quickgrading', $instance['quickgrading']); + } // hidden params $mform->addElement('hidden', 'contextid', $instance['contextid']); diff --git a/mod/assign/gradingtable.php b/mod/assign/gradingtable.php index 3ab2e07701f..a48eb0bffbe 100644 --- a/mod/assign/gradingtable.php +++ b/mod/assign/gradingtable.php @@ -48,6 +48,8 @@ class assign_grading_table extends table_sql implements renderable { private $gradinginfo = null; /** @var int $tablemaxrows */ private $tablemaxrows = 10000; + /** @var boolean $quickgrading */ + private $quickgrading = false; /** * overridden constructor keeps a reference to the assignment class that is displaying this table @@ -56,12 +58,14 @@ class assign_grading_table extends table_sql implements renderable { * @param int $perpage how many per page * @param string $filter The current filter * @param int $rowoffset For showing a subsequent page of results + * @param bool $quickgrading Is this table wrapped in a quickgrading form? */ - function __construct(assign $assignment, $perpage, $filter, $rowoffset=0) { + function __construct(assign $assignment, $perpage, $filter, $rowoffset, $quickgrading) { global $CFG, $PAGE, $DB; parent::__construct('mod_assign_grading'); $this->assignment = $assignment; $this->perpage = $perpage; + $this->quickgrading = $quickgrading; $this->output = $PAGE->get_renderer('mod_assign'); $this->define_baseurl(new moodle_url($CFG->wwwroot . '/mod/assign/view.php', array('action'=>'grading', 'id'=>$assignment->get_course_module()->id))); @@ -115,7 +119,7 @@ class assign_grading_table extends table_sql implements renderable { // Select $columns[] = 'select'; - $headers[] = get_string('select') . '
                            '; + $headers[] = get_string('select') . '
                            '; // Edit links if (!$this->is_downloading()) { @@ -224,13 +228,14 @@ class assign_grading_table extends table_sql implements renderable { * Display a grade with scales etc. * * @param string $grade + * @param boolean $editable * @return string The formatted grade */ - function display_grade($grade) { + function display_grade($grade, $editable, $userid, $modified) { if ($this->is_downloading()) { return $grade; } - $o = $this->assignment->display_grade($grade); + $o = $this->assignment->display_grade($grade, $editable, $userid, $modified); return $o; } @@ -247,7 +252,20 @@ class assign_grading_table extends table_sql implements renderable { $options = make_grades_menu(-$outcome->scaleid); $options[0] = get_string('nooutcome', 'grades'); - $outcomes .= $this->output->container($outcome->name . ': ' . $options[$outcome->grades[$row->userid]->grade], 'outcome'); + if ($this->quickgrading&& !($outcome->grades[$row->userid]->locked)) { + $select = ''; + $outcomes .= $this->output->container($outcome->name . ': ' . $select, 'outcome'); + } else { + $outcomes .= $this->output->container($outcome->name . ': ' . $options[$outcome->grades[$row->userid]->grade], 'outcome'); + } } return $outcomes; @@ -284,7 +302,7 @@ class assign_grading_table extends table_sql implements renderable { * @return string */ function col_select(stdClass $row) { - return ''; + return ''; } /** @@ -322,12 +340,7 @@ class assign_grading_table extends table_sql implements renderable { $separator = $this->output->spacer(array(), true); } - - if ($row->grade) { - $grade = $this->display_grade($row->grade); - } else { - $grade = '-'; - } + $grade = $this->display_grade($row->grade, $this->quickgrading, $row->userid, $row->timemarked); //return $grade . $separator . $link; @@ -345,7 +358,7 @@ class assign_grading_table extends table_sql implements renderable { $grade = $this->get_gradebook_data_for_user($row->userid); if ($grade) { - $o = $this->display_grade($grade->grade); + $o = $this->display_grade($grade->grade, false, $row->userid, $row->timemarked); } return $o; diff --git a/mod/assign/lang/en/assign.php b/mod/assign/lang/en/assign.php index b279a78a54f..4141c424345 100644 --- a/mod/assign/lang/en/assign.php +++ b/mod/assign/lang/en/assign.php @@ -101,6 +101,8 @@ for \'{$a->assignment}\' at {$a->timeupdated}

                            It is available on the web site.'; $string['enabled'] = 'Enabled'; $string['errornosubmissions'] = 'There are no submissions to download'; +$string['errorquickgradingnotcompatiblewithadvancedgrading'] = 'The grades were not saved because this assignment is currently using advanced grading'; +$string['errorrecordmodified'] = 'The grades were not saved because someone has modified one or more records more recently than when you loaded the page.'; $string['feedbackcomments'] = 'Feedback comments'; $string['feedback'] = 'Feedback'; $string['feedbackplugins'] = 'Feedback plugins'; @@ -168,11 +170,16 @@ $string['preventlatesubmissions_help'] = 'If enabled, students will not be able $string['preventsubmissions'] = 'Prevent the user from making any more submissions to this assignment.'; $string['preventsubmissionsshort'] = 'Prevent submission changes'; $string['previous'] = 'Previous'; +$string['quickgrading'] = 'Quick grading'; +$string['quickgradingresult'] = 'Quick grading'; +$string['quickgradingchangessaved'] = 'The grade changes were saved'; +$string['quickgrading_help'] = 'Quick grading allows you to assign grades (and outcomes) directly in the submissions table. Quick grading is not compatible with advanced grading and is not recommended when there are multiple markers.'; $string['reverttodraftforstudent'] = 'Revert submission to draft for student: (id={$a->id}, fullname={$a->fullname}).'; $string['reverttodraft'] = 'Revert the submission to draft status.'; $string['reverttodraftshort'] = 'Revert the submission to draft'; $string['reviewed'] = 'Reviewed'; $string['savechanges'] = 'Save changes'; +$string['saveallchanges'] = 'Save all changes'; $string['savenext'] = 'Save and show next'; $string['sendnotifications'] = 'Send notifications to graders'; $string['sendnotifications_help'] = 'If enabled, graders (usually teachers) receive a message whenever a student submits an assignment, early, on time and late. Message methods are configurable.'; diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index 9cd960d92cf..ddf8edcf080 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -348,6 +348,9 @@ class assign { //cancel button $action = 'grading'; } + }else if ($action == 'quickgrade') { + $message = $this->process_save_quick_grades(); + $action = 'quickgradingresult'; }else if ($action == 'saveoptions') { $this->process_save_grading_options(); $action = 'grading'; @@ -360,6 +363,9 @@ class assign { if ($action == 'previousgrade') { $mform = null; $o .= $this->view_single_grade_page($mform, -1); + } else if ($action == 'quickgradingresult') { + $mform = null; + $o .= $this->view_quickgrading_result($message); } else if ($action == 'nextgrade') { $mform = null; $o .= $this->view_single_grade_page($mform, 1); @@ -882,17 +888,20 @@ class assign { * Return a grade in user-friendly form, whether it's a scale or not * * @param mixed $grade int|null + * @param boolean $editing Are we allowing changes to this grade? * @return string User-friendly representation of grade */ - public function display_grade($grade) { + public function display_grade($grade, $editing, $userid=0, $modified=0) { global $DB; static $scalegrades = array(); - - if ($this->get_instance()->grade >= 0) { // Normal number - if ($grade == -1 || $grade === null) { + if ($editing) { + $o = ''; + $o .= ' / ' . format_float($this->get_instance()->grade,2); + return $o; + } else if ($grade == -1 || $grade === null) { return '-'; } else { return format_float(($grade),2) .' / '. format_float($this->get_instance()->grade,2); @@ -906,11 +915,26 @@ class assign { return '-'; } } - $scaleid = (int)$grade; - if (isset($this->cache['scale'][$scaleid])) { - return $this->cache['scale'][$scaleid]; + if ($editing) { + $o = ''; + $o .= ''; + return $o; + } else { + $scaleid = (int)$grade; + if (isset($this->cache['scale'][$scaleid])) { + return $this->cache['scale'][$scaleid]; + } + return '-'; } - return '-'; } } @@ -961,7 +985,7 @@ class assign { */ private function get_grading_userid_list(){ $filter = get_user_preferences('assign_filter', ''); - $table = new assign_grading_table($this, 0, $filter); + $table = new assign_grading_table($this, 0, $filter, 0, false); $useridlist = $table->get_column_data('userid'); @@ -987,7 +1011,7 @@ class assign { } $filter = get_user_preferences('assign_filter', ''); - $table = new assign_grading_table($this, 0, $filter); + $table = new assign_grading_table($this, 0, $filter, 0, false); $userid = $table->get_cell_data($num, 'userid', $last); @@ -1203,11 +1227,28 @@ class assign { return $result; } + /** + * Display a grading error + * + * @param string $message - The description of the result + * @return string + */ + private function view_quickgrading_result($message) { + $o = ''; + $o .= $this->output->render(new assign_header($this->get_instance(), + $this->get_context(), + $this->show_intro(), + $this->get_course_module()->id, + get_string('quickgradingresult', 'assign'))); + $o .= $this->output->render(new assign_quickgrading_result($message, $this->get_course_module()->id)); + $o .= $this->view_footer(); + return $o; + } /** * Display the page footer * - * @return None + * @return string */ private function view_footer() { return $this->output->render_footer(); @@ -1523,6 +1564,7 @@ class assign { // Include grading options form require_once($CFG->dirroot . '/mod/assign/gradingoptionsform.php'); require_once($CFG->dirroot . '/mod/assign/gradingactionsform.php'); + require_once($CFG->dirroot . '/mod/assign/quickgradingform.php'); require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php'); $o = ''; @@ -1548,13 +1590,25 @@ class assign { 'post', '', array('class'=>'gradingactionsform')); + $gradingmanager = get_grading_manager($this->get_context(), 'mod_assign', 'submissions'); + $perpage = get_user_preferences('assign_perpage', 10); $filter = get_user_preferences('assign_filter', ''); + $controller = $gradingmanager->get_active_controller(); + $showquickgrading = empty($controller); + if (optional_param('action', '', PARAM_ALPHA) == 'saveoptions') { + $quickgrading = optional_param('quickgrading', false, PARAM_BOOL); + set_user_preference('assign_quickgrading', $quickgrading); + } + $quickgrading = get_user_preferences('assign_quickgrading', false); + // print options for changing the filter and changing the number of results per page $gradingoptionsform = new mod_assign_grading_options_form(null, array('cm'=>$this->get_course_module()->id, 'contextid'=>$this->context->id, - 'userid'=>$USER->id), + 'userid'=>$USER->id, + 'showquickgrading'=>$showquickgrading, + 'quickgrading'=>$quickgrading), 'post', '', array('class'=>'gradingoptionsform')); @@ -1577,10 +1631,18 @@ class assign { } $o .= $this->output->render(new assign_form('gradingactionsform', $gradingactionsform)); - $o .= $this->output->render(new assign_form('gradingoptionsform', $gradingoptionsform)); + $o .= $this->output->render(new assign_form('gradingoptionsform', $gradingoptionsform, 'M.mod_assign.init_grading_options')); // load and print the table of submissions - $o .= $this->output->render(new assign_grading_table($this, $perpage, $filter)); + if ($showquickgrading && $quickgrading) { + $table = $this->output->render(new assign_grading_table($this, $perpage, $filter, 0, true)); + $quickgradingform = new mod_assign_quick_grading_form(null, + array('cm'=>$this->get_course_module()->id, + 'gradingtable'=>$table)); + $o .= $this->output->render(new assign_form('quickgradingform', $quickgradingform)); + } else { + $o .= $this->output->render(new assign_grading_table($this, $perpage, $filter, 0, false)); + } $currentgroup = groups_get_activity_group($this->get_course_module(), true); $users = array_keys($this->list_participants($currentgroup, true)); @@ -1658,7 +1720,7 @@ class assign { $this->get_course_module()->id, get_string('editsubmission', 'assign'))); - $o .= $this->output->notification('This assignment is no longer accepting submissions'); + $o .= $this->output->notification(get_string('submissionsclosed', 'assign')); $o .= $this->view_footer(); @@ -1682,9 +1744,7 @@ class assign { require_capability('mod/assign:submit', $this->context); if (!$this->submissions_open()) { - $subclosed = ''; - $subclosed .= $this->view_student_error_message(); - return $subclosed; + return $this->view_student_error_message(); } $o .= $this->output->render(new assign_header($this->get_instance(), $this->get_context(), @@ -1875,7 +1935,7 @@ class assign { $gradebookgrade->str_long_grade, has_capability('mod/assign:grade', $this->get_context())); } else { - $gradefordisplay = $this->display_grade($gradebookgrade->grade); + $gradefordisplay = $this->display_grade($gradebookgrade->grade, false); } $gradeddate = $gradebookgrade->dategraded; @@ -2256,6 +2316,118 @@ class assign { } } + /** + * save quick grades + * + * @return string - The result of the save operation + */ + private function process_save_quick_grades() { + global $USER, $DB, $CFG; + + // Need grade permission + require_capability('mod/assign:grade', $this->context); + + // make sure advanced grading is disabled + $gradingmanager = get_grading_manager($this->get_context(), 'mod_assign', 'submissions'); + $controller = $gradingmanager->get_active_controller(); + if (!empty($controller)) { + return get_string('errorquickgradingnotcompatiblewithadvancedgrading', 'assign'); + } + + $users = array(); + // first check all the last modified values + $len = strlen('grademodified_'); + foreach ($_POST as $key => $value) { + if (substr($key, 0, $len) === 'grademodified_') { + // gather the userid, updated grade and last modified value + $record = new stdClass(); + $record->userid = (int)substr($key, $len); + $record->grade = required_param('quickgrade_' . $record->userid, PARAM_INT); + $record->lastmodified = $value; + $record->gradinginfo = grade_get_grades($this->get_course()->id, 'mod', 'assign', $this->get_instance()->id, array($record->userid)); + $users[$record->userid] = $record; + } + } + list($userids, $useridparams) = $DB->get_in_or_equal(array_keys($users)); + + // check them all for currency + $currentgrades = $DB->get_recordset_sql('SELECT u.id as userid, + g.grade as grade, + g.timemodified as lastmodified + FROM {user} u + LEFT JOIN {assign_grades} g ON + u.id = g.userid AND + g.assignment = ? WHERE u.id ' . + $userids, + array_merge(array($this->get_instance()->id), + $useridparams)); + + $modifiedusers = array(); + foreach ($currentgrades as $current) { + $modified = $users[(int)$current->userid]; + + // check to see if the outcomes were modified + if ($CFG->enableoutcomes) { + foreach ($modified->gradinginfo->outcomes as $outcomeid => $outcome) { + $oldoutcome = $outcome->grades[$modified->userid]->grade; + $newoutcome = optional_param('outcome_' . $outcomeid . '_' . $modified->userid, -1, PARAM_INT); + if ($oldoutcome != $newoutcome) { + // can't check modified time for outcomes because it is not reported + $modifiedusers[$modified->userid] = $modified; + continue; + } + } + } + + + if (($current->grade < 0 || $current->grade === NULL) && + ($modified->grade < 0 || $modified->grade === NULL)) { + // different ways to indicate no grade + continue; + } + if ($current->grade != $modified->grade) { + // grade changed + if ((int)$current->lastmodified > (int)$modified->lastmodified) { + // error - record has been modified since viewing the page + return get_string('errorrecordmodified', 'assign'); + } else { + $modifiedusers[$modified->userid] = $modified; + } + } + + } + + // ok - ready to process the updates + foreach ($modifiedusers as $userid => $modified) { + $grade = $this->get_user_grade($userid, true); + $grade->grade= grade_floatval($modified->grade); + $grade->grader= $USER->id; + + $this->update_grade($grade); + + // save outcomes + if ($CFG->enableoutcomes) { + $data = array(); + foreach ($modified->gradinginfo->outcomes as $outcomeid => $outcome) { + $oldoutcome = $outcome->grades[$modified->userid]->grade; + $newoutcome = optional_param('outcome_' . $outcomeid . '_' . $modified->userid, -1, PARAM_INT); + if ($oldoutcome != $newoutcome) { + $data[$outcomeid] = $newoutcome; + } + } + if (count($data) > 0) { + grade_update_outcomes('mod/assign', $this->course->id, 'mod', 'assign', $this->get_instance()->id, $userid, $data); + } + } + + $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); + + $this->add_to_log('grade submission', $this->format_grade_for_log($grade)); + } + + return get_string('quickgradingchangessaved', 'assign'); + } + /** * save grading options * @@ -2272,7 +2444,7 @@ class assign { - $mform = new mod_assign_grading_options_form(null, array('cm'=>$this->get_course_module()->id, 'contextid'=>$this->context->id, 'userid'=>$USER->id)); + $mform = new mod_assign_grading_options_form(null, array('cm'=>$this->get_course_module()->id, 'contextid'=>$this->context->id, 'userid'=>$USER->id, 'showquickgrading'=>false)); if ($formdata = $mform->get_data()) { set_user_preference('assign_perpage', $formdata->perpage); @@ -2295,7 +2467,7 @@ class assign { $info = get_string('gradestudent', 'assign', array('id'=>$user->id, 'fullname'=>fullname($user))); if ($grade->grade != '') { - $info .= get_string('grade') . ': ' . $this->display_grade($grade->grade) . '. '; + $info .= get_string('grade') . ': ' . $this->display_grade($grade->grade, false) . '. '; } else { $info .= get_string('nograde', 'assign'); } diff --git a/mod/assign/module.js b/mod/assign/module.js index 386a117b959..841da27257a 100644 --- a/mod/assign/module.js +++ b/mod/assign/module.js @@ -39,23 +39,25 @@ M.mod_assign.init_grading_table = function(Y) { }); var selectall = Y.one('th.c0 input'); - selectall.on('change', function(e) { - if (e.currentTarget.get('checked')) { - checkboxes = Y.all('td.c0 input'); - checkboxes.each(function(node) { - rowelement = node.get('parentNode').get('parentNode'); - node.set('checked', true); - rowelement.setAttribute('class', 'selectedrow'); - }); - } else { - checkboxes = Y.all('td.c0 input'); - checkboxes.each(function(node) { - rowelement = node.get('parentNode').get('parentNode'); - node.set('checked', false); - rowelement.setAttribute('class', 'unselectedrow'); - }); - } - }); + if (selectall) { + selectall.on('change', function(e) { + if (e.currentTarget.get('checked')) { + checkboxes = Y.all('td.c0 input'); + checkboxes.each(function(node) { + rowelement = node.get('parentNode').get('parentNode'); + node.set('checked', true); + rowelement.setAttribute('class', 'selectedrow'); + }); + } else { + checkboxes = Y.all('td.c0 input'); + checkboxes.each(function(node) { + rowelement = node.get('parentNode').get('parentNode'); + node.set('checked', false); + rowelement.setAttribute('class', 'unselectedrow'); + }); + } + }); + } var batchform = Y.one('form.gradingbatchoperationsform'); batchform.on('submit', function(e) { @@ -99,8 +101,72 @@ M.mod_assign.init_grading_table = function(Y) { }); + quickgrade = Y.all('.gradingtable .quickgrade'); + quickgrade.each(function(quick) { + quick.on('change', function(e) { + parent = this.get('parentNode'); + parent.addClass('quickgrademodified'); + }); + }); + }); +}; + +M.mod_assign.check_dirty_quickgrading_form = function(e) { + + if (!M.core_formchangechecker.get_form_dirty_state()) { + // the form is not dirty, so don't display any message + return; + } + + // This is the error message that we'll show to browsers which support it + var warningmessage = 'There are unsaved quickgrading changes. Do you really wanto to leave this page?'; + + // Most browsers are happy with the returnValue being set on the event + // But some browsers do not consistently pass the event + if (e) { + e.returnValue = warningmessage; + } + + // But some require it to be returned instead + return warningmessage; +} +M.mod_assign.init_grading_options = function(Y) { + Y.use('node', function(Y) { + + var paginationelement = Y.one('#id_perpage'); + paginationelement.on('change', function(e) { + Y.one('form.gradingoptionsform').submit(); + }); + var filterelement = Y.one('#id_filter'); + filterelement.on('change', function(e) { + Y.one('form.gradingoptionsform').submit(); + }); + var quickgradingelement = Y.one('#id_quickgrading'); + quickgradingelement.on('change', function(e) { + Y.one('form.gradingoptionsform').submit(); + }); }); }; +// override the default dirty form behaviour to ignore any input with the class "ignoredirty" +M.mod_assign.set_form_changed = M.core_formchangechecker.set_form_changed; +M.core_formchangechecker.set_form_changed = function(e) { + target = e.currentTarget; + if (!target.hasClass('ignoredirty')) { + M.mod_assign.set_form_changed(e); + } +} + +M.mod_assign.get_form_dirty_state = M.core_formchangechecker.get_form_dirty_state; +M.core_formchangechecker.get_form_dirty_state = function() { + var state = M.core_formchangechecker.stateinformation; + if (state.focused_element) { + if (state.focused_element.element.hasClass('ignoredirty')) { + state.focused_element.initial_value = state.focused_element.element.get('value') + } + } + return M.mod_assign.get_form_dirty_state(); +} + diff --git a/mod/assign/quickgradingform.php b/mod/assign/quickgradingform.php new file mode 100644 index 00000000000..0598b570d2f --- /dev/null +++ b/mod/assign/quickgradingform.php @@ -0,0 +1,62 @@ +. + +/** + * This file contains the forms to create and edit an instance of this module + * + * @package mod_assign + * @copyright 2012 NetSpot {@link http://www.netspot.com.au} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); + + +/** Include formslib.php */ +require_once ($CFG->libdir.'/formslib.php'); +/** Include locallib.php */ +require_once($CFG->dirroot . '/mod/assign/locallib.php'); + +/** + * Assignment quick grading form + * + * @package mod_assign + * @copyright 2012 NetSpot {@link http://www.netspot.com.au} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class mod_assign_quick_grading_form extends moodleform { + /** + * Define this form - called from the parent constructor + */ + function definition() { + $mform = $this->_form; + $instance = $this->_customdata; + + // visible elements + $mform->addElement('html', $instance['gradingtable']); + + // hidden params + $mform->addElement('hidden', 'id', $instance['cm']); + $mform->setType('id', PARAM_INT); + $mform->addElement('hidden', 'action', 'quickgrade'); + $mform->setType('action', PARAM_ALPHA); + + // buttons + $mform->addElement('header', 'general', get_string('quickgrading', 'assign')); + $mform->addElement('submit', 'savequickgrades', get_string('saveallchanges', 'assign')); + } +} + diff --git a/mod/assign/renderable.php b/mod/assign/renderable.php index 6ce054c52a4..fa7a9fe4f40 100644 --- a/mod/assign/renderable.php +++ b/mod/assign/renderable.php @@ -48,6 +48,29 @@ class assign_submit_for_grading_page implements renderable { } +/** + * Implements a renderable grading error notification + * @package mod_assign + * @copyright 2012 NetSpot {@link http://www.netspot.com.au} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class assign_quickgrading_result implements renderable { + /** @var string $message is the message to display to the user */ + var $message = ''; + /** @var int $coursemoduleid */ + var $coursemoduleid = 0; + + /** + * Constructor + * @param string $message This is the message to display + */ + public function __construct($message, $coursemoduleid) { + $this->message = $message; + $this->coursemoduleid = $coursemoduleid; + } + +} + /** * Implements a renderable grading options form * @package mod_assign @@ -59,19 +82,24 @@ class assign_form implements renderable { var $form = null; /** @var string $classname is the name of the class to assign to the container */ var $classname = ''; + /** @var string $jsinitfunction is an optional js function to add to the page requires */ + var $jsinitfunction = ''; /** * Constructor - * @param string $classname - * @param moodleform $form + * @param string $classname This is the class name for the container div + * @param moodleform $form This is the moodleform + * @param string $jsinitfunction This is an optional js function to add to the page requires */ - public function __construct($classname, moodleform $form) { + public function __construct($classname, moodleform $form, $jsinitfunction = '') { $this->classname = $classname; $this->form = $form; + $this->jsinitfunction = $jsinitfunction; } } + /** * Implements a renderable user summary * @package mod_assign diff --git a/mod/assign/renderer.php b/mod/assign/renderer.php index 8fca9b03864..7efed66cd83 100644 --- a/mod/assign/renderer.php +++ b/mod/assign/renderer.php @@ -86,6 +86,24 @@ class mod_assign_renderer extends plugin_renderer_base { $table->data[] = $row; } + /** + * Render a grading error notification + * @param assign_quickgrading_result $result The result to render + * @return string + */ + public function render_assign_quickgrading_result(assign_quickgrading_result $result) { + $o = ''; + $o .= $this->output->heading(get_string('quickgradingresult', 'assign'), 4); + + $o .= $this->output->notification($result->message); + + $o .= $this->output->continue_button(new moodle_url('/mod/assign/view.php', + array('id' => $result->coursemoduleid, + 'action'=>'grading'))); + + return $o; + } + /** * Render the generic form * @param assign_form $form The form to render @@ -93,6 +111,9 @@ class mod_assign_renderer extends plugin_renderer_base { */ public function render_assign_form(assign_form $form) { $o = ''; + if ($form->jsinitfunction) { + $this->page->requires->js_init_call($form->jsinitfunction, array()); + } $o .= $this->output->box_start('boxaligncenter ' . $form->classname); $o .= $this->moodleform($form->form); $o .= $this->output->box_end(); diff --git a/mod/assign/styles.css b/mod/assign/styles.css index 55523a942ce..de28899866e 100644 --- a/mod/assign/styles.css +++ b/mod/assign/styles.css @@ -128,3 +128,7 @@ div.earlysubmission { border: 0px; } +#page-mod-assign-view div.gradingtable tr .quickgrademodified { + background-color: #FFCC99; +} + From 5bd2824a797a5406c2b25bb91e461ca3d3021b36 Mon Sep 17 00:00:00 2001 From: Wiktor Wandachowicz Date: Tue, 15 May 2012 15:33:53 +0200 Subject: [PATCH 189/455] MDL-32204 MNet: set auth method to mnet for users enrolled remotely --- enrol/mnet/enrol.php | 1 + 1 file changed, 1 insertion(+) diff --git a/enrol/mnet/enrol.php b/enrol/mnet/enrol.php index 7a0a0af5a63..c09cd7e4601 100644 --- a/enrol/mnet/enrol.php +++ b/enrol/mnet/enrol.php @@ -145,6 +145,7 @@ class enrol_mnet_mnetservice_enrol { // users {@link http://tracker.moodle.org/browse/MDL-21327} $user = mnet_strip_user((object)$userdata, mnet_fields_to_import($client)); $user->mnethostid = $client->id; + $user->auth = 'mnet'; try { $user->id = $DB->insert_record('user', $user); } catch (Exception $e) { From 5ef18d825013dce24d4ebea785efd85b87cb47b2 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 15 May 2012 17:55:29 +0100 Subject: [PATCH 190/455] MDL-33020 qtype unit tests: improve failure messages. --- question/engine/tests/helpers.php | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/question/engine/tests/helpers.php b/question/engine/tests/helpers.php index 0f3c8914dc1..40c7ccff2d6 100644 --- a/question/engine/tests/helpers.php +++ b/question/engine/tests/helpers.php @@ -423,33 +423,38 @@ abstract class data_loading_method_test_base extends advanced_testcase { abstract class question_testcase extends advanced_testcase { - public function assert($expectation, $compare, $message = '') { - $message = (isset($expectation->message) and $expectation->message !== '') ? $expectation->message : $message; + public function assert($expectation, $compare, $notused = '') { if (get_class($expectation) === 'question_pattern_expectation') { - $this->assertRegExp($expectation->pattern, $compare, $message); + $this->assertRegExp($expectation->pattern, $compare, + 'Expected regex ' . $expectation->pattern . ' not found in ' . $compare); return; } else if (get_class($expectation) === 'question_no_pattern_expectation') { - $this->assertNotRegExp($expectation->pattern, $compare, $message); + $this->assertNotRegExp($expectation->pattern, $compare, + 'Unexpected regex ' . $expectation->pattern . ' found in ' . $compare); return; } else if (get_class($expectation) === 'question_contains_tag_with_attributes') { - $this->assertTag(array('tag'=>$expectation->tag, 'attributes'=>$expectation->expectedvalues), $compare, $message); + $this->assertTag(array('tag'=>$expectation->tag, 'attributes'=>$expectation->expectedvalues), $compare, + 'Looking for a ' . $expectation->tag . ' with attributes ' . html_writer::attributes($expectation->expectedvalues) . ' in ' . $compare); foreach ($expectation->forbiddenvalues as $k=>$v) { $attr = $expectation->expectedvalues; $attr[$k] = $v; - $this->assertNotTag(array('tag'=>$expectation->tag, 'attributes'=>$attr), $compare, $message); + $this->assertNotTag(array('tag'=>$expectation->tag, 'attributes'=>$attr), $compare, + $expectation->tag . ' had a ' . $k . ' attribute that should not be there in ' . $compare); } return; } else if (get_class($expectation) === 'question_contains_tag_with_attribute') { $attr = array($expectation->attribute=>$expectation->value); - $this->assertTag(array('tag'=>$expectation->tag, 'attributes'=>$attr), $compare, $message); + $this->assertTag(array('tag'=>$expectation->tag, 'attributes'=>$attr), $compare, + 'Looking for a ' . $expectation->tag . ' with attribute ' . html_writer::attributes($attr) . ' in ' . $compare); return; } else if (get_class($expectation) === 'question_does_not_contain_tag_with_attributes') { - $this->assertNotTag(array('tag'=>$expectation->tag, 'attributes'=>$expectation->attributes), $compare, $message); + $this->assertNotTag(array('tag'=>$expectation->tag, 'attributes'=>$expectation->attributes), $compare, + 'Unexpected ' . $expectation->tag . ' with attributes ' . html_writer::attributes($expectation->attributes) . ' found in ' . $compare); return; } else if (get_class($expectation) === 'question_contains_select_expectation') { @@ -492,7 +497,8 @@ abstract class question_testcase extends advanced_testcase { return; } else if (get_class($expectation) === 'question_contains_tag_with_contents') { - $this->assertTag(array('tag'=>$expectation->tag, 'content'=>$expectation->content), $compare, $message); + $this->assertTag(array('tag'=>$expectation->tag, 'content'=>$expectation->content), $compare, + 'Looking for a ' . $expectation->tag . ' with content ' . $expectation->content . ' in ' . $compare); return; } @@ -652,8 +658,8 @@ abstract class qbehaviour_walkthrough_test_base extends question_testcase { } protected function check_current_state($state) { - $this->assertEquals($this->quba->get_question_state($this->slot), $state, - 'Questions is in the wrong state: %s.'); + $this->assertEquals($state, $this->quba->get_question_state($this->slot), + 'Questions is in the wrong state.'); } protected function check_current_mark($mark) { @@ -666,7 +672,7 @@ abstract class qbehaviour_walkthrough_test_base extends question_testcase { $this->assertNotNull($this->quba->get_question_mark($this->slot)); } $this->assertEquals($mark, $this->quba->get_question_mark($this->slot), - 'Expected mark and actual mark differ: %s.', 0.000001); + 'Expected mark and actual mark differ.', 0.000001); } } From 7fd5786e6f24db2a6c702062705e33bef514bbac Mon Sep 17 00:00:00 2001 From: Henning Bostelmann Date: Sat, 22 Oct 2011 23:43:11 +0100 Subject: [PATCH 191/455] MDL-28557 Calendar filters: show all group events in course to teacher --- calendar/lib.php | 51 ++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/calendar/lib.php b/calendar/lib.php index 7d55605209b..c5e1e232a98 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -1374,6 +1374,10 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) { $user = false; $group = false; + // capabilities that allow seeing group events from all groups + // TODO: rewrite so that moodle/calendar:manageentries is not necessary here + $allgroupscaps = array('moodle/site:accessallgroups', 'moodle/calendar:manageentries'); + $isloggedin = isloggedin(); if ($ignorefilters || calendar_show_event_type(CALENDAR_EVENT_COURSE)) { @@ -1399,26 +1403,35 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) { if (!empty($courseeventsfrom) && (calendar_show_event_type(CALENDAR_EVENT_GROUP) || $ignorefilters)) { - if (!empty($CFG->calendar_adminseesall) && has_capability('moodle/calendar:manageentries', get_system_context())) { - $group = true; - } else if ($isloggedin) { - $groupids = array(); - - // We already have the courses to examine in $courses - // For each course... - foreach ($courseeventsfrom as $courseid => $course) { - // If the user is an editing teacher in there, - if (!empty($USER->groupmember[$course->id])) { - // We've already cached the users groups for this course so we can just use that - $groupids = array_merge($groupids, $USER->groupmember[$course->id]); - } else if (($course->groupmode != NOGROUPS || !$course->groupmodeforce) && has_capability('moodle/calendar:manageentries', get_context_instance(CONTEXT_COURSE, $course->id))) { - // If this course has groups, show events from all of them - $coursegroups = groups_get_user_groups($course->id, $USER->id); - $groupids = array_merge($groupids, $coursegroups['0']); - } + if (count($courseeventsfrom)==1) { + $course = reset($courseeventsfrom); + if (has_any_capability($allgroupscaps, get_context_instance(CONTEXT_COURSE, $course->id))) { + $coursegroups = groups_get_all_groups($course->id, 0, 0, 'g.id'); + $group = array_keys($coursegroups); } - if (!empty($groupids)) { - $group = $groupids; + } + if ($group === false) { + if (!empty($CFG->calendar_adminseesall) && has_any_capability($allgroupscaps, get_system_context())) { + $group = true; + } else if ($isloggedin) { + $groupids = array(); + + // We already have the courses to examine in $courses + // For each course... + foreach ($courseeventsfrom as $courseid => $course) { + // If the user is an editing teacher in there, + if (!empty($USER->groupmember[$course->id])) { + // We've already cached the users groups for this course so we can just use that + $groupids = array_merge($groupids, $USER->groupmember[$course->id]); + } else if ($course->groupmode != NOGROUPS || !$course->groupmodeforce) { + // If this course has groups, show events from all of those related to the current user + $coursegroups = groups_get_user_groups($course->id, $USER->id); + $groupids = array_merge($groupids, $coursegroups['0']); + } + } + if (!empty($groupids)) { + $group = $groupids; + } } } } From 3a68419430b0c87d65a53fced73a939a900ccf10 Mon Sep 17 00:00:00 2001 From: Jerome Mouneyrac Date: Wed, 16 May 2012 12:04:13 +0800 Subject: [PATCH 192/455] MDL-33028 display debuginfo when server die at developer mode --- webservice/amf/server.php | 2 ++ webservice/rest/server.php | 2 ++ webservice/soap/server.php | 2 ++ webservice/xmlrpc/server.php | 2 ++ 4 files changed, 8 insertions(+) diff --git a/webservice/amf/server.php b/webservice/amf/server.php index 4103f002d06..32a460227a5 100644 --- a/webservice/amf/server.php +++ b/webservice/amf/server.php @@ -37,6 +37,8 @@ require('../../config.php'); require_once("$CFG->dirroot/webservice/amf/locallib.php"); if (!webservice_protocol_is_enabled('amf')) { + debugging('The server died because the web services or the AMF protocol are not enable', + DEBUG_DEVELOPER); die; } diff --git a/webservice/rest/server.php b/webservice/rest/server.php index 5e9f515179d..c0f02bce2ef 100644 --- a/webservice/rest/server.php +++ b/webservice/rest/server.php @@ -37,6 +37,8 @@ require('../../config.php'); require_once("$CFG->dirroot/webservice/rest/locallib.php"); if (!webservice_protocol_is_enabled('rest')) { + debugging('The server died because the web services or the REST protocol are not enable', + DEBUG_DEVELOPER); die; } diff --git a/webservice/soap/server.php b/webservice/soap/server.php index 468c3257e9d..b110cfeaa89 100644 --- a/webservice/soap/server.php +++ b/webservice/soap/server.php @@ -37,6 +37,8 @@ require('../../config.php'); require_once("$CFG->dirroot/webservice/soap/locallib.php"); if (!webservice_protocol_is_enabled('soap')) { + debugging('The server died because the web services or the SOAP protocol are not enable', + DEBUG_DEVELOPER); die; } diff --git a/webservice/xmlrpc/server.php b/webservice/xmlrpc/server.php index b601bdc6c40..bb07369d3ed 100644 --- a/webservice/xmlrpc/server.php +++ b/webservice/xmlrpc/server.php @@ -37,6 +37,8 @@ require('../../config.php'); require_once("$CFG->dirroot/webservice/xmlrpc/locallib.php"); if (!webservice_protocol_is_enabled('xmlrpc')) { + debugging('The server died because the web services or the XMLRPC protocol are not enable', + DEBUG_DEVELOPER); die; } From eb7b030a8bd487b10e6d59cad6d7123ec45d2f20 Mon Sep 17 00:00:00 2001 From: Andrew Robert Nicols Date: Wed, 16 May 2012 13:52:11 +0100 Subject: [PATCH 193/455] MDL-33040 Validate dates correctly on log page --- report/log/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/report/log/index.php b/report/log/index.php index c0a94fe1114..a672f2af990 100644 --- a/report/log/index.php +++ b/report/log/index.php @@ -42,7 +42,7 @@ if (empty($host_course)) { $group = optional_param('group', 0, PARAM_INT); // Group to display $user = optional_param('user', 0, PARAM_INT); // User to display -$date = optional_param('date', 0, PARAM_FILE); // Date to display - number or some string +$date = optional_param('date', 0, PARAM_INT); // Date to display $modname = optional_param('modname', '', PARAM_PLUGIN); // course_module->id $modid = optional_param('modid', 0, PARAM_FILE); // number or 'site_errors' $modaction = optional_param('modaction', '', PARAM_PATH); // an action as recorded in the logs From 66b494771ffc731472a374bef1b5cd12befd53b2 Mon Sep 17 00:00:00 2001 From: Aaron Barnes Date: Thu, 17 May 2012 15:40:03 +1200 Subject: [PATCH 194/455] MDL-33063 course: Reuse get_all_sections() --- course/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course/lib.php b/course/lib.php index 382ae358cee..2599958db9c 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1066,7 +1066,7 @@ function get_array_of_activities($courseid) { return $mod; // always return array } - if ($sections = $DB->get_records("course_sections", array("course"=>$courseid), "section ASC")) { + if ($sections = get_all_sections($courseid)) { foreach ($sections as $section) { if (!empty($section->sequence)) { $sequence = explode(",", $section->sequence); From 096d4d876746d7576d0a6561dbd594f67c08a87e Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Thu, 17 May 2012 15:02:48 +0800 Subject: [PATCH 195/455] MDL-29924 Glossary: Entry attachments displayed in Moodle dialogue --- filter/glossary/yui/autolinker/autolinker.js | 3 ++- mod/glossary/showentry_ajax.php | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/filter/glossary/yui/autolinker/autolinker.js b/filter/glossary/yui/autolinker/autolinker.js index 46d04bca80f..e9af017e0ad 100644 --- a/filter/glossary/yui/autolinker/autolinker.js +++ b/filter/glossary/yui/autolinker/autolinker.js @@ -70,7 +70,8 @@ YUI.add('moodle-filter_glossary-autolinker', function(Y) { this.overlay.hide(); //hide progress indicator for (key in data.entries) { - new M.core.alert({title:data.entries[key].concept, message:data.entries[key].definition, lightbox:false}); + definition = data.entries[key].definition + data.entries[key].attachments + new M.core.alert({title:data.entries[key].concept, message:definition, lightbox:false}); } return true; diff --git a/mod/glossary/showentry_ajax.php b/mod/glossary/showentry_ajax.php index 9703a062874..5df4c0fe59f 100644 --- a/mod/glossary/showentry_ajax.php +++ b/mod/glossary/showentry_ajax.php @@ -70,6 +70,12 @@ if ($entries) { $options->context = $context; $entries[$key]->definition = format_text($definition, $entry->definitionformat, $options); + $entries[$key]->attachments = ''; + if (!empty($entries[$key]->attachment)) { + $attachments = glossary_print_attachments($entry, $cm, 'html'); + $entries[$key]->attachments = html_writer::tag('p', $attachments); + } + $entries[$key]->footer = "

                            » wwwroot/mod/glossary/view.php?g=$entry->glossaryid\">".format_string($entry->glossaryname,true)."

                            "; add_to_log($entry->courseid, 'glossary', 'view entry', "showentry.php?eid=$entry->id", $entry->id, $entry->cmid); } From b64300fc425e36407be5b9af82c23fc20a9b0065 Mon Sep 17 00:00:00 2001 From: Davo Smith Date: Thu, 17 May 2012 13:59:54 +0100 Subject: [PATCH 196/455] MDL-22504 Improved drag and drop status message, fixed text dragged from firefox, fix icon --- course/dndupload.js | 66 +++++++++++++++++++++++++++++++++-------- course/dndupload.php | 4 +++ course/dnduploadlib.php | 8 ++++- lang/en/moodle.php | 8 ++++- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/course/dndupload.js b/course/dndupload.js index b0d35a3dc83..3dbe326eddb 100644 --- a/course/dndupload.js +++ b/course/dndupload.js @@ -92,14 +92,12 @@ M.course_dndupload = { this.init_events(el); }, this); - var div = this.add_status_div(); - div.setContent(M.util.get_string('dndworking', 'moodle')); + this.add_status_div(); }, /** * Add a div element to tell the user that drag and drop upload * is available (or to explain why it is not available) - * @return the DOM element to add messages to */ add_status_div: function() { var div = document.createElement('div'); @@ -108,7 +106,34 @@ M.course_dndupload = { if (coursecontents) { coursecontents.insertBefore(div, coursecontents.firstChild); } - return this.Y.one(div); + div = this.Y.one(div); + + var handlefile = (this.handlers.filehandlers.length > 0); + var handletext = false; + var handlelink = false; + var i; + for (i=0; iprocess($displayname, $contents); diff --git a/course/dnduploadlib.php b/course/dnduploadlib.php index 7c7756cd3a9..b5fbc0ae560 100644 --- a/course/dnduploadlib.php +++ b/course/dnduploadlib.php @@ -52,7 +52,13 @@ function dndupload_add_to_course($course, $modnames) { 'fullpath' => new moodle_url('/course/dndupload.js'), 'strings' => array( array('addfilehere', 'moodle'), - array('dndworking', 'moodle'), + array('dndworkingfiletextlink', 'moodle'), + array('dndworkingfilelink', 'moodle'), + array('dndworkingfiletext', 'moodle'), + array('dndworkingfile', 'moodle'), + array('dndworkingtextlink', 'moodle'), + array('dndworkingtext', 'moodle'), + array('dndworkinglink', 'moodle'), array('filetoolarge', 'moodle'), array('actionchoice', 'moodle'), array('servererror', 'moodle'), diff --git a/lang/en/moodle.php b/lang/en/moodle.php index cf4b6981db1..8950c320020 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -466,7 +466,13 @@ $string['dndenabled'] = 'Drag and drop available'; $string['dndenabled_help'] = 'You can drag one or more files from your desktop and drop them onto the box below to upload them.
                            Note: this may not work with other web browsers'; $string['dndenabled_insentence'] = 'drag and drop available'; $string['dndenabled_inbox'] = 'drag and drop files here to upload them'; -$string['dndworking'] = 'Drag and drop files, text or links onto course sections to upload them'; +$string['dndworkingfiletextlink'] = 'Drag and drop files, text or links onto course sections to upload them'; +$string['dndworkingfilelink'] = 'Drag and drop files or links onto course sections to upload them'; +$string['dndworkingfiletext'] = 'Drag and drop files or text onto course sections to upload them'; +$string['dndworkingfile'] = 'Drag and drop files onto course sections to upload them'; +$string['dndworkingtextlink'] = 'Drag and drop text or links onto course sections to upload them'; +$string['dndworkingtext'] = 'Drag and drop text onto course sections to upload it'; +$string['dndworkinglink'] = 'Drag and drop links onto course sections to upload them'; $string['documentation'] = 'Moodle documentation'; $string['down'] = 'Down'; $string['download'] = 'Download'; From 5a4decbc2d271d4459dd8a9e6eb131df956570e9 Mon Sep 17 00:00:00 2001 From: Davo Smith Date: Thu, 17 May 2012 21:19:52 +0100 Subject: [PATCH 197/455] MDL-22504 Course drag and drop upload - (mostly) fixed the dragging of text between Firefox <==> Chrome --- course/dndupload.js | 73 ++++++++++++++++++++++++++++++++--------- course/dnduploadlib.php | 2 +- 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/course/dndupload.js b/course/dndupload.js index 3dbe326eddb..bdfe18a99d9 100644 --- a/course/dndupload.js +++ b/course/dndupload.js @@ -235,15 +235,17 @@ M.course_dndupload = { // Check for files first. if (this.types_includes(e, 'Files')) { - if (this.handlers.filehandlers.length == 0) { - return false; // No available file handlers - ignore this drag. + if (e.type != 'drop' || e._event.dataTransfer.files.length != 0) { + if (this.handlers.filehandlers.length == 0) { + return false; // No available file handlers - ignore this drag. + } + return { + realtype: 'Files', + addmessage: M.util.get_string('addfilehere', 'moodle'), + namemessage: null, // Should not be asked for anyway + type: 'Files' + }; } - return { - realtype: 'Files', - addmessage: M.util.get_string('addfilehere', 'moodle'), - namemessage: null, // Should not be asked for anyway - type: 'Files' - }; } // Check each of the registered types. @@ -703,6 +705,11 @@ M.course_dndupload = { if (result.onclick) { resel.a.onclick = result.onclick; } + if (self.Y.UA.gecko > 0) { + // Fix a Firefox bug which makes sites with a '~' in their wwwroot + // log the user out when clicking on the link (before refreshing the page). + resel.div.innerHTML = unescape(resel.div.innerHTML); + } self.add_editing(result.elementid); } else { // Error - remove the dummy element @@ -844,6 +851,7 @@ M.course_dndupload = { * @param contents the actual data that was dropped * @param section the DOM element representing the selected course section * @param sectionnumber the number of the selected course section + * @param module the module chosen to handle this upload */ upload_item: function(name, type, contents, section, sectionnumber, module) { @@ -877,6 +885,11 @@ M.course_dndupload = { if (result.onclick) { resel.a.onclick = result.onclick; } + if (self.Y.UA.gecko > 0) { + // Fix a Firefox bug which makes sites with a '~' in their wwwroot + // log the user out when clicking on the link (before refreshing the page). + resel.div.innerHTML = unescape(resel.div.innerHTML); + } self.add_editing(result.elementid, sectionnumber); } else { // Error - remove the dummy element @@ -890,6 +903,34 @@ M.course_dndupload = { } }; + if (type == 'text/html') { + // If this was html content dragged from Chrome => Firefox, we will + // need to fix the byte order of the content. + if (this.Y.UA.gecko > 0) { + if (contents.indexOf('<') == -1) { + // There are no html tags in this content => it probably needs fixing. + var codes = new Array(); + for (i=0; i it is probably correct. + contents = fixedcontents; + } + } + } + } + // Prepare the data to send var formData = new FormData(); formData.append('contents', contents); @@ -900,15 +941,17 @@ M.course_dndupload = { formData.append('type', type); formData.append('module', module); - // Contents from Firefox have their unicode byte-order reversed, swap back and - // provide as an alternative. if (type == 'text/html') { - var fixedcontents = ''; - for (i=0; i 0 && this.Y.UA.os == 'linux') { + var fixedcontents = ''; + for (i=0; iadd_type('url', array('url', 'text/uri-list'), get_string('addlinkhere', 'moodle'), + $this->add_type('url', array('url', 'text/uri-list', 'text/x-moz-url'), get_string('addlinkhere', 'moodle'), get_string('nameforlink', 'moodle'), 10); $this->add_type('text/html', array('text/html'), get_string('addpagehere', 'moodle'), get_string('nameforpage', 'moodle'), 20); From 957983b702a1e61de9d084e8a50f2a9863e73dba Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Fri, 18 May 2012 10:37:44 +1200 Subject: [PATCH 198/455] MDL-33066 navigation: Fixed ambiguously defined columns in DB queries for Oracle --- lib/navigationlib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/navigationlib.php b/lib/navigationlib.php index 707ea920e05..694c567860e 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -1701,7 +1701,7 @@ class global_navigation extends navigation_node { FROM {course_categories} cc JOIN {context} ctx ON cc.id = ctx.instanceid"; $sqlwhere = "WHERE ctx.contextlevel = ".CONTEXT_COURSECAT; - $sqlorder = "ORDER BY depth ASC, sortorder ASC, id ASC"; + $sqlorder = "ORDER BY cc.depth ASC, cc.sortorder ASC, cc.id ASC"; $params = array(); $categoriestoload = array(); @@ -2912,7 +2912,7 @@ class global_navigation_for_ajax extends global_navigation { JOIN {context} ctx ON cc.id = ctx.instanceid WHERE ctx.contextlevel = ".CONTEXT_COURSECAT." AND (cc.id = :categoryid1 OR cc.parent = :categoryid2) - ORDER BY depth ASC, sortorder ASC, id ASC"; + ORDER BY cc.depth ASC, cc.sortorder ASC, cc.id ASC"; $params = array('categoryid1' => $categoryid, 'categoryid2' => $categoryid); $categories = $DB->get_recordset_sql($sql, $params, 0, $limit); $subcategories = array(); From ad4dc7d2655247748dce9072ba6e365aa9555b59 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Fri, 18 May 2012 01:35:07 +0200 Subject: [PATCH 199/455] MDL-33079 Enable IMS-CC export (backup converter) --- backup/util/helper/convert_helper.class.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/backup/util/helper/convert_helper.class.php b/backup/util/helper/convert_helper.class.php index 8f481dec7f2..e5d21b8fbaf 100644 --- a/backup/util/helper/convert_helper.class.php +++ b/backup/util/helper/convert_helper.class.php @@ -55,12 +55,6 @@ abstract class convert_helper { $converters = array(); - // Only apply for backup converters if the (experimental) setting enables it. - // This will be out once we get proper support of backup converters. MDL-29956 - if (!$restore && empty($CFG->enablebackupconverters)) { - return $converters; - } - $plugins = get_list_of_plugins('backup/converter'); foreach ($plugins as $name) { $filename = $restore ? 'lib.php' : 'backuplib.php'; From 96d3b93ba3ea16b26166b23ef057745726fcbde9 Mon Sep 17 00:00:00 2001 From: Jerome Mouneyrac Date: Fri, 18 May 2012 14:45:15 +0800 Subject: [PATCH 200/455] MDL-33060 remove some get_string from exceptions --- course/externallib.php | 12 ++---- enrol/externallib.php | 4 +- group/externallib.php | 21 ++++------ lang/en/webservice.php | 6 --- webservice/lib.php | 80 +++++++++++++++++++++++---------------- webservice/pluginfile.php | 2 +- 6 files changed, 62 insertions(+), 63 deletions(-) diff --git a/course/externallib.php b/course/externallib.php index fef36477c9d..deed6962ce9 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -302,8 +302,7 @@ class core_course_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $course->id; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid', 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam); } require_capability('moodle/course:view', $context); @@ -520,23 +519,20 @@ class core_course_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->catid = $course['categoryid']; - throw new moodle_exception( - get_string('errorcatcontextnotvalid', 'webservice', $exceptionparam)); + throw new moodle_exception('errorcatcontextnotvalid', 'webservice', '', $exceptionparam); } require_capability('moodle/course:create', $context); // Make sure lang is valid if (key_exists('lang', $course) and empty($availablelangs[$course['lang']])) { - throw new moodle_exception( - get_string('errorinvalidparam', 'webservice', 'lang')); + throw new moodle_exception('errorinvalidparam', 'webservice', '', 'lang'); } // Make sure theme is valid if (key_exists('forcetheme', $course)) { if (!empty($CFG->allowcoursethemes)) { if (empty($availablethemes[$course['forcetheme']])) { - throw new moodle_exception( - get_string('errorinvalidparam', 'webservice', 'forcetheme')); + throw new moodle_exception('errorinvalidparam', 'webservice', '', 'forcetheme'); } else { $course['theme'] = $course['forcetheme']; } diff --git a/enrol/externallib.php b/enrol/externallib.php index 57b6ac13efd..08438e18b77 100644 --- a/enrol/externallib.php +++ b/enrol/externallib.php @@ -207,7 +207,7 @@ class core_enrol_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; - throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } if ($courseid == SITEID) { @@ -543,7 +543,7 @@ class moodle_enrol_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; - throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } if ($courseid == SITEID) { diff --git a/group/externallib.php b/group/externallib.php index 128ad9e4ba5..ab4b6eb90f9 100644 --- a/group/externallib.php +++ b/group/externallib.php @@ -95,8 +95,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -168,8 +167,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -231,8 +229,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -310,8 +307,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -369,8 +365,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -450,8 +445,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -529,8 +523,7 @@ class core_group_external extends external_api { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); diff --git a/lang/en/webservice.php b/lang/en/webservice.php index 7eb7ce449aa..08c3d40bbb9 100644 --- a/lang/en/webservice.php +++ b/lang/en/webservice.php @@ -25,7 +25,6 @@ $string['accessexception'] = 'Access control exception'; $string['actwebserviceshhdr'] = 'Active web service protocols'; -$string['accesstofunctionnotallowed'] = 'Access to the function {$a}() is not allowed. Please check if a service containing the function is enabled. In the service settings: if the service is restricted check that the user is listed. Still in the service settings check for IP restriction or if the service requires a capability.'; $string['addaservice'] = 'Add service'; $string['addcapabilitytousers'] = 'Check users capability'; $string['addcapabilitytousersdescription'] = 'Users should have two capabilities - webservice:createtoken and a capability matching the protocols used, for example webservice/rest:use, webservice/soap:use. To achieve this, create a web services role with the appropriate capabilities allowed and assign it to the web services user as a system role.'; @@ -75,7 +74,6 @@ $string['enableprotocols'] = 'Enable protocols'; $string['enableprotocolsdescription'] = 'At least one protocol should be enabled. For security reasons, only protocols that are to be used should be enabled.'; $string['enablews'] = 'Enable web services'; $string['enablewsdescription'] = 'Web services must be enabled in Advanced features.'; -$string['enabledirectdownload'] = 'Web service file downloading must be enabled in external service settings'; $string['entertoken'] = 'Enter a security key/token:'; $string['error'] = 'Error: {$a}'; $string['errorcatcontextnotvalid'] = 'You cannot execute functions in the category context (category id:{$a->catid}). The context error message was: {$a->message}'; @@ -106,7 +104,6 @@ $string['invalidextresponse'] = 'Invalid external api response: {$a}'; $string['invalidiptoken'] = 'Invalid token - your IP is not supported'; $string['invalidtimedtoken'] = 'Invalid token - token expired'; $string['invalidtoken'] = 'Invalid token - token not found'; -$string['invalidtokensession'] = 'Invalid session based token - session not found or expired'; $string['iprestriction'] = 'IP restriction'; $string['iprestriction_help'] = 'The user will need to call web service from the listed IPs.'; $string['key'] = 'Key'; @@ -136,7 +133,6 @@ $string['potusers'] = 'Not authorised users'; $string['potusersmatching'] = 'Not authorised users matching'; $string['print'] = 'Print all'; $string['protocol'] = 'Protocol'; -$string['protocolnotallowed'] = 'You are not allowed to use the {$a} protocol (missing capability: webservice/{$a}:use)'; $string['removefunction'] = 'Remove'; $string['removefunctionconfirm'] = 'Do you really want to remove function "{$a->function}" from service "{$a->service}"?'; $string['requireauthentication'] = 'This method requires authentication with xxx permission.'; @@ -205,8 +201,6 @@ $string['wsaccessuserexpired'] = 'Refused web service access for password expire $string['wsaccessusernologin'] = 'Refused web service access for nologin authentication username: {$a}'; $string['wsaccessusersuspended'] = 'Refused web service access for suspended username: {$a}'; $string['wsaccessuserunconfirmed'] = 'Refused web service access for unconfirmed username: {$a}'; -$string['wsauthmissing'] = 'The web service authentication plugin is missing.'; -$string['wsauthnotenabled'] = 'The web service authentication plugin is disabled.'; $string['wsclientdoc'] = 'Moodle web service client documentation'; $string['wsdocapi'] = 'API Documentation'; $string['wsdocumentation'] = 'Web service documentation'; diff --git a/webservice/lib.php b/webservice/lib.php index 1b0ff8b274b..7946bd88a97 100644 --- a/webservice/lib.php +++ b/webservice/lib.php @@ -60,25 +60,27 @@ class webservice { // web service must be enabled to use this script if (!$CFG->enablewebservices) { - throw new webservice_access_exception(get_string('enablewsdescription', 'webservice')); + throw new webservice_access_exception('Web services are not enabled in Advanced features.'); } // Obtain token record if (!$token = $DB->get_record('external_tokens', array('token' => $token))) { - throw new webservice_access_exception(get_string('invalidtoken', 'webservice')); + //client may want to display login form => moodle_exception + throw new moodle_exception('invalidtoken', 'webservice'); } // Validate token date if ($token->validuntil and $token->validuntil < time()) { add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('invalidtimedtoken', 'webservice'), 0); $DB->delete_records('external_tokens', array('token' => $token->token)); - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice')); + throw new webservice_access_exception('Invalid token - token expired - check validuntil time for the token'); } // Check ip if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) { add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . getremoteaddr(), 0); - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice')); + throw new webservice_access_exception('Invalid token - IP:' . getremoteaddr() + . ' is not supported'); } //retrieve user link to the token @@ -95,26 +97,27 @@ class webservice { $session = session_get_instance(); if (!$session->session_exists($token->sid)) { $DB->delete_records('external_tokens', array('sid' => $token->sid)); - throw new webservice_access_exception(get_string('invalidtokensession', 'webservice')); + throw new webservice_access_exception('Invalid session based token - session not found or expired'); } } //Non admin can not authenticate if maintenance mode $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user); if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) { - throw new webservice_access_exception(get_string('sitemaintenance', 'admin')); + //this is usually temporary, client want to implement code logic => moodle_exception + throw new moodle_exception('sitemaintenance', 'admin'); } //retrieve web service record $service = $DB->get_record('external_services', array('id' => $token->externalserviceid, 'enabled' => 1)); if (empty($service)) { // will throw exception if no token found - throw new webservice_access_exception(get_string('servicenotavailable', 'webservice')); + throw new webservice_access_exception('Web service is not available (it doesn\'t exist or might be disabled)'); } //check if there is any required system capability if ($service->requiredcapability and !has_capability($service->requiredcapability, get_context_instance(CONTEXT_SYSTEM), $user)) { - throw new webservice_access_exception(get_string('missingrequiredcapability', 'webservice', $service->requiredcapability)); + throw new webservice_access_exception('The capability ' . $service->requiredcapability . ' is required.'); } //specific checks related to user restricted service @@ -122,34 +125,37 @@ class webservice { $authoriseduser = $DB->get_record('external_services_users', array('externalserviceid' => $service->id, 'userid' => $user->id)); if (empty($authoriseduser)) { - throw new webservice_access_exception(get_string('usernotallowed', 'webservice', $service->name)); + throw new webservice_access_exception( + 'The user is not allowed for this service. First you need to allow this user on the ' + . $service->name . '\'s allowed users administration page.'); } if (!empty($authoriseduser->validuntil) and $authoriseduser->validuntil < time()) { - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice')); + throw new webservice_access_exception('Invalid service - service expired - check validuntil time for this allowed user'); } if (!empty($authoriseduser->iprestriction) and !address_in_subnet(getremoteaddr(), $authoriseduser->iprestriction)) { - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice')); + throw new webservice_access_exception('Invalid service - IP:' . getremoteaddr() + . ' is not supported - check this allowed user'); } } //only confirmed user should be able to call web service if (empty($user->confirmed)) { add_to_log(SITEID, 'webservice', 'user unconfirmed', '', $user->username); - throw new webservice_access_exception(get_string('usernotconfirmed', 'moodle', $user->username)); + throw new moodle_exception('usernotconfirmed', 'moodle', '', $user->username); } //check the user is suspended if (!empty($user->suspended)) { add_to_log(SITEID, 'webservice', 'user suspended', '', $user->username); - throw new webservice_access_exception(get_string('usersuspended', 'webservice')); + throw new webservice_access_exception('Refused web service access for suspended username: ' . $user->username); } //check if the auth method is nologin (in this case refuse connection) if ($user->auth == 'nologin') { add_to_log(SITEID, 'webservice', 'nologin auth attempt with web service', '', $user->username); - throw new webservice_access_exception(get_string('nologinauth', 'webservice')); + throw new webservice_access_exception('Refused web service access for nologin authentication username: ' . $user->username); } //Check if the user password is expired @@ -158,7 +164,7 @@ class webservice { $days2expire = $auth->password_expire($user->username); if (intval($days2expire) < 0) { add_to_log(SITEID, 'webservice', 'expired password', '', $user->username); - throw new webservice_access_exception(get_string('passwordisexpired', 'webservice')); + throw new moodle_exception('passwordisexpired', 'webservice'); } } @@ -686,6 +692,10 @@ class webservice { /** * Exception indicating access control problem in web service call + * This exception should return general errors about web service setup. + * Errors related to the user like wrong username/password should not use it, + * you should not use this exception if you want to let the client implement + * some code logic against an access error. * * @package core_webservice * @copyright 2009 Petr Skodak @@ -818,27 +828,27 @@ abstract class webservice_server implements webservice_server_interface { //we check that authentication plugin is enabled //it is only required by simple authentication if (!is_enabled_auth('webservice')) { - throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice')); + throw new webservice_access_exception('The web service authentication plugin is disabled.'); } if (!$auth = get_auth_plugin('webservice')) { - throw new webservice_access_exception(get_string('wsauthmissing', 'webservice')); + throw new webservice_access_exception('The web service authentication plugin is missing.'); } $this->restricted_context = get_context_instance(CONTEXT_SYSTEM); if (!$this->username) { - throw new webservice_access_exception(get_string('missingusername', 'webservice')); + throw new moodle_exception('missingusername', 'webservice'); } if (!$this->password) { - throw new webservice_access_exception(get_string('missingpassword', 'webservice')); + throw new moodle_exception('missingpassword', 'webservice'); } if (!$auth->user_login_webservice($this->username, $this->password)) { // log failed login attempts add_to_log(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".$this->username."/".$this->password." - ".getremoteaddr() , 0); - throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice')); + throw new moodle_exception('wrongusernamepassword', 'webservice'); } $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST); @@ -852,25 +862,25 @@ abstract class webservice_server implements webservice_server_interface { //Non admin can not authenticate if maintenance mode $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user); if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) { - throw new webservice_access_exception(get_string('sitemaintenance', 'admin')); + throw new moodle_exception('sitemaintenance', 'admin'); } //only confirmed user should be able to call web service if (!empty($user->deleted)) { add_to_log(SITEID, '', '', '', get_string('wsaccessuserdeleted', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessuserdeleted', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for deleted username: ' . $user->username); } //only confirmed user should be able to call web service if (empty($user->confirmed)) { add_to_log(SITEID, '', '', '', get_string('wsaccessuserunconfirmed', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessuserunconfirmed', 'webservice', $user->username)); + throw new moodle_exception('wsaccessuserunconfirmed', 'webservice', '', $user->username); } //check the user is suspended if (!empty($user->suspended)) { add_to_log(SITEID, '', '', '', get_string('wsaccessusersuspended', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessusersuspended', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for suspended username: ' . $user->username); } //retrieve the authentication plugin if no previously done @@ -883,14 +893,14 @@ abstract class webservice_server implements webservice_server_interface { $days2expire = $auth->password_expire($user->username); if (intval($days2expire) < 0 ) { add_to_log(SITEID, '', '', '', get_string('wsaccessuserexpired', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessuserexpired', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for password expired username: ' . $user->username); } } //check if the auth method is nologin (in this case refuse connection) if ($user->auth=='nologin') { add_to_log(SITEID, '', '', '', get_string('wsaccessusernologin', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessusernologin', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for nologin authentication username: ' . $user->username); } // now fake user login, the session is completely empty too @@ -899,7 +909,7 @@ abstract class webservice_server implements webservice_server_interface { $this->userid = $user->id; if ($this->authmethod != WEBSERVICE_AUTHMETHOD_SESSION_TOKEN && !has_capability("webservice/$this->wsname:use", $this->restricted_context)) { - throw new webservice_access_exception(get_string('protocolnotallowed', 'webservice', $this->wsname)); + throw new webservice_access_exception('You are not allowed to use the {$a} protocol (missing capability: webservice/' . $this->wsname . ':use)'); } external_api::set_context_restriction($this->restricted_context); @@ -917,25 +927,26 @@ abstract class webservice_server implements webservice_server_interface { if (!$token = $DB->get_record('external_tokens', array('token'=>$this->token, 'tokentype'=>$tokentype))) { // log failed login attempts add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".$this->token. " - ".getremoteaddr() , 0); - throw new webservice_access_exception(get_string('invalidtoken', 'webservice')); + throw new moodle_exception('invalidtoken', 'webservice'); } if ($token->validuntil and $token->validuntil < time()) { $DB->delete_records('external_tokens', array('token'=>$this->token, 'tokentype'=>$tokentype)); - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice')); + throw new webservice_access_exception('Invalid token - token expired - check validuntil time for the token'); } if ($token->sid){//assumes that if sid is set then there must be a valid associated session no matter the token type $session = session_get_instance(); if (!$session->session_exists($token->sid)){ $DB->delete_records('external_tokens', array('sid'=>$token->sid)); - throw new webservice_access_exception(get_string('invalidtokensession', 'webservice')); + throw new webservice_access_exception('Invalid session based token - session not found or expired'); } } if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) { add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".getremoteaddr() , 0); - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice')); + throw new webservice_access_exception('Invalid service - IP:' . getremoteaddr() + . ' is not supported - check this allowed user'); } $this->restricted_context = get_context_instance_by_id($token->contextid); @@ -1585,7 +1596,12 @@ abstract class webservice_base_server extends webservice_server { } $rs->close(); if (!$allowed) { - throw new webservice_access_exception(get_string('accesstofunctionnotallowed', 'webservice', $this->functionname)); + throw new webservice_access_exception( + 'Access to the function '.$this->functionname.'() is not allowed. + Please check if a service containing the function is enabled. + In the service settings: if the service is restricted check that + the user is listed. Still in the service settings check for + IP restriction or if the service requires a capability.'); } // we have all we need now diff --git a/webservice/pluginfile.php b/webservice/pluginfile.php index acc3f1ca0b8..f49480f9856 100644 --- a/webservice/pluginfile.php +++ b/webservice/pluginfile.php @@ -46,7 +46,7 @@ $authenticationinfo = $webservicelib->authenticate_user($token); //check the service allows file download $enabledfiledownload = (int) ($authenticationinfo['service']->downloadfiles); if (empty($enabledfiledownload)) { - throw new webservice_access_exception(get_string('enabledirectdownload', 'webservice')); + throw new webservice_access_exception('Web service file downloading must be enabled in external service settings'); } //finally we can serve the file :) From f32ecd2fbeeabc9af3e6d5661cdda5e7112e0313 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Thu, 17 May 2012 18:36:46 +0200 Subject: [PATCH 201/455] MDL-33075 find correct location of failed test case classes --- lib/phpunit/classes/hint_resultprinter.php | 28 +++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/phpunit/classes/hint_resultprinter.php b/lib/phpunit/classes/hint_resultprinter.php index 02a09f8e222..638b4d0b112 100644 --- a/lib/phpunit/classes/hint_resultprinter.php +++ b/lib/phpunit/classes/hint_resultprinter.php @@ -44,16 +44,28 @@ class Hint_ResultPrinter extends PHPUnit_TextUI_ResultPrinter { $exception = $defect->thrownException(); $trace = $exception->getTrace(); - $file = null; - $dirroot = realpath($CFG->dirroot).DIRECTORY_SEPARATOR; - $classpath = realpath("$CFG->dirroot/lib/phpunit/classes").DIRECTORY_SEPARATOR; - foreach ($trace as $item) { - if (strpos($item['file'], $dirroot) === 0 and strpos($item['file'], $classpath) !== 0) { - $file = $item['file']; - break; + + if (class_exists('ReflectionClass')) { + $reflection = new ReflectionClass($testName); + $file = $reflection->getFileName(); + + } else { + $file = false; + $dirroot = realpath($CFG->dirroot).DIRECTORY_SEPARATOR; + $classpath = realpath("$CFG->dirroot/lib/phpunit/classes").DIRECTORY_SEPARATOR; + foreach ($trace as $item) { + if (strpos($item['file'], $dirroot) === 0 and strpos($item['file'], $classpath) !== 0) { + if ($content = file_get_contents($item['file'])) { + if (preg_match('/class\s+'.$testName.'\s+extends/', $content)) { + $file = $item['file']; + break; + } + } + } } } - if ($file === null) { + + if ($file === false) { return; } From dfa6a3463804b618505afb3f99c547509383186f Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Wed, 16 May 2012 17:24:17 +0200 Subject: [PATCH 202/455] MDL-33034 some more accesslib tests It is not complete yet, but it should be enough to verify patch in MDL-8249 works properly. --- lib/tests/accesslib_test.php | 1264 +++++++++++++++++++++++++++++++++- 1 file changed, 1260 insertions(+), 4 deletions(-) diff --git a/lib/tests/accesslib_test.php b/lib/tests/accesslib_test.php index 9e8555996ac..ac51a372a76 100644 --- a/lib/tests/accesslib_test.php +++ b/lib/tests/accesslib_test.php @@ -43,7 +43,7 @@ class context_inspection extends context_helper { */ class accesslib_testcase extends advanced_testcase { - //TODO: add more tests for the remaining accesslib parts that were not touched by the refactoring in 2.2dev + //TODO: add more tests for the remaining accesslib parts such as enrol related api /** * Verify comparison of context instances in phpunit asserts @@ -61,10 +61,1262 @@ class accesslib_testcase extends advanced_testcase { } /** - * A small functional test of accesslib functions and classes. + * Test resetting works. + */ + public function test_accesslib_clear_all_caches() { + global $ACCESSLIB_PRIVATE; + + $this->resetAfterTest(); + + $this->setAdminUser(); + load_all_capabilities(); + + $this->assertNotEmpty($ACCESSLIB_PRIVATE->rolepermissions); + $this->assertNotEmpty($ACCESSLIB_PRIVATE->rolepermissions); + $this->assertNotEmpty($ACCESSLIB_PRIVATE->accessdatabyuser); + accesslib_clear_all_caches(true); + $this->assertEmpty($ACCESSLIB_PRIVATE->rolepermissions); + $this->assertEmpty($ACCESSLIB_PRIVATE->rolepermissions); + $this->assertEmpty($ACCESSLIB_PRIVATE->dirtycontexts); + $this->assertEmpty($ACCESSLIB_PRIVATE->accessdatabyuser); + } + + /** + * Test getting of role access * @return void */ - public function test_everything_in_accesslib() { + public function test_get_role_access() { + global $DB; + + $roles = $DB->get_records('role'); + foreach ($roles as $role) { + $access = get_role_access($role->id); + + $this->assertTrue(is_array($access)); + $this->assertTrue(is_array($access['ra'])); + $this->assertTrue(is_array($access['rdef'])); + $this->assertTrue(isset($access['rdef_count'])); + $this->assertTrue(is_array($access['loaded'])); + $this->assertTrue(isset($access['time'])); + $this->assertTrue(is_array($access['rsw'])); + } + + // Note: the data is validated in the functional permission evaluation test at the end of this testcase. + } + + /** + * Test getting of guest role. + * @return void + */ + public function test_get_guest_role() { + global $CFG; + + $guest = get_guest_role(); + $this->assertEquals('guest', $guest->archetype); + $this->assertEquals('guest', $guest->shortname); + + $this->assertEquals($CFG->guestroleid, $guest->id); + } + + /** + * Test if user is admin. + * @return void + */ + public function test_is_siteadmin() { + global $DB; + + $this->resetAfterTest(); + + $users = $DB->get_records('user'); + + foreach ($users as $user) { + $this->setUser(0); + if ($user->username === 'admin') { + $this->assertTrue(is_siteadmin($user)); + $this->assertTrue(is_siteadmin($user->id)); + $this->setUser($user); + $this->assertTrue(is_siteadmin()); + $this->assertTrue(is_siteadmin(null)); + } else { + $this->assertFalse(is_siteadmin($user)); + $this->assertFalse(is_siteadmin($user->id)); + $this->setUser($user); + $this->assertFalse(is_siteadmin()); + $this->assertFalse(is_siteadmin(null)); + } + } + } + + /** + * Test logged in test. + * @return void + */ + public function test_isloggedin() { + global $USER; + + $this->resetAfterTest(); + + $USER->id = 0; + $this->assertFalse(isloggedin()); + $USER->id = 1; + $this->assertTrue(isloggedin()); + } + + /** + * Test guest user test. + * @return void + */ + public function test_isguestuser() { + global $DB; + + $this->resetAfterTest(); + + $guest = $DB->get_record('user', array('username'=>'guest')); + $this->setUser(0); + $this->assertFalse(isguestuser()); + $this->setAdminUser(); + $this->assertFalse(isguestuser()); + $this->assertTrue(isguestuser($guest)); + $this->assertTrue(isguestuser($guest->id)); + $this->setUser($guest); + $this->assertTrue(isguestuser()); + + $users = $DB->get_records('user'); + foreach ($users as $user) { + if ($user->username === 'guest') { + continue; + } + $this->assertFalse(isguestuser($user)); + } + } + + /** + * Test capability riskiness. + * @return void + */ + public function test_is_safe_capability() { + global $DB; + // Note: there is not much to test, just make sure no notices are throw for the most dangerous cap. + $capability = $DB->get_record('capabilities', array('name'=>'moodle/site:config'), '*', MUST_EXIST); + $this->assertFalse(is_safe_capability($capability)); + } + + /** + * Test context fetching. + * @return void + */ + public function test_get_context_info_array() { + $this->resetAfterTest(); + + $syscontext = context_system::instance(); + $user = $this->getDataGenerator()->create_user(); + $usercontext = context_user::instance($user->id); + $course = $this->getDataGenerator()->create_course(); + $catcontext = context_coursecat::instance($course->category); + $coursecontext = context_course::instance($course->id); + $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); + $modcontext = context_module::instance($page->cmid); + $cm = get_coursemodule_from_instance('page', $page->id); + $block1 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$coursecontext->id)); + $block1context = context_block::instance($block1->id); + $block2 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$modcontext->id)); + $block2context = context_block::instance($block2->id); + + $result = get_context_info_array($syscontext->id); + $this->assertCount(3, $result); + $this->assertSame($syscontext, $result[0]); + $this->assertSame(null, $result[1]); + $this->assertSame(null, $result[2]); + + $result = get_context_info_array($usercontext->id); + $this->assertCount(3, $result); + $this->assertSame($usercontext, $result[0]); + $this->assertSame(null, $result[1]); + $this->assertSame(null, $result[2]); + + $result = get_context_info_array($catcontext->id); + $this->assertCount(3, $result); + $this->assertSame($catcontext, $result[0]); + $this->assertSame(null, $result[1]); + $this->assertSame(null, $result[2]); + + $result = get_context_info_array($coursecontext->id); + $this->assertCount(3, $result); + $this->assertSame($coursecontext, $result[0]); + $this->assertEquals($course->id, $result[1]->id); + $this->assertEquals($course->shortname, $result[1]->shortname); + $this->assertSame(null, $result[2]); + + $result = get_context_info_array($block1context->id); + $this->assertCount(3, $result); + $this->assertSame($block1context, $result[0]); + $this->assertEquals($course->id, $result[1]->id); + $this->assertEquals($course->shortname, $result[1]->shortname); + $this->assertSame(null, $result[2]); + + $result = get_context_info_array($modcontext->id); + $this->assertCount(3, $result); + $this->assertSame($modcontext, $result[0]); + $this->assertEquals($course->id, $result[1]->id); + $this->assertEquals($course->shortname, $result[1]->shortname); + $this->assertEquals($cm->id, $result[2]->id); + $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly); + + $result = get_context_info_array($block2context->id); + $this->assertCount(3, $result); + $this->assertSame($block2context, $result[0]); + $this->assertEquals($course->id, $result[1]->id); + $this->assertEquals($course->shortname, $result[1]->shortname); + $this->assertEquals($cm->id, $result[2]->id); + $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly); + } + + /** + * Test looking for course contacts. + * @return void + */ + public function test_has_coursecontact_role() { + global $DB, $CFG; + + $this->resetAfterTest(); + + $users = $DB->get_records('user'); + + // Nobody is expected to have any course level roles. + $this->assertNotEmpty($CFG->coursecontact); + foreach($users as $user) { + $this->assertFalse(has_coursecontact_role($user->id)); + } + + $user = $this->getDataGenerator()->create_user(); + $course = $this->getDataGenerator()->create_course(); + role_assign($CFG->coursecontact, $user->id, context_course::instance($course->id)); + $this->assertTrue(has_coursecontact_role($user->id)); + } + + /** + * Test creation of roles. + * @return void + */ + public function test_create_role() { + global $DB; + + $this->resetAfterTest(); + + $id = create_role('New student role', 'student2', 'New student description', 'student'); + $role = $DB->get_record('role', array('id'=>$id)); + + $this->assertNotEmpty($role); + $this->assertEquals('New student role', $role->name); + $this->assertEquals('student2', $role->shortname); + $this->assertEquals('New student description', $role->description); + $this->assertEquals('student', $role->archetype); + } + + /** + * Test adding of capabilities to roles. + */ + public function test_assign_capability() { + global $DB; + + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(); + $syscontext = context_system::instance(); + $frontcontext = context_course::instance(SITEID); + $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to student by default + $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'))); + $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'))); + + $this->setUser($user); + $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $frontcontext->id); + $this->assertTrue($result); + $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')); + $this->assertNotEmpty($permission); + $this->assertEquals(CAP_ALLOW, $permission->permission); + $this->assertEquals($user->id, $permission->modifierid); + + $this->setUser(0); + $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, false); + $this->assertTrue($result); + $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')); + $this->assertNotEmpty($permission); + $this->assertEquals(CAP_ALLOW, $permission->permission); + $this->assertEquals(3, $permission->modifierid); + + $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, true); + $this->assertTrue($result); + $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')); + $this->assertNotEmpty($permission); + $this->assertEquals(CAP_PROHIBIT, $permission->permission); + $this->assertEquals(0, $permission->modifierid); + + $result = assign_capability('moodle/backup:backupcourse', CAP_INHERIT, $student->id, $frontcontext->id); + $this->assertTrue($result); + $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')); + $this->assertEmpty($permission); + } + + /** + * Test removing of capabilities from roles. + */ + public function test_unassign_capability() { + global $DB; + + $this->resetAfterTest(); + + $syscontext = context_system::instance(); + $frontcontext = context_course::instance(SITEID); + $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST); + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to manager by default + assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id); + + $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + + $result = unassign_capability('moodle/backup:backupcourse', $manager->id, $syscontext->id); + $this->assertTrue($result); + $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + unassign_capability('moodle/backup:backupcourse', $manager->id, $frontcontext); + $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + + assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id); + assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id); + $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + + $result = unassign_capability('moodle/backup:backupcourse', $manager->id); + $this->assertTrue($result); + $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse'))); + } + + /** + * Test role assigning + */ + public function test_role_assign() { + global $DB, $USER; + + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(); + $course = $this->getDataGenerator()->create_course(); + $role = $DB->get_record('role', array('shortname'=>'student')); + + $this->setUser(0); + $context = context_system::instance(); + $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id))); + role_assign($role->id, $user->id, $context->id); + $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)); + $this->assertNotEmpty($ras); + $this->assertSame('', $ras->component); + $this->assertSame('0', $ras->itemid); + $this->assertEquals($USER->id, $ras->modifierid); + + $this->setAdminUser(); + $context = context_course::instance($course->id); + $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id))); + role_assign($role->id, $user->id, $context->id, 'enrol_self', 1, 666); + $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)); + $this->assertNotEmpty($ras); + $this->assertSame('enrol_self', $ras->component); + $this->assertSame('1', $ras->itemid); + $this->assertEquals($USER->id, $ras->modifierid); + $this->assertEquals(666, $ras->timemodified); + } + + /** + * Test role unassigning + * @return void + */ + public function test_role_unassign() { + global $DB; + + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(); + $course = $this->getDataGenerator()->create_course(); + $role = $DB->get_record('role', array('shortname'=>'student')); + + $context = context_system::instance(); + role_assign($role->id, $user->id, $context->id); + $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id))); + role_unassign($role->id, $user->id, $context->id); + $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id))); + + role_assign($role->id, $user->id, $context->id, 'enrol_self', 1); + $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id))); + role_unassign($role->id, $user->id, $context->id, 'enrol_self', 1); + $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id))); + } + + /** + * Test role unassigning + * @return void + */ + public function test_role_unassign_all() { + global $DB; + + $this->resetAfterTest(); + + $user = $this->getDataGenerator()->create_user(); + $course = $this->getDataGenerator()->create_course(); + $role = $DB->get_record('role', array('shortname'=>'student')); + $syscontext = context_system::instance(); + $coursecontext = context_course::instance($course->id); + $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); + $modcontext = context_module::instance($page->cmid); + + role_assign($role->id, $user->id, $syscontext->id); + role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1); + $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id))); + role_unassign_all(array('userid'=>$user->id, 'roleid'=>$role->id)); + $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id))); + + role_assign($role->id, $user->id, $syscontext->id); + role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1); + role_assign($role->id, $user->id, $modcontext->id); + $this->assertEquals(3, $DB->count_records('role_assignments', array('userid'=>$user->id))); + role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), false); + $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id))); + role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), true); + $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id))); + role_unassign_all(array('userid'=>$user->id)); + $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id))); + + role_assign($role->id, $user->id, $syscontext->id); + role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1); + role_assign($role->id, $user->id, $coursecontext->id); + role_assign($role->id, $user->id, $modcontext->id); + $this->assertEquals(4, $DB->count_records('role_assignments', array('userid'=>$user->id))); + role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id, 'component'=>'enrol_self'), true, true); + $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id))); + } + + /** + * Test role queries. + * @return void + */ + public function test_get_roles_with_capability() { + global $DB; + + $this->resetAfterTest(); + + $syscontext = context_system::instance(); + $frontcontext = context_course::instance(SITEID); + $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST); + $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST); + + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok + $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse')); + + $roles = get_roles_with_capability('moodle/backup:backupcourse'); + $this->assertEquals(array(), $roles); + + assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id); + assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $manager->id, $frontcontext->id); + assign_capability('moodle/backup:backupcourse', CAP_PREVENT, $teacher->id, $frontcontext->id); + + $roles = get_roles_with_capability('moodle/backup:backupcourse'); + $this->assertEquals(array($teacher->id, $manager->id), array_keys($roles), '', 0, 10, true); + + $roles = get_roles_with_capability('moodle/backup:backupcourse', CAP_ALLOW); + $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true); + + $roles = get_roles_with_capability('moodle/backup:backupcourse', NULL, $syscontext); + $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true); + } + + /** + * Test deleting of roles. + * @return void + */ + public function test_delete_role() { + global $DB; + + $this->resetAfterTest(); + + $role = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST); + $user = $this->getDataGenerator()->create_user(); + role_assign($role->id, $user->id, context_system::instance()); + $course = $this->getDataGenerator()->create_course(); + $rolename = (object)array('roleid'=>$role->id, 'name'=>'Man', 'contextid'=>context_course::instance($course->id)->id); + $DB->insert_record('role_names', $rolename); + + $this->assertTrue($DB->record_exists('role_assignments', array('roleid'=>$role->id))); + $this->assertTrue($DB->record_exists('role_capabilities', array('roleid'=>$role->id))); + $this->assertTrue($DB->record_exists('role_names', array('roleid'=>$role->id))); + $this->assertTrue($DB->record_exists('role_context_levels', array('roleid'=>$role->id))); + $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$role->id))); + $this->assertTrue($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id))); + $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$role->id))); + $this->assertTrue($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id))); + + $result = delete_role($role->id); + $this->assertTrue($result); + $this->assertFalse($DB->record_exists('role', array('id'=>$role->id))); + $this->assertFalse($DB->record_exists('role_assignments', array('roleid'=>$role->id))); + $this->assertFalse($DB->record_exists('role_capabilities', array('roleid'=>$role->id))); + $this->assertFalse($DB->record_exists('role_names', array('roleid'=>$role->id))); + $this->assertFalse($DB->record_exists('role_context_levels', array('roleid'=>$role->id))); + $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$role->id))); + $this->assertFalse($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id))); + $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$role->id))); + $this->assertFalse($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id))); + } + + /** + * Test fetching of all roles. + * @return void + */ + public function test_get_all_roles() { + $allroles = get_all_roles(); + $this->assertEquals('array', gettype($allroles)); + $this->assertCount(8, $allroles); // there are 8 roles is standard install + + $role = reset($allroles); + $role = (array)$role; + + $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype'), array_keys($role), '', 0, 10, true); + + foreach($allroles as $roleid => $role) { + $this->assertEquals($role->id, $roleid); + } + } + + /** + * Test getting of all archetypes. + * @return void + */ + public function test_get_role_archetypes() { + $archetypes = get_role_archetypes(); + $this->assertCount(8, $archetypes); // there are 8 archetypes in standard install + foreach ($archetypes as $k=>$v) { + $this->assertSame($k, $v); + } + } + + /** + * Test getting of roles with given archetype. + * @return void + */ + public function test_get_archetype_roles() { + $this->resetAfterTest(); + + // New install should have 1 role for each archetype. + $archetypes = get_role_archetypes(); + foreach ($archetypes as $archetype) { + $roles = get_archetype_roles($archetype); + $this->assertCount(1, $roles); + $role = reset($roles); + $this->assertEquals($archetype, $role->archetype); + } + + create_role('New student role', 'student2', 'New student description', 'student'); + $roles = get_archetype_roles('student'); + $this->assertCount(2, $roles); + } + + /** + * Test aliased role names + * @return void + */ + public function test_role_get_name() { + global $DB; + + $this->resetAfterTest(); + + $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST); + $allroles = $DB->get_records('role'); + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + + $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id); + $DB->insert_record('role_names', $teacherename); + + foreach ($allroles as $role) { + $this->assertNotEmpty(role_get_name($role, $coursecontext)); + if ($role->id == $teacher->id) { + $this->assertSame($teacherename->name, role_get_name($role, $coursecontext)); + } + } + } + + /** + * Test tweaking of role name arrays + * @return void + */ + public function test_role_fix_names() { + global $DB; + + $this->resetAfterTest(); + + $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST); + $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + $otherid = create_role('Other role', 'other', 'Some other role', ''); + $anotherid = create_role('Another role', 'another', 'Yet another other role', ''); + $allroles = $DB->get_records('role'); + + $syscontext = context_system::instance(); + $frontcontext = context_course::instance(SITEID); + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $category = $DB->get_record('course_categories', array('id'=>$course->category), '*', MUST_EXIST); + $categorycontext = context_coursecat::instance($category->id); + + $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id); + $DB->insert_record('role_names', $teacherename); + $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id); + $DB->insert_record('role_names', $otherrename); + $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name'); + + // Make sure all localname contain proper values for each ROLENAME_ constant, + // note role_get_name() on frontpage is used to get the original name for future comatibility. + $roles = $allroles; + unset($roles[$student->id]); // Remove one roel to make sure no role is added or removed. + $rolenames = array(); + foreach ($roles as $role) { + $rolenames[$role->id] = $role->name; + } + + /* TODO: unsupported! MDL-8249 + $fixed = role_fix_names($roles, $coursecontext, ROLENAME_SHORT); + $this->assertCount(count($roles), $fixed); + foreach($fixed as $rolename) { + $this->assertInstanceOf('stdClass', $rolename); + $role = $roles[$rolename->id]; + $this->assertSame($role->shortname, $rolename->localname); + } + */ + + /* TODO: unsupported! MDL-8249 + $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ORIGINALANDSHORT); + $this->assertCount(count($roles), $fixed); + foreach($fixed as $rolename) { + $this->assertInstanceOf('stdClass', $rolename); + $role = $roles[$rolename->id]; + $this->assertSame("$role->name ($role->shortname)", $rolename->localname); + } + */ + + $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ORIGINAL); + $this->assertCount(count($roles), $fixed); + foreach($fixed as $roleid=>$rolename) { + $this->assertInstanceOf('stdClass', $rolename); + $role = $roles[$roleid]; + $name = role_get_name($role, $frontcontext); + $this->assertSame($name, $rolename->localname); + } + $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_ORIGINAL); + $this->assertCount(count($rolenames), $fixed); + foreach($fixed as $roleid=>$rolename) { + $role = $roles[$roleid]; + $name = role_get_name($role, $frontcontext); + $this->assertSame($name, $rolename); + } + + $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ALIAS); + $this->assertCount(count($roles), $fixed); + foreach($fixed as $roleid=>$rolename) { + $this->assertInstanceOf('stdClass', $rolename); + $role = $roles[$roleid]; + $this->assertSame(role_get_name($role, $coursecontext), $rolename->localname); + } + $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_ALIAS); + $this->assertCount(count($rolenames), $fixed); + foreach($fixed as $roleid=>$rolename) { + $role = $roles[$roleid]; + $this->assertSame(role_get_name($role, $coursecontext), $rolename); + } + + /* TODO: buggy! MDL-8249 + $fixed = role_fix_names($roles, $coursecontext, ROLENAME_BOTH); + $this->assertCount(count($roles), $fixed); + foreach($fixed as $roleid=>$rolename) { + $this->assertInstanceOf('stdClass', $rolename); + $role = $roles[$roleid]; + $name = role_get_name($role, $frontcontext); + if (isset($renames[$roleid])) { + $this->assertSame("$renames[$roleid] ($name)", $rolename->localname); + } else { + $this->assertSame(role_get_name($role, $coursecontext), $rolename->localname); + } + } + */ + $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_BOTH); + $this->assertCount(count($rolenames), $fixed); + foreach($fixed as $roleid=>$rolename) { + $role = $roles[$roleid]; + if (isset($renames[$roleid])) { + $name = role_get_name($role, $frontcontext); + $this->assertSame("$renames[$roleid] ($name)", $rolename); + } else { + $this->assertSame(role_get_name($role, $coursecontext), $rolename); + } + } + + $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ALIAS_RAW); + $this->assertCount(count($roles), $fixed); + foreach($fixed as $roleid=>$rolename) { + $this->assertInstanceOf('stdClass', $rolename); + if (isset($renames[$roleid])) { + $this->assertSame($renames[$roleid], $rolename->localname); + } else { + $this->assertSame('', $rolename->localname); + } + } + $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_ALIAS_RAW); + $this->assertCount(count($rolenames), $fixed); + foreach($fixed as $roleid=>$rolename) { + if (isset($renames[$roleid])) { + $this->assertSame($renames[$roleid], $rolename); + } else { + $this->assertSame('', $rolename); + } + } + } + + /** + * Test allowing of role assignments. + * @return void + */ + public function test_allow_assign() { + global $DB; + + $this->resetAfterTest(); + + $otherid = create_role('Other role', 'other', 'Some other role', ''); + $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + + $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id))); + allow_assign($otherid, $student->id); + $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id))); + } + + /** + * Test allowing of role overrides. + * @return void + */ + public function test_allow_override() { + global $DB; + + $this->resetAfterTest(); + + $otherid = create_role('Other role', 'other', 'Some other role', ''); + $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + + $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id))); + allow_override($otherid, $student->id); + $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id))); + } + + /** + * Test allowing of role switching. + * @return void + */ + public function test_allow_switch() { + global $DB; + + $this->resetAfterTest(); + + $otherid = create_role('Other role', 'other', 'Some other role', ''); + $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + + $this->assertFalse($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id))); + allow_switch($otherid, $student->id); + $this->assertTrue($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id))); + } + + /** + * Test returning of assignable roles in context. + * @return void + */ + public function test_get_assignable_roles() { + global $DB; + + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + + $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST); + $teacher = $this->getDataGenerator()->create_user(); + role_assign($teacherrole->id, $teacher->id, $coursecontext); + $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id); + $DB->insert_record('role_names', $teacherename); + + $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + $student = $this->getDataGenerator()->create_user(); + role_assign($studentrole->id, $student->id, $coursecontext); + + $contexts = $DB->get_records('context'); + $users = $DB->get_records('user'); + $allroles = $DB->get_records('role'); + + // Evaluate all results for all users in all contexts. + foreach($users as $user) { + $this->setUser($user); + foreach ($contexts as $contextid=>$unused) { + $context = context_helper::instance_by_id($contextid); + $roles = get_assignable_roles($context, ROLENAME_SHORT); + foreach ($allroles as $roleid=>$role) { + if (isset($roles[$roleid])) { + if (is_siteadmin()) { + $this->assertTrue($DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid))); + } else { + $this->assertTrue(user_can_assign($context, $roleid), "u:$user->id r:$roleid"); + } + $this->assertEquals($role->shortname, $roles[$roleid]); + } else { + $allowed = $DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid)); + if (is_siteadmin()) { + $this->assertFalse($allowed); + } else { + $this->assertFalse($allowed and user_can_assign($context, $roleid), "u:$user->id, r:{$allroles[$roleid]->name}, c:$context->contextlevel"); + } + } + } + } + } + + // not-logged-in user + $this->setUser(0); + foreach ($contexts as $contextid=>$unused) { + $context = context_helper::instance_by_id($contextid); + $roles = get_assignable_roles($context, ROLENAME_SHORT); + $this->assertSame(array(), $roles); + } + + // Test current user. + $this->setUser(0); + $admin = $DB->get_record('user', array('username'=>'admin'), '*', MUST_EXIST); + $roles1 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin); + $roles2 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin->id); + $this->setAdminUser(); + $roles3 = get_assignable_roles($coursecontext, ROLENAME_SHORT); + $this->assertSame($roles1, $roles3); + $this->assertSame($roles2, $roles3); + + // Test parameter defaults. + $this->setAdminUser(); + $roles1 = get_assignable_roles($coursecontext); + $roles2 = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin); + $this->assertEquals($roles2, $roles1); + + // Verify returned names - let's allow all roles everywhere to simplify this a bit. + $alllevels = context_helper::get_all_levels(); + $alllevels = array_keys($alllevels); + foreach($allroles as $roleid=>$role) { + set_role_contextlevels($roleid, $alllevels); + } + $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT); + foreach ($alltypes as $type) { + if ($type == ROLENAME_SHORT or $type == ROLENAME_ORIGINALANDSHORT or $type == ROLENAME_BOTH) { + // TODO: skip for now, remove after role_fix_names() is fixed and supports all types MDL-8249 + continue; + } + $rolenames = role_fix_names($allroles, $coursecontext, $type); + $roles = get_assignable_roles($coursecontext, $type, false, $admin); + foreach ($roles as $roleid=>$rolename) { + $this->assertSame($rolenames[$roleid]->localname, $rolename); + } + } + + // Verify counts. + //TODO: test all types - ROLENAME_SHORT is borked here for example MDL-8249 + $roles = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin); + list($rolenames, $rolecounts, $nameswithcounts) = get_assignable_roles($coursecontext, ROLENAME_ALIAS, true, $admin); + $this->assertEquals($roles, $rolenames); + foreach ($rolenames as $roleid=>$name) { + if ($roleid == $teacherrole->id or $roleid == $studentrole->id) { + $this->assertEquals(1, $rolecounts[$roleid]); + } else { + $this->assertEquals(0, $rolecounts[$roleid]); + } + $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]); + } + } + + /** + * Test getting of all switchable roles. + * @retrun void + */ + public function test_get_switchable_roles() { + global $DB; + + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + + $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST); + $teacher = $this->getDataGenerator()->create_user(); + role_assign($teacherrole->id, $teacher->id, $coursecontext); + $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id); + $DB->insert_record('role_names', $teacherename); + + $contexts = $DB->get_records('context'); + $users = $DB->get_records('user'); + $allroles = $DB->get_records('role'); + + // Evaluate all results for all users in all contexts. + foreach($users as $user) { + $this->setUser($user); + foreach ($contexts as $contextid=>$unused) { + $context = context_helper::instance_by_id($contextid); + $roles = get_switchable_roles($context); + foreach ($allroles as $roleid=>$role) { + if (is_siteadmin()) { + $this->assertTrue(isset($roles[$roleid])); + } else { + $parents = $context->get_parent_context_ids(true); + $pcontexts = implode(',' , $parents); + $allowed = $DB->record_exists_sql( + "SELECT r.id + FROM {role} r + JOIN {role_allow_switch} ras ON ras.allowswitch = r.id + JOIN {role_assignments} ra ON ra.roleid = ras.roleid + WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid + ", + array('userid'=>$user->id, 'roleid'=>$roleid) + ); + if (isset($roles[$roleid])) { + $this->assertTrue($allowed); + } else { + $this->assertFalse($allowed); + } + } + + if (isset($roles[$roleid])) { + $coursecontext = $context->get_course_context(false); + if ($coursecontext) { + $this->assertEquals(role_get_name($role, $coursecontext), $roles[$roleid]); + } else { + // TODO: switch to role_get_name() once it supports all contexts and rolename types MDL-8249 + $this->assertEquals($role->name, $roles[$roleid]); + } + } + } + } + } + } + + /** + * Test getting of all overridable roles. + * @return void + */ + public function test_get_overridable_roles() { + global $DB; + + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + + $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST); + $teacher = $this->getDataGenerator()->create_user(); + role_assign($teacherrole->id, $teacher->id, $coursecontext); + $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id); + $DB->insert_record('role_names', $teacherename); + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok + assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $teacher->id, $coursecontext->id); + + $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST); + $student = $this->getDataGenerator()->create_user(); + role_assign($studentrole->id, $student->id, $coursecontext); + + $contexts = $DB->get_records('context'); + $users = $DB->get_records('user'); + $allroles = $DB->get_records('role'); + + // Evaluate all results for all users in all contexts. + foreach($users as $user) { + $this->setUser($user); + foreach ($contexts as $contextid=>$unused) { + $context = context_helper::instance_by_id($contextid); + $roles = get_overridable_roles($context, ROLENAME_SHORT); + foreach ($allroles as $roleid=>$role) { + $hascap = has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context); + if (is_siteadmin()) { + $this->assertTrue(isset($roles[$roleid])); + } else { + $parents = $context->get_parent_context_ids(true); + $pcontexts = implode(',' , $parents); + $allowed = $DB->record_exists_sql( + "SELECT r.id + FROM {role} r + JOIN {role_allow_override} rao ON r.id = rao.allowoverride + JOIN {role_assignments} ra ON rao.roleid = ra.roleid + WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid + ", + array('userid'=>$user->id, 'roleid'=>$roleid) + ); + if (isset($roles[$roleid])) { + $this->assertTrue($hascap); + $this->assertTrue($allowed); + } else { + $this->assertFalse($hascap and $allowed); + } + } + + if (isset($roles[$roleid])) { + //TODO: ROLENAME_SHORT borked! MDL-8249 + //$this->assertEquals($role->shortname, $roles[$roleid]); + } + } + } + } + + // Test parameter defaults. + $this->setAdminUser(); + $roles1 = get_overridable_roles($coursecontext); + $roles2 = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false); + $this->assertEquals($roles2, $roles1); + + $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT); + foreach ($alltypes as $type) { + if ($type == ROLENAME_SHORT or $type == ROLENAME_ORIGINALANDSHORT or $type == ROLENAME_BOTH) { + // TODO: skip for now, remove after role_fix_names() is fixed and supports all types MDL-8249 + continue; + } + $rolenames = role_fix_names($allroles, $coursecontext, $type); + $roles = get_overridable_roles($coursecontext, $type, false); + foreach ($roles as $roleid=>$rolename) { + $this->assertSame($rolenames[$roleid]->localname, $rolename); + } + } + + // Verify counts. + $roles = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false); + list($rolenames, $rolecounts, $nameswithcounts) = get_overridable_roles($coursecontext, ROLENAME_ALIAS, true); + $this->assertEquals($roles, $rolenames); + foreach ($rolenames as $roleid=>$name) { + if ($roleid == $teacherrole->id) { + $this->assertEquals(1, $rolecounts[$roleid]); + } else { + $this->assertEquals(0, $rolecounts[$roleid]); + } + $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]); + } + } + + /** + * Test we have context level defaults. + * @return void + */ + public function test_get_default_contextlevels() { + $archetypes = get_role_archetypes(); + $alllevels = context_helper::get_all_levels(); + foreach ($archetypes as $archetype) { + $defaults = get_default_contextlevels($archetype); + $this->assertTrue(is_array($defaults)); + foreach ($defaults as $level) { + $this->assertTrue(isset($alllevels[$level])); + } + } + } + + /** + * Test role context level setup. + * @return void + */ + public function test_set_role_contextlevels() { + global $DB; + + $this->resetAfterTest(); + + $roleid = create_role('New student role', 'student2', 'New student description', 'student'); + + $this->assertFalse($DB->record_exists('role_context_levels', array('roleid' => $roleid))); + + set_role_contextlevels($roleid, array(CONTEXT_COURSE, CONTEXT_MODULE)); + $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel'); + $this->assertCount(2, $levels); + $this->assertTrue(isset($levels[CONTEXT_COURSE])); + $this->assertTrue(isset($levels[CONTEXT_MODULE])); + + set_role_contextlevels($roleid, array(CONTEXT_COURSE)); + $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel'); + $this->assertCount(1, $levels); + $this->assertTrue(isset($levels[CONTEXT_COURSE])); + } + + /** + * Test getting of role context levels + * @return void + */ + public function test_get_roles_for_contextlevels() { + global $DB; + + $allroles = get_all_roles(); + foreach (context_helper::get_all_levels() as $level=>$unused) { + $roles = get_roles_for_contextlevels($level); + foreach ($allroles as $roleid=>$unused) { + $exists = $DB->record_exists('role_context_levels', array('contextlevel'=>$level, 'roleid'=>$roleid)); + if (in_array($roleid, $roles)) { + $this->assertTrue($exists); + } else { + $this->assertFalse($exists); + } + } + } + } + + /** + * Test default enrol roles. + * @return void + */ + public function test_get_default_enrol_roles() { + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + + $id2 = create_role('New student role', 'student2', 'New student description', 'student'); + set_role_contextlevels($id2, array(CONTEXT_COURSE)); + + //TODO: add role name alias MDL-8249 + + $allroles = get_all_roles(); + $expected = array($id2=>$allroles[$id2]); + + foreach(get_role_archetypes() as $archetype) { + $defaults = get_default_contextlevels($archetype); + if (in_array(CONTEXT_COURSE, $defaults)) { + $roles = get_archetype_roles($archetype); + foreach($roles as $role) { + $expected[$role->id] = $role; + } + } + } + + $roles = get_default_enrol_roles($coursecontext); + foreach ($allroles as $role) { + $this->assertEquals(isset($expected[$role->id]), isset($roles[$role->id])); + if (isset($roles[$role->id])) { + $this->assertEquals(role_get_name($role, $coursecontext), $roles[$role->id]); + } + } + } + + /** + * Test has_capability(), has_any_capability() and has_all_capabilities(). + */ + public function test_has_capability_and_friends() { + global $DB; + + $this->resetAfterTest(); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST); + $teacher = $this->getDataGenerator()->create_user(); + role_assign($teacherrole->id, $teacher->id, $coursecontext); + $admin = $DB->get_record('user', array('username'=>'admin')); + + // Note: Here are used default capabilities, the full test is in permission evaluation bellow, + // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user. + + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupsection'))); + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); + $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/site:approvecourse'))); + + $sca = array('moodle/backup:backupsection', 'moodle/backup:backupcourse', 'moodle/site:approvecourse'); + $sc = array('moodle/backup:backupsection', 'moodle/backup:backupcourse'); + + $this->setUser(0); + $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext)); + $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext)); + $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext)); + $this->assertFalse(has_any_capability($sca, $coursecontext)); + $this->assertFalse(has_all_capabilities($sca, $coursecontext)); + + $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $teacher)); + $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $teacher)); + $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $teacher)); + $this->assertTrue(has_any_capability($sca, $coursecontext, $teacher)); + $this->assertTrue(has_all_capabilities($sc, $coursecontext, $teacher)); + $this->assertFalse(has_all_capabilities($sca, $coursecontext, $teacher)); + + $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $admin)); + $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $admin)); + $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext, $admin)); + $this->assertTrue(has_any_capability($sca, $coursecontext, $admin)); + $this->assertTrue(has_all_capabilities($sc, $coursecontext, $admin)); + $this->assertTrue(has_all_capabilities($sca, $coursecontext, $admin)); + + $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, $admin, false)); + $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, $admin, false)); + $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $admin, false)); + $this->assertFalse(has_any_capability($sca, $coursecontext, $admin, false)); + $this->assertFalse(has_all_capabilities($sc, $coursecontext, $admin, false)); + $this->assertFalse(has_all_capabilities($sca, $coursecontext, $admin, false)); + + $this->setUser($teacher); + $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext)); + $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext)); + $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext)); + $this->assertTrue(has_any_capability($sca, $coursecontext)); + $this->assertTrue(has_all_capabilities($sc, $coursecontext)); + $this->assertFalse(has_all_capabilities($sca, $coursecontext)); + + $this->setAdminUser(); + $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext)); + $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext)); + $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext)); + $this->assertTrue(has_any_capability($sca, $coursecontext)); + $this->assertTrue(has_all_capabilities($sc, $coursecontext)); + $this->assertTrue(has_all_capabilities($sca, $coursecontext)); + + $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, 0)); + $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, 0)); + $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, 0)); + $this->assertFalse(has_any_capability($sca, $coursecontext, 0)); + $this->assertFalse(has_all_capabilities($sca, $coursecontext, 0)); + } + + /** + * Test require_capability() exceptions. + * @return void + */ + public function test_require_capability() { + $this->resetAfterTest(); + + $syscontext = context_system::instance(); + + $this->setUser(0); + $this->assertFalse(has_capability('moodle/site:config', $syscontext)); + try { + require_capability('moodle/site:config', $syscontext); + $this->fail('Exception expected from require_capability()'); + } catch (Exception $e) { + $this->assertInstanceOf('required_capability_exception', $e); + } + $this->setAdminUser(); + $this->assertFalse(has_capability('moodle/site:config', $syscontext, 0)); + try { + require_capability('moodle/site:config', $syscontext, 0); + $this->fail('Exception expected from require_capability()'); + } catch (Exception $e) { + $this->assertInstanceOf('required_capability_exception', $e); + } + $this->assertFalse(has_capability('moodle/site:config', $syscontext, null, false)); + try { + require_capability('moodle/site:config', $syscontext, null, false); + $this->fail('Exception expected from require_capability()'); + } catch (Exception $e) { + $this->assertInstanceOf('required_capability_exception', $e); + } + + + } + + /** + * A small functional test of permission evaluations. + * @return void + */ + public function test_permission_evaluation() { global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE; $this->resetAfterTest(true); @@ -124,7 +1376,7 @@ class accesslib_testcase extends advanced_testcase { $catcontext = context_coursecat::instance($cat->id); $parentcat = $cat->id; - if ($i >=4) { + if ($i >= 4) { continue; } @@ -982,6 +2234,10 @@ class accesslib_testcase extends advanced_testcase { unset($caps); } + /** + * Test updating of role capabilities during upgrade + * @return void + */ public function test_update_capabilities() { global $DB, $SITE; From 33d9f44bc6118f165d9b8d97f8d1fef070150575 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 13 May 2012 17:12:30 +0200 Subject: [PATCH 203/455] MDL-18763 add 512x512px user avatar support --- lib/filelib.php | 30 +++++++++++++++++++----------- lib/gdlib.php | 20 ++++++++++++++++++++ lib/outputcomponents.php | 3 +++ pix/u/f3.png | Bin 0 -> 21588 bytes theme/upgrade.txt | 5 +++++ 5 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 pix/u/f3.png diff --git a/lib/filelib.php b/lib/filelib.php index f10d8ca5d63..81fef8a60e4 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3413,7 +3413,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) { } // fix file name automatically - if ($filename !== 'f1' and $filename !== 'f2') { + if ($filename !== 'f1' and $filename !== 'f2' and $filename !== 'f3') { $filename = 'f1'; } @@ -3426,20 +3426,28 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) { redirect($theme->pix_url('u/'.$filename, 'moodle')); // intentionally not cached } - if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.png')) { - if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.jpg')) { - // bad reference - try to prevent future retries as hard as possible! - if ($user = $DB->get_record('user', array('id'=>$context->instanceid), 'id, picture')) { - if ($user->picture == 1 or $user->picture > 10) { - $DB->set_field('user', 'picture', 0, array('id'=>$user->id)); + if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'.png')) { + if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'.jpg')) { + if ($filename === 'f3') { + // f3 400x400px was introduced in 2.3, there might be only the smaller version. + if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', 'f1.png')) { + $file = $fs->get_file($context->id, 'user', 'icon', 0, '/', 'f1.jpg'); } } - // no redirect here because it is not cached - $theme = theme_config::load($themename); - $imagefile = $theme->resolve_image_location('u/'.$filename, 'moodle'); - send_file($imagefile, basename($imagefile), 60*60*24*14); } } + if (!$file) { + // bad reference - try to prevent future retries as hard as possible! + if ($user = $DB->get_record('user', array('id'=>$context->instanceid), 'id, picture')) { + if ($user->picture > 0) { + $DB->set_field('user', 'picture', 0, array('id'=>$user->id)); + } + } + // no redirect here because it is not cached + $theme = theme_config::load($themename); + $imagefile = $theme->resolve_image_location('u/'.$filename, 'moodle'); + send_file($imagefile, basename($imagefile), 60*60*24*14); + } send_stored_file($file, 60*60*24*365, 0, false, array('preview' => $preview)); // enable long caching, there are many images on each page diff --git a/lib/gdlib.php b/lib/gdlib.php index 68d891aac81..65e6d5ebd7b 100644 --- a/lib/gdlib.php +++ b/lib/gdlib.php @@ -166,19 +166,27 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil if (function_exists('imagecreatetruecolor') and $CFG->gdversion >= 2) { $im1 = imagecreatetruecolor(100, 100); $im2 = imagecreatetruecolor(35, 35); + $im3 = imagecreatetruecolor(512, 512); if ($image->type == IMAGETYPE_PNG and $imagefnc === 'imagepng') { imagealphablending($im1, false); $color = imagecolorallocatealpha($im1, 0, 0, 0, 127); imagefill($im1, 0, 0, $color); imagesavealpha($im1, true); + imagealphablending($im2, false); $color = imagecolorallocatealpha($im2, 0, 0, 0, 127); imagefill($im2, 0, 0, $color); imagesavealpha($im2, true); + + imagealphablending($im3, false); + $color = imagecolorallocatealpha($im3, 0, 0, 0, 127); + imagefill($im3, 0, 0, $color); + imagesavealpha($im3, true); } } else { $im1 = imagecreate(100, 100); $im2 = imagecreate(35, 35); + $im3 = imagecreate(512, 512); } $cx = $image->width / 2; @@ -192,6 +200,7 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil imagecopybicubic($im1, $im, 0, 0, $cx - $half, $cy - $half, 100, 100, $half * 2, $half * 2); imagecopybicubic($im2, $im, 0, 0, $cx - $half, $cy - $half, 35, 35, $half * 2, $half * 2); + imagecopybicubic($im3, $im, 0, 0, $cx - $half, $cy - $half, 512, 512, $half * 2, $half * 2); $fs = get_file_storage(); @@ -220,6 +229,17 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil $icon['filename'] = 'f2'.$imageext; $fs->create_file_from_string($icon, $data); + ob_start(); + if (!$imagefnc($im3, NULL, $quality, $filters)) { + ob_end_clean(); + $fs->delete_area_files($context->id, $component, $filearea, $itemid); + return false; + } + $data = ob_get_clean(); + imagedestroy($im3); + $icon['filename'] = 'f3'.$imageext; + $fs->create_file_from_string($icon, $data); + return $file1->get_id(); } diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index 514eac9b055..4bd0673dc2b 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -321,6 +321,9 @@ class user_picture implements renderable { } else if ($this->size === true or $this->size == 1) { $filename = 'f1'; $size = 100; + } else if ($this->size > 100) { + $filename = 'f3'; + $size = (int)$this->size; } else if ($this->size >= 50) { $filename = 'f1'; $size = (int)$this->size; diff --git a/pix/u/f3.png b/pix/u/f3.png new file mode 100644 index 0000000000000000000000000000000000000000..27e351620465e08c711741df1230df71cc74a4c0 GIT binary patch literal 21588 zcmZU41yqzl_xC(YEZwElQc{u%0uoC}hlHS{BBGMgy-SHGN{5Jqf=Gi%3hasshzeMM zQi~w9w8E0R-{brLzW4mk`8bEe%y4J!#GRQt_xF2JtSyb08ICgm0GLgT4Qv2Fz)1w4 zqlN$c4gaKi{d z=kYZ7U56Wc>3b2A&GB|+<<+aKrlzkSR|-VgT{W(K){ug$UEd^nXuKt< zITal#EoArosf&^NVc2OLjaHEpq7=00f0DjYa!%auJ?#}6Xpm_5eSHC?wf&J#sBHb# z@{)X0R5Z`EFQ#ESxA->~P7~K=3f}%XR(s~$g!#~=-etiZN3~M*Mv*jqvD-qz8}09n z-_`FIJXtcx8s87S(cm>6Yt~+fV&RnRV?5G)mJxWiB2a%+ljm=xv%|zf*afBcM4_ko z>b7AN-ff=9r1OjJ!|uc5*hKMtHbYr+M=6xP(0$R)-8t!`&gNw_ioqTyqmA`>g}kk{J`3sC12lJON=@y(u~Pj zKG$C@W;PP-X%SlT6&-fWL)F>-m&(}D?lt$Elh&2o(hfH!YV87JRJ+9DZeo6F-E}E& z^{E=U#Leqh^G(5GeXP2t&c1P=Ds-^=*6ZjKLflq&l^XRmktUtup?7)T`4v3oMamp| zQ}*O?kNt~M>)be#t%9@UhrEpIHSJGJ(~f=oVwX}(Nwn|3uE8kq8Pi4y+K77hv{7`U zhnA(d?x$+znxN=uc?aJ?ZbHwQ4%Vp)zMq1HShOIX!RLn6b7qV^{CBT~31~0Lv=}1_8jx`R^A31%-S7Kz=vu9D^M#%r!jx zedRA-^}pgNAMP6fO9P-8t^p@~J%cZ!!hL=Gf;7UlME@h90jK{JD~O{0BNFVbCF*El zjnelI^hBMOKP|5)s?C5xp)>=pUemBKIQM_6!#OR{>%qYR8VU+wVPW!Nr{w(uy%dzx z)zuXgl@*kgY$p34{z%$4r@J2xJ4Szq>zjiNQ@ec{s5*7WY z=)XVz)6c6O|J4%^66o_EEmu7hJbgTUJ^g}%6qMwZ6#m;dTvzj|helAym7AU(!T;&^ zf1CTy0Q4?ka-ph5G%N(j>!&Xf^5Nk>1hdyI84o4Tm1e(KN*{&X&U? zo2{pw)k7)r(2F7j!cO$I(y9N6iOyM9N?smC{#&`}ioI*j4rD(giQX~F}eWlQ;%?1$}`@orz5YnN2|-*zkh#E!E<$1(%{~+Woq75+i?mM-jaV#-kVR z+9-@ncoY2uwhx8koMb>)8>;RXLgx!<_ZiatzU+3DPYkob(ofS{lC1cm|0VRmZ!$Zu zY&{N1XeB`X^~p%o(D|Wt_T5TEz+e82#lADWLL;9PVw0ab-H5u?y6zO{`)SX@bZzpL ztCQE2drINef1+*+l(Zk(L2CQVj*-zgjrM7BXIH^(fz@YfGEQVmql49;(UFPSZ`%*F zTYO%hADnbHeQmOFm}r-PQmSNt!!$ zS#RVHI}pq*qBQC{iR&~}BqmN9S)zAWHSJZ_eB{(E5B6NK_wEF{IQ%^u;zDZt$QYo| zd8jlOo5eBjc;vAlMfwpNLm6LgmpXr<(|WK=r*~qYxNAM=6=nX>&)ze}E^3t_^M%>c z%njdYyjsVznjFJyqYt8@{|J0)WC*1C@jd6M(!C$@RuWEotF}EVq+`-HBO#Vxu<_bz zl&#}ulHsco3n$mGvAyX^f>p6U9jXXXCPDgxPEz;#zR!My_b#=Xb0R(E7B;(jKSc zd6`P!zMItgMON(ni>o2-9&6hi4h#9!z9)+^UmTjbTr|6a4%M2R&VCe7cTR2eUL%dV z!_-BScGaL!^s>OE(?XBV3YW_-GDf^G(BcJZFF>O2EnGjqU07$MPYz*-RQ8K6eX=-af)X zG=cBCN5~uPy0Vh)fvNA8svQz19aQX`4PmLEZJY>oWj}sEwqk~Ac=mGcn+7?*V&mXt zU*4BovzOkKvytl~&Wtq%4=+B^tZU@3{b1AQ6v)!2je9GrYPiJLIDZNZew^AeIwl3m z5ogLP$44u-ZR0H_?4`5c{}s zI@J7nP9!irIr?pTaa4NJVeO|}WAu?yS_~^C#w_h@$ka3HfaO0&?Z<3|`lK4?gGL4K zf{8ePmxXRtbo5aYp9h;spLnldFUN;Z^^cljZF}TN7j4UEGa8{tbCdiR`DPE^=@f5) z#TU{LVfvsP>0X<&i0k7K0^n9+CJ_VfLkVQ&apO*FsYz7{gG2Nh@{jb4)`F3_v_N~z@6Kc1X(EP|=>uJ@ z$pNqll#lz10Ne5GHByz{vpJ1DRfnTmDA#6LVlr_06Y sdsJ9^?Hvtv;XApnh9yr zuk4-TOV?;(E6bPDB0lO9Ch?V|3QN5~p$FocC+62czNOvJLg!Riz&Y~e`~mP_{axod!O_#h#0 z-MQEm!c)PC0H$ts+UIvv;Iu%3|Al1sf3Cb5UBMBB*|6jZk04wz*6wRHT!{aEy&rA| z?8*g=&-&~B86X=m{>wsBY?R!~mMs57m@BKQGWk48SpQ{Wo_ExVv9rM~T(cA9aNWF( z)2fdUC5A&!7`9TsZczg6vQCz5FDT7;d{W`}FC7;@`9H=I-Gb?oCS_Z@c= zhW#wCl6r~U+}Q)^XbZtpGhTW`S$Ipyn`0Q;(A&N=oD7Vqso~BDmdD4`cD4v%FB$0B zpXa6nV8cR>?x?umiGHj@6u(v_pV7CoPF@x^%K^{1gp0q43C5FdCAmQ{t_G9U8M^yqxK?+_01x%R;-AdH;qqG zvVSbxEQsD(6~JyBnis%na9H4f8|hb)mllJ4R^z?0z$bp9Scr+xL3;kIAu0;`=|0IxC*Ihvu0{x$nXp0{m z+5KDU!y>KUo5={QB%CJjMf=KQ{i9KEdX8Qs+K>fv8u5iyf(g!V@OL5_LM^de-wt6T z5MXnnN#`X0JmsG9S$hMxZ&O9Hc2)MRosFUJUT)9a#0H4qwZ}FuuV_03v2q~5E_-CX z#Uvib@q#W4JAFBcl8wasok}i4f*IBZop9KPGpcmLoPy29XK2hqGbBOSMcT*&jOBf? z#&c+MVd0}B!{dP}kSu-Mfdu_CW)O+bEK>;3%437FIxvlIp}~~fRG}nr2fkhV+@XLg zZ5XKTjVme026|q_zzVQpVOH4_g|^2iw#T}6jxvY-jObNvmkdzyks_qCAKyFR^&!PH zt+li?Wps=IgniZcw}3SMV{EdJ1NW_?(o@4|wqk1Do$rh(VHcDjD{qPD)qAd7WMjm@O$KqqJ8(((MKLWhgAX`gsOCEx&|s~ z5kJa`G9`9d3pXTDL=|OarA7KsV@*O#br;)m0YdnkCV2h>B$;1a+jq3Lw;@!J4|hCz zFqZwV8RqJUCz5bO^mmj@VMV?{3qU~JY4DP&mPx!e>z|GW!G=ja zD68Rp8PbM0f2F1Qd!|7PM{CSYVS9V#P5{@>CfcN-*CGa~l&&Q${Mw!>aF`L&)5(+y+whW!>AfX(Cs$@f5Z%_USTAF8k_?u2&ZY^9LZl4^;hH z!e# zTkkl-faNAj>#mcsB7H}Tx5TsQqHvm?%m=!j1GWUxg0L?gs=13 z6|cob4PoWYq`74_##?ea>fqzZb)y>bJBa344-;_kN=xTq0EI7dS{1CmW~dk%iuCOs#dCXi_9IlI8I z6HM8U(h^F0z2h=!GTuVvpU4W09maiI_(6@IP`fs5q>g=hrH?ZZfD6B7SGom;7;hc? zWW*Fxu~ngT2bMQ&`+})W(>!mY2c&r~&@Xma7ChVQhlUgNCwnECF4%9EQm0D-MPV+` z#vJp)H9c&_)n#|y%0OF~Xd2%p-Ys*7Izz@T;Vy`wET7zaP^I>~WOQ05&pbbJvZeN= z?^#DTVcR_fNT;O%b??nolN4VLbd|3s;TR;mw@I(e6Y2Em);p=%lL>BjL)xo{N%wEB zC}+%ko4asqm}D@gA2;l||1h-uo!^^?gr`k?DjGlO*$BpSH61G<2QLOg9>-OaxnC*R z1Dl7tVNJWO;-vBNOj1pzwSCS@-|+=jM}@fC+%^$Zw&uT2gF{5|hZj!VfLF6HqsE#= zS7xDZ-G#huJ9Z{SOzGT>f@>wzb25m#+PvpB6CSn>$7~hn@;u{!9z8pjNaI6?I^z&m zFV+8B*`4h*d%py?KaCJjQ&EL)t$=&R&t)pBN(4lh~x(46IQH4QjJUV~CT&4$zHIX@sOIycfW8;t|b#5X1`e!In$#3F> zUt=^^Q2D06IQKqs5C2{!kK$T<4VS&b`i4U|ULCF^00$&1C`7mwEO_h`ysuBeTDa(V zyenW$=OAC34q&OllY|~Q=Tb_3Z&cqS*eWfGUwC!}b#5tGSPBt9mCp!R^y_%W8T>2| zO{RF%4~5T!K1sTsy@yqU!^*E)d?k9NFc{2w8UFeExbqz?Icqsr$KFZVkD5qcGo=r+ z_@V$}-w8#4a6s@%{eHP(c_k(nvuriZDN?#VxVZf^0#U#vCCc%{)#=FRe0`o3D^?r1 zt0E5dcuJcDH1`??m70_cb>KpP=@Q?=87A0B-g-mX^%Tjpz$)s)y> z0f^E;?C>f#9yQ^9s;S3z!zrU9R^Hz!rCvG($xT~-G~Q0PvH-2TE27`CgYZKeLcqVh zBC#7&s}81qwx$K>)DT+h4>pFYMG5tF<;*inG>TnR!A{fm!d2r-@tjCuAP9y8F8!Rb_s9JhnN7ncbitP~{ zh}BKm5UzICg|Nj}Xxi^YJMJA{Ac+8HvSMCIyxY_i)^XJ4p(BP)_vTkUM}z%zY=4wu z^8kb|+O^Dgat)IL8zDAIm`9)1iTe~X`NZTA9Y$(qwj;wU7uR*7IT_2ahr{VaXbK$( zP%#XEXe!yit=)sxfKVMiv+liXzw2~QXJO4~@y&6Y(KJ`@f{lt#iGP(kGm(ZS&58Cr}@H}O872j0y2Gl<*>$2-X4O*%nFlo0GDnZHTo{`;;F-}9pcPR^z zyJClz{cY4`elnKS5w&%#&8TBs!3dw;J$EF*N+$9 z_@17&5TlTfvO4Obh|?!-?CD^i#v{P18M*M{#k`w~vo7@=!dU-|WxnX%OO?zP|ojur#u^-2`GH^P(f8C;m*e5Is?rDdJy3~4J_>(XQ0;0e9Ac?53~Nk>I1m-RgXcTKc;Xxnd&g)?KZW8sKlYI2;@@lJKmj) zm7x*6p+KDCK@}#~w<3C}fO=;-NswHF#F}H;I4iq(G#)I+T&cyx$Yt(yD3Rm)wLKQD zvw#HEa39TSrvqt{&JS_`ugzx6+0mrOtom*TReY@KjwLI%n9VOh1e!KvU481$}PK8n~JcD+lTA{HAig!c)ENBAtnIRRbFv%Pv zG0}u}C9YLLLXtKoU0i=!6*vq|3}Cf6_DOZbDpv;|y%LknP`gKhcBomw9pfpRO`fjx zorNx{_9JNGSd`9lrSf=JISfBTIDBw~cFVfoEDrG9QSOmE3q7Hppu*g`SXy-RkM|^{ z?Ff3-NV?Oz*X+`8hv^wx9kHYMv~l0G-F582s?f^sIE5{6N3p?8(0?@9^?bbtgqL zqE`J@R^uu-2^J=g9S-uBH}b0fIJBvPc@J)E9WingXAgR}z;%{j-<_ShFGxVUYmNya z9Xuol98sOrU+1lk94+QzzoYYwsA%U}1e1i0k0@P)pX{BwSRbwlef`O77Ylc=Lg zPNJ$Yzf;BqgP&gVU?M?j?^Tld2_#{DcMSKqb;5}(1%ZPv$+J}``{!jD=Y%#zEWR7_ zk84w-`9KSxA@uG((@`hs)M2pe!wbN!-V|$E_MrLg%|*e6CfX--cpGCxCqzEnTd2ed zI3vLUq3>r^mAGj(TY_0Jf-?T!Sgh|wGP){vj3@qD+9}YTgY8G zdqvWdXw_f8$epY@OVrO{^XKVqa+BXoi=!pnOY~}?xPO)vN7Y9pygY-x8HmEFo6CSi zP-j>*>0k9-VMGT{qUR{`!#Escs~&qruI|Xx&~A>C*Y;vcmFuC%`#c1f>}a2-(It8l z9+4f1Zo)?$U_U&o`!OMsx1wPRvfj{ey99u)t3U+dZhSE4oEdZLv|w3EtH5 zD6teuEDeom5z1>~0K8weH#R99vAygn)b5k1r;i{t+JqLo#r6uVqfrWn;m-;r%5Fx> z45fdDOL>WC2%M8EGj&W;!2`qkJGe;jZ6>GM_PfpdSEm~o>KEeXT%^40pv6)=r?_VOiK{>B})h6pU8T1)_pfbF@ z8ZW`JPPB_6eA~sx#Ii(7g%bZiOL|2-Jb~+?4DxCH<1{$s`_1Dygyop1buxw#Kn%f zFp85Qn8C<(2DZ}7feC7-{k#DxfDKAF+izls^OayqPiP17cS0DSDaZFE>MR^12soB& z_exoOH6CwC9p&}<;D`Mi-NoLrjw4Ykx&r}W@9pso*X7vxqTAARkaNCsF{L~8P8|kR z7_NIg=0)p+3#F3B*n0C-jp zRLS^;F@jnfud*q)G2L_qboYZYZUTcIVSLC&N>{tJFzF~{tmAE#C6-r= zn?(9>v=0L0JB@}Gwo;{`)ZYu9#0EJbEaS{%TxE@WJs-fgo6u9TpA0$1#%=(#(ggz1 z8??zMq`Rp+Sur9ZTNB%X<%9ac{&z>}d0@0BZ#RjJHjDN~ihDXrgyj|DoaA;$9i*n} zls0=B(SaJ-E-u(b!Un&-%9vwU%0YiZNzty$23vw;WWduj-j9VHmW6K=D(5uaA}hta zm~9(`s}KTszF-9w*g<`ny&=X}(55}b&qftTZu0oE*}|~;3u=>6-DG{u8W0oh25_mj z2*-UQwC`nt_J9W_Rmx)a6rx!oAZUzTMLR+8yR|gPY&8XSqDM;g&?)lw(<9~aJY4S+z7O>h$L#0g*`jZUbm-N5;t9Oje)MP z-A?juxWR$y`6W>HD@uI`j=u_zGmNz`2t@*ojNOj{sTrFyK4pnV6G3;7gtuiik;}1= z-`z?Cn@JQ+F(&8junFDwASz8zA+FLrv<(ymHw-rxQvT2c_&@86-_I=lrD<+~H0L0^ zld61cta7-y4&j>{IgiR*-mD8?7smH)f=onOiXbs);kxDaR2dR$gZId++P3PV#U7-; z*w=Z4tyIQtW5TXe2eX@I0*Ihp)(M7mB94^KO+0=gj;^725I8lpKSW*Mrvk;#3Bn1t z$h+BvPt{AKG6Ac(DfB@ijFlWD=+sT#)<#%uZU5CCi-- z(1hT+k;v(kxXO@Ku|pvYd1Sy-6G%#yf3GN_!gpO9SLLZg-p9)K*c}!J(FN!{+lu4k z8BAh^d@kpIg(q~b29u}-!j0KzSz$vpp8PgJ0EE&@bSI^Nq(t85M?+gQ*t0!q0TwN4 z^;wUBuLK+x%?_wIWChPqcHyzzKap5vd{BCaR9ic=W+o%9rg}orwJ>Y)1K0!toc`NS zKU3kk+64epXV6y8Ikf0sgc?;M1W-uNp3zy^`&h!6kLSDFN+Fbyyt$gHrTd{vu@48z zkMai}fdFm1@ZOTPWyV_50en_9MG~{votg{vw9h=FZ97vrjADL+ejf=|eDs~R1#gF# zPksbI+O(IxH}g-UH#h!*Fycf0?3cbHR-hhm;Kr%}#osA=g?PdS@B%B2aeXAsu^^SO zPD%QW#PohDU{-R2&(Rvl)15g3!WX#_MW5NQ#f(_S`2+LzEpIHV z6LG|jC)=wL3I)vROQH~{)2%Y+Q+OTmkbgva2c%PNM5!UchOag4;QNV(9`ukvVLMKz zKogX?`?SfM{XT7ig~QE~*D90wXb4vnZ*l(n2N=4_Q4&K9pV$ea0b02O*Z)Pdd9S75 zjdazJ-dS%e5o#AxLX-a=7eK8&sN_t@+WdSWgy#!gF}^RBN?C9>XEE2MBM`ES5>$9$ z+$2GLmU@=b?ig6K0R#jFA>gAs*i(F|xN$+?q`KA9CaA|>x*ZBy!@LXy)}6m~xb+f) z8bS*tsRKmXG9Z+p=|;tfu1K4Z$3m72mUC7ml2YV`1Zzn+ifz5^&`jY+!S(aNvVY9t zJ|2nXnpz#ozhyBWzG8yVRI22U{3r|KGgm+UW?i@@6MX6!TRK&MXs>gG2N41A+wb2m z7iKChK`5oUusN=V#%E}k(OY$ZkkGiPsdCL76s0LCpl_=7o3Nt&^v8;o9J+aTrEY){ z^AMJ8Oy%Zd>tB2MM2K&dir{dLepg;3kvxC$7KxLB1fGL@SR~>2Tz30}dZ7>X)g-n< zp|10<>awb;v^(KBGUik=*<+%2o0Jpv)hbRpsXK3jmwp zlT4bh*#e0(if7dDNBt^CudM<5ama{aK^Wc% z(`B7!^?I$3K@%)^twlU4WXb;lFlLpic^#V&p?fYhF0(OilYD88tLwcux|$l_*x$aQ z<^V{u9s=nvH`euUH%2LN_NG>+D^J+IpB05YMBS5Vf8Y~&Q?L8p zByn$5AAqsP1P%@Ps;)foU3lpi`>>-p*Tt}*LlpZGjGCWjOpvsL3R9IBr*WeplSW=> zzi2EY$ER7MRSvYx_A>+ykjP(kY-0)v)OsO;{ni@}#abz9pZ&D58g%+^uay*?cp$?0 zQ5=MNv(QDvMWt~L-7jKIWghL3fjkyetHIaZv9M-STQyAE(M5zwpM z9Xh<{rbp*G)1veijCKsg-P{+UUFxv>*^*OL6*;rstd|Xk{I2i4k=X3j z5W@0j3_#b%TXe$g4F{0;?~QvpF+$c}dQ{h;JkPqkus~IGBqYH53AvaQOS0Vk{L#&O zkEjgVc-lLKA0aoKrNSZk+d8D6OmKrb7>eJknA=AL2tjp*ri&OpkYT;%;x3PU^eYGi z#{%}fe2Mg39el_h9aM5S{ea_5mztFMm$8Tj6ZFnd4;BQ-MN?R156>gklC?(Fe`qa1 z8>b9PsSo)M{us5M?6iu6!{+6+zD||IOL}xRquZk_ykMt~5tFf?wO&D&9Hsn(fo#=m`=De*$Z% zWCjrs8pv*uJ28IKNNi9h$Bt;G`QdCVj`z_ZZT?Rsfjs9QZhk0tcc3OY^{JTiaAKBp z#c~j-4tVj!*Q=jbo_$_Ny!wVLPMn=V(mxjH=hSoWaL009mcwu#R?fL$mF{wbOZ`Qhf^5qj_x73MZ z0Pb=xP6k?r@QeXg(KPsP`GbcIXI}R)HnM?1v*p;qkR$y@oV>J$A4^jZ$UnB>?C33$ zIQ)vC*`gs5$)^Yg6Nc6|J+U1RdbDC(YMP6y=`L#WqHlTy$lGv31&r4A_Qh0q6ck_{ z=tB0H#&kxJJeS5Sxbg2ya+sD3bpN@ZeUc#x2Pe?o>}(SWUxHS4A@(yh>+Q|80e3 zs`PzDHKFzzYuT0NJ*&DfwYvb`)ECLpqqrf`Ol-GmY~heJB;60S@wK=m;P|42(DwH4 zr$8{0T8*~d5qIJ!r9YWtNGnQV#4f4?IHy*2So0%>ckrszgq*mESU@;i=6qB|U3Q!t zt{_KRZ+@tOyEgz9IyeZ9i+dkJ0{&h|k^wEs*dXSOs7`Mk2WCLJW|CG^gGlE;{476Y zGGK8P$d_l+3=(}3F4VUO^xaNJ~v_7M8w`{=YktL3nZ}>CoarY;iRPWdj z&sbsw2OISa>xOTjC+5Q9LI>q_%*8-v_@1$SdA#J_<2w&giixPl!5keZn-n`6I7qAK z2;9SL)?ySEYdO$#gsG1z!-pO4nMdg9HA7ye6quvbfA;7lyHB(fTRCG5d8}I6ko|QWk=}uFyAq2VLLSo5&Sh(QDs{ zFGgh3;7aEd?(PO35tF!HEtH7ar#sqsnOO;B%N<0Z%f8tg*r|_F>NSID` z(E=?GQ}0W^X-~1LqS}#Kb$F#7e1sM?R z0x|+w(Q5_A>_O*nUvn^XJiG)OzjD?{(NnMZ&Ze9%^EQNGfEA6DbH~b#19yI#ThZ0j znlOI1rPL<54)6Ph2M&B_gEHciM7H0X*UPJ(oVG~sn-#%O_R@lt?gl^pCc;Jw#=!Jn z$-HfUZ!*+^O2i_7g6pj5N|9llZhWwkDZfGd=`YQzO#%&d;=z{{Jxb_uk$C4ots`3t z3>>l_dCRvzg0T14TuZSVK6|oPXvI^u7KLn*Oy@S8>#JllP&V(v-l1`_b&S|6Hnp+7 zHI&Wpt7nfy4qw|GziVN^sGvtjXn8)&niAa2_cU?Wj^zrUCEvHCx?&}31#K>X^(@l^ zq3vM@S;;isjVTFIKoQj|^(Do4Tfnhn%!K!qS44@XTqbV5zF4De`W#;>n0J@lJI{-2 zCc_;Bz4=6TG=ycnk}A6Ske=<8DGW6wYwlOZtH`SNO2G*97G#Y8ThH07ELNTlQH~Ds zYWCcer_WB@`?AT)3Q{@U)DO{8;LolQPc!xV4V4gU{o8+O|If&qa?Sl ztU>O|CEl6$sxF=&m~*&9^{&Pwh@rH}(eO)8D=l zT*Y(grB_w&zcw=vw|g^>KFxp#pUv9uBv@@98tv-Sd-q<_1BxlN2y4CVK{Bg|@%02_ zIgVdJ?GAKctv{Kt?i#NXDol@=;&g9Cjxl&olmfg|_k@)~(az`Yc^bZ4sqZ0^I<4!R z9N1UvvtIXB>xgCEZWk!Cryw?>@cfH!{g=29*r;FJaaEBQkZG@RMTeQ`Q2#i}bzxy1Oy$NxY3FbwZOrjs*8F;8Vy8aCQHe8oKG{NuWuCC_e@WmyVs{y1$sHz|y!W~8mV&r9xp zY2`t7d9?Ibk`A*gGzaja!RYF$o7PP=Sv21pdFVwkGxeD1P$mO*Y_*caA-t%PE-Q1> zvu?uLwxbyTZ86HshmS?fY`ole)Ofu}!K>bm=s$>`ErP*xE3#DmVsVTa$2o0d$Omh& zF3~53d4l)Ff@y6}9%!01ALBxu>dv&u zOzl&iZ~C9jkkW6(oZCG$sha&_Zhz4U8v4OU6h7H_PgK`HBg3-D1XIB8UQ4d3D%yi! z0JiyNgCC(LTKrIb#y{%NyS;dIbGlj3)!y;bs3vf(Q6z-CzixgixRiG{txum!CeyCQ z6FXvaSuW(*%{*qsI)K63ty3`{;k{*?`X(jzuT^W~`^MDj1}?c*MN~q-(JI@O-Z)1Y z#`e?hHRWE?SlWM|XmI<8#u`CbEGyVydU4eJerWcyEWZ865gWOI=h2-mVldvhhIDQD za2)!iinJNUq;4LQS?mewMGsKTAjT4PglQYr$D<^<4;Hks5-?#{iYoD9v^cG4HtNku z%qPZlRE#mYc+|$s9!7J2w#3|~>A3s?MI|D@E&I_{3FG1?xxYC+md-nRwx--5<)eL7 z3BW&lySw5ul9cCUdO)o;SLvrccTD5?TqRxbyK6>9ziI#uoQgwI8ye{On9T zjnxYe_wX|e3|lp{!{W<%4 z3#uQc{gE3Mxse9E5nv=%3fmu0@-p7-1NCFNh%Hqz5+Y(A0}o z&$ucs$04k}!1Lvzv)y%}6q3mQ>vEgbp zZOumO{e(98%W_liie*=uhzmOj4h-F|e-iJpfy2aX@9A9ns^8^2IEE;q-0;y@0APSV zzILKiO2-75;_Z0NW9BX;K5dktXLFac6#_ASl+!yD5@|Gy)sE)%88@i^a?&5?YMtg{ zu5du;Kgj@%-8aF;sg!AgySSF<6?-iz;N+oY)?#iiuA^iPzYqhi@?KU-1{=$R2B^C<+e30&iKpPMAHpKwt}5_adaD3_n%^x!Apqil$t>J@{oFW zA|upA(&B6MxBY`63JkHCVux&X32z?4S7&in(3|By9d!ro(BEbmn)X2~upRU6-O1lD z!Tv)jPBy_=&Lr!JAE_8sDim#MD{L#CTkV#V%NdRhI%$lj6eu3y}sx6RepwSDl%Ofojj73z(Sn4SL8&y>TJp@ zTR8B3Pybxl)kbL4Hp^XZPDvJL=(+H*mbQeQE&6feoOU(S+zWEd7#P*@FtAdyPx2eWfni; zJ>Gk`+I8gvL+u%SGWD~%O$mB8Af2fW%%3BIOeB8&{zX!q(&72jI-s{41iCF`M1~`g zodFK4xgAF;1|{W*uI!E+$MI&s%mgN3%b)n=;NF-}8a6Y&665x!m}5tKs{R9bkjTn7 zCIEE_e-kU|afzbYy$e}zz2v4XpOq!ip7d<|N3i5kIIK-4twzCYCc3@sd%}4-g-O{C z_$NJ6GIUjRyWZ0bm}16sDpv3x`Lz#Y+ZjQ`0}dVbW10$+I{0J8(vY@+dr}AQhDRyZ zjs+0`k*-y8v^{49$0env;v3~-*_Uc#D2pGS_OB(&y1zkai=#x3#PwBo{GAxQ{jgI; zW|GIQq;?CN1(NQUbiypwP z3YM_NC&^t@;e{#A&O6=yGerLVvR`E2a3bXKxMF@Jcv+er`j53sS?OBAGu;YZ&&u08)?(IH~^!DtLD6?Y;_iNsrrHP{E9V zghdje^W&#IzVHIm3vY9x{7jJ`s(UrKQ}z8&B%*V8K?8EMtg^vRdAE3>>4v0}zstJ6 zV!jK*o{ZW`I$=}v5SmA}Gw2xk=JtZ}q3salE<|>H@f#bdP$gP&86tACMGQ&8bMKMJ zHoy%|fAIcQyJwgC5A%M}R6L0UKKiEgY#H4b(<5hmW=r~Jm87`2*x{$DM6X&c7~{zm zW!iDTORg*hd9NOXcJKf6M}lz=X89!? zq$V~)@jJ%d5w>(U;K$ZxJ9E4+VSMb1js@4ZrQ6#vRx&C4b%r+(gcESs-JF`V8~NRd zML({dK6b~yrjiw`q**b&Bt2cFCyXAD)~8Xy=wkR0sv@8EIEV}TVQU9G=TN*bm1nkV z_WkcuIuOn3|E?k%5o48wfVWSLw;9cOMBO{P8{~XaYzzEaSUS1ru9P|+RXxQRC8*Zh zu@B+HHkBsq_G%+(mOFAON9&jv&eCr+@!?c;uw&Q1B_vSfN4ZQPS7De+_wSI#S0RGq zn1Svm#^ECH&pcS-)B2veIp{)aI_0xLeqDwPSYI2c?;Qh1c5GUna!xNjkBB30a5#QI zfCq75OZx|>d!<5L?%iREq&++!`41am->yX|s>aU3z}i#{g=_2e+e2cS0Dvt~y`jfx z{WHuQ^2dH+wq}L-FTs^p4=at|hJ3_CoLKS;4f=ODJ$7|8 zTZ9d&tP(4XA^et(YUOcCE5draF1C2XC_xzO{luficczxq#Xw`hWS4KSc=%Dv-w?*a z-zb^9JKT==dRn0xcdMS5=BNW(Qe-$QmU}}~x#4hi>zhV^#Wf3Lsw6=z{DW3G^_T$2 zXeBB%vw}7uRq>Mg5X}b91fEC2*6*v!tm6%MsqSn!v*0AYOT75j_DDrApbnxrq!s?t zx<(0G#YBn<4+`SD8c3ZC;r58XNAShMVeqr>lv03CXIecbVF)d5@sXNqNs$(_}ob#$W80h?_@4YR8t2Q)ZZ8 zi^R*q-(;w&TMLIApTW&r32lXUkER3L<7XbstG8WwOkfqDme*-3_eo z`tw|UM4QrYyIZkOMYl9!|#}KV>cvKS$!&)}CAJ2297*C&2OGHr)rYVtm z%B5H$77>8xG+ZA)+#kdFc?d&5^8$T?hvC=LF#>zjILsEz(n{+~xRIzps}7K&-^<`O zCAo<(7pd?R$nQy}K6Hj+Y*Bxn6K9##ctT|sGlRa!g15VA$=o~p8ozf)KhG|(gWU9+ zJZ0Yz8dI7=tn8&O8|)7s?M}*q_WQ<&L+wgsT=oZ@oQ*zp1XiM~H)56R`CY7~pid4U z>SCu)8C|oA1ko4iBqQ9SdvUyEvP!%#Xz5v?cKqO$gnL3CFZvM`PCY*eGnn2`S%0yo z8=3V!40=fEzFz@@T8{8!mMP=;1!Xu_G^8Nhn}xuSTj1jn+ZgMkVK1-0O_<182&|-V zZ)qfBSC22s4XI>(#YYF;$6kv7Hf741519jWY<`eK=1HiJyd%dKV>QAQ#`H>NkP*dH!`&u@M-To4=b*1 zKkZTg(U0tk!F0I!oXasZ2Kz^`3ZUF~-Z2JoA6k6U66%8ed&&SpgyuZYJh%s zB6Swph4DMc1nUNed_sSnJbN#x*5ZNV0DpPc?5xIMjfFaFRngfyS~7L=Wh^JoltgAB|y6f81CBsQbZhD zihlHL@A{v68%V5}dsn8axI1i$OvKOh^ef3Z%;A8gKl$uQ&4r(JRi;(e%r)fs`Usp+ zg$__-lNNbu5Br~gd2lk+`E~4y&rls**ipIj$1+TgMSVfJW!Uo;sD!R&mS&{B&A991PK{k;PTXR90Wo z+wL^^_G>+hEK>t_04Xhjp8LVvaN{`4WR1CFTfxa=(#mpsTCo!BK1?!3IG>}tjDo4% zYn&iTLYM6j1ZexnW3@-$#|O9b?%OueDf3u1T}UaggZlzWdTOiI`DYy+evCbA0Rb0k zYBui2y%a@PLk8Ni0~>TTeUTSU^SKddbd2)IXPNKc>nk6*vKu$=Z6Cnjf+>%@^Ot1g zh)7G*R=`WL_h|U=&#P}G2w)!@H~;x=fOFj))n~;Ay_ps|1K8nPvotf5lYD6%s%g_I>l_Lxa~StnzOLK(7TkbN6%BuSrSOf$`l82g?v zwi&C!>qEJL~k7Y;2?xjbAE4*+p;Dr z1FC2kr-BD14cpVgS9S5PIXIM>!YSp33>4_`@_{CW4zus$U~=#s?YSuPE2l56;O4bc z*q^jyPSa}AH{8}#901Xu|@DC47-!3FdB<=ic?^2`MUKQFG%+L06V66 zu9d&sy0gmS*!nNu8sa-@(4(%fe9F>rt?7v0nmKKum$TIZwe?Z{WKFP{dSMsYNG^ODJ|E$%qf)dqF0ElJpoC_elm}(I-#bzZzDZIN|G5|x2Jl;ob zPq*8a#&ov~=I1MFwfN4}Mo@La+7{V(ZGEka{)*A1evAnm|)DgD$ zbQyYAr%}|`Wc@EtmP_=p+NkYp2t~){WcwfG+qZ12{o^-Z9wM{Dcn6!l(%k@x!wWJ; z+IMVI8({Kqfec25(MN4-J24p$@+os)>)#LzZNmx9tGWUMStH#pd*o!1W#&3rtvz`7 za@Vz|EI^%m;4t!*n^1tZ7%iYfCd-ldG!rO zZ@xvq_~B61US98eJ8R)obr}LgU+!U(=zIB5eDoCvYbkSjrBLLyl+$E)jPqSl!m#+L zzKh!SU%->&V2G#Vm)N|K%q47*;Y3#GF0jbXIo%vhnTTKi3}%?lVwe zDB8f+nU!2qpAZ1z{rKAws>a5PoAYjY*)QGfjQ-%gRhC0U%0Tly(q22wZCv0%kK>Ovc!oDerx&_3HU-!nB`S=ct3HhUZhK`^txXs>j!C3O@pI)-aY zXT89>LYs!Pdq~^`VLPoJu@NyyaM`wHTkjj_lUQp-RuSyXh~Q8xW<KA zxkjga@laoaOfXveG7d)LuW$`&MJ7n?c@OmixsL?@t_`BYSz$e)$HB1^?~z8ddVlY2 z>^ju8uk*D;x~vUJQZ7v97V}2@e6#|j(!Dz-Z6h3Ba9vfkhp$r`X$63_ntS5&FT72) z)L+;?hb^V=cg+3qwDDYjap96}IaALTGGo%aQ+ua#rRDC!=5$qk z{(W!{BzNd+bR;;0Mh7^D$2zzn8|&%21#WP)Y+T(}ID!zcHfsTFUABvvOsDIVUe5Fz zSGOYUIYHq_ap5{30M_7sCy@~_=g_2!`Kn@_IP_=n7biPJ2;oGMpJGti2N$_?#*iSu z6lB;9J2FGbi3cBxUPShF_Q4w`AY5uHj*?Eg;QBid_p5vG6XaATeu(D@PeR+B@jWk` zv+4V|IPdoq4hsZjY{Z3GN4UtJ3qBa}B);Z{wNNO%eEkhnC8yz z==4&ia``(b+Ff^mSb%mAJxgn;5M)%IwD6QH*MDVYW}DOoAq(R>l=fMfzaQ+#W4J;; z3u90oC$dFCvYZ91j`J+90KV96t`jE#2Ci9_D=?^)Ypv&JVb#w;ze9R|(ETr49xBoN(*xEg48FeqsLSZ8N8^FV2F}iQ`vbdFr(hI3GXv*1Rqea z8%J%y z@{G@8StW2YBV-*}?mrenhfsImH-e>47LK}9Nwg-)pV1Q#U5Cds>`&iucpLY) z@~)|$SR9KI!PKv`LytgO9IgGRY~S;Ha`Hy6d-8X-Y_cNl7AJhHp;dLfmFiB49Ef~A zxKoLp!n`Rzbc> z-r)(n5w;uhVmEx!h>7pl3!ppwThHUxXDf|Cj)Sq!xI55Dj#u|EHllBSh}5)~|Es$U zr7#PXm#!a$c5#`|Y|UKij`eCU^>p33Rsj;FC4|)evYC*C7P6C9SqHTdX1uIu2=IKH z8FaXCWz)mBJ9h4D=4ttr5M%XR#Lh7u=!_(#Ag=4K`wqfo+YuWX<6Yq;94z+Mj z>p`-+R&3DX<&+a|c#MLE<23O~z&8vhxX;xBU95Zr$I6|CzE(i`xQjzIac5LOEY$}Vr<;Radmdblk*{}$Bmr}CrSaUZA|XQeP|oS5dX z=#2hHw^MIYp@6Skrf%tGPCc&_G9a=>y0LvivoJQu>1YiU<>Rp;u9TkJRoLAgT9mlv zrcVzzwPF}P_QdxVr#GBpDRIE)@TfrV)+T*>x%cbwZ+#IUb@3ElhvO5B`u}u2#R|KN z?#f-J~+h0|roN=Mhw%c#K=P%7Xsoc!*-kvQHh3Kwz-N$rnO28X>_X zbr(``e7#;HUf3QhZK%n+BDl1xgt~Q;%L~arT}BwK8h690z}`ouFU|pA^NKbi>sJf= z?z#cXthH6flm&Q?I5|vPrCg0T03kQq-{GK7Kw?gFcLEf4p<@B`s|I*t-n6y*D}##v zd~3R(;}Wtmo=I9}mk#x{vqSAnBx&Zt-wQ67NkFNRmT)5nK=lFfm4=sdBs|ox{q$60m)H76+e}N3Gm#JnQnU1PO=F>35Q`KtXiS%} zXI^y7DtCY1QA!hX6@r995D7fv5PMLo^+)}rdB+!SCCho z!!K5`7Sc?!tr^Vp?QhNFvCa2SBZeF^dKEopVMgVwuu&7C1PsU4Q_lKfE-i%`E1nyc ztUL9>B2H?%_npV z!6r5MkZaI$V>j}ixN9N4ShH>(#0J@0Bv&6EGE+QBWhXpFnr9iSEY|!TVLxrPcA?!F@Pkn7K;#TwLVR3nmp9^^5JYy! zez>1*pIMyQOX~$+^XSP( z8mf(zN4s*p7u;h-@NNt&2j3Cg!|sngGcFtL()-PE+ORM7RaVUI)c2Rmt$R|Ye3ydn zMSN*rK)&MZl#RI5V*h6>qQP6?E#hrRXjCIT`irk|eV;6zU5)Hl_e{~vi_ozr$8DD_ zcr9~ESC6oA{d!lM8i?-*{vQd3{9o4`Z044ZJNI^-jO51a*z)u)iSD}9vrypI*Iqrr zJ^h71fp@2S_Y?9q+mO3jr2L4a;e`gbT-zQZQojs1C{7OdC_TATOv{^*uAWJWjM(@W z?$+;|jheC?mvh-WB$A?;B|>VpOOkd77GO(^A25jUDfjjW$7gP3aXq?*dO{6XO&UXb zOoCVSmKAq3W#ZYtXvDC`_3XLx2XJzl%?)FTX3mc`{Qv395vS)hA2cC=7$y{qEpsKN zr)&PT)vjMnXjOLl;&Qlw+cYzn(>sZ#59Q^uQtCiGimR*3_B8KSstm7h;7J&hr!GfRwD^|nOHvI> z`SR!DwMtz;Wfx9jmV5WskKeTqDk=td)z+haJ##jk8t_B3==nCNXVx-nD#=k(&ARJK zc)Ed1%K$~|63dcO`H0%BCq#j5`@G%Vk^uXzUQ^t8}`|UG74o2aL z6dEE)ita3N@i+oeTxG52Jq`telKqv>L>DPK^?WdBOHz#psAyv@gK-hgE6tm4%>X>N zJ@~*4d=A^s)wQO)e9dR?X1A>0Y|FvNHoH|mil3C)!=c=5AN9A_tumPZX{=L!(0=_s zv#v|Dwae7y5+uHuAaryOjM{`YMsLLj55-+hRTo-ipai`1cq<)*R93>RvNzeYuj;qv z{4}ji*`>Q-56$51ZB9XxEeD~h$>IW?xJcjT8bXY?-p*AQT2YjAK=paZYd(j)^zq)T zkEpq2Y(Q{o*i@}lF!iHm$A}&B%YVdf+T#yisYeTya_Y%qX*5M*8ZB=%*L2c6`AwU^kG@)=UF=O;r+JOK2u%_Xm{iS%L0rr7_ zUU83W?E{f$6$kr%wj9xVz7;1g5g6bQH5r|7k4GSU;%oj8?><#up`rv1>xh=86UNl| z{0k+_j86>&wIX3w9sUo-c_wQQ-W5mE#@_75ypW(&~#rR?{)z6>p_l?C7wXXN!Ms;Eew072#0tr42+H psbD Date: Sun, 13 May 2012 19:06:55 +0200 Subject: [PATCH 204/455] MDL-32972 keep gif transparency when processing user avatar images --- lib/gdlib.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/gdlib.php b/lib/gdlib.php index 65e6d5ebd7b..b4e4918713f 100644 --- a/lib/gdlib.php +++ b/lib/gdlib.php @@ -119,6 +119,7 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil $image->height = $imageinfo[1]; $image->type = $imageinfo[2]; + $t = null; switch ($image->type) { case IMAGETYPE_GIF: if (function_exists('imagecreatefromgif')) { @@ -127,6 +128,11 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil debugging('GIF not supported on this server'); return false; } + // Guess transparent colour from GIF. + $transparent = imagecolortransparent($im); + if ($transparent != -1) { + $t = imagecolorsforindex($im, $transparent); + } break; case IMAGETYPE_JPEG: if (function_exists('imagecreatefromjpeg')) { @@ -167,7 +173,17 @@ function process_new_icon($context, $component, $filearea, $itemid, $originalfil $im1 = imagecreatetruecolor(100, 100); $im2 = imagecreatetruecolor(35, 35); $im3 = imagecreatetruecolor(512, 512); - if ($image->type == IMAGETYPE_PNG and $imagefnc === 'imagepng') { + if ($image->type != IMAGETYPE_JPEG and $imagefnc === 'imagepng') { + if ($t) { + // Transparent GIF hacking... + $transparentcolour = imagecolorallocate($im1 , $t['red'] , $t['green'] , $t['blue']); + imagecolortransparent($im1 , $transparentcolour); + $transparentcolour = imagecolorallocate($im2 , $t['red'] , $t['green'] , $t['blue']); + imagecolortransparent($im2 , $transparentcolour); + $transparentcolour = imagecolorallocate($im3 , $t['red'] , $t['green'] , $t['blue']); + imagecolortransparent($im3 , $transparentcolour); + } + imagealphablending($im1, false); $color = imagecolorallocatealpha($im1, 0, 0, 0, 127); imagefill($im1, 0, 0, $color); From fb1ec806c537d83061f2abcd14e1c7a9ea827eb3 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 13 May 2012 22:31:29 +0200 Subject: [PATCH 205/455] MDL-32564 fix admin/timezone.php page setup --- admin/timezone.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin/timezone.php b/admin/timezone.php index 34e1fa40fda..e031be44bbe 100644 --- a/admin/timezone.php +++ b/admin/timezone.php @@ -9,6 +9,9 @@ $zone = clean_param($zone, PARAM_PATH); } + $PAGE->set_url('/admin/timezone.php'); + $PAGE->set_context(context_system::instance()); + require_login(); require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); @@ -18,7 +21,6 @@ $strusers = get_string("users"); $strall = get_string("all"); - $PAGE->set_url('/admin/timezone.php'); $PAGE->set_title($strtimezone); $PAGE->set_heading($strtimezone); $PAGE->navbar->add($strtimezone); From 103f34d88de2055f7ca85f1b27eeea8112563688 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 11 May 2012 21:58:03 +0200 Subject: [PATCH 206/455] MDL-32379 fix forum cron user caching --- mod/forum/lib.php | 136 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 105 insertions(+), 31 deletions(-) diff --git a/mod/forum/lib.php b/mod/forum/lib.php index d3b609e6588..74aaf296322 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -44,6 +44,11 @@ define('FORUM_TRACKING_OFF', 0); define('FORUM_TRACKING_OPTIONAL', 1); define('FORUM_TRACKING_ON', 2); +if (!defined('FORUM_CRON_USER_CACHE')) { + /** Defines how many full user records are cached in forum cron. */ + define('FORUM_CRON_USER_CACHE', 5000); +} + /// STANDARD FUNCTIONS /////////////////////////////////////////////////////////// /** @@ -378,6 +383,28 @@ function forum_get_email_message_id($postid, $usertoid, $hostname) { return '<'.hash('sha256',$postid.'to'.$usertoid.'@'.$hostname).'>'; } +/** + * Removes properties from user record that are not necessary + * for sending post notifications. + * @param stdClass $user + * @return void, $user parameter is modified + */ +function forum_cron_minimise_user_record(stdClass $user) { + + // We store large amount of users in one huge array, + // make sure we do not store info there we do not actually need + // in mail generation code or messaging. + + unset($user->institution); + unset($user->department); + unset($user->address); + unset($user->city); + unset($user->url); + unset($user->currentlogin); + unset($user->description); + unset($user->descriptionformat); +} + /** * Function to be run periodically according to the moodle cron * Finds all posts that have yet to be mailed out, and mails them @@ -397,8 +424,11 @@ function forum_cron() { $site = get_site(); - // all users that are subscribed to any post that needs sending + // All users that are subscribed to any post that needs sending, + // please increase $CFG->extramemorylimit on large sites that + // send notifications to a large number of users. $users = array(); + $userscount = 0; // Cached user counter - count($users) in PHP is horribly slow!!! // status arrays $mailcount = array(); @@ -479,13 +509,23 @@ function forum_cron() { $modcontext = get_context_instance(CONTEXT_MODULE, $coursemodules[$forumid]->id); if ($subusers = forum_subscribed_users($courses[$courseid], $forums[$forumid], 0, $modcontext, "u.*")) { foreach ($subusers as $postuser) { - unset($postuser->description); // not necessary // this user is subscribed to this forum $subscribedusers[$forumid][$postuser->id] = $postuser->id; - // this user is a user we have to process later - $users[$postuser->id] = $postuser; + $userscount++; + if ($userscount > FORUM_CRON_USER_CACHE) { + // Store minimal user info. + $minuser = new stdClass(); + $minuser->id = $postuser->id; + $users[$postuser->id] = $minuser; + } else { + // Cache full user record. + forum_cron_minimise_user_record($postuser); + $users[$postuser->id] = $postuser; + } } - unset($subusers); // release memory + // Release memory. + unset($subusers); + unset($postuser); } } @@ -503,16 +543,23 @@ function forum_cron() { @set_time_limit(120); // terminate if processing of any account takes longer than 2 minutes - // set this so that the capabilities are cached, and environment matches receiving user - cron_setup_user($userto); - mtrace('Processing user '.$userto->id); - // init caches + // Init user caches - we keep the cache for one cycle only, + // otherwise it could consume too much memory. + if (isset($userto->username)) { + $userto = clone($userto); + } else { + $userto = $DB->get_record('user', array('id' => $userto->id)); + forum_cron_minimise_user_record($userto); + } $userto->viewfullnames = array(); $userto->canpost = array(); $userto->markposts = array(); + // set this so that the capabilities are cached, and environment matches receiving user + cron_setup_user($userto); + // reset the caches foreach ($coursemodules as $forumid=>$unused) { $coursemodules[$forumid]->cache = new stdClass(); @@ -544,9 +591,20 @@ function forum_cron() { // Get info about the sending user if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; + if (!isset($userfrom->idnumber)) { + // Minimalised user info, fetch full record. + $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); + forum_cron_minimise_user_record($userfrom); + } + } else if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { - unset($userfrom->description); // not necessary - $users[$userfrom->id] = $userfrom; // fetch only once, we can add it to user list, it will be skipped anyway + forum_cron_minimise_user_record($userfrom); + // Fetch only once if possible, we can add it to user list, it will be skipped anyway. + if ($userscount <= FORUM_CRON_USER_CACHE) { + $userscount++; + $users[$userfrom->id] = $userfrom; + } + } else { mtrace('Could not find user '.$post->userid); continue; @@ -569,10 +627,14 @@ function forum_cron() { if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); - $users[$userfrom->id]->groups = array(); + if (isset($users[$userfrom->id])) { + $users[$userfrom->id]->groups = array(); + } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); - $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; + if (isset($users[$userfrom->id])) { + $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; + } } // Make sure groups allow this user to see this email @@ -678,6 +740,7 @@ function forum_cron() { // mark processed posts as read forum_tp_mark_posts_read($userto, $userto->markposts); + unset($userto); } } @@ -733,15 +796,6 @@ function forum_cron() { $userdiscussions = array(); foreach ($digestposts_rs as $digestpost) { - if (!isset($users[$digestpost->userid])) { - if ($user = $DB->get_record('user', array('id' => $digestpost->userid))) { - $users[$digestpost->userid] = $user; - } else { - continue; - } - } - $postuser = $users[$digestpost->userid]; - if (!isset($posts[$digestpost->postid])) { if ($post = $DB->get_record('forum_posts', array('id' => $digestpost->postid))) { $posts[$digestpost->postid] = $post; @@ -798,17 +852,23 @@ function forum_cron() { // First of all delete all the queue entries for this user $DB->delete_records_select('forum_queue', "userid = ? AND timemodified < ?", array($userid, $digesttime)); - $userto = $users[$userid]; + + // Init user caches - we keep the cache for one cycle only, + // otherwise it would unnecessarily consume memory. + if (array_key_exists($userid, $users) and isset($users[$userid]->username)) { + $userto = clone($users[$userid]); + } else { + $userto = $DB->get_record('user', array('id' => $userid)); + forum_cron_minimise_user_record($userto); + } + $userto->viewfullnames = array(); + $userto->canpost = array(); + $userto->markposts = array(); // Override the language and timezone of the "current" user, so that // mail is customised for the receiver. cron_setup_user($userto); - // init caches - $userto->viewfullnames = array(); - $userto->canpost = array(); - $userto->markposts = array(); - $postsubject = get_string('digestmailsubject', 'forum', format_string($site->shortname, true)); $headerdata = new stdClass(); @@ -881,8 +941,18 @@ function forum_cron() { if (array_key_exists($post->userid, $users)) { // we might know him/her already $userfrom = $users[$post->userid]; + if (!isset($userfrom->idnumber)) { + $userfrom = $DB->get_record('user', array('id' => $userfrom->id)); + forum_cron_minimise_user_record($userfrom); + } + } else if ($userfrom = $DB->get_record('user', array('id' => $post->userid))) { - $users[$userfrom->id] = $userfrom; // fetch only once, we can add it to user list, it will be skipped anyway + forum_cron_minimise_user_record($userfrom); + if ($userscount <= FORUM_CRON_USER_CACHE) { + $userscount++; + $users[$userfrom->id] = $userfrom; + } + } else { mtrace('Could not find user '.$post->userid); continue; @@ -891,10 +961,14 @@ function forum_cron() { if (!isset($userfrom->groups[$forum->id])) { if (!isset($userfrom->groups)) { $userfrom->groups = array(); - $users[$userfrom->id]->groups = array(); + if (isset($users[$userfrom->id])) { + $users[$userfrom->id]->groups = array(); + } } $userfrom->groups[$forum->id] = groups_get_all_groups($course->id, $userfrom->id, $cm->groupingid); - $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; + if (isset($users[$userfrom->id])) { + $users[$userfrom->id]->groups[$forum->id] = $userfrom->groups[$forum->id]; + } } $userfrom->customheaders = array ("Precedence: Bulk"); From 65f78adf42323a7f12cdad1a6071f78552e5cdcf Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 19 May 2012 20:48:48 +0200 Subject: [PATCH 207/455] MDL-27575 use new skype call URI As described in official Skype page at http://www.skype.com/intl/en-us/tell-a-friend/get-a-skype-button/ --- user/profile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user/profile.php b/user/profile.php index 989702e7aaa..80dcdd9d469 100644 --- a/user/profile.php +++ b/user/profile.php @@ -280,7 +280,7 @@ if ($user->icq && !isset($hiddenfields['icqnumber'])) { } if ($user->skype && !isset($hiddenfields['skypeid'])) { - print_row(get_string('skypeid').':',''.s($user->skype). + print_row(get_string('skypeid').':',''.s($user->skype). ' '.get_string('status').''); } From b3d5a51a8d0b65722c22acc211c15132a1b3d8ec Mon Sep 17 00:00:00 2001 From: Mary Evans Date: Sun, 20 May 2012 01:15:25 +0100 Subject: [PATCH 208/455] MDL-33110 themes: removed redundent boilerplate.css from Boxxie and all layout files from Serenity. --- theme/boxxie/style/boilerplate.css | 147 ---------------------------- theme/serenity/layout/embedded.php | 23 ----- theme/serenity/layout/frontpage.php | 117 ---------------------- theme/serenity/layout/general.php | 121 ----------------------- 4 files changed, 408 deletions(-) delete mode 100644 theme/boxxie/style/boilerplate.css delete mode 100644 theme/serenity/layout/embedded.php delete mode 100644 theme/serenity/layout/frontpage.php delete mode 100644 theme/serenity/layout/general.php diff --git a/theme/boxxie/style/boilerplate.css b/theme/boxxie/style/boilerplate.css deleted file mode 100644 index 3bf99fc640b..00000000000 --- a/theme/boxxie/style/boilerplate.css +++ /dev/null @@ -1,147 +0,0 @@ -/* -------------------------------------------------------------- - - Boilerplate reset.css - * Resets default browser CSS. - --------------------------------------------------------------- */ - -html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } -body { line-height: 1.5; background: #fff; margin: 0; } -table { border-collapse: collapse; border-spacing: 0; } -caption, th, td { text-align: left; font-weight:400; } -blockquote:before, blockquote:after, q:before, q:after { content: ""; } -blockquote, q { quotes: "" ""; } -a img { border: none; } -input,textarea { margin: 0; } - -/* Removes Firefox imposed outline */ -a { outline: none; } - -/* Clearing floats without extra markup */ -.wrapper { display: inline-block; } -.wrapper:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -* html .wrapper { height: 1%; } -.wrapper { display: block; } - -/* -------------------------------------------------------------- - - Boilerplate typography.css - * Sets up some sensible default typography. - --------------------------------------------------------------- */ - -/* This is where you set your desired font size. The line-heights - and vertical margins are automatically calculated from this. - The percentage is of 16px (0.75 * 16px = 12px). */ -body { font-size: 85%; } - - -/* Default fonts and colors. */ -body,h1,h2,h3,h4,h5,h6,p,ul,ol,dl,input,textarea { font-family: Helvetica, Arial, sans-serif; } - - -/* Headings --------------------------------------------------------------- */ - -h1,h2,h3,h4,h5,h6 { font-weight: bold; } - -h1 { font-size: 2.25em; line-height: 1; margin-bottom: 0.5em; } -h2 { font-size: 1.75em; margin-bottom: 0.5em; } -h3 { font-size: 1.5em; line-height: 1; margin-bottom: 1em; } -h4 { font-size: 1.2em; line-height: 1.25; margin-bottom: 1em; } -h5 { font-size: 1em; margin-bottom: 1.5em; } -h6 { font-size: 1em; } - - -/* Text elements --------------------------------------------------------------- */ - -p { margin: 0 0 1em; } - -ul, ol { margin: 0 1.5em 1.5em 1.5em; } -ul { list-style-type: circle; } -ol { list-style-type: decimal; } - -dl { margin: 0 0 1.5em 0; } -dl dt { font-weight: bold; } -dl dd { margin-left: 1.5em; } - -abbr, acronym { border-bottom: 1px dotted #000; } -address { margin-top: 1.5em; font-style: italic; } -del { color: #000; } - -a { color: #009; text-decoration: none; } -a:hover { text-decoration: underline; } - -blockquote { margin: 1.5em; } -strong { font-weight: bold; } -em, dfn { font-style: italic; } -dfn { font-weight: bold; } -pre, code { margin: 1.5em 0; white-space: pre; } -pre, code, tt { font: 1.2em monospace; line-height: 1.5; } -tt { display: block; margin: 1.5em 0; line-height: 1.5; } - - -/* Tables --------------------------------------------------------------- */ - -th { border-bottom: 2px solid #ddd; font-weight: bold; } -th,td { padding: 4px;vertical-align: middle } -tfoot { font-style: italic; } -caption { background: #ffc; } - - -/* Some default classes --------------------------------------------------------------- */ - -.small { font-size: .8em; margin-bottom: 1.875em; line-height: 1.875em; } -.large { font-size: 1.25em; line-height:1.5em; margin-bottom: 1em; } -.quiet { color: #999; } - -.hide { display: none; } -.highlight { background: #ffc; } - -.top { margin-top: 0; padding-top: 0; } -.bottom { margin-bottom: 0; padding-bottom: 0; } - -/* -------------------------------------------------------------- - - Boilerplate forms.css - * Sets up some default styling for forms - --------------------------------------------------------------- */ - -label { font-weight: bold; } - -/* Fieldsets */ -fieldset { padding: 1.4em; margin: 0 0 1.5em 0; border: 1px solid #ddd; } -legend { padding: 0 .4em; font-weight: bold; font-size: 1.2em; } - -/* Textareas */ -textarea { margin: 0.5em 0.5em 0 0; } -textarea { padding: .4em; } - - -/* hForm --------------------------------------------------------------- */ -form.hform p { margin: 0 0 .5em; } -form.hform p label { float: left; width: 100px; } - -form.hform p input { width: 200px; } -form.hform p select { width: 200px; } - -form.hform p input.button { width: auto; } -form.hform p input.checkbox { width: auto; } -form.hform p input.radio { width: auto; } - -form.hform p.checkbox { margin-left: 100px; } -form.hform p.checkbox label { float: none; } -form.hform p.checkbox input { width: auto; } - - -/* vForm --------------------------------------------------------------- */ -form.vform p { margin: 0 0 .5em; } -form.vform p label { display: block; } - -form.vform p.checkbox label { display: inline; } diff --git a/theme/serenity/layout/embedded.php b/theme/serenity/layout/embedded.php deleted file mode 100644 index 9d39e027491..00000000000 --- a/theme/serenity/layout/embedded.php +++ /dev/null @@ -1,23 +0,0 @@ -doctype() ?> -htmlattributes() ?>> - - <?php echo $PAGE->title ?> - - standard_head_html() ?> - - -standard_top_of_body_html() ?> - -
                            - - - -
                            - main_content() ?> -
                            - - -
                            -standard_end_of_body_html() ?> - - \ No newline at end of file diff --git a/theme/serenity/layout/frontpage.php b/theme/serenity/layout/frontpage.php deleted file mode 100644 index 3c21eaaa6b7..00000000000 --- a/theme/serenity/layout/frontpage.php +++ /dev/null @@ -1,117 +0,0 @@ -layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT)); -$hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); - -$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT)); -$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); -$custommenu = $OUTPUT->custom_menu(); -$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); - -$bodyclasses = array(); -if ($showsidepre && !$showsidepost) { - $bodyclasses[] = 'side-pre-only'; -} else if ($showsidepost && !$showsidepre) { - $bodyclasses[] = 'side-post-only'; -} else if (!$showsidepost && !$showsidepre) { - $bodyclasses[] = 'content-only'; -} -if ($hassidepre || $hassidepost) { - $bodyclasses[] = 'background'; -} -if ($hascustommenu) { - $bodyclasses[] = 'has_custom_menu'; -} - -echo $OUTPUT->doctype() ?> -htmlattributes() ?>> - - <?php echo $PAGE->title ?> - - - standard_head_html() ?> - - -standard_top_of_body_html() ?> - -
                            -
                            - - - - - -
                            - - - - - -
                            -
                            -
                            -
                            - -
                            -
                            -
                            - main_content() ?> -
                            -
                            -
                            - - -
                            -
                            - blocks_for_region('side-pre') ?> -
                            -
                            - - - -
                            -
                            - blocks_for_region('side-post') ?> -
                            -
                            - - -
                            -
                            -
                            -
                            - - - -
                            - - - - - - -
                            -standard_end_of_body_html() ?> - - diff --git a/theme/serenity/layout/general.php b/theme/serenity/layout/general.php deleted file mode 100644 index 3c454f3e470..00000000000 --- a/theme/serenity/layout/general.php +++ /dev/null @@ -1,121 +0,0 @@ -heading); -$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar()); -$hasfooter = (empty($PAGE->layout_options['nofooter'])); -$hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT)); -$hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT)); - -$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT)); -$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT)); -$custommenu = $OUTPUT->custom_menu(); -$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu)); - -$bodyclasses = array(); -if ($showsidepre && !$showsidepost) { - $bodyclasses[] = 'side-pre-only'; -} else if ($showsidepost && !$showsidepre) { - $bodyclasses[] = 'side-post-only'; -} else if (!$showsidepost && !$showsidepre) { - $bodyclasses[] = 'content-only'; -} -if ($hascustommenu) { - $bodyclasses[] = 'has_custom_menu'; -} -echo $OUTPUT->doctype() ?> -htmlattributes() ?>> - - <?php echo $PAGE->title ?> - - standard_head_html() ?> - - -standard_top_of_body_html() ?> - -
                            -
                            - - - - - -
                            - - - - - - - - - - -
                            -
                            -
                            -
                            - -
                            -
                            -
                            - main_content() ?> -
                            -
                            -
                            - - -
                            -
                            - blocks_for_region('side-pre') ?> -
                            -
                            - - - -
                            -
                            - blocks_for_region('side-post') ?> -
                            -
                            - - -
                            -
                            -
                            -
                            - -
                            - - - - - -
                            -standard_end_of_body_html() ?> - - From 5429460127cfb193f31926fa60d6189d195461bd Mon Sep 17 00:00:00 2001 From: Vadim Dvorovenko Date: Wed, 16 May 2012 18:48:45 +0700 Subject: [PATCH 209/455] MDL-26562 --- mod/forum/lang/en/forum.php | 4 ++-- mod/forum/lib.php | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mod/forum/lang/en/forum.php b/mod/forum/lang/en/forum.php index 48e5d76a925..b078a6d90d3 100644 --- a/mod/forum/lang/en/forum.php +++ b/mod/forum/lang/en/forum.php @@ -300,8 +300,8 @@ $string['oldpostdays'] = 'Read after days'; $string['openmode0'] = 'No discussions, no replies'; $string['openmode1'] = 'No discussions, but replies are allowed'; $string['openmode2'] = 'Discussions and replies are allowed'; -$string['overviewnumpostssince'] = 'posts since last login'; -$string['overviewnumunread'] = 'total unread'; +$string['overviewnumpostssince'] = '{$a} posts since last login'; +$string['overviewnumunread'] = '{$a} total unread'; $string['page-mod-forum-x'] = 'Any forum module page'; $string['page-mod-forum-view'] = 'Forum module main page'; $string['page-mod-forum-discuss'] = 'Forum module discussion thread page'; diff --git a/mod/forum/lib.php b/mod/forum/lib.php index d3b609e6588..c778e0a528d 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -1306,8 +1306,6 @@ function forum_print_overview($courses,&$htmlarray) { } $strforum = get_string('modulename','forum'); - $strnumunread = get_string('overviewnumunread','forum'); - $strnumpostssince = get_string('overviewnumpostssince','forum'); foreach ($forums as $forum) { $str = ''; @@ -1326,9 +1324,9 @@ function forum_print_overview($courses,&$htmlarray) { $str .= '
                            '.$strforum.': '. $forum->name.'
                            '; $str .= '
                            '; - $str .= $count.' '.$strnumpostssince.""; + $str .= get_string('overviewnumpostssince', 'forum', $count).""; if (!empty($showunread)) { - $str .= '
                            '.$thisunread .' '.$strnumunread.'
                            '; + $str .= '
                            '.get_string('overviewnumunread', 'forum', $thisunread).'
                            '; } $str .= '
                            '; } From 3542c4f4a9f814d08b7ca643304ef2d771169210 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Tue, 1 May 2012 00:44:06 +0200 Subject: [PATCH 210/455] MDL-32709 book: general comments and phpdocs cleanup --- mod/book/backup/moodle1/lib.php | 3 +- .../backup_book_activity_task.class.php | 9 +-- .../moodle2/backup_book_settingslib.php | 5 +- .../backup/moodle2/backup_book_stepslib.php | 7 +- .../restore_book_activity_task.class.php | 11 +-- .../backup/moodle2/restore_book_stepslib.php | 12 ++- mod/book/db/access.php | 7 +- mod/book/db/log.php | 7 +- mod/book/db/subplugins.php | 9 +-- mod/book/db/upgrade.php | 23 +++--- mod/book/db/upgradelib.php | 30 +++---- mod/book/delete.php | 19 +++-- mod/book/edit.php | 13 ++-- mod/book/edit_form.php | 6 +- mod/book/index.php | 11 ++- mod/book/lang/en/book.php | 5 +- mod/book/lib.php | 62 ++++++++------- mod/book/locallib.php | 52 ++++++++++--- mod/book/mod_form.php | 9 +-- mod/book/move.php | 35 ++++----- mod/book/settings.php | 10 +-- mod/book/show.php | 12 ++- mod/book/tool/exportimscp/db/access.php | 5 +- mod/book/tool/exportimscp/index.php | 5 +- .../lang/en/booktool_exportimscp.php | 7 +- mod/book/tool/exportimscp/lib.php | 15 ++-- mod/book/tool/exportimscp/locallib.php | 27 +++++-- mod/book/tool/exportimscp/version.php | 5 +- mod/book/tool/importhtml/db/access.php | 5 +- mod/book/tool/importhtml/import_form.php | 7 +- mod/book/tool/importhtml/index.php | 9 +-- .../lang/en/booktool_importhtml.php | 5 +- mod/book/tool/importhtml/lib.php | 15 ++-- mod/book/tool/importhtml/locallib.php | 78 ++++++++++++++++--- mod/book/tool/importhtml/version.php | 5 +- mod/book/tool/print/db/access.php | 5 +- mod/book/tool/print/index.php | 24 +++--- .../tool/print/lang/en/booktool_print.php | 5 +- mod/book/tool/print/lib.php | 21 +++-- mod/book/tool/print/locallib.php | 11 ++- mod/book/tool/print/version.php | 5 +- mod/book/version.php | 5 +- mod/book/view.php | 31 ++++---- 43 files changed, 372 insertions(+), 280 deletions(-) diff --git a/mod/book/backup/moodle1/lib.php b/mod/book/backup/moodle1/lib.php index 9d4dcc9ab93..5a5852603f5 100755 --- a/mod/book/backup/moodle1/lib.php +++ b/mod/book/backup/moodle1/lib.php @@ -17,8 +17,7 @@ /** * Provides support for the conversion of moodle1 backup to the moodle2 format * - * @package mod - * @subpackage book + * @package mod_book * @copyright 2011 Tõnis Tartes * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/backup/moodle2/backup_book_activity_task.class.php b/mod/book/backup/moodle2/backup_book_activity_task.class.php index 04b78098a11..e6b2b82a1b2 100644 --- a/mod/book/backup/moodle2/backup_book_activity_task.class.php +++ b/mod/book/backup/moodle2/backup_book_activity_task.class.php @@ -17,9 +17,8 @@ /** * Description of book backup task * - * @package mod - * @subpackage book - * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,10 +27,6 @@ defined('MOODLE_INTERNAL') || die; require_once($CFG->dirroot.'/mod/book/backup/moodle2/backup_book_stepslib.php'); // Because it exists (must) require_once($CFG->dirroot.'/mod/book/backup/moodle2/backup_book_settingslib.php'); // Because it exists (optional) -/** - * book backup task that provides all the settings and steps to perform one - * complete backup of the activity - */ class backup_book_activity_task extends backup_activity_task { /** diff --git a/mod/book/backup/moodle2/backup_book_settingslib.php b/mod/book/backup/moodle2/backup_book_settingslib.php index 58157d1e393..f52d803ec8b 100644 --- a/mod/book/backup/moodle2/backup_book_settingslib.php +++ b/mod/book/backup/moodle2/backup_book_settingslib.php @@ -17,9 +17,8 @@ /** * Description of book backup settings * - * @package mod - * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/backup/moodle2/backup_book_stepslib.php b/mod/book/backup/moodle2/backup_book_stepslib.php index e10e3426e62..27f1c89099b 100644 --- a/mod/book/backup/moodle2/backup_book_stepslib.php +++ b/mod/book/backup/moodle2/backup_book_stepslib.php @@ -17,16 +17,15 @@ /** * Define all the backup steps that will be used by the backup_book_activity_task * - * @package mod - * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; /** - * Define the complete book structure for backup, with file and id annotations + * Structure step to backup one book activity */ class backup_book_activity_structure_step extends backup_activity_structure_step { diff --git a/mod/book/backup/moodle2/restore_book_activity_task.class.php b/mod/book/backup/moodle2/restore_book_activity_task.class.php index 180615e2fcc..bbe9b4af08b 100644 --- a/mod/book/backup/moodle2/restore_book_activity_task.class.php +++ b/mod/book/backup/moodle2/restore_book_activity_task.class.php @@ -15,11 +15,10 @@ // along with Moodle. If not, see . /** - * Define all the restore tasks + * Description of book restore task * - * @package mod - * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,10 +26,6 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/book/backup/moodle2/restore_book_stepslib.php'); // Because it exists (must) -/** - * book restore task that provides all the settings and steps to perform one - * complete restore of the activity - */ class restore_book_activity_task extends restore_activity_task { /** diff --git a/mod/book/backup/moodle2/restore_book_stepslib.php b/mod/book/backup/moodle2/restore_book_stepslib.php index 021716a8982..05fbd132d0c 100644 --- a/mod/book/backup/moodle2/restore_book_stepslib.php +++ b/mod/book/backup/moodle2/restore_book_stepslib.php @@ -17,9 +17,9 @@ /** * Define all the restore steps that will be used by the restore_book_activity_task * - * @package mod + * @package mod_book * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -39,6 +39,10 @@ class restore_book_activity_structure_step extends restore_activity_structure_st return $this->prepare_activity_structure($paths); } + /** + * Process book tag information + * @param array $data information + */ protected function process_book($data) { global $DB; @@ -50,6 +54,10 @@ class restore_book_activity_structure_step extends restore_activity_structure_st $this->apply_activity_instance($newitemid); } + /** + * Process chapter tag information + * @param array $data information + */ protected function process_book_chapter($data) { global $DB; diff --git a/mod/book/db/access.php b/mod/book/db/access.php index 378b3c5d5c8..d831e3bfad5 100644 --- a/mod/book/db/access.php +++ b/mod/book/db/access.php @@ -17,12 +17,13 @@ /** * Book module capability definition * - * @package mod - * @subpackage book - * @copyright 2009-2012 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2009-2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + $capabilities = array( 'mod/book:addinstance' => array( diff --git a/mod/book/db/log.php b/mod/book/db/log.php index c83481abe80..979f58e8e03 100644 --- a/mod/book/db/log.php +++ b/mod/book/db/log.php @@ -15,11 +15,10 @@ // along with Moodle. If not, see . /** - * Definition of log events + * Book module log events definition * - * @package mod - * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/db/subplugins.php b/mod/book/db/subplugins.php index 7a0979d09e6..e3e2e90a47f 100644 --- a/mod/book/db/subplugins.php +++ b/mod/book/db/subplugins.php @@ -15,10 +15,9 @@ // along with Moodle. If not, see . /** - * Book subplugin types declaration + * Book module subplugin types declaration * - * @package mod - * @subpackage book + * @package mod_book * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -26,5 +25,5 @@ defined('MOODLE_INTERNAL') || die(); $subplugins = array( - 'booktool' => 'mod/book/tool', - ); + 'booktool' => 'mod/book/tool', +); diff --git a/mod/book/db/upgrade.php b/mod/book/db/upgrade.php index d1314998e9d..9e3d3d38726 100644 --- a/mod/book/db/upgrade.php +++ b/mod/book/db/upgrade.php @@ -17,14 +17,19 @@ /** * Book module upgrade code * - * @package mod - * @subpackage book - * @copyright 2009-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2009-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; +/** + * Book module upgrade task + * + * @param int $oldversion the version we are upgrading from + * @return bool always true + */ function xmldb_book_upgrade($oldversion) { global $CFG, $DB; @@ -36,20 +41,20 @@ function xmldb_book_upgrade($oldversion) { if ($oldversion < 2007052001) { - /// Changing type of field importsrc on table book_chapters to char + // Changing type of field importsrc on table book_chapters to char $table = new xmldb_table('book_chapters'); $field = new xmldb_field('importsrc', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'timemodified'); - /// Launch change of type for field importsrc + // Launch change of type for field importsrc $dbman->change_field_type($table, $field); upgrade_mod_savepoint(true, 2007052001, 'book'); } -//===== 1.9.0 upgrade line ======// +// 1.9.0 upgrade line. if ($oldversion < 2010120801) { - // Rename field summary on table book to intro + // Rename field summary on table book to intro $table = new xmldb_table('book'); $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'name'); @@ -63,7 +68,7 @@ function xmldb_book_upgrade($oldversion) { } if ($oldversion < 2010120802) { - // Rename field summary on table book to intro + // Rename field summary on table book to intro $table = new xmldb_table('book'); $field = new xmldb_field('intro', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'name'); @@ -84,7 +89,7 @@ function xmldb_book_upgrade($oldversion) { $dbman->add_field($table, $field); } - // conditionally migrate to html format in intro + // Conditionally migrate to html format in intro if ($CFG->texteditors !== 'textarea') { $rs = $DB->get_recordset('book', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat'); foreach ($rs as $b) { diff --git a/mod/book/db/upgradelib.php b/mod/book/db/upgradelib.php index dcf49d6e917..7a610e63d6a 100644 --- a/mod/book/db/upgradelib.php +++ b/mod/book/db/upgradelib.php @@ -15,11 +15,10 @@ // along with Moodle. If not, see . /** - * Resource module upgrade related helper functions + * Book module upgrade related helper functions * - * @package mod - * @subpackage book - * @copyright 2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -73,7 +72,7 @@ function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) { $filename = clean_param($item->getFilename(), PARAM_FILE); if ($filename === '') { - //unsupported chars, sorry + // unsupported chars, sorry unset($item); // release file handle continue; } @@ -94,7 +93,7 @@ function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) { @unlink($oldpathname); } else { - //migrate recursively all subdirectories + // migrate recursively all subdirectories $oldpathname = $base.$item->getFilename().'/'; $subpath = $path.$item->getFilename().'/'; unset($item); // release file handle @@ -102,7 +101,7 @@ function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) { @rmdir($oldpathname); // deletes dir if empty } } - unset($items); //release file handles + unset($items); // release file handles } /** @@ -130,14 +129,15 @@ function mod_book_migrate_all_areas() { /** * Migrate one area, this should be probably part of moodle core... - * @param $record - * @param $field - * @param $table - * @param $courseid - * @param $context - * @param $component - * @param $filearea - * @param $itemid + * + * @param stdClass $record object to migrate files (book, chapter) + * @param string $field field in the record we are going to migrate + * @param string $table DB table containing the information to migrate + * @param int $courseid id of the course the book module belongs to + * @param context_module $context context of the book module + * @param string $component component to be used for the migrated files + * @param string $filearea filearea to be used for the migrated files + * @param int $itemid id to be used for the migrated files * @return void */ function mod_book_migrate_area($record, $field, $table, $courseid, $context, $component, $filearea, $itemid) { diff --git a/mod/book/delete.php b/mod/book/delete.php index 7fb9b978a86..694505fcd6d 100644 --- a/mod/book/delete.php +++ b/mod/book/delete.php @@ -17,9 +17,8 @@ /** * Delete book chapter * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -45,15 +44,15 @@ $PAGE->set_url('/mod/book/delete.php', array('id'=>$id, 'chapterid'=>$chapterid) $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); -///header and strings +// Header and strings. $PAGE->set_title(format_string($book->name)); $PAGE->add_body_class('mod_book'); $PAGE->set_heading(format_string($course->fullname)); -///form processing +// Form processing. if ($confirm) { // the operation was confirmed. $fs = get_file_storage(); - if (!$chapter->subchapter) { //delete all its subchapters if any + if (!$chapter->subchapter) { // Delete all its sub-chapters if any $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter'); $found = false; foreach($chapters as $ch) { @@ -73,7 +72,7 @@ if ($confirm) { // the operation was confirmed. add_to_log($course->id, 'course', 'update mod', '../mod/book/view.php?id='.$cm->id, 'book '.$book->id); add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id, $book->id, $cm->id); - book_preload_chapters($book); //fix structure + book_preload_chapters($book); // Fix structure. $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id)); redirect('view.php?id='.$cm->id); @@ -81,11 +80,11 @@ if ($confirm) { // the operation was confirmed. echo $OUTPUT->header(); -// the operation has not been confirmed yet so ask the user to do so +// The operation has not been confirmed yet so ask the user to do so. if ($chapter->subchapter) { - $strconfirm = get_string('confchapterdelete','mod_book'); + $strconfirm = get_string('confchapterdelete', 'mod_book'); } else { - $strconfirm = get_string('confchapterdeleteall','mod_book'); + $strconfirm = get_string('confchapterdeleteall', 'mod_book'); } echo '
                            '; $continue = new moodle_url('/mod/book/delete.php', array('id'=>$cm->id, 'chapterid'=>$chapter->id, 'confirm'=>1)); diff --git a/mod/book/edit.php b/mod/book/edit.php index 1957003bccb..c0710f04477 100644 --- a/mod/book/edit.php +++ b/mod/book/edit.php @@ -17,9 +17,8 @@ /** * Edit book chapter * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -42,7 +41,7 @@ $context = get_context_instance(CONTEXT_MODULE, $cm->id); require_capability('mod/book:edit', $context); $PAGE->set_url('/mod/book/edit.php', array('cmid'=>$cmid, 'id'=>$chapterid, 'pagenum'=>$pagenum, 'subchapter'=>$subchapter)); -$PAGE->set_pagelayout('admin'); //this is a bloody hack! +$PAGE->set_pagelayout('admin'); // TODO: Something. This is a bloody hack! if ($chapterid) { $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); @@ -59,7 +58,7 @@ $chapter = file_prepare_standard_editor($chapter, 'content', $options, $context, $mform = new book_chapter_edit_form(null, array('chapter'=>$chapter, 'options'=>$options)); -/// If data submitted, then process and store. +// If data submitted, then process and store. if ($mform->is_cancelled()) { if (empty($chapter->id)) { redirect("view.php?id=$cm->id"); @@ -78,7 +77,7 @@ if ($mform->is_cancelled()) { add_to_log($course->id, 'book', 'update', 'view.php?id='.$cm->id.'&chapterid='.$data->id, $book->id, $cm->id); } else { - /// adding new chapter + // adding new chapter $data->bookid = $book->id; $data->hidden = 0; $data->timecreated = time(); @@ -108,7 +107,7 @@ if ($mform->is_cancelled()) { redirect("view.php?id=$cm->id&chapterid=$data->id"); } -/// Otherwise fill and print the form. +// Otherwise fill and print the form. $PAGE->set_title(format_string($book->name)); $PAGE->add_body_class('mod_book'); $PAGE->set_heading(format_string($course->fullname)); diff --git a/mod/book/edit_form.php b/mod/book/edit_form.php index ffa942da4d5..ca1e54fb27e 100644 --- a/mod/book/edit_form.php +++ b/mod/book/edit_form.php @@ -17,9 +17,8 @@ /** * Chapter edit form * - * @package mod - * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -58,7 +57,6 @@ class book_chapter_edit_form extends moodleform { $mform->addElement('hidden', 'pagenum'); $mform->setType('pagenum', PARAM_INT); - $this->add_action_buttons(true); // set the defaults diff --git a/mod/book/index.php b/mod/book/index.php index 64d23dae27d..abe89f381fe 100644 --- a/mod/book/index.php +++ b/mod/book/index.php @@ -17,16 +17,15 @@ /** * This page lists all the instances of book in a particular course * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require(dirname(__FILE__).'/../../config.php'); require_once(dirname(__FILE__).'/locallib.php'); -$id = required_param('id', PARAM_INT); // Course Module ID +$id = required_param('id', PARAM_INT); // Course ID. $course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST); @@ -35,7 +34,7 @@ unset($id); require_course_login($course, true); $PAGE->set_pagelayout('incourse'); -/// Get all required strings +// Get all required strings $strbooks = get_string('modulenameplural', 'mod_book'); $strbook = get_string('modulename', 'mod_book'); $strsectionname = get_string('sectionname', 'format_'.$course->format); @@ -51,7 +50,7 @@ echo $OUTPUT->header(); add_to_log($course->id, 'book', 'view all', 'index.php?id='.$course->id, ''); -/// Get all the appropriate data +// Get all the appropriate data if (!$books = get_all_instances_in_course('book', $course)) { notice(get_string('thereareno', 'moodle', $strbooks), "$CFG->wwwroot/course/view.php?id=$course->id"); die; diff --git a/mod/book/lang/en/book.php b/mod/book/lang/en/book.php index a6a246c0c7c..acbced657c2 100644 --- a/mod/book/lang/en/book.php +++ b/mod/book/lang/en/book.php @@ -17,9 +17,8 @@ /** * Book module language strings * - * @package mod - * @subpackage book - * @copyright 2004-2012 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/lib.php b/mod/book/lib.php index 759105129af..849adeeba08 100644 --- a/mod/book/lib.php +++ b/mod/book/lib.php @@ -17,9 +17,8 @@ /** * Book module core interaction API * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -33,10 +32,12 @@ function book_get_numbering_types() { global $CFG; // required for the include require_once(dirname(__FILE__).'/locallib.php'); - return array (BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), - BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), - BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), - BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') ); + return array ( + BOOK_NUM_NONE => get_string('numbering0', 'mod_book'), + BOOK_NUM_NUMBERS => get_string('numbering1', 'mod_book'), + BOOK_NUM_BULLETS => get_string('numbering2', 'mod_book'), + BOOK_NUM_INDENTED => get_string('numbering3', 'mod_book') + ); } /** @@ -144,10 +145,10 @@ function book_user_outline($course, $user, $mod, $book) { * Print a detailed representation of what a user has done with * a given particular instance of this module, for user activity reports. * - * @param $course - * @param $user - * @param $mod - * @param $book + * @param stdClass $course + * @param stdClass $user + * @param stdClass $mod + * @param stdClass $book * @return bool */ function book_user_complete($course, $user, $mod, $book) { @@ -157,13 +158,13 @@ function book_user_complete($course, $user, $mod, $book) { /** * Given a course and a time, this module should find recent activity * that has occurred in book activities and print it out. - * Return true if there was output, or false is there was none. - * @param $course - * @param $isteacher - * @param $timestart - * @return bool + * + * @param stdClass $course + * @param bool $viewfullnames + * @param int $timestart + * @return bool true if there was output, or false is there was none */ -function book_print_recent_activity($course, $isteacher, $timestart) { +function book_print_recent_activity($course, $viewfullnames, $timestart) { return false; // True if anything was printed, otherwise false } @@ -179,18 +180,25 @@ function book_cron () { /** * No grading in book. * - * @param $bookid + * @param int $bookid * @return null */ function book_grades($bookid) { return null; } +/** + * Returns the users with data in one book + * + * @todo deprecated - to be deleted in 2.2 + * @param int $bookid + * @return array + */ function book_get_participants($bookid) { - //Must return an array of user records (all data) who are participants - //for a given instance of book. Must include every user involved - //in the instance, independent of his role (student, teacher, admin...) - //See other modules as example. + // Must return an array of user records (all data) who are participants + // for a given instance of book. Must include every user involved + // in the instance, independent of his role (student, teacher, admin...) + // See other modules as example. return false; } @@ -201,8 +209,8 @@ function book_get_participants($bookid) { * modified if necessary. See book, glossary or journal modules * as reference. * - * @param $bookid int - * @param $scaleid int + * @param int $bookid + * @param int $scaleid * @return boolean True if the scale is used by any journal */ function book_scale_used($bookid,$scaleid) { @@ -214,8 +222,8 @@ function book_scale_used($bookid,$scaleid) { * * This is used to find out if scale used anywhere * - * @param $scaleid int - * @return boolean True if the scale is used by any journal + * @param int $scaleid + * @return bool true if the scale is used by any book */ function book_scale_used_anywhere($scaleid) { return false; @@ -380,7 +388,7 @@ function book_get_file_info($browser, $areas, $course, $cm, $context, $filearea, require_once("$CFG->dirroot/mod/book/locallib.php"); if (is_null($itemid)) { - return new book_file_info($browser, $course, $cm, $context, $areas, $filearea, $itemid); + return new book_file_info($browser, $course, $cm, $context, $areas, $filearea); } $fs = get_file_storage(); diff --git a/mod/book/locallib.php b/mod/book/locallib.php index 5cfc7bc0816..8fcade9a7ff 100644 --- a/mod/book/locallib.php +++ b/mod/book/locallib.php @@ -17,9 +17,8 @@ /** * Book module local lib functions * - * @package mod - * @subpackage book - * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -124,6 +123,15 @@ function book_preload_chapters($book) { return $chapters; } +/** + * Returns the title for a given chapter + * + * @param int $chid + * @param array $chapters + * @param stdClass $book + * @param context_module $context + * @return string + */ function book_get_chapter_title($chid, $chapters, $book, $context) { $ch = $chapters[$chid]; $title = trim(format_string($ch->title, true, array('context'=>$context))); @@ -165,6 +173,15 @@ function book_log($str1, $str2, $level = 0) { } } +/** + * Add the book TOC sticky block to the 1st region available + * + * @param array $chapters + * @param stdClass $chapter + * @param stdClass $book + * @param stdClass $cm + * @param bool $edit + */ function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { global $OUTPUT, $PAGE; @@ -199,9 +216,9 @@ function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { function book_get_toc($chapters, $chapter, $book, $cm, $edit) { global $USER, $OUTPUT; - $toc = ''; //representation of toc (HTML) - $nch = 0; //chapter number - $ns = 0; //subchapter number + $toc = ''; // Representation of toc (HTML) + $nch = 0; // Chapter number + $ns = 0; // Subchapter number $first = 1; $context = get_context_instance(CONTEXT_MODULE, $cm->id); @@ -222,7 +239,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { } - if ($edit) { ///teacher's TOC + if ($edit) { // Teacher's TOC $toc .= '
                              '; $i = 0; foreach($chapters as $ch) { @@ -282,7 +299,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { $first = 0; } $toc .= '
                          '; - } else { //normal students view + } else { // Normal students view $toc .= '
                            '; foreach($chapters as $ch) { $title = trim(format_string($ch->title, true, array('context'=>$context))); @@ -315,7 +332,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { $toc .= ''; - $toc = str_replace('
                              ', '', $toc); //cleanup of invalid structures + $toc = str_replace('
                                ', '', $toc); // Cleanup of invalid structures. return $toc; } @@ -323,13 +340,30 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) { /** * File browsing support class + * + * @copyright 2010-2011 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class book_file_info extends file_info { + /** @var stdClass Course object */ protected $course; + /** @var stdClass Course module object */ protected $cm; + /** @var array Available file areas */ protected $areas; + /** @var string File area to browse */ protected $filearea; + /** + * Constructor + * + * @param file_browser $browser file_browser instance + * @param stdClass $course course object + * @param stdClass $cm course module object + * @param stdClass $context module context + * @param array $areas available file areas + * @param string $filearea file area to browse + */ public function __construct($browser, $course, $cm, $context, $areas, $filearea) { parent::__construct($browser, $context); $this->course = $course; diff --git a/mod/book/mod_form.php b/mod/book/mod_form.php index 1a5c6ec85a5..cd7934ed489 100644 --- a/mod/book/mod_form.php +++ b/mod/book/mod_form.php @@ -17,9 +17,8 @@ /** * Instance add/edit form * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -37,7 +36,6 @@ class mod_book_mod_form extends moodleform_mod { $config = get_config('book'); -//------------------------------------------------------------------------------- $mform->addElement('header', 'general', get_string('general', 'form')); $mform->addElement('text', 'name', get_string('name'), array('size'=>'64')); @@ -49,7 +47,6 @@ class mod_book_mod_form extends moodleform_mod { $mform->addRule('name', null, 'required', null, 'client'); $this->add_intro_editor($config->requiremodintro, get_string('summary')); - $alloptions = book_get_numbering_types(); $allowed = explode(',', $config->numberingoptions); $options = array(); @@ -73,10 +70,8 @@ class mod_book_mod_form extends moodleform_mod { $mform->addHelpButton('customtitles', 'customtitles', 'mod_book'); $mform->setDefault('customtitles', 0); -//------------------------------------------------------------------------------- $this->standard_coursemodule_elements(); -//------------------------------------------------------------------------------- $this->add_action_buttons(); } diff --git a/mod/book/move.php b/mod/book/move.php index 6a2011dc715..7ae9b118713 100644 --- a/mod/book/move.php +++ b/mod/book/move.php @@ -17,9 +17,8 @@ /** * Move book chapter * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -62,13 +61,13 @@ foreach ($oldchapters as $ch) { $chs = $i; $che = $chs; if ($ch->subchapter) { - $found = 1;//subchapter moves alone + $found = 1;// Subchapter moves alone. } } else if ($chs) { if ($found) { - //nothing + // Nothing. } else if ($ch->subchapter) { - $che = $i; // chapter with subchapter(s) + $che = $i; // Chapter with subchapter(s). } else { $found = 1; } @@ -76,27 +75,27 @@ foreach ($oldchapters as $ch) { $i++; } -// find target chapter(s) -if ($chapters[$chs]->subchapter) { //moving single subchapter up or down +// Find target chapter(s). +if ($chapters[$chs]->subchapter) { // Moving single subchapter up or down. if ($up) { if ($chs == 1) { - $nothing = 1; //already first + $nothing = 1; // Already first. } else { $ts = $chs - 1; $te = $ts; } - } else { //down + } else { // Down. if ($che == count($chapters)) { - $nothing = 1; //already last + $nothing = 1; // Already last. } else { $ts = $che + 1; $te = $ts; } } -} else { // moving chapter and looking for next/previous chapter - if ($up) { //up +} else { // Moving chapter and looking for next/previous chapter. + if ($up) { // Up. if ($chs == 1) { - $nothing = 1; //already first + $nothing = 1; // Already first. } else { $te = $chs - 1; for($i = $chs-1; $i >= 1; $i--) { @@ -108,9 +107,9 @@ if ($chapters[$chs]->subchapter) { //moving single subchapter up or down } } } - } else { //down + } else { // Down. if ($che == count($chapters)) { - $nothing = 1; //already last + $nothing = 1; // Already last. } else { $ts = $che + 1; $found = 0; @@ -130,7 +129,7 @@ if ($chapters[$chs]->subchapter) { //moving single subchapter up or down } } -//recreated newly sorted list of chapters +// Recreated newly sorted list of chapters. if (!$nothing) { $newchapters = array(); @@ -170,7 +169,7 @@ if (!$nothing) { } } - //store chapters in the new order + // Store chapters in the new order. $i = 1; foreach ($newchapters as $ch) { $ch->pagenum = $i; diff --git a/mod/book/settings.php b/mod/book/settings.php index 0ab07e29ea6..c741e6a8f8e 100644 --- a/mod/book/settings.php +++ b/mod/book/settings.php @@ -17,9 +17,8 @@ /** * Book plugin settings * - * @package mod - * @subpackage book - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,7 +27,7 @@ defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { require_once("$CFG->dirroot/mod/book/lib.php"); - //--- general settings ----------------------------------------------------------------------------------- + // General settings $settings->add(new admin_setting_configcheckbox('book/requiremodintro', get_string('requiremodintro', 'admin'), get_string('configrequiremodintro', 'admin'), 1)); @@ -40,7 +39,8 @@ if ($ADMIN->fulltree) { array_keys($options), $options)); - //--- modedit defaults ----------------------------------------------------------------------------------- + // Modedit defaults. + $settings->add(new admin_setting_heading('bookmodeditdefaults', get_string('modeditdefaults', 'admin'), get_string('condifmodeditdefaults', 'admin'))); $settings->add(new admin_setting_configselect('book/numbering', diff --git a/mod/book/show.php b/mod/book/show.php index fdda808b5b4..7c9269bfab9 100644 --- a/mod/book/show.php +++ b/mod/book/show.php @@ -17,9 +17,8 @@ /** * Show/hide book chapter * - * @package mod - * @subpackage book - * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} + * @package mod_book + * @copyright 2004-2010 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -43,14 +42,13 @@ $PAGE->set_url('/mod/book/show.php', array('id'=>$id, 'chapterid'=>$chapterid)); $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST); - -///switch hidden state +// Switch hidden state. $chapter->hidden = $chapter->hidden ? 0 : 1; -// update record +// Update record. $DB->update_record('book_chapters', $chapter); -///change visibility of subchapters too +// Change visibility of subchapters too. if (!$chapter->subchapter) { $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter, hidden'); $found = 0; diff --git a/mod/book/tool/exportimscp/db/access.php b/mod/book/tool/exportimscp/db/access.php index 9e4396d8e9d..0d60721cd0c 100644 --- a/mod/book/tool/exportimscp/db/access.php +++ b/mod/book/tool/exportimscp/db/access.php @@ -17,9 +17,8 @@ /** * Book module capability definition * - * @package booktool - * @subpackage exportimscp - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/tool/exportimscp/index.php b/mod/book/tool/exportimscp/index.php index fcb6861c707..02ad83f399e 100644 --- a/mod/book/tool/exportimscp/index.php +++ b/mod/book/tool/exportimscp/index.php @@ -17,10 +17,9 @@ /** * Book IMSCP export plugin * - * @package booktool - * @subpackage exportimscp + * @package booktool_exportimscp * @copyright 2001-3001 Antonio Vicent {@link http://ludens.es} - * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com} + * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://stronk7.com} * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php b/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php index 2aa40818a92..2273e55db7d 100644 --- a/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php +++ b/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php @@ -15,11 +15,10 @@ // along with Moodle. If not, see . /** - * Book module language strings + * exportimscp booktool language strings * - * @package booktool - * @subpackage exportimscp - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/tool/exportimscp/lib.php b/mod/book/tool/exportimscp/lib.php index 6316768c395..d655c31963e 100644 --- a/mod/book/tool/exportimscp/lib.php +++ b/mod/book/tool/exportimscp/lib.php @@ -17,15 +17,20 @@ /** * IMSCP export lib * - * @package booktool - * @subpackage exportimscp - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; -function booktool_exportimscp_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { +/** + * Adds module specific settings to the settings block + * + * @param settings_navigation $settings The settings navigation object + * @param navigation_node $node The node to add module settings to + */ +function booktool_exportimscp_extend_settings_navigation(settings_navigation $settings, navigation_node $node) { global $USER, $PAGE, $CFG, $DB, $OUTPUT; if ($PAGE->cm->modname !== 'book') { @@ -39,6 +44,6 @@ function booktool_exportimscp_extend_settings_navigation(settings_navigation $se if (has_capability('booktool/exportimscp:export', $PAGE->cm->context)) { $url = new moodle_url('/mod/book/tool/exportimscp/index.php', array('id'=>$PAGE->cm->id)); $icon = new pix_icon('generate', '', 'booktool_exportimscp', array('class'=>'icon')); - $booknode->add(get_string('generateimscp', 'booktool_exportimscp'), $url, navigation_node::TYPE_SETTING, null, null, $icon); + $node->add(get_string('generateimscp', 'booktool_exportimscp'), $url, navigation_node::TYPE_SETTING, null, null, $icon); } } \ No newline at end of file diff --git a/mod/book/tool/exportimscp/locallib.php b/mod/book/tool/exportimscp/locallib.php index 37b5a68781e..e8f695fe2f7 100644 --- a/mod/book/tool/exportimscp/locallib.php +++ b/mod/book/tool/exportimscp/locallib.php @@ -17,10 +17,9 @@ /** * Book imscp export lib * - * @package booktool - * @subpackage exportimscp + * @package booktool_exportimscp * @copyright 2001-3001 Antonio Vicent {@link http://ludens.es} - * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://contiento.com} + * @copyright 2001-3001 Eloy Lafuente (stronk7) {@link http://stronk7.com} * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -30,7 +29,13 @@ defined('MOODLE_INTERNAL') || die; require_once(dirname(__FILE__).'/lib.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); - +/** + * Export one book as IMSCP package + * + * @param stdClass $book book instance + * @param context_module $context + * @return bool|stored_file + */ function booktool_exportimscp_build_package($book, $context) { global $DB; @@ -76,7 +81,12 @@ function booktool_exportimscp_build_package($book, $context) { return $packagefile; } - +/** + * Prepare temp area with the files used by book html contents + * + * @param stdClass $book book instance + * @param context_module $context + */ function booktool_exportimscp_prepare_files($book, $context) { global $CFG, $DB; @@ -202,6 +212,13 @@ function booktool_exportimscp_prepare_files($book, $context) { $fs->create_file_from_string($manifest_file_record, $imsmanifest); } +/** + * Returns the html contents of one book's chapter to be exported as IMSCP + * + * @param stdClass $chapter the chapter to be exported + * @param context_module $context context the chapter belongs to + * @return string the contents of the chapter + */ function booktool_exportimscp_chapter_content($chapter, $context) { $options = new stdClass(); diff --git a/mod/book/tool/exportimscp/version.php b/mod/book/tool/exportimscp/version.php index 4a7ce6779a9..34e022cc3d5 100644 --- a/mod/book/tool/exportimscp/version.php +++ b/mod/book/tool/exportimscp/version.php @@ -17,9 +17,8 @@ /** * Book IMSCP export plugin version info * - * @package booktool - * @subpackage exportimscp - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_exportimscp + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/tool/importhtml/db/access.php b/mod/book/tool/importhtml/db/access.php index cf87c1fddba..4cc00b17950 100644 --- a/mod/book/tool/importhtml/db/access.php +++ b/mod/book/tool/importhtml/db/access.php @@ -17,9 +17,8 @@ /** * Book import capability definition * - * @package booktool - * @subpackage importhtml - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/tool/importhtml/import_form.php b/mod/book/tool/importhtml/import_form.php index 55e9c90c4df..1340a18b601 100644 --- a/mod/book/tool/importhtml/import_form.php +++ b/mod/book/tool/importhtml/import_form.php @@ -17,9 +17,8 @@ /** * Book import form * - * @package booktool - * @subpackage importhtml - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package booktool_importhtml + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -36,7 +35,7 @@ class booktool_importhtml_form extends moodleform { $mform->addElement('header', 'general', get_string('import')); $options = array( - //'0'=>get_string('typeonefile', 'booktool_importhtml'), + // '0'=>get_string('typeonefile', 'booktool_importhtml'), '1'=>get_string('typezipdirs', 'booktool_importhtml'), '2'=>get_string('typezipfiles', 'booktool_importhtml'), ); diff --git a/mod/book/tool/importhtml/index.php b/mod/book/tool/importhtml/index.php index 9e557ca8eac..970f81f7d0b 100644 --- a/mod/book/tool/importhtml/index.php +++ b/mod/book/tool/importhtml/index.php @@ -17,9 +17,8 @@ /** * Book import * - * @package booktool - * @subpackage importhtml - * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} + * @package booktool_importhtml + * @copyright 2004-2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -53,13 +52,13 @@ $PAGE->set_title(format_string($book->name)); $PAGE->add_body_class('mod_book'); $PAGE->set_heading(format_string($course->fullname)); -///prepare the page header +// Prepare the page header. $strbook = get_string('modulename', 'mod_book'); $strbooks = get_string('modulenameplural', 'mod_book'); $mform = new booktool_importhtml_form(null, array('id'=>$id, 'chapterid'=>$chapterid)); -/// If data submitted, then process and store. +// If data submitted, then process and store. if ($mform->is_cancelled()) { if (empty($chapter->id)) { redirect("view.php?id=$cm->id"); diff --git a/mod/book/tool/importhtml/lang/en/booktool_importhtml.php b/mod/book/tool/importhtml/lang/en/booktool_importhtml.php index f58616e5910..c5640092b80 100644 --- a/mod/book/tool/importhtml/lang/en/booktool_importhtml.php +++ b/mod/book/tool/importhtml/lang/en/booktool_importhtml.php @@ -17,9 +17,8 @@ /** * Book import language strings * - * @package booktool - * @subpackage importhtml - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/book/tool/importhtml/lib.php b/mod/book/tool/importhtml/lib.php index 59eb547c30e..1bb81f555cb 100644 --- a/mod/book/tool/importhtml/lib.php +++ b/mod/book/tool/importhtml/lib.php @@ -17,15 +17,20 @@ /** * HTML import lib * - * @package booktool - * @subpackage importhtml - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die; -function booktool_importhtml_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) { +/** + * Adds module specific settings to the settings block + * + * @param settings_navigation $settings The settings navigation object + * @param navigation_node $node The node to add module settings to + */ +function booktool_importhtml_extend_settings_navigation(settings_navigation $settings, navigation_node $node) { global $USER, $PAGE, $CFG, $DB, $OUTPUT; if ($PAGE->cm->modname !== 'book') { @@ -38,6 +43,6 @@ function booktool_importhtml_extend_settings_navigation(settings_navigation $set if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) { $url = new moodle_url('/mod/book/tool/importhtml/index.php', array('id'=>$PAGE->cm->id)); - $booknode->add(get_string('import', 'booktool_importhtml'), $url, navigation_node::TYPE_SETTING, null, null, null); + $node->add(get_string('import', 'booktool_importhtml'), $url, navigation_node::TYPE_SETTING, null, null, null); } } \ No newline at end of file diff --git a/mod/book/tool/importhtml/locallib.php b/mod/book/tool/importhtml/locallib.php index 37d87b54373..dd08bee56dd 100644 --- a/mod/book/tool/importhtml/locallib.php +++ b/mod/book/tool/importhtml/locallib.php @@ -17,9 +17,8 @@ /** * HTML import lib * - * @package booktool - * @subpackage importhtml - * @copyright 2011 Petr Skoda {@link http://skodak.org} + * @package booktool_importhtml + * @copyright 2011 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,6 +27,15 @@ defined('MOODLE_INTERNAL') || die; require_once(dirname(__FILE__).'/lib.php'); require_once($CFG->dirroot.'/mod/book/locallib.php'); +/** + * Import HTML pages packaged into one zip archive + * + * @param stored_file $package + * @param string $type type of the package ('typezipdirs' or 'typezipfiles') + * @param stdClass $book + * @param context_module $context + * @param bool $verbose + */ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $verbose = true) { global $DB, $OUTPUT; @@ -36,8 +44,8 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $ $packer = get_file_packer('application/zip'); $fs->delete_area_files($context->id, 'mod_book', 'importhtmltemp', 0); $package->extract_to_storage($packer, $context->id, 'mod_book', 'importhtmltemp', 0, '/'); - //$datafiles = $fs->get_area_files($context->id, 'mod_book', 'importhtmltemp', 0, 'id', false); - //echo "
                                ";p(var_export($datafiles, true));
                                +    // $datafiles = $fs->get_area_files($context->id, 'mod_book', 'importhtmltemp', 0, 'id', false);
                                +    // echo "
                                ";p(var_export($datafiles, true));
                                 
                                     $chapters = array();
                                 
                                @@ -49,7 +57,7 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $
                                         if ($file = $fs->get_file_by_hash("$context->id/mod_book/importhtmltemp/0/$chapterfile->pathname")) {
                                             $htmlcontent = toolbook_importhtml_fix_encoding($file->get_content());
                                             $htmlchapters = toolbook_importhtml_parse_headings(toolbook_importhtml_parse_body($htmlcontent));
                                -            //TODO: process h1 as main chapter and h2 as subchapters
                                +            // TODO: process h1 as main chapter and h2 as subchapters
                                         }
                                     } else {
                                         foreach ($chapterfiles as $chapterfile) {
                                @@ -67,7 +75,7 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $
                                                 $chapter->hidden        = 0;
                                                 $chapter->timecreated   = time();
                                                 $chapter->timemodified  = time();
                                -                if (preg_match('/_sub(\/|\.htm)/i', $chapter->importsrc)) { //if filename or directory ends with *_sub treat as subchapters
                                +                if (preg_match('/_sub(\/|\.htm)/i', $chapter->importsrc)) { // If filename or directory ends with *_sub treat as subchapters
                                                     $chapter->subchapter = 1;
                                                 } else {
                                                     $chapter->subchapter = 0;
                                @@ -129,7 +137,8 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $
                                                 $chapterpath = toolbook_importhtml_fix_path($chapterpath);
                                                 foreach ($allchapters as $target) {
                                                     if ($target->importsrc === $chapterpath) {
                                -                        $newcontent = str_replace($match, 'href="'.new moodle_url('/mod/book/view.php', array('id'=>$context->instanceid, 'chapter'=>$target->id)).'"', $newcontent);
                                +                        $newcontent = str_replace($match, 'href="'.new moodle_url('/mod/book/view.php',
                                +                                array('id'=>$context->instanceid, 'chapter'=>$target->id)).'"', $newcontent);
                                                     }
                                                 }
                                             }
                                @@ -147,15 +156,27 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $
                                     $DB->set_field('book', 'revision', $book->revision+1, array('id'=>$book->id));
                                 }
                                 
                                +/**
                                + * Parse the headings of the imported package of type 'typeonefile'
                                + * (currently unsupported)
                                + *
                                + * @param string $html html content to parse
                                + * @todo implement this once the type 'typeonefile' is enabled
                                + */
                                 function toolbook_importhtml_parse_headings($html) {
                                -    //TODO
                                 }
                                 
                                +/**
                                + * Parse the links to external css sheets of the imported html content
                                + *
                                + * @param string $html html content to parse
                                + * @return string all the links to external css sheets
                                + */
                                 function toolbook_importhtml_parse_styles($html) {
                                     $styles = '';
                                     if (preg_match('/]*>(.+)<\/head>/is', $html, $matches)) {
                                         $head = $matches[1];
                                -        if (preg_match_all('/]+rel="stylesheet"[^>]*>/i', $head, $matches)) { //dlnsk extract links to css
                                +        if (preg_match_all('/]+rel="stylesheet"[^>]*>/i', $head, $matches)) { // Extract links to css.
                                             for($i=0; $i]*>(.+)<\/head>/is', $html, $matches)) {
                                         $head = $matches[1];
                                @@ -188,6 +221,12 @@ function toolbook_importhtml_fix_encoding($html) {
                                     return iconv('UTF-8', 'UTF-8//IGNORE', $html);
                                 }
                                 
                                +/**
                                + * Extract the body from any html contents
                                + *
                                + * @param string $html the html to parse
                                + * @return string the contents of the body
                                + */
                                 function toolbook_importhtml_parse_body($html) {
                                     $matches = null;
                                     if (preg_match('/]*>(.+)<\/body>/is', $html, $matches)) {
                                @@ -197,7 +236,14 @@ function toolbook_importhtml_parse_body($html) {
                                     }
                                 }
                                 
                                -function  toolbook_importhtml_parse_title($html, $default) {
                                +/**
                                + * Extract the title of any html content, getting it from the title tag
                                + *
                                + * @param string $html the html to parse
                                + * @param string $default default title to apply if no title is found
                                + * @return string the resulting title
                                + */
                                +function toolbook_importhtml_parse_title($html, $default) {
                                     $matches = null;
                                     if (preg_match('/([^<]+)<\/title>/i', $html, $matches)) {
                                         return $matches[1];
                                @@ -206,6 +252,14 @@ function  toolbook_importhtml_parse_title($html, $default) {
                                     }
                                 }
                                 
                                +/**
                                + * Returns all the html files (chapters) from a file package
                                + *
                                + * @param stored_file $package file to be processed
                                + * @param string $type type of the package ('typezipdirs' or 'typezipfiles')
                                + *
                                + * @return array the html files found in the package
                                + */
                                 function toolbook_importhtml_get_chapter_files($package, $type) {
                                     $packer = get_file_packer('application/zip');
                                     $files = $package->list_files($packer);
                                diff --git a/mod/book/tool/importhtml/version.php b/mod/book/tool/importhtml/version.php
                                index 2a96e4bf801..3c5d0f4a830 100644
                                --- a/mod/book/tool/importhtml/version.php
                                +++ b/mod/book/tool/importhtml/version.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book import plugin version info
                                  *
                                - * @package    booktool
                                - * @subpackage importhtml
                                - * @copyright  2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_importhtml
                                + * @copyright  2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                diff --git a/mod/book/tool/print/db/access.php b/mod/book/tool/print/db/access.php
                                index fe57fb2229f..a4c9371c947 100644
                                --- a/mod/book/tool/print/db/access.php
                                +++ b/mod/book/tool/print/db/access.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book module capability definition
                                  *
                                - * @package    booktool
                                - * @subpackage print
                                - * @copyright  2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_print
                                + * @copyright  2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                diff --git a/mod/book/tool/print/index.php b/mod/book/tool/print/index.php
                                index b1949dd7731..ff5e283e53a 100644
                                --- a/mod/book/tool/print/index.php
                                +++ b/mod/book/tool/print/index.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book printing
                                  *
                                - * @package    booktool
                                - * @subpackage print
                                - * @copyright  2004-2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_print
                                + * @copyright  2004-2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                @@ -43,12 +42,12 @@ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                 require_capability('mod/book:read', $context);
                                 require_capability('booktool/print:print', $context);
                                 
                                -//check all variables
                                +// Check all variables.
                                 if ($chapterid) {
                                -    //single chapter printing - only visible!
                                +    // Single chapter printing - only visible!
                                     $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST);
                                 } else {
                                -    //complete book
                                +    // Complete book.
                                     $chapter = false;
                                 }
                                 
                                @@ -56,11 +55,10 @@ $PAGE->set_url('/mod/book/print.php', array('id'=>$id, 'chapterid'=>$chapterid))
                                 
                                 unset($id);
                                 unset($chapterid);
                                -// =========================================================================
                                -// security checks END
                                -// =========================================================================
                                 
                                -/// read chapters
                                +// Security checks END.
                                +
                                +// read chapters
                                 $chapters = book_preload_chapters($book);
                                 
                                 $strbooks = get_string('modulenameplural', 'mod_book');
                                @@ -81,7 +79,7 @@ if ($chapter) {
                                 
                                     add_to_log($course->id, 'book', 'print', 'tool/print/index.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id);
                                 
                                -    /// page header
                                +    // page header
                                     ?>
                                     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
                                     <html>
                                @@ -117,7 +115,7 @@ if ($chapter) {
                                     add_to_log($course->id, 'book', 'print', 'tool/print/index.php?id='.$cm->id, $book->id, $cm->id);
                                     $allchapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum');
                                 
                                -    /// page header
                                +    // page header
                                     ?>
                                     <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
                                     <html>
                                @@ -170,7 +168,7 @@ if ($chapter) {
                                         $content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $context->id, 'mod_book', 'chapter', $ch->id);
                                         echo format_text($content, $chapter->contentformat, array('noclean'=>true, 'context'=>$context));
                                         echo '</div>';
                                -        //echo '<a href="#toc">'.$strtop.'</a>';
                                +        // echo '<a href="#toc">'.$strtop.'</a>';
                                     }
                                     echo '</body> </html>';
                                 }
                                diff --git a/mod/book/tool/print/lang/en/booktool_print.php b/mod/book/tool/print/lang/en/booktool_print.php
                                index ef87324614f..e059fe18ccd 100644
                                --- a/mod/book/tool/print/lang/en/booktool_print.php
                                +++ b/mod/book/tool/print/lang/en/booktool_print.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book module language strings
                                  *
                                - * @package    booktool
                                - * @subpackage print
                                - * @copyright  2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_print
                                + * @copyright  2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                diff --git a/mod/book/tool/print/lib.php b/mod/book/tool/print/lib.php
                                index 54e801218af..5a2e92c27c9 100644
                                --- a/mod/book/tool/print/lib.php
                                +++ b/mod/book/tool/print/lib.php
                                @@ -17,15 +17,20 @@
                                 /**
                                  * Print lib
                                  *
                                - * @package    booktool
                                - * @subpackage print
                                - * @copyright  2004-2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_print
                                + * @copyright  2004-2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -function booktool_print_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) {
                                +/**
                                + * Adds module specific settings to the settings block
                                + *
                                + * @param settings_navigation $settings The settings navigation object
                                + * @param navigation_node $node The node to add module settings to
                                + */
                                +function booktool_print_extend_settings_navigation(settings_navigation $settings, navigation_node $node) {
                                     global $USER, $PAGE, $CFG, $DB, $OUTPUT;
                                 
                                     if ($PAGE->cm->modname !== 'book') {
                                @@ -36,21 +41,21 @@ function booktool_print_extend_settings_navigation(settings_navigation $settings
                                         $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance);
                                     }
                                 
                                -
                                     $params = $PAGE->url->params();
                                 
                                     if (empty($params['id']) or empty($params['chapterid'])) {
                                         return;
                                     }
                                 
                                -
                                     if (has_capability('booktool/print:print', $PAGE->cm->context)) {
                                         $url1 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id']));
                                         $url2 = new moodle_url('/mod/book/tool/print/index.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid']));
                                         $action = new action_link($url1, get_string('printbook', 'booktool_print'), new popup_action('click', $url1));
                                -        $booknode->add(get_string('printbook', 'booktool_print'), $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('book', '', 'booktool_print', array('class'=>'icon')));
                                +        $node->add(get_string('printbook', 'booktool_print'), $action, navigation_node::TYPE_SETTING, null, null,
                                +                new pix_icon('book', '', 'booktool_print', array('class'=>'icon')));
                                         $action = new action_link($url2, get_string('printchapter', 'booktool_print'), new popup_action('click', $url2));
                                -        $booknode->add(get_string('printchapter', 'booktool_print'), $action, navigation_node::TYPE_SETTING, null, null, new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon')));
                                +        $node->add(get_string('printchapter', 'booktool_print'), $action, navigation_node::TYPE_SETTING, null, null,
                                +                new pix_icon('chapter', '', 'booktool_print', array('class'=>'icon')));
                                     }
                                 }
                                 
                                diff --git a/mod/book/tool/print/locallib.php b/mod/book/tool/print/locallib.php
                                index c3b716432db..a26adaa55c5 100644
                                --- a/mod/book/tool/print/locallib.php
                                +++ b/mod/book/tool/print/locallib.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * HTML import lib
                                  *
                                - * @package    booktool
                                - * @subpackage print
                                - * @copyright  2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_print
                                + * @copyright  2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                @@ -42,7 +41,7 @@ function booktool_print_get_toc($chapters, $book, $cm) {
                                 
                                     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                 
                                -    $toc = ''; //representation of toc (HTML)
                                +    $toc = ''; // Representation of toc (HTML).
                                 
                                     switch ($book->numbering) {
                                       case BOOK_NUM_NONE:
                                @@ -59,7 +58,7 @@ function booktool_print_get_toc($chapters, $book, $cm) {
                                           break;
                                     }
                                 
                                -    $toc .= '<a name="toc"></a>'; //representation of toc (HTML)
                                +    $toc .= '<a name="toc"></a>'; // Representation of toc (HTML).
                                 
                                     if ($book->customtitles) {
                                         $toc .= '<h1>'.get_string('toc', 'mod_book').'</h1>';
                                @@ -83,7 +82,7 @@ function booktool_print_get_toc($chapters, $book, $cm) {
                                     }
                                     $toc .= '</ul></li></ul>';
                                     $toc .= '</div>';
                                -    $toc = str_replace('<ul></ul>', '', $toc); //cleanup of invalid structures
                                +    $toc = str_replace('<ul></ul>', '', $toc); // Cleanup of invalid structures.
                                 
                                     return array($toc, $titles);
                                 }
                                diff --git a/mod/book/tool/print/version.php b/mod/book/tool/print/version.php
                                index e566b67fa28..01ad0f171e1 100644
                                --- a/mod/book/tool/print/version.php
                                +++ b/mod/book/tool/print/version.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book print plugin version info
                                  *
                                - * @package    booktool
                                - * @subpackage print
                                - * @copyright  2004-2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    booktool_print
                                + * @copyright  2004-2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                diff --git a/mod/book/version.php b/mod/book/version.php
                                index 45fceaea8b4..a1851794780 100644
                                --- a/mod/book/version.php
                                +++ b/mod/book/version.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book plugin version info
                                  *
                                - * @package    mod
                                - * @subpackage book
                                - * @copyright  2004-2012 Petr Skoda  {@link http://skodak.org}
                                + * @package    mod_book
                                + * @copyright  2004-2012 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                diff --git a/mod/book/view.php b/mod/book/view.php
                                index afec9da20da..ee7ab0eab82 100644
                                --- a/mod/book/view.php
                                +++ b/mod/book/view.php
                                @@ -17,9 +17,8 @@
                                 /**
                                  * Book view page
                                  *
                                - * @package    mod
                                - * @subpackage book
                                - * @copyright  2004-2011 Petr Skoda  {@link http://skodak.org}
                                + * @package    mod_book
                                + * @copyright  2004-2011 Petr Skoda {@link http://skodak.org}
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                @@ -68,14 +67,14 @@ if ($allowedit) {
                                     $edit = 0;
                                 }
                                 
                                -/// read chapters
                                +// read chapters
                                 $chapters = book_preload_chapters($book);
                                 
                                 if ($allowedit and !$chapters) {
                                -    redirect('edit.php?cmid='.$cm->id); //no chapters - add new one
                                +    redirect('edit.php?cmid='.$cm->id); // No chapters - add new one.
                                 }
                                -/// check chapterid and read chapter data
                                -if ($chapterid == '0') { // go to first chapter if no given
                                +// Check chapterid and read chapter data
                                +if ($chapterid == '0') { // Go to first chapter if no given.
                                     foreach($chapters as $ch) {
                                         if ($edit) {
                                             $chapterid = $ch->id;
                                @@ -92,7 +91,7 @@ if (!$chapterid or !$chapter = $DB->get_record('book_chapters', array('id'=>$cha
                                     print_error('errorchapter', 'mod_book', new moodle_url('/course/view.php', array('id'=>$course->id)));
                                 }
                                 
                                -/// chapter is hidden for students
                                +// chapter is hidden for students
                                 if ($chapter->hidden and !$viewhidden) {
                                     print_error('errorchapter', 'mod_book', new moodle_url('/course/view.php', array('id'=>$course->id)));
                                 }
                                @@ -100,32 +99,28 @@ if ($chapter->hidden and !$viewhidden) {
                                 $PAGE->set_url('/mod/book/view.php', array('id'=>$id, 'chapterid'=>$chapterid));
                                 
                                 
                                -//unset all page parameters
                                +// Unset all page parameters.
                                 unset($id);
                                 unset($bid);
                                 unset($chapterid);
                                 
                                -
                                -// =========================================================================
                                -// security checks  END
                                -// =========================================================================
                                +// Security checks END.
                                 
                                 add_to_log($course->id, 'book', 'view', 'view.php?id='.$cm->id.'&chapterid='.$chapter->id, $book->id, $cm->id);
                                 
                                -
                                -///read standard strings
                                +// Read standard strings.
                                 $strbooks = get_string('modulenameplural', 'mod_book');
                                 $strbook  = get_string('modulename', 'mod_book');
                                 $strtoc   = get_string('toc', 'mod_book');
                                 
                                -/// prepare header
                                +// prepare header
                                 $PAGE->set_title(format_string($book->name));
                                 $PAGE->add_body_class('mod_book');
                                 $PAGE->set_heading(format_string($course->fullname));
                                 
                                 book_add_fake_block($chapters, $chapter, $book, $cm, $edit);
                                 
                                -/// prepare chapter navigation icons
                                +// prepare chapter navigation icons
                                 $previd = null;
                                 $nextid = null;
                                 $last = null;
                                @@ -195,7 +190,7 @@ echo format_text($chaptertext, $chapter->contentformat, array('noclean'=>true, '
                                 
                                 echo $OUTPUT->box_end();
                                 
                                -/// lower navigation
                                +// lower navigation
                                 echo '<div class="navbottom">'.$chnavigation.'</div>';
                                 
                                 echo $OUTPUT->footer();
                                
                                From 98cef39d280c914ac8df74e5c7f049e84375bf26 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Tue, 1 May 2012 01:06:50 +0200
                                Subject: [PATCH 211/455] MDL-32709 book: Add some missing MOODLE_INTERNALs
                                
                                ---
                                 mod/book/backup/moodle2/restore_book_stepslib.php | 2 ++
                                 mod/book/tool/exportimscp/db/access.php           | 2 ++
                                 mod/book/tool/importhtml/db/access.php            | 2 ++
                                 mod/book/tool/print/db/access.php                 | 2 ++
                                 4 files changed, 8 insertions(+)
                                
                                diff --git a/mod/book/backup/moodle2/restore_book_stepslib.php b/mod/book/backup/moodle2/restore_book_stepslib.php
                                index 05fbd132d0c..09ee5a0b877 100644
                                --- a/mod/book/backup/moodle2/restore_book_stepslib.php
                                +++ b/mod/book/backup/moodle2/restore_book_stepslib.php
                                @@ -23,6 +23,8 @@
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                +defined('MOODLE_INTERNAL') || die;
                                +
                                 /**
                                  * Structure step to restore one book activity
                                  */
                                diff --git a/mod/book/tool/exportimscp/db/access.php b/mod/book/tool/exportimscp/db/access.php
                                index 0d60721cd0c..5a5cb244f39 100644
                                --- a/mod/book/tool/exportimscp/db/access.php
                                +++ b/mod/book/tool/exportimscp/db/access.php
                                @@ -22,6 +22,8 @@
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                +defined('MOODLE_INTERNAL') || die;
                                +
                                 $capabilities = array(
                                     'booktool/exportimscp:export' => array(
                                         'captype' => 'read',
                                diff --git a/mod/book/tool/importhtml/db/access.php b/mod/book/tool/importhtml/db/access.php
                                index 4cc00b17950..d1fb35d5e1a 100644
                                --- a/mod/book/tool/importhtml/db/access.php
                                +++ b/mod/book/tool/importhtml/db/access.php
                                @@ -22,6 +22,8 @@
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                +defined('MOODLE_INTERNAL') || die;
                                +
                                 $capabilities = array(
                                     'booktool/importhtml:import' => array(
                                         'riskbitmask' => RISK_XSS,
                                diff --git a/mod/book/tool/print/db/access.php b/mod/book/tool/print/db/access.php
                                index a4c9371c947..5e5c2b17b86 100644
                                --- a/mod/book/tool/print/db/access.php
                                +++ b/mod/book/tool/print/db/access.php
                                @@ -22,6 +22,8 @@
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                +defined('MOODLE_INTERNAL') || die;
                                +
                                 $capabilities = array(
                                     'booktool/print:print' => array(
                                         'captype' => 'read',
                                
                                From 1fc9e895ef7332e8fb24a97cdec1233d0c0fac64 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Tue, 1 May 2012 02:13:32 +0200
                                Subject: [PATCH 212/455] MDL-32709 book: replace some deprecated stuff. Some
                                 pending yet, blame $PAGE
                                
                                ---
                                 mod/book/db/upgrade.php                  |  2 +-
                                 mod/book/db/upgradelib.php               |  7 +++----
                                 mod/book/delete.php                      |  2 +-
                                 mod/book/edit.php                        |  2 +-
                                 mod/book/index.php                       |  2 +-
                                 mod/book/locallib.php                    |  2 +-
                                 mod/book/move.php                        |  2 +-
                                 mod/book/show.php                        |  2 +-
                                 mod/book/tool/exportimscp/index.php      |  2 +-
                                 mod/book/tool/exportimscp/locallib.php   |  2 +-
                                 mod/book/tool/importhtml/import_form.php |  2 +-
                                 mod/book/tool/importhtml/index.php       |  4 ++--
                                 mod/book/tool/importhtml/locallib.php    | 10 +++++-----
                                 mod/book/tool/print/index.php            |  2 +-
                                 mod/book/tool/print/locallib.php         |  2 +-
                                 mod/book/view.php                        |  2 +-
                                 16 files changed, 23 insertions(+), 24 deletions(-)
                                
                                diff --git a/mod/book/db/upgrade.php b/mod/book/db/upgrade.php
                                index 9e3d3d38726..35750b7ceb3 100644
                                --- a/mod/book/db/upgrade.php
                                +++ b/mod/book/db/upgrade.php
                                @@ -141,7 +141,7 @@ function xmldb_book_upgrade($oldversion) {
                                                 upgrade_set_timeout(360); // set up timeout, may also abort execution
                                                 $pbar->update($i, $count, "Migrating book files - $i/$count.");
                                 
                                -                $context = get_context_instance(CONTEXT_MODULE, $book->cmid);
                                +                $context = context_module::instance($book->cmid);
                                 
                                                 mod_book_migrate_moddata_dir_to_legacy($book, $context, '/');
                                 
                                diff --git a/mod/book/db/upgradelib.php b/mod/book/db/upgradelib.php
                                index 7a610e63d6a..5411930443c 100644
                                --- a/mod/book/db/upgradelib.php
                                +++ b/mod/book/db/upgradelib.php
                                @@ -46,7 +46,6 @@ function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) {
                                     }
                                 
                                     $fs      = get_file_storage();
                                -    $textlib = textlib_get_instance();
                                     $items   = new DirectoryIterator($fulldir);
                                 
                                     foreach ($items as $item) {
                                @@ -77,7 +76,7 @@ function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) {
                                                 continue;
                                             }
                                 
                                -            if ($textlib->strlen($filepath) > 255) {
                                +            if (textlib::strlen($filepath) > 255) {
                                                 echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fulldir.$item->getFilename());
                                                 unset($item); // release file handle
                                                 continue;
                                @@ -115,7 +114,7 @@ function mod_book_migrate_all_areas() {
                                     foreach($rsbooks as $book) {
                                         upgrade_set_timeout(360); // set up timeout, may also abort execution
                                         $cm = get_coursemodule_from_instance('book', $book->id);
                                -        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +        $context = context_module::instance($cm->id);
                                         mod_book_migrate_area($book, 'intro', 'book', $book->course, $context, 'mod_book', 'intro', 0);
                                 
                                         $rschapters = $DB->get_recordset('book_chapters', array('bookid'=>$book->id));
                                @@ -147,7 +146,7 @@ function mod_book_migrate_area($record, $field, $table, $courseid, $context, $co
                                 
                                     foreach(array(get_site()->id, $courseid) as $cid) {
                                         $matches = null;
                                -        $ooldcontext = get_context_instance(CONTEXT_COURSE, $cid);
                                +        $ooldcontext = context_course::instance($cid);
                                         if (preg_match_all("|$CFG->wwwroot/file.php(\?file=)?/$cid(/[^\s'\"&\?#]+)|", $record->$field, $matches)) {
                                             $file_record = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid);
                                             foreach ($matches[2] as $i=>$filepath) {
                                diff --git a/mod/book/delete.php b/mod/book/delete.php
                                index 694505fcd6d..254f0c51098 100644
                                --- a/mod/book/delete.php
                                +++ b/mod/book/delete.php
                                @@ -36,7 +36,7 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST);
                                 require_login($course, false, $cm);
                                 require_sesskey();
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:edit', $context);
                                 
                                 $PAGE->set_url('/mod/book/delete.php', array('id'=>$id, 'chapterid'=>$chapterid));
                                diff --git a/mod/book/edit.php b/mod/book/edit.php
                                index c0710f04477..aa3eee29cf0 100644
                                --- a/mod/book/edit.php
                                +++ b/mod/book/edit.php
                                @@ -37,7 +37,7 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST);
                                 
                                 require_login($course, false, $cm);
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:edit', $context);
                                 
                                 $PAGE->set_url('/mod/book/edit.php', array('cmid'=>$cmid, 'id'=>$chapterid, 'pagenum'=>$pagenum, 'subchapter'=>$subchapter));
                                diff --git a/mod/book/index.php b/mod/book/index.php
                                index abe89f381fe..02ed62dbda5 100644
                                --- a/mod/book/index.php
                                +++ b/mod/book/index.php
                                @@ -75,7 +75,7 @@ if ($usesections) {
                                 $modinfo = get_fast_modinfo($course);
                                 $currentsection = '';
                                 foreach ($books as $book) {
                                -    $cm = $modinfo->cms[$book->coursemodule];
                                +    $cm = $modinfo->get_cm($book->coursemodule);
                                     if ($usesections) {
                                         $printsection = '';
                                         if ($book->section !== $currentsection) {
                                diff --git a/mod/book/locallib.php b/mod/book/locallib.php
                                index 8fcade9a7ff..8d0d06eaff9 100644
                                --- a/mod/book/locallib.php
                                +++ b/mod/book/locallib.php
                                @@ -221,7 +221,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) {
                                     $ns = 0;    // Subchapter number
                                     $first = 1;
                                 
                                -    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +    $context = context_module::instance($cm->id);
                                 
                                     switch ($book->numbering) {
                                       case BOOK_NUM_NONE:
                                diff --git a/mod/book/move.php b/mod/book/move.php
                                index 7ae9b118713..40cecad893b 100644
                                --- a/mod/book/move.php
                                +++ b/mod/book/move.php
                                @@ -37,7 +37,7 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST);
                                 require_login($course, false, $cm);
                                 require_sesskey();
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:edit', $context);
                                 
                                 $chapter = $DB->get_record('book_chapters', array('id'=>$chapterid, 'bookid'=>$book->id), '*', MUST_EXIST);
                                diff --git a/mod/book/show.php b/mod/book/show.php
                                index 7c9269bfab9..a32cda9ec5c 100644
                                --- a/mod/book/show.php
                                +++ b/mod/book/show.php
                                @@ -35,7 +35,7 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST);
                                 require_login($course, false, $cm);
                                 require_sesskey();
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:edit', $context);
                                 
                                 $PAGE->set_url('/mod/book/show.php', array('id'=>$id, 'chapterid'=>$chapterid));
                                diff --git a/mod/book/tool/exportimscp/index.php b/mod/book/tool/exportimscp/index.php
                                index 02ad83f399e..d243ddc4d94 100644
                                --- a/mod/book/tool/exportimscp/index.php
                                +++ b/mod/book/tool/exportimscp/index.php
                                @@ -40,7 +40,7 @@ $PAGE->set_url('/mod/book/tool/exportimscp/index.php', array('id'=>$id));
                                 
                                 require_login($course, false, $cm);
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:read', $context);
                                 require_capability('booktool/exportimscp:export', $context);
                                 
                                diff --git a/mod/book/tool/exportimscp/locallib.php b/mod/book/tool/exportimscp/locallib.php
                                index e8f695fe2f7..3a64999e095 100644
                                --- a/mod/book/tool/exportimscp/locallib.php
                                +++ b/mod/book/tool/exportimscp/locallib.php
                                @@ -159,7 +159,7 @@ function booktool_exportimscp_prepare_files($book, $context) {
                                         // Update prevlevel
                                         $prevlevel = $currlevel;
                                 
                                -        // Calculate the number of spaces (for visual xml-text formating)
                                +        // Calculate the number of spaces (for visual xml-text formatting)
                                         $currspaces = substr('                ', 0, $currlevel * 2);
                                 
                                         $chaptertitle = format_string($chapter->title, true, array('context'=>$context));
                                diff --git a/mod/book/tool/importhtml/import_form.php b/mod/book/tool/importhtml/import_form.php
                                index 1340a18b601..ddbae84b46b 100644
                                --- a/mod/book/tool/importhtml/import_form.php
                                +++ b/mod/book/tool/importhtml/import_form.php
                                @@ -64,7 +64,7 @@ class booktool_importhtml_form extends moodleform {
                                             return $errors;
                                         }
                                 
                                -        $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
                                +        $usercontext = context_user::instance($USER->id);
                                         $fs = get_file_storage();
                                 
                                         if (!$files = $fs->get_area_files($usercontext->id, 'user', 'draft', $data['importfile'], 'id', false)) {
                                diff --git a/mod/book/tool/importhtml/index.php b/mod/book/tool/importhtml/index.php
                                index 970f81f7d0b..f28bd445b17 100644
                                --- a/mod/book/tool/importhtml/index.php
                                +++ b/mod/book/tool/importhtml/index.php
                                @@ -35,7 +35,7 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST);
                                 
                                 require_login($course, false, $cm);
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('booktool/importhtml:import', $context);
                                 
                                 $PAGE->set_url('/mod/book/tool/importhtml/index.php', array('id'=>$id, 'chapterid'=>$chapterid));
                                @@ -73,7 +73,7 @@ if ($mform->is_cancelled()) {
                                     // this is a bloody hack - children do not try this at home!
                                     $fs = get_file_storage();
                                     $draftid = file_get_submitted_draft_itemid('importfile');
                                -    if (!$files = $fs->get_area_files(get_context_instance(CONTEXT_USER, $USER->id)->id, 'user', 'draft', $draftid, 'id DESC', false)) {
                                +    if (!$files = $fs->get_area_files(context_user::instance($USER->id)->id, 'user', 'draft', $draftid, 'id DESC', false)) {
                                         redirect($PAGE->url);
                                     }
                                     $file = reset($files);
                                diff --git a/mod/book/tool/importhtml/locallib.php b/mod/book/tool/importhtml/locallib.php
                                index dd08bee56dd..b8c44c00174 100644
                                --- a/mod/book/tool/importhtml/locallib.php
                                +++ b/mod/book/tool/importhtml/locallib.php
                                @@ -215,7 +215,7 @@ function toolbook_importhtml_fix_encoding($html) {
                                         $head = $matches[1];
                                         if (preg_match('/charset=([^"]+)/is', $head, $matches)) {
                                             $enc = $matches[1];
                                -            return textlib_get_instance()->convert($html, $enc, 'utf-8');
                                +            return textlib::convert($html, $enc, 'utf-8');
                                         }
                                     }
                                     return iconv('UTF-8', 'UTF-8//IGNORE', $html);
                                @@ -299,9 +299,9 @@ function toolbook_importhtml_get_chapter_files($package, $type) {
                                         }
                                     }
                                     // TODO: natural dir sorting would be nice here...
                                -    textlib_get_instance()->asort($tophtmlfiles);
                                -    textlib_get_instance()->asort($subhtmlfiles);
                                -    textlib_get_instance()->asort($topdirs);
                                +    textlib::asort($tophtmlfiles);
                                +    textlib::asort($subhtmlfiles);
                                +    textlib::asort($topdirs);
                                 
                                     $chapterfiles = array();
                                 
                                @@ -313,7 +313,7 @@ function toolbook_importhtml_get_chapter_files($package, $type) {
                                             if (empty($htmlfiles)) {
                                                 continue;
                                             }
                                -            textlib_get_instance()->asort($htmlfiles);
                                +            textlib::asort($htmlfiles);
                                             if (isset($htmlfiles[$dir.'/index.html'])) {
                                                 $htmlfile = $htmlfiles[$dir.'/index.html'];
                                             } else if (isset($htmlfiles[$dir.'/index.htm'])) {
                                diff --git a/mod/book/tool/print/index.php b/mod/book/tool/print/index.php
                                index ff5e283e53a..c793ad97bbb 100644
                                --- a/mod/book/tool/print/index.php
                                +++ b/mod/book/tool/print/index.php
                                @@ -38,7 +38,7 @@ $book = $DB->get_record('book', array('id'=>$cm->instance), '*', MUST_EXIST);
                                 
                                 require_course_login($course, true, $cm);
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:read', $context);
                                 require_capability('booktool/print:print', $context);
                                 
                                diff --git a/mod/book/tool/print/locallib.php b/mod/book/tool/print/locallib.php
                                index a26adaa55c5..2cae0484168 100644
                                --- a/mod/book/tool/print/locallib.php
                                +++ b/mod/book/tool/print/locallib.php
                                @@ -39,7 +39,7 @@ function booktool_print_get_toc($chapters, $book, $cm) {
                                     $first = true;
                                     $titles = array();
                                 
                                -    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +    $context = context_module::instance($cm->id);
                                 
                                     $toc = ''; // Representation of toc (HTML).
                                 
                                diff --git a/mod/book/view.php b/mod/book/view.php
                                index ee7ab0eab82..e1802cbd4c5 100644
                                --- a/mod/book/view.php
                                +++ b/mod/book/view.php
                                @@ -47,7 +47,7 @@ if ($id) {
                                 
                                 require_course_login($course, true, $cm);
                                 
                                -$context = get_context_instance(CONTEXT_MODULE, $cm->id);
                                +$context = context_module::instance($cm->id);
                                 require_capability('mod/book:read', $context);
                                 
                                 $allowedit  = has_capability('mod/book:edit', $context);
                                
                                From 29656fe24b1fd94741b0a6a0f1462642d4cb2f84 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Tue, 15 May 2012 01:58:37 +0200
                                Subject: [PATCH 213/455] MDL-32709 book: coding style, deprecated and minor
                                 fixes
                                
                                ---
                                 mod/book/delete.php   |  4 +--
                                 mod/book/edit.php     |  1 -
                                 mod/book/lib.php      | 53 ++++++++++++++--------------------------
                                 mod/book/locallib.php | 57 ++++++++++++++++++++++++-------------------
                                 mod/book/mod_form.php |  4 +--
                                 mod/book/move.php     |  5 ++--
                                 mod/book/settings.php |  2 +-
                                 mod/book/show.php     |  2 +-
                                 mod/book/version.php  |  9 +++----
                                 mod/book/view.php     | 12 +++++----
                                 10 files changed, 67 insertions(+), 82 deletions(-)
                                
                                diff --git a/mod/book/delete.php b/mod/book/delete.php
                                index 254f0c51098..02203bb82dc 100644
                                --- a/mod/book/delete.php
                                +++ b/mod/book/delete.php
                                @@ -55,7 +55,7 @@ if ($confirm) {  // the operation was confirmed.
                                     if (!$chapter->subchapter) { // Delete all its sub-chapters if any
                                         $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter');
                                         $found = false;
                                -        foreach($chapters as $ch) {
                                +        foreach ($chapters as $ch) {
                                             if ($ch->id == $chapter->id) {
                                                 $found = true;
                                             } else if ($found and $ch->subchapter) {
                                @@ -91,4 +91,4 @@ $continue = new moodle_url('/mod/book/delete.php', array('id'=>$cm->id, 'chapter
                                 $cancel = new moodle_url('/mod/book/view.php', array('id'=>$cm->id, 'chapterid'=>$chapter->id));
                                 echo $OUTPUT->confirm("<strong>$chapter->title</strong><p>$strconfirm</p>", $continue, $cancel);
                                 
                                -echo $OUTPUT->footer();
                                +echo $OUTPUT->footer();
                                \ No newline at end of file
                                diff --git a/mod/book/edit.php b/mod/book/edit.php
                                index aa3eee29cf0..0af2b99f2d6 100644
                                --- a/mod/book/edit.php
                                +++ b/mod/book/edit.php
                                @@ -122,4 +122,3 @@ if (debugging()) {
                                 $mform->display();
                                 
                                 echo $OUTPUT->footer();
                                -
                                diff --git a/mod/book/lib.php b/mod/book/lib.php
                                index 849adeeba08..cc15f1d2b53 100644
                                --- a/mod/book/lib.php
                                +++ b/mod/book/lib.php
                                @@ -93,10 +93,7 @@ function book_update_instance($data, $mform) {
                                 }
                                 
                                 /**
                                - *
                                - * Given an ID of an instance of this module,
                                - * this function will permanently delete the instance
                                - * and any data that depends on it.
                                + * Delete book instance by activity id
                                  *
                                  * @param int $id
                                  * @return bool success
                                @@ -138,7 +135,7 @@ function book_user_outline($course, $user, $mod, $book) {
                                 
                                         return $result;
                                     }
                                -    return NULL;
                                +    return null;
                                 }
                                 
                                 /**
                                @@ -187,22 +184,6 @@ function book_grades($bookid) {
                                     return null;
                                 }
                                 
                                -/**
                                - * Returns the users with data in one book
                                - *
                                - * @todo deprecated - to be deleted in 2.2
                                - * @param int $bookid
                                - * @return array
                                - */
                                -function book_get_participants($bookid) {
                                -    // Must return an array of user records (all data) who are participants
                                -    // for a given instance of book. Must include every user involved
                                -    // in the instance, independent of his role (student, teacher, admin...)
                                -    // See other modules as example.
                                -
                                -    return false;
                                -}
                                -
                                 /**
                                  * This function returns if a scale is being used by one book
                                  * it it has support for grading and scales. Commented code should be
                                @@ -213,7 +194,7 @@ function book_get_participants($bookid) {
                                  * @param int $scaleid
                                  * @return boolean True if the scale is used by any journal
                                  */
                                -function book_scale_used($bookid,$scaleid) {
                                +function book_scale_used($bookid, $scaleid) {
                                     return false;
                                 }
                                 
                                @@ -239,7 +220,7 @@ function book_get_view_actions() {
                                     $return = array('view', 'view all');
                                 
                                     $plugins = get_plugin_list('booktool');
                                -    foreach($plugins as $plugin=>$dir) {
                                +    foreach ($plugins as $plugin => $dir) {
                                         if (file_exists("$dir/lib.php")) {
                                             require_once("$dir/lib.php");
                                         }
                                @@ -264,7 +245,7 @@ function book_get_post_actions() {
                                     $return = array('update');
                                 
                                     $plugins = get_plugin_list('booktool');
                                -    foreach($plugins as $plugin=>$dir) {
                                +    foreach ($plugins as $plugin => $dir) {
                                         if (file_exists("$dir/lib.php")) {
                                             require_once("$dir/lib.php");
                                         }
                                @@ -296,6 +277,7 @@ function book_supports($feature) {
                                         case FEATURE_GRADE_HAS_GRADE:         return false;
                                         case FEATURE_GRADE_OUTCOMES:          return false;
                                         case FEATURE_BACKUP_MOODLE2:          return true;
                                +        case FEATURE_SHOW_DESCRIPTION:        return true;
                                 
                                         default: return null;
                                     }
                                @@ -320,7 +302,7 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig
                                     }
                                 
                                     $plugins = get_plugin_list('booktool');
                                -    foreach($plugins as $plugin=>$dir) {
                                +    foreach ($plugins as $plugin => $dir) {
                                         if (file_exists("$dir/lib.php")) {
                                             require_once("$dir/lib.php");
                                         }
                                @@ -360,7 +342,7 @@ function book_get_file_areas($course, $cm, $context) {
                                 }
                                 
                                 /**
                                - * File browsing support for book module ontent area.
                                + * File browsing support for book module chapter area.
                                  * @param object $browser
                                  * @param object $areas
                                  * @param object $course
                                @@ -385,7 +367,7 @@ function book_get_file_info($browser, $areas, $course, $cm, $context, $filearea,
                                         return null;
                                     }
                                 
                                -    require_once("$CFG->dirroot/mod/book/locallib.php");
                                +    require_once(dirname(__FILE__).'/locallib.php');
                                 
                                     if (is_null($itemid)) {
                                         return new book_file_info($browser, $course, $cm, $context, $areas, $filearea);
                                @@ -411,15 +393,16 @@ function book_get_file_info($browser, $areas, $course, $cm, $context, $filearea,
                                 /**
                                  * Serves the book attachments. Implements needed access control ;-)
                                  *
                                - * @param object $course
                                - * @param object $cm
                                - * @param object $context
                                - * @param string $filearea
                                - * @param array $args
                                - * @param bool $forcedownload
                                + * @param stdClass $course course object
                                + * @param cm_info $cm course module object
                                + * @param context $context context object
                                + * @param string $filearea file area
                                + * @param array $args extra arguments
                                + * @param bool $forcedownload whether or not force download
                                + * @param array $options additional options affecting the file serving
                                  * @return bool false if file not found, does not return if found - just send the file
                                  */
                                -function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) {
                                +function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
                                     global $DB;
                                 
                                     if ($context->contextlevel != CONTEXT_MODULE) {
                                @@ -458,7 +441,7 @@ function book_pluginfile($course, $cm, $context, $filearea, $args, $forcedownloa
                                     }
                                 
                                     // finally send the file
                                -    send_stored_file($file, 360, 0, false);
                                +    send_stored_file($file, 360, 0, $forcedownload, $options);
                                 }
                                 
                                 /**
                                diff --git a/mod/book/locallib.php b/mod/book/locallib.php
                                index 8d0d06eaff9..3ba4af5100b 100644
                                --- a/mod/book/locallib.php
                                +++ b/mod/book/locallib.php
                                @@ -24,7 +24,7 @@
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -require_once($CFG->dirroot.'/mod/book/lib.php');
                                +require_once(dirname(__FILE__).'/lib.php');
                                 require_once($CFG->libdir.'/filelib.php');
                                 
                                 define('BOOK_NUM_NONE',     '0');
                                @@ -58,7 +58,7 @@ function book_preload_chapters($book) {
                                     $pagenum = 0; // chapter sort
                                     $i = 0;       // main chapter num
                                     $j = 0;       // subchapter num
                                -    foreach($chapters as $id=>$ch) {
                                +    foreach ($chapters as $id => $ch) {
                                         $oldch = clone($ch);
                                         $pagenum++;
                                         $ch->pagenum = $pagenum;
                                @@ -224,25 +224,24 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) {
                                     $context = context_module::instance($cm->id);
                                 
                                     switch ($book->numbering) {
                                -      case BOOK_NUM_NONE:
                                -          $toc .= '<div class="book_toc_none">';
                                -          break;
                                -      case BOOK_NUM_NUMBERS:
                                -          $toc .= '<div class="book_toc_numbered">';
                                -          break;
                                -      case BOOK_NUM_BULLETS:
                                -          $toc .= '<div class="book_toc_bullets">';
                                -          break;
                                -      case BOOK_NUM_INDENTED:
                                -          $toc .= '<div class="book_toc_indented">';
                                -          break;
                                +        case BOOK_NUM_NONE:
                                +            $toc .= '<div class="book_toc_none">';
                                +            break;
                                +        case BOOK_NUM_NUMBERS:
                                +            $toc .= '<div class="book_toc_numbered">';
                                +            break;
                                +        case BOOK_NUM_BULLETS:
                                +            $toc .= '<div class="book_toc_bullets">';
                                +            break;
                                +        case BOOK_NUM_INDENTED:
                                +            $toc .= '<div class="book_toc_indented">';
                                +            break;
                                     }
                                 
                                -
                                     if ($edit) { // Teacher's TOC
                                         $toc .= '<ul>';
                                         $i = 0;
                                -        foreach($chapters as $ch) {
                                +        foreach ($chapters as $ch) {
                                             $i++;
                                             $title = trim(format_string($ch->title, true, array('context'=>$context)));
                                             if (!$ch->subchapter) {
                                @@ -281,19 +280,27 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) {
                                             }
                                             $toc .=  '  ';
                                             if ($i != 1) {
                                -                $toc .=  ' <a title="'.get_string('up').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=1&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/up').'" class="iconsmall" alt="'.get_string('up').'" /></a>';
                                +                $toc .=  ' <a title="'.get_string('up').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.
                                +                        '&up=1&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/up').'" class="iconsmall" alt="'.get_string('up').'" /></a>';
                                             }
                                             if ($i != count($chapters)) {
                                -                $toc .=  ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.'&up=0&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/down').'" class="iconsmall" alt="'.get_string('down').'" /></a>';
                                +                $toc .=  ' <a title="'.get_string('down').'" href="move.php?id='.$cm->id.'&chapterid='.$ch->id.
                                +                        '&up=0&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/down').'" class="iconsmall" alt="'.get_string('down').'" /></a>';
                                             }
                                -            $toc .=  ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&id='.$ch->id.'"><img src="'.$OUTPUT->pix_url('t/edit').'" class="iconsmall" alt="'.get_string('edit').'" /></a>';
                                -            $toc .=  ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/delete').'" class="iconsmall" alt="'.get_string('delete').'" /></a>';
                                +            $toc .=  ' <a title="'.get_string('edit').'" href="edit.php?cmid='.$cm->id.'&id='.$ch->id.'"><img src="'.
                                +                    $OUTPUT->pix_url('t/edit').'" class="iconsmall" alt="'.get_string('edit').'" /></a>';
                                +            $toc .=  ' <a title="'.get_string('delete').'" href="delete.php?id='.$cm->id.'&chapterid='.$ch->id.
                                +                    '&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/delete').'" class="iconsmall" alt="'.get_string('delete').'" /></a>';
                                             if ($ch->hidden) {
                                -                $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/show').'" class="iconsmall" alt="'.get_string('show').'" /></a>';
                                +                $toc .= ' <a title="'.get_string('show').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.
                                +                        '&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/show').'" class="iconsmall" alt="'.get_string('show').'" /></a>';
                                             } else {
                                -                $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.'&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/hide').'" class="iconsmall" alt="'.get_string('hide').'" /></a>';
                                +                $toc .= ' <a title="'.get_string('hide').'" href="show.php?id='.$cm->id.'&chapterid='.$ch->id.
                                +                        '&sesskey='.$USER->sesskey.'"><img src="'.$OUTPUT->pix_url('t/hide').'" class="iconsmall" alt="'.get_string('hide').'" /></a>';
                                             }
                                -            $toc .= ' <a title="'.get_string('addafter', 'mod_book').'" href="edit.php?cmid='.$cm->id.'&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="'.$OUTPUT->pix_url('add', 'mod_book').'" class="iconsmall" alt="'.get_string('addafter', 'mod_book').'" /></a>';
                                +            $toc .= ' <a title="'.get_string('addafter', 'mod_book').'" href="edit.php?cmid='.$cm->id.
                                +                    '&pagenum='.$ch->pagenum.'&subchapter='.$ch->subchapter.'"><img src="'.
                                +                    $OUTPUT->pix_url('add', 'mod_book').'" class="iconsmall" alt="'.get_string('addafter', 'mod_book').'" /></a>';
                                 
                                             $toc .= (!$ch->subchapter) ? '<ul>' : '</li>';
                                             $first = 0;
                                @@ -301,7 +308,7 @@ function book_get_toc($chapters, $chapter, $book, $cm, $edit) {
                                         $toc .= '</ul></li></ul>';
                                     } else { // Normal students view
                                         $toc .= '<ul>';
                                -        foreach($chapters as $ch) {
                                +        foreach ($chapters as $ch) {
                                             $title = trim(format_string($ch->title, true, array('context'=>$context)));
                                             if (!$ch->hidden) {
                                                 if (!$ch->subchapter) {
                                @@ -420,7 +427,7 @@ class book_file_info extends file_info {
                                 
                                         $children = array();
                                         $chapters = $DB->get_records('book_chapters', array('bookid'=>$this->cm->instance), 'pagenum', 'id, pagenum');
                                -        foreach ($chapters as $itemid=>$unused) {
                                +        foreach ($chapters as $itemid => $unused) {
                                             if ($child = $this->browser->get_file_info($this->context, 'mod_book', $this->filearea, $itemid)) {
                                                 $children[] = $child;
                                             }
                                diff --git a/mod/book/mod_form.php b/mod/book/mod_form.php
                                index cd7934ed489..d58cce3d673 100644
                                --- a/mod/book/mod_form.php
                                +++ b/mod/book/mod_form.php
                                @@ -24,7 +24,7 @@
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -require_once($CFG->dirroot.'/mod/book/locallib.php');
                                +require_once(dirname(__FILE__).'/locallib.php');
                                 require_once($CFG->dirroot.'/course/moodleform_mod.php');
                                 
                                 class mod_book_mod_form extends moodleform_mod {
                                @@ -74,6 +74,4 @@ class mod_book_mod_form extends moodleform_mod {
                                 
                                         $this->add_action_buttons();
                                     }
                                -
                                -
                                 }
                                diff --git a/mod/book/move.php b/mod/book/move.php
                                index 40cecad893b..b1fd5e4f172 100644
                                --- a/mod/book/move.php
                                +++ b/mod/book/move.php
                                @@ -22,7 +22,6 @@
                                  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                  */
                                 
                                -
                                 require(dirname(__FILE__).'/../../config.php');
                                 require_once(dirname(__FILE__).'/locallib.php');
                                 
                                @@ -98,7 +97,7 @@ if ($chapters[$chs]->subchapter) { // Moving single subchapter up or down.
                                             $nothing = 1; // Already first.
                                         } else {
                                             $te = $chs - 1;
                                -            for($i = $chs-1; $i >= 1; $i--) {
                                +            for ($i = $chs-1; $i >= 1; $i--) {
                                                 if ($chapters[$i]->subchapter) {
                                                     $ts = $i;
                                                 } else {
                                @@ -113,7 +112,7 @@ if ($chapters[$chs]->subchapter) { // Moving single subchapter up or down.
                                         } else {
                                             $ts = $che + 1;
                                             $found = 0;
                                -            for($i = $che+1; $i <= count($chapters); $i++) {
                                +            for ($i = $che+1; $i <= count($chapters); $i++) {
                                                 if ($chapters[$i]->subchapter) {
                                                     $te = $i;
                                                 } else {
                                diff --git a/mod/book/settings.php b/mod/book/settings.php
                                index c741e6a8f8e..810ad3c76f4 100644
                                --- a/mod/book/settings.php
                                +++ b/mod/book/settings.php
                                @@ -25,7 +25,7 @@
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                 if ($ADMIN->fulltree) {
                                -    require_once("$CFG->dirroot/mod/book/lib.php");
                                +    require_once(dirname(__FILE__).'/lib.php');
                                 
                                     // General settings
                                 
                                diff --git a/mod/book/show.php b/mod/book/show.php
                                index a32cda9ec5c..ca52ac5820a 100644
                                --- a/mod/book/show.php
                                +++ b/mod/book/show.php
                                @@ -52,7 +52,7 @@ $DB->update_record('book_chapters', $chapter);
                                 if (!$chapter->subchapter) {
                                     $chapters = $DB->get_records('book_chapters', array('bookid'=>$book->id), 'pagenum', 'id, subchapter, hidden');
                                     $found = 0;
                                -    foreach($chapters as $ch) {
                                +    foreach ($chapters as $ch) {
                                         if ($ch->id == $chapter->id) {
                                             $found = 1;
                                         } else if ($found and $ch->subchapter) {
                                diff --git a/mod/book/version.php b/mod/book/version.php
                                index a1851794780..507b0e0b789 100644
                                --- a/mod/book/version.php
                                +++ b/mod/book/version.php
                                @@ -24,10 +24,7 @@
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -$module->version   = 2012042100; // The current module version (Date: YYYYMMDDXX)
                                -$module->requires  = 2011070100; // Requires this Moodle version
                                -$module->cron      = 0;          // Period for cron to check this module (secs)
                                 $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics)
                                -
                                -$module->maturity  = MATURITY_STABLE;
                                -$module->release   = "2.1 (20111105)"; // User-friendly version number
                                +$module->version   = 2012051500; // The current module version (Date: YYYYMMDDXX)
                                +$module->requires  = 2012051100; // Requires this Moodle version
                                +$module->cron      = 0;          // Period for cron to check this module (secs)
                                diff --git a/mod/book/view.php b/mod/book/view.php
                                index e1802cbd4c5..0ec34cffc00 100644
                                --- a/mod/book/view.php
                                +++ b/mod/book/view.php
                                @@ -75,7 +75,7 @@ if ($allowedit and !$chapters) {
                                 }
                                 // Check chapterid and read chapter data
                                 if ($chapterid == '0') { // Go to first chapter if no given.
                                -    foreach($chapters as $ch) {
                                +    foreach ($chapters as $ch) {
                                         if ($edit) {
                                             $chapterid = $ch->id;
                                             break;
                                @@ -140,12 +140,14 @@ foreach ($chapters as $ch) {
                                 
                                 $chnavigation = '';
                                 if ($previd) {
                                -    $chnavigation .= '<a title="'.get_string('navprev', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$previd.'"><img src="'.$OUTPUT->pix_url('nav_prev', 'mod_book').'" class="bigicon" alt="'.get_string('navprev', 'book').'"/></a>';
                                +    $chnavigation .= '<a title="'.get_string('navprev', 'book').'" href="view.php?id='.$cm->id.
                                +            '&chapterid='.$previd.'"><img src="'.$OUTPUT->pix_url('nav_prev', 'mod_book').'" class="bigicon" alt="'.get_string('navprev', 'book').'"/></a>';
                                 } else {
                                     $chnavigation .= '<img src="'.$OUTPUT->pix_url('nav_prev_dis', 'mod_book').'" class="bigicon" alt="" />';
                                 }
                                 if ($nextid) {
                                -    $chnavigation .= '<a title="'.get_string('navnext', 'book').'" href="view.php?id='.$cm->id.'&chapterid='.$nextid.'"><img src="'.$OUTPUT->pix_url('nav_next', 'mod_book').'" class="bigicon" alt="'.get_string('navnext', 'book').'" /></a>';
                                +    $chnavigation .= '<a title="'.get_string('navnext', 'book').'" href="view.php?id='.$cm->id.
                                +            '&chapterid='.$nextid.'"><img src="'.$OUTPUT->pix_url('nav_next', 'mod_book').'" class="bigicon" alt="'.get_string('navnext', 'book').'" /></a>';
                                 } else {
                                     $sec = '';
                                     if ($section = $DB->get_record('course_sections', array('id'=>$cm->section))) {
                                @@ -156,7 +158,8 @@ if ($nextid) {
                                     } else {
                                         $returnurl = "$CFG->wwwroot/course/view.php?id=$course->id#section-$sec";
                                     }
                                -    $chnavigation .= '<a title="'.get_string('navexit', 'book').'" href="'.$returnurl.'"><img src="'.$OUTPUT->pix_url('nav_exit', 'mod_book').'" class="bigicon" alt="'.get_string('navexit', 'book').'" /></a>';
                                +    $chnavigation .= '<a title="'.get_string('navexit', 'book').'" href="'.$returnurl.'"><img src="'.$OUTPUT->pix_url('nav_exit', 'mod_book').
                                +            '" class="bigicon" alt="'.get_string('navexit', 'book').'" /></a>';
                                 
                                     // we are cheating a bit here, viewing the last page means user has viewed the whole book
                                     $completion = new completion_info($course);
                                @@ -194,4 +197,3 @@ echo $OUTPUT->box_end();
                                 echo '<div class="navbottom">'.$chnavigation.'</div>';
                                 
                                 echo $OUTPUT->footer();
                                -
                                
                                From b9a363548dd5a08045e7040908f79bad874b5f6b Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Tue, 15 May 2012 03:12:32 +0200
                                Subject: [PATCH 214/455] MDL-32709 book: DB definition & upgrade cleanup
                                
                                ---
                                 mod/book/db/install.xml    |  44 +++++-----
                                 mod/book/db/upgrade.php    | 168 +------------------------------------
                                 mod/book/db/upgradelib.php | 168 -------------------------------------
                                 3 files changed, 24 insertions(+), 356 deletions(-)
                                 delete mode 100644 mod/book/db/upgradelib.php
                                
                                diff --git a/mod/book/db/install.xml b/mod/book/db/install.xml
                                index 217f0f1d821..29626a83f89 100644
                                --- a/mod/book/db/install.xml
                                +++ b/mod/book/db/install.xml
                                @@ -1,43 +1,43 @@
                                 <?xml version="1.0" encoding="UTF-8" ?>
                                -<XMLDB PATH="mod/book/db" VERSION="20111009" COMMENT="XMLDB file for Moodle mod_book"
                                +<XMLDB PATH="mod/book/db" VERSION="20120515" COMMENT="XMLDB file for Moodle mod_book"
                                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                     xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
                                 >
                                   <TABLES>
                                     <TABLE NAME="book" COMMENT="Defines book" NEXT="book_chapters">
                                       <FIELDS>
                                -        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="course"/>
                                -        <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
                                +        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="course"/>
                                +        <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
                                         <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="course" NEXT="intro"/>
                                -        <FIELD NAME="intro" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/>
                                -        <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="intro" NEXT="numbering"/>
                                -        <FIELD NAME="numbering" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="introformat" NEXT="customtitles"/>
                                -        <FIELD NAME="customtitles" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="numbering" NEXT="revision"/>
                                -        <FIELD NAME="revision" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" PREVIOUS="customtitles" NEXT="timecreated"/>
                                -        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="revision" NEXT="timemodified"/>
                                -        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated"/>
                                +        <FIELD NAME="intro" TYPE="text" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/>
                                +        <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="intro" NEXT="numbering"/>
                                +        <FIELD NAME="numbering" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="introformat" NEXT="customtitles"/>
                                +        <FIELD NAME="customtitles" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="numbering" NEXT="revision"/>
                                +        <FIELD NAME="revision" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="customtitles" NEXT="timecreated"/>
                                +        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="revision" NEXT="timemodified"/>
                                +        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated"/>
                                       </FIELDS>
                                       <KEYS>
                                -        <KEY NAME="primary" TYPE="primary" FIELDS="id" />
                                +        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
                                       </KEYS>
                                     </TABLE>
                                     <TABLE NAME="book_chapters" COMMENT="Defines book_chapters" PREVIOUS="book">
                                       <FIELDS>
                                -        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" SEQUENCE="true" NEXT="bookid"/>
                                -        <FIELD NAME="bookid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="pagenum"/>
                                -        <FIELD NAME="pagenum" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="bookid" NEXT="subchapter"/>
                                -        <FIELD NAME="subchapter" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="pagenum" NEXT="title"/>
                                +        <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="bookid"/>
                                +        <FIELD NAME="bookid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="pagenum"/>
                                +        <FIELD NAME="pagenum" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="bookid" NEXT="subchapter"/>
                                +        <FIELD NAME="subchapter" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="pagenum" NEXT="title"/>
                                         <FIELD NAME="title" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="subchapter" NEXT="content"/>
                                -        <FIELD NAME="content" TYPE="text" LENGTH="big" NOTNULL="true" SEQUENCE="false" PREVIOUS="title" NEXT="contentformat"/>
                                -        <FIELD NAME="contentformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="content" NEXT="hidden"/>
                                -        <FIELD NAME="hidden" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="contentformat" NEXT="timecreated"/>
                                -        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="hidden" NEXT="timemodified"/>
                                -        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated" NEXT="importsrc"/>
                                +        <FIELD NAME="content" TYPE="text" NOTNULL="true" SEQUENCE="false" PREVIOUS="title" NEXT="contentformat"/>
                                +        <FIELD NAME="contentformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="content" NEXT="hidden"/>
                                +        <FIELD NAME="hidden" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="contentformat" NEXT="timecreated"/>
                                +        <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="hidden" NEXT="timemodified"/>
                                +        <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="timecreated" NEXT="importsrc"/>
                                         <FIELD NAME="importsrc" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="timemodified"/>
                                       </FIELDS>
                                       <KEYS>
                                -        <KEY NAME="primary" TYPE="primary" FIELDS="id" />
                                +        <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
                                       </KEYS>
                                     </TABLE>
                                   </TABLES>
                                -</XMLDB>
                                +</XMLDB>
                                \ No newline at end of file
                                diff --git a/mod/book/db/upgrade.php b/mod/book/db/upgrade.php
                                index 35750b7ceb3..77a1ba90210 100644
                                --- a/mod/book/db/upgrade.php
                                +++ b/mod/book/db/upgrade.php
                                @@ -35,172 +35,8 @@ function xmldb_book_upgrade($oldversion) {
                                 
                                     $dbman = $DB->get_manager();
                                 
                                -    if ($oldversion < 2004081100) {
                                -        throw new upgrade_exception('mod_book', $oldversion, 'Can not upgrade such an old book module, sorry, you should have upgraded it long time ago in 1.9 already.');
                                -    }
                                -
                                -    if ($oldversion < 2007052001) {
                                -
                                -        // Changing type of field importsrc on table book_chapters to char
                                -        $table = new xmldb_table('book_chapters');
                                -        $field = new xmldb_field('importsrc', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'timemodified');
                                -
                                -        // Launch change of type for field importsrc
                                -        $dbman->change_field_type($table, $field);
                                -
                                -        upgrade_mod_savepoint(true, 2007052001, 'book');
                                -    }
                                -
                                -// 1.9.0 upgrade line.
                                -
                                -    if ($oldversion < 2010120801) {
                                -        // Rename field summary on table book to intro
                                -        $table = new xmldb_table('book');
                                -        $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'name');
                                -
                                -        // Launch rename field summary
                                -        if ($dbman->field_exists($table, $field)) {
                                -            $dbman->rename_field($table, $field, 'intro');
                                -        }
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2010120801, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2010120802) {
                                -        // Rename field summary on table book to intro
                                -        $table = new xmldb_table('book');
                                -        $field = new xmldb_field('intro', XMLDB_TYPE_TEXT, 'big', null, null, null, null, 'name');
                                -
                                -        // Launch rename field summary
                                -        $dbman->change_field_precision($table, $field);
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2010120802, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2010120803) {
                                -        // Define field introformat to be added to book
                                -        $table = new xmldb_table('book');
                                -        $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'intro');
                                -
                                -        // Launch add field introformat
                                -        if (!$dbman->field_exists($table, $field)) {
                                -            $dbman->add_field($table, $field);
                                -        }
                                -
                                -        // Conditionally migrate to html format in intro
                                -        if ($CFG->texteditors !== 'textarea') {
                                -            $rs = $DB->get_recordset('book', array('introformat'=>FORMAT_MOODLE), '', 'id,intro,introformat');
                                -            foreach ($rs as $b) {
                                -                $b->intro       = text_to_html($b->intro, false, false, true);
                                -                $b->introformat = FORMAT_HTML;
                                -                $DB->update_record('book', $b);
                                -                upgrade_set_timeout();
                                -            }
                                -            unset($b);
                                -            $rs->close();
                                -        }
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2010120803, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2010120804) {
                                -        // Define field introformat to be added to book
                                -        $table = new xmldb_table('book_chapters');
                                -        $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'content');
                                -
                                -        // Launch add field introformat
                                -        if (!$dbman->field_exists($table, $field)) {
                                -            $dbman->add_field($table, $field);
                                -        }
                                -
                                -        $DB->set_field('book_chapters', 'contentformat', FORMAT_HTML, array());
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2010120804, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2010120805) {
                                -        require_once("$CFG->dirroot/mod/book/db/upgradelib.php");
                                -
                                -        $sqlfrom = "FROM {book} b
                                -                    JOIN {modules} m ON m.name = 'book'
                                -                    JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = b.id)";
                                -
                                -        $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom");
                                -
                                -        if ($rs = $DB->get_recordset_sql("SELECT b.id, b.course, cm.id AS cmid $sqlfrom ORDER BY b.course, b.id")) {
                                -
                                -            $pbar = new progress_bar('migratebookfiles', 500, true);
                                -
                                -            $i = 0;
                                -            foreach ($rs as $book) {
                                -                $i++;
                                -                upgrade_set_timeout(360); // set up timeout, may also abort execution
                                -                $pbar->update($i, $count, "Migrating book files - $i/$count.");
                                -
                                -                $context = context_module::instance($book->cmid);
                                -
                                -                mod_book_migrate_moddata_dir_to_legacy($book, $context, '/');
                                -
                                -                // remove dirs if empty
                                -                @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id/");
                                -                @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/book/");
                                -                @rmdir("$CFG->dataroot/$book->course/$CFG->moddata/");
                                -                @rmdir("$CFG->dataroot/$book->course/");
                                -            }
                                -            $rs->close();
                                -        }
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2010120805, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2011011600) {
                                -        // Define field disableprinting to be dropped from book
                                -        $table = new xmldb_table('book');
                                -        $field = new xmldb_field('disableprinting');
                                -
                                -        // Conditionally launch drop field disableprinting
                                -        if ($dbman->field_exists($table, $field)) {
                                -            $dbman->drop_field($table, $field);
                                -        }
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2011011600, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2011011601) {
                                -        unset_config('book_tocwidth');
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2011011601, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2011090800) {
                                -        require_once("$CFG->dirroot/mod/book/db/upgradelib.php");
                                -
                                -        mod_book_migrate_all_areas();
                                -
                                -        upgrade_mod_savepoint(true, 2011090800, 'book');
                                -    }
                                -
                                -    if ($oldversion < 2011100900) {
                                -
                                -        // Define field revision to be added to book
                                -        $table = new xmldb_table('book');
                                -        $field = new xmldb_field('revision', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'customtitles');
                                -
                                -        // Conditionally launch add field revision
                                -        if (!$dbman->field_exists($table, $field)) {
                                -            $dbman->add_field($table, $field);
                                -        }
                                -
                                -        // book savepoint reached
                                -        upgrade_mod_savepoint(true, 2011100900, 'book');
                                -    }
                                +    // Moodle v2.2.0 release upgrade line
                                +    // Put any upgrade step following this
                                 
                                     return true;
                                 }
                                diff --git a/mod/book/db/upgradelib.php b/mod/book/db/upgradelib.php
                                deleted file mode 100644
                                index 5411930443c..00000000000
                                --- a/mod/book/db/upgradelib.php
                                +++ /dev/null
                                @@ -1,168 +0,0 @@
                                -<?php
                                -// This file is part of Book module for 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/>.
                                -
                                -/**
                                - * Book module upgrade related helper functions
                                - *
                                - * @package    mod_book
                                - * @copyright  2010 Petr Skoda {@link http://skodak.org}
                                - * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                - */
                                -
                                -defined('MOODLE_INTERNAL') || die;
                                -
                                -/**
                                - * Migrate book files stored in moddata folders.
                                - *
                                - * Please note it was a big mistake to store the files there in the first place!
                                - *
                                - * @param stdClass $book
                                - * @param stdClass $context
                                - * @param string $path
                                - * @return void
                                - */
                                -function mod_book_migrate_moddata_dir_to_legacy($book, $context, $path) {
                                -    global $OUTPUT, $CFG;
                                -
                                -    $base = "$CFG->dataroot/$book->course/$CFG->moddata/book/$book->id";
                                -    $fulldir = $base.$path;
                                -
                                -    if (!is_dir($fulldir)) {
                                -        // does not exist
                                -        return;
                                -    }
                                -
                                -    $fs      = get_file_storage();
                                -    $items   = new DirectoryIterator($fulldir);
                                -
                                -    foreach ($items as $item) {
                                -        if ($item->isDot()) {
                                -            unset($item); // release file handle
                                -            continue;
                                -        }
                                -
                                -        if ($item->isLink()) {
                                -            // do not follow symlinks - they were never supported in moddata, sorry
                                -            unset($item); // release file handle
                                -            continue;
                                -        }
                                -
                                -        if ($item->isFile()) {
                                -            if (!$item->isReadable()) {
                                -                echo $OUTPUT->notification(" File not readable, skipping: ".$fulldir.$item->getFilename());
                                -                unset($item); // release file handle
                                -                continue;
                                -            }
                                -
                                -            $filepath = clean_param("/$CFG->moddata/book/$book->id".$path, PARAM_PATH);
                                -            $filename = clean_param($item->getFilename(), PARAM_FILE);
                                -
                                -            if ($filename === '') {
                                -                // unsupported chars, sorry
                                -                unset($item); // release file handle
                                -                continue;
                                -            }
                                -
                                -            if (textlib::strlen($filepath) > 255) {
                                -                echo $OUTPUT->notification(" File path longer than 255 chars, skipping: ".$fulldir.$item->getFilename());
                                -                unset($item); // release file handle
                                -                continue;
                                -            }
                                -
                                -            if (!$fs->file_exists($context->id, 'course', 'legacy', '0', $filepath, $filename)) {
                                -                $file_record = array('contextid'=>$context->id, 'component'=>'course', 'filearea'=>'legacy', 'itemid'=>0, 'filepath'=>$filepath, 'filename'=>$filename,
                                -                                     'timecreated'=>$item->getCTime(), 'timemodified'=>$item->getMTime());
                                -                $fs->create_file_from_pathname($file_record, $fulldir.$item->getFilename());
                                -            }
                                -            $oldpathname = $fulldir.$item->getFilename();
                                -            unset($item); // release file handle
                                -            @unlink($oldpathname);
                                -
                                -        } else {
                                -            // migrate recursively all subdirectories
                                -            $oldpathname = $base.$item->getFilename().'/';
                                -            $subpath     = $path.$item->getFilename().'/';
                                -            unset($item);  // release file handle
                                -            mod_book_migrate_moddata_dir_to_legacy($book, $context, $subpath);
                                -            @rmdir($oldpathname); // deletes dir if empty
                                -        }
                                -    }
                                -    unset($items); // release file handles
                                -}
                                -
                                -/**
                                - * Migrate legacy files in intro and chapters
                                - * @return void
                                - */
                                -function mod_book_migrate_all_areas() {
                                -    global $DB;
                                -
                                -    $rsbooks = $DB->get_recordset('book');
                                -    foreach($rsbooks as $book) {
                                -        upgrade_set_timeout(360); // set up timeout, may also abort execution
                                -        $cm = get_coursemodule_from_instance('book', $book->id);
                                -        $context = context_module::instance($cm->id);
                                -        mod_book_migrate_area($book, 'intro', 'book', $book->course, $context, 'mod_book', 'intro', 0);
                                -
                                -        $rschapters = $DB->get_recordset('book_chapters', array('bookid'=>$book->id));
                                -        foreach ($rschapters as $chapter) {
                                -            mod_book_migrate_area($chapter, 'content', 'book_chapters', $book->course, $context, 'mod_book', 'chapter', $chapter->id);
                                -        }
                                -        $rschapters->close();
                                -    }
                                -    $rsbooks->close();
                                -}
                                -
                                -/**
                                - * Migrate one area, this should be probably part of moodle core...
                                - *
                                - * @param stdClass $record object to migrate files (book, chapter)
                                - * @param string $field field in the record we are going to migrate
                                - * @param string $table DB table containing the information to migrate
                                - * @param int $courseid id of the course the book module belongs to
                                - * @param context_module $context context of the book module
                                - * @param string $component component to be used for the migrated files
                                - * @param string $filearea filearea to be used for the migrated files
                                - * @param int $itemid id to be used for the migrated files
                                - * @return void
                                - */
                                -function mod_book_migrate_area($record, $field, $table, $courseid, $context, $component, $filearea, $itemid) {
                                -    global $CFG, $DB;
                                -
                                -    $fs = get_file_storage();
                                -
                                -    foreach(array(get_site()->id, $courseid) as $cid) {
                                -        $matches = null;
                                -        $ooldcontext = context_course::instance($cid);
                                -        if (preg_match_all("|$CFG->wwwroot/file.php(\?file=)?/$cid(/[^\s'\"&\?#]+)|", $record->$field, $matches)) {
                                -            $file_record = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid);
                                -            foreach ($matches[2] as $i=>$filepath) {
                                -                if (!$file = $fs->get_file_by_hash(sha1("/$ooldcontext->id/course/legacy/0".$filepath))) {
                                -                    continue;
                                -                }
                                -                try {
                                -                    if (!$newfile = $fs->get_file_by_hash(sha1("/$context->id/$component/$filearea/$itemid".$filepath))) {
                                -                        $fs->create_file_from_storedfile($file_record, $file);
                                -                    }
                                -                    $record->$field = str_replace($matches[0][$i], '@@PLUGINFILE@@'.$filepath, $record->$field);
                                -                } catch (Exception $ex) {
                                -                    // ignore problems
                                -                }
                                -                $DB->set_field($table, $field, $record->$field, array('id'=>$record->id));
                                -            }
                                -        }
                                -    }
                                -}
                                \ No newline at end of file
                                
                                From fc11586b03bdf0d62f6c2d31b81cb08a36e8d2c9 Mon Sep 17 00:00:00 2001
                                From: Mary Evans <lazydaisy@visible-expression.co.uk>
                                Date: Sun, 20 May 2012 22:37:54 +0100
                                Subject: [PATCH 215/455] MDL-33118 theme_mymobile: changed MAIN_CONTENT_TOKEN
                                 in layout/embedded.php to new format
                                
                                ---
                                 theme/mymobile/layout/embedded.php | 6 +++---
                                 1 file changed, 3 insertions(+), 3 deletions(-)
                                
                                diff --git a/theme/mymobile/layout/embedded.php b/theme/mymobile/layout/embedded.php
                                index e7fe4f0bdd3..172bc3dcdaa 100644
                                --- a/theme/mymobile/layout/embedded.php
                                +++ b/theme/mymobile/layout/embedded.php
                                @@ -52,7 +52,7 @@ echo $OUTPUT->doctype() ?>
                                     <!-- END OF HEADER -->
                                     <?php if ($mypagetype == 'mod-chat-gui_ajax-index') { ?>
                                     <div data-role="page" id="chatpage" data-fullscreen="true" data-title="<?php p($SITE->shortname) ?>">
                                -        <?php echo core_renderer::MAIN_CONTENT_TOKEN ?>
                                +        <?php echo $OUTPUT->main_content(); ?>
                                         <input type="button" value="back" data-role="none" id="chatback" onClick="history.back()">
                                     </div>
                                     <?php } else { ?>
                                @@ -64,11 +64,11 @@ echo $OUTPUT->doctype() ?>
                                             <?php } ?>
                                         </div>
                                         <div data-role="content" data-theme="<?php echo $databodytheme;?>">
                                -            <?php echo core_renderer::MAIN_CONTENT_TOKEN ?>
                                +            <?php echo $OUTPUT->main_content(); ?>
                                         </div>
                                     </div>
                                     <?php } ?>
                                     <!-- START OF FOOTER -->
                                     <?php echo $OUTPUT->standard_end_of_body_html() ?>
                                 </body>
                                -</html>
                                \ No newline at end of file
                                +</html>
                                
                                From a87aa28d514de977873e737ad05cd0f578add688 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Mon, 21 May 2012 00:33:58 +0200
                                Subject: [PATCH 216/455] MDL-32709 book: Fix logs handling
                                
                                ---
                                 .../restore_book_activity_task.class.php      | 13 +++++++--
                                 mod/book/db/log.php                           |  4 +--
                                 mod/book/tool/exportimscp/db/log.php          | 29 +++++++++++++++++++
                                 mod/book/tool/exportimscp/index.php           |  2 +-
                                 mod/book/tool/exportimscp/version.php         |  3 +-
                                 mod/book/tool/importhtml/version.php          |  3 +-
                                 mod/book/tool/print/db/log.php                | 29 +++++++++++++++++++
                                 mod/book/tool/print/version.php               |  3 +-
                                 mod/book/version.php                          |  4 +--
                                 9 files changed, 80 insertions(+), 10 deletions(-)
                                 create mode 100644 mod/book/tool/exportimscp/db/log.php
                                 create mode 100644 mod/book/tool/print/db/log.php
                                
                                diff --git a/mod/book/backup/moodle2/restore_book_activity_task.class.php b/mod/book/backup/moodle2/restore_book_activity_task.class.php
                                index bbe9b4af08b..da1b75f94d4 100644
                                --- a/mod/book/backup/moodle2/restore_book_activity_task.class.php
                                +++ b/mod/book/backup/moodle2/restore_book_activity_task.class.php
                                @@ -96,10 +96,17 @@ class restore_book_activity_task extends restore_activity_task {
                                     static public function define_restore_log_rules() {
                                         $rules = array();
                                 
                                +        $rules[] = new restore_log_rule('book', 'add', 'view.php?id={course_module}', '{book}');
                                +        $rules[] = new restore_log_rule('book', 'update', 'view.php?id={course_module}&chapterid={book_chapter}', '{book}');
                                         $rules[] = new restore_log_rule('book', 'update', 'view.php?id={course_module}', '{book}');
                                +        $rules[] = new restore_log_rule('book', 'view', 'view.php?id={course_module}&chapterid={book_chapter}', '{book}');
                                         $rules[] = new restore_log_rule('book', 'view', 'view.php?id={course_module}', '{book}');
                                -        $rules[] = new restore_log_rule('book', 'view all', 'view.php?id={course_module}', '{book}');
                                -        $rules[] = new restore_log_rule('book', 'print', 'view.php?id={course_module}', '{book}');
                                +        $rules[] = new restore_log_rule('book', 'print', 'tool/print/index.php?id={course_module}&chapterid={book_chapter}', '{book}');
                                +        $rules[] = new restore_log_rule('book', 'print', 'tool/print/index.php?id={course_module}', '{book}');
                                +        $rules[] = new restore_log_rule('book', 'exportimscp', 'tool/exportimscp/index.php?id={course_module}', '{book}');
                                +        // To convert old 'generateimscp' log entries
                                +        $rules[] = new restore_log_rule('book', 'generateimscp', 'tool/generateimscp/index.php?id={course_module}', '{book}',
                                +                'book', 'exportimscp', 'tool/exportimscp/index.php?id={course_module}', '{book}');
                                 
                                         return $rules;
                                     }
                                @@ -119,6 +126,8 @@ class restore_book_activity_task extends restore_activity_task {
                                     static public function define_restore_log_rules_for_course() {
                                         $rules = array();
                                 
                                +        $rules[] = new restore_log_rule('book', 'view all', 'index.php?id={course}', null);
                                +
                                         return $rules;
                                     }
                                 }
                                diff --git a/mod/book/db/log.php b/mod/book/db/log.php
                                index 979f58e8e03..cec6003b1e2 100644
                                --- a/mod/book/db/log.php
                                +++ b/mod/book/db/log.php
                                @@ -25,7 +25,7 @@
                                 defined('MOODLE_INTERNAL') || die();
                                 
                                 $logs = array(
                                +    array('module'=>'book', 'action'=>'add', 'mtable'=>'book', 'field'=>'name'),
                                     array('module'=>'book', 'action'=>'update', 'mtable'=>'book', 'field'=>'name'),
                                -    array('module'=>'book', 'action'=>'view', 'mtable'=>'book', 'field'=>'name'),
                                -    array('module'=>'book', 'action'=>'view all', 'mtable'=>'book', 'field'=>'name'),
                                +    array('module'=>'book', 'action'=>'view', 'mtable'=>'book', 'field'=>'name')
                                 );
                                diff --git a/mod/book/tool/exportimscp/db/log.php b/mod/book/tool/exportimscp/db/log.php
                                new file mode 100644
                                index 00000000000..4a130dc52c8
                                --- /dev/null
                                +++ b/mod/book/tool/exportimscp/db/log.php
                                @@ -0,0 +1,29 @@
                                +<?php
                                +// This file is part of Book module for 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/>.
                                +
                                +/**
                                + * Export to IMSCP booktool log events definition
                                + *
                                + * @package    booktool_exportimscp
                                + * @copyright  2012 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
                                + * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                + */
                                +
                                +defined('MOODLE_INTERNAL') || die();
                                +
                                +$logs = array(
                                +    array('module'=>'book', 'action'=>'exportimscp', 'mtable'=>'book', 'field'=>'name')
                                +);
                                diff --git a/mod/book/tool/exportimscp/index.php b/mod/book/tool/exportimscp/index.php
                                index d243ddc4d94..a0fa3f2079e 100644
                                --- a/mod/book/tool/exportimscp/index.php
                                +++ b/mod/book/tool/exportimscp/index.php
                                @@ -48,7 +48,7 @@ $strbooks = get_string('modulenameplural', 'book');
                                 $strbook  = get_string('modulename', 'book');
                                 $strtop  = get_string('top', 'book');
                                 
                                -add_to_log($course->id, 'book', 'generateimscp', 'tool/generateimscp/index.php?id='.$cm->id, $book->id, $cm->id);
                                +add_to_log($course->id, 'book', 'exportimscp', 'tool/exportimscp/index.php?id='.$cm->id, $book->id, $cm->id);
                                 
                                 $file = booktool_exportimscp_build_package($book, $context);
                                 
                                diff --git a/mod/book/tool/exportimscp/version.php b/mod/book/tool/exportimscp/version.php
                                index 34e022cc3d5..3fd6550db65 100644
                                --- a/mod/book/tool/exportimscp/version.php
                                +++ b/mod/book/tool/exportimscp/version.php
                                @@ -24,5 +24,6 @@
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -$plugin->version   = 2011101400; // The current plugin version (Date: YYYYMMDDXX)
                                 $plugin->component = 'booktool_exportimscp'; // Full name of the plugin (used for diagnostics)
                                +$plugin->version   = 2012052100; // The current plugin version (Date: YYYYMMDDXX)
                                +$plugin->requires  = 2012051900; // Requires this Moodle version
                                diff --git a/mod/book/tool/importhtml/version.php b/mod/book/tool/importhtml/version.php
                                index 3c5d0f4a830..e7f46c6af45 100644
                                --- a/mod/book/tool/importhtml/version.php
                                +++ b/mod/book/tool/importhtml/version.php
                                @@ -24,5 +24,6 @@
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -$plugin->version   = 2011101400; // The current plugin version (Date: YYYYMMDDXX)
                                 $plugin->component = 'booktool_importhtml'; // Full name of the plugin (used for diagnostics)
                                +$plugin->version   = 2012052100; // The current plugin version (Date: YYYYMMDDXX)
                                +$plugin->requires  = 2012051900; // Requires this Moodle version
                                diff --git a/mod/book/tool/print/db/log.php b/mod/book/tool/print/db/log.php
                                new file mode 100644
                                index 00000000000..efaa6844671
                                --- /dev/null
                                +++ b/mod/book/tool/print/db/log.php
                                @@ -0,0 +1,29 @@
                                +<?php
                                +// This file is part of Book module for 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/>.
                                +
                                +/**
                                + * Print booktool log events definition
                                + *
                                + * @package    booktool_print
                                + * @copyright  2012 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
                                + * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
                                + */
                                +
                                +defined('MOODLE_INTERNAL') || die();
                                +
                                +$logs = array(
                                +    array('module'=>'book', 'action'=>'print', 'mtable'=>'book', 'field'=>'name')
                                +);
                                diff --git a/mod/book/tool/print/version.php b/mod/book/tool/print/version.php
                                index 01ad0f171e1..0251d1fa6a5 100644
                                --- a/mod/book/tool/print/version.php
                                +++ b/mod/book/tool/print/version.php
                                @@ -24,5 +24,6 @@
                                 
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                -$plugin->version   = 2011101400; // The current plugin version (Date: YYYYMMDDXX)
                                 $plugin->component = 'booktool_print'; // Full name of the plugin (used for diagnostics)
                                +$plugin->version   = 2012052100; // The current plugin version (Date: YYYYMMDDXX)
                                +$plugin->requires  = 2012051900; // Requires this Moodle version
                                diff --git a/mod/book/version.php b/mod/book/version.php
                                index 507b0e0b789..fe07130751e 100644
                                --- a/mod/book/version.php
                                +++ b/mod/book/version.php
                                @@ -25,6 +25,6 @@
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                 $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics)
                                -$module->version   = 2012051500; // The current module version (Date: YYYYMMDDXX)
                                -$module->requires  = 2012051100; // Requires this Moodle version
                                +$module->version   = 2012052100; // The current module version (Date: YYYYMMDDXX)
                                +$module->requires  = 2012051900; // Requires this Moodle version
                                 $module->cron      = 0;          // Period for cron to check this module (secs)
                                
                                From f7e6dd4d419b4b4c09b6339696d641e50d7f89e2 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Mon, 21 May 2012 00:54:53 +0200
                                Subject: [PATCH 217/455] MDL-32709 book: now standard module + new strings
                                 added
                                
                                Note the lang file is completely disordered yet
                                ---
                                 lib/pluginlib.php         |  6 +++++-
                                 mod/book/lang/en/book.php | 13 +++++++++++--
                                 2 files changed, 16 insertions(+), 3 deletions(-)
                                
                                diff --git a/lib/pluginlib.php b/lib/pluginlib.php
                                index 8a19144cf61..0dc33d00626 100644
                                --- a/lib/pluginlib.php
                                +++ b/lib/pluginlib.php
                                @@ -380,6 +380,10 @@ class plugin_manager {
                                                 'social_activities', 'tag_flickr', 'tag_youtube', 'tags'
                                             ),
                                 
                                +            'booktool' => array(
                                +                'exportimscp', 'importhtml', 'print'
                                +            ),
                                +
                                             'coursereport' => array(
                                                 //deprecated!
                                             ),
                                @@ -441,7 +445,7 @@ class plugin_manager {
                                             ),
                                 
                                             'mod' => array(
                                -                'assign', 'assignment', 'chat', 'choice', 'data', 'feedback', 'folder',
                                +                'assign', 'assignment', 'book', 'chat', 'choice', 'data', 'feedback', 'folder',
                                                 'forum', 'glossary', 'imscp', 'label', 'lesson', 'lti', 'page',
                                                 'quiz', 'resource', 'scorm', 'survey', 'url', 'wiki', 'workshop'
                                             ),
                                diff --git a/mod/book/lang/en/book.php b/mod/book/lang/en/book.php
                                index acbced657c2..facfdb95498 100644
                                --- a/mod/book/lang/en/book.php
                                +++ b/mod/book/lang/en/book.php
                                @@ -25,8 +25,15 @@
                                 defined('MOODLE_INTERNAL') || die;
                                 
                                 $string['modulename'] = 'Book';
                                +$string['modulename_help'] = 'The book module enables a teacher to create a multi-page resource in a book-like format, with chapters and subchapters. Books can contain media files as well as text and are useful for displaying lengthy passages of information which can be broken down into sections.
                                +
                                +A book may be used
                                +
                                +* To display reading material for individual modules of study
                                +* As a staff departmental handbook
                                +* As a showcase portfolio of student work';
                                +$string['modulename_link'] = 'mod/book/view';
                                 $string['modulenameplural'] = 'Books';
                                -$string['modulename_help'] = 'Book is a simple multipage study material.';
                                 $string['pluginname'] = 'Book';
                                 $string['pluginadministration'] = 'Book administration';
                                 
                                @@ -102,4 +109,6 @@ $string['errorchapter'] = 'Error reading book chapter.';
                                 
                                 $string['page-mod-book-x'] = 'Any book module page';
                                 
                                -$string['missingfilemanagement'] = 'Dear users of Book module, I supposed you have already notised that it is not possible to delete or manage files used in Book chapters. Please vote in {$a} to get this fixed, thanks. Petr Škoda';
                                \ No newline at end of file
                                +$string['missingfilemanagement'] = 'Dear users of Book module, I supposed you have already notised that it is not possible to delete or manage files used in Book chapters. Please vote in {$a} to get this fixed, thanks. Petr Škoda';
                                +$string['subplugintype_booktool'] = 'Book tool';
                                +$string['subplugintype_booktool_plural'] = 'Book tools';
                                
                                From 9717aa2ddd552566a3f76a26c9eaeb2e8533663f Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Mon, 21 May 2012 01:26:52 +0200
                                Subject: [PATCH 218/455] MDL-32709 book: delete some not needed stuff
                                
                                ---
                                 mod/book/edit.php                 | 4 ----
                                 mod/book/lang/en/book.php         | 1 -
                                 mod/book/lib.php                  | 4 ----
                                 mod/book/tool/exportimscp/lib.php | 6 +-----
                                 mod/book/tool/importhtml/lib.php  | 6 +-----
                                 mod/book/tool/print/lib.php       | 4 ----
                                 6 files changed, 2 insertions(+), 23 deletions(-)
                                
                                diff --git a/mod/book/edit.php b/mod/book/edit.php
                                index 0af2b99f2d6..50088adf8d3 100644
                                --- a/mod/book/edit.php
                                +++ b/mod/book/edit.php
                                @@ -115,10 +115,6 @@ $PAGE->set_heading(format_string($course->fullname));
                                 echo $OUTPUT->header();
                                 echo $OUTPUT->heading(get_string('editingchapter', 'mod_book'));
                                 
                                -if (debugging()) {
                                -    echo $OUTPUT->box($OUTPUT->notification(get_string('missingfilemanagement', 'mod_book', html_writer::link('http://tracker.moodle.org/browse/MDL-28019', 'MDL-28019'))));
                                -}
                                -
                                 $mform->display();
                                 
                                 echo $OUTPUT->footer();
                                diff --git a/mod/book/lang/en/book.php b/mod/book/lang/en/book.php
                                index facfdb95498..f737bda401f 100644
                                --- a/mod/book/lang/en/book.php
                                +++ b/mod/book/lang/en/book.php
                                @@ -109,6 +109,5 @@ $string['errorchapter'] = 'Error reading book chapter.';
                                 
                                 $string['page-mod-book-x'] = 'Any book module page';
                                 
                                -$string['missingfilemanagement'] = 'Dear users of Book module, I supposed you have already notised that it is not possible to delete or manage files used in Book chapters. Please vote in {$a} to get this fixed, thanks. Petr Škoda';
                                 $string['subplugintype_booktool'] = 'Book tool';
                                 $string['subplugintype_booktool_plural'] = 'Book tools';
                                diff --git a/mod/book/lib.php b/mod/book/lib.php
                                index cc15f1d2b53..80d21160ca3 100644
                                --- a/mod/book/lib.php
                                +++ b/mod/book/lib.php
                                @@ -297,10 +297,6 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig
                                         return;
                                     }
                                 
                                -    if (empty($PAGE->cm->context)) {
                                -        $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance);
                                -    }
                                -
                                     $plugins = get_plugin_list('booktool');
                                     foreach ($plugins as $plugin => $dir) {
                                         if (file_exists("$dir/lib.php")) {
                                diff --git a/mod/book/tool/exportimscp/lib.php b/mod/book/tool/exportimscp/lib.php
                                index d655c31963e..f807c13d513 100644
                                --- a/mod/book/tool/exportimscp/lib.php
                                +++ b/mod/book/tool/exportimscp/lib.php
                                @@ -37,13 +37,9 @@ function booktool_exportimscp_extend_settings_navigation(settings_navigation $se
                                         return;
                                     }
                                 
                                -    if (empty($PAGE->cm->context)) {
                                -        $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance);
                                -    }
                                -
                                     if (has_capability('booktool/exportimscp:export', $PAGE->cm->context)) {
                                         $url = new moodle_url('/mod/book/tool/exportimscp/index.php', array('id'=>$PAGE->cm->id));
                                         $icon = new pix_icon('generate', '', 'booktool_exportimscp', array('class'=>'icon'));
                                         $node->add(get_string('generateimscp', 'booktool_exportimscp'), $url, navigation_node::TYPE_SETTING, null, null, $icon);
                                     }
                                -}
                                \ No newline at end of file
                                +}
                                diff --git a/mod/book/tool/importhtml/lib.php b/mod/book/tool/importhtml/lib.php
                                index 1bb81f555cb..833324070ee 100644
                                --- a/mod/book/tool/importhtml/lib.php
                                +++ b/mod/book/tool/importhtml/lib.php
                                @@ -37,12 +37,8 @@ function booktool_importhtml_extend_settings_navigation(settings_navigation $set
                                          return;
                                      }
                                 
                                -     if (empty($PAGE->cm->context)) {
                                -         $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance);
                                -     }
                                -
                                      if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) {
                                          $url = new moodle_url('/mod/book/tool/importhtml/index.php', array('id'=>$PAGE->cm->id));
                                          $node->add(get_string('import', 'booktool_importhtml'), $url, navigation_node::TYPE_SETTING, null, null, null);
                                      }
                                -}
                                \ No newline at end of file
                                +}
                                diff --git a/mod/book/tool/print/lib.php b/mod/book/tool/print/lib.php
                                index 5a2e92c27c9..8172c07be7e 100644
                                --- a/mod/book/tool/print/lib.php
                                +++ b/mod/book/tool/print/lib.php
                                @@ -37,10 +37,6 @@ function booktool_print_extend_settings_navigation(settings_navigation $settings
                                         return;
                                     }
                                 
                                -    if (empty($PAGE->cm->context)) {
                                -        $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance);
                                -    }
                                -
                                     $params = $PAGE->url->params();
                                 
                                     if (empty($params['id']) or empty($params['chapterid'])) {
                                
                                From a1448fc012d025d140c6c250249ec0800a80aa23 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Mon, 21 May 2012 01:27:40 +0200
                                Subject: [PATCH 219/455] MDL-32709 book: fix send_stored_file() call
                                
                                ---
                                 mod/book/tool/exportimscp/index.php | 2 +-
                                 1 file changed, 1 insertion(+), 1 deletion(-)
                                
                                diff --git a/mod/book/tool/exportimscp/index.php b/mod/book/tool/exportimscp/index.php
                                index a0fa3f2079e..a9cdd0c3616 100644
                                --- a/mod/book/tool/exportimscp/index.php
                                +++ b/mod/book/tool/exportimscp/index.php
                                @@ -52,4 +52,4 @@ add_to_log($course->id, 'book', 'exportimscp', 'tool/exportimscp/index.php?id='.
                                 
                                 $file = booktool_exportimscp_build_package($book, $context);
                                 
                                -send_stored_file($file, 10, 0, true, clean_filename($book->name).'.zip');
                                +send_stored_file($file, 10, 0, true, array('filename' => clean_filename($book->name).'.zip'));
                                
                                From 079be74dd5812d582d6c60acb7d6c106bb050cd3 Mon Sep 17 00:00:00 2001
                                From: "Eloy Lafuente (stronk7)" <stronk7@moodle.org>
                                Date: Mon, 21 May 2012 01:50:20 +0200
                                Subject: [PATCH 220/455] MDL-32709 book: finish coding style review (errors
                                 only)
                                
                                ---
                                 mod/book/tool/exportimscp/locallib.php | 26 ++++++++++++++++----------
                                 mod/book/tool/importhtml/lib.php       | 16 ++++++++--------
                                 mod/book/tool/importhtml/locallib.php  | 10 +++++-----
                                 mod/book/tool/print/index.php          |  2 +-
                                 mod/book/tool/print/locallib.php       | 26 +++++++++++++-------------
                                 5 files changed, 43 insertions(+), 37 deletions(-)
                                
                                diff --git a/mod/book/tool/exportimscp/locallib.php b/mod/book/tool/exportimscp/locallib.php
                                index 3a64999e095..788c2f4cc43 100644
                                --- a/mod/book/tool/exportimscp/locallib.php
                                +++ b/mod/book/tool/exportimscp/locallib.php
                                @@ -73,7 +73,7 @@ function booktool_exportimscp_build_package($book, $context) {
                                              WHERE contextid = :contextid AND component = 'booktool_exportimscp' AND itemid < :revision";
                                     $params = array('contextid'=>$context->id, 'revision'=>$book->revision);
                                     $revisions = $DB->get_records_sql($sql, $params);
                                -    foreach ($revisions as $rev=>$unused) {
                                +    foreach ($revisions as $rev => $unused) {
                                         $fs->delete_area_files($context->id, 'booktool_exportimscp', 'temp', $rev);
                                         $fs->delete_area_files($context->id, 'booktool_exportimscp', 'package', $rev);
                                     }
                                @@ -108,11 +108,13 @@ function booktool_exportimscp_prepare_files($book, $context) {
                                             $file->delete();
                                         }
                                         $content = booktool_exportimscp_chapter_content($chapter, $context);
                                -        $index_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision, 'filepath'=>"/$chapter->pagenum/", 'filename'=>'index.html');
                                +        $index_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp',
                                +                'itemid'=>$book->revision, 'filepath'=>"/$chapter->pagenum/", 'filename'=>'index.html');
                                         $fs->create_file_from_string($index_file_record, $content);
                                     }
                                 
                                -    $css_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision, 'filepath'=>"/css/", 'filename'=>'styles.css');
                                +    $css_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp',
                                +            'itemid'=>$book->revision, 'filepath'=>"/css/", 'filename'=>'styles.css');
                                     $fs->create_file_from_pathname($css_file_record, dirname(__FILE__).'/imscp.css');
                                 
                                     // Init imsmanifest and others
                                @@ -137,6 +139,7 @@ function booktool_exportimscp_prepare_files($book, $context) {
                                 
                                     // To store the prev level (book only have 0 and 1)
                                     $prevlevel = null;
                                +    $currlevel = 0;
                                     foreach ($chapters as $chapter) {
                                         // Calculate current level ((book only have 0 and 1)
                                         $currlevel = empty($chapter->subchapter) ? 0 : 1;
                                @@ -164,9 +167,10 @@ function booktool_exportimscp_prepare_files($book, $context) {
                                 
                                         $chaptertitle = format_string($chapter->title, true, array('context'=>$context));
                                 
                                -       // Add the imsitems
                                -        $imsitems .= $currspaces .'        <item identifier="ITEM-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum .'" isvisible="true" identifierref="RES-' . $book->course . '-' . $book->id . '-' . $chapter->pagenum . '">
                                - ' . $currspaces . '         <title>' . htmlspecialchars($chaptertitle) . '' . "\n";
                                +        // Add the imsitems
                                +        $imsitems .= $currspaces .'        \n" .
                                +                $currspaces . '         ' . htmlspecialchars($chaptertitle) . '' . "\n";
                                 
                                         // Add the imsresources
                                         // First, check if we have localfiles
                                @@ -177,9 +181,10 @@ function booktool_exportimscp_prepare_files($book, $context) {
                                         // Now add the dependency to css
                                         $cssdependency = "\n" . '      ';
                                         // Now build the resources section
                                -        $imsresources .= '    
                                -      ' . implode($localfiles) . $cssdependency . '
                                -    ' . "\n";
                                +        $imsresources .= '    ' . "\n" .
                                +                '      ' . implode($localfiles) . $cssdependency . "\n".
                                +                '    ' . "\n";
                                     }
                                 
                                     // Close items (the latest chapter)
                                @@ -208,7 +213,8 @@ function booktool_exportimscp_prepare_files($book, $context) {
                                     // Close manifest
                                     $imsmanifest .= "\n\n";
                                 
                                -    $manifest_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp', 'itemid'=>$book->revision, 'filepath'=>"/", 'filename'=>'imsmanifest.xml');
                                +    $manifest_file_record = array('contextid'=>$context->id, 'component'=>'booktool_exportimscp', 'filearea'=>'temp',
                                +            'itemid'=>$book->revision, 'filepath'=>"/", 'filename'=>'imsmanifest.xml');
                                     $fs->create_file_from_string($manifest_file_record, $imsmanifest);
                                 }
                                 
                                diff --git a/mod/book/tool/importhtml/lib.php b/mod/book/tool/importhtml/lib.php
                                index 833324070ee..bf9c7d7d9d1 100644
                                --- a/mod/book/tool/importhtml/lib.php
                                +++ b/mod/book/tool/importhtml/lib.php
                                @@ -31,14 +31,14 @@ defined('MOODLE_INTERNAL') || die;
                                  * @param navigation_node $node The node to add module settings to
                                  */
                                 function booktool_importhtml_extend_settings_navigation(settings_navigation $settings, navigation_node $node) {
                                -     global $USER, $PAGE, $CFG, $DB, $OUTPUT;
                                +    global $USER, $PAGE, $CFG, $DB, $OUTPUT;
                                 
                                -     if ($PAGE->cm->modname !== 'book') {
                                -         return;
                                -     }
                                +    if ($PAGE->cm->modname !== 'book') {
                                +        return;
                                +    }
                                 
                                -     if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) {
                                -         $url = new moodle_url('/mod/book/tool/importhtml/index.php', array('id'=>$PAGE->cm->id));
                                -         $node->add(get_string('import', 'booktool_importhtml'), $url, navigation_node::TYPE_SETTING, null, null, null);
                                -     }
                                +    if (has_capability('booktool/importhtml:import', $PAGE->cm->context)) {
                                +        $url = new moodle_url('/mod/book/tool/importhtml/index.php', array('id'=>$PAGE->cm->id));
                                +        $node->add(get_string('import', 'booktool_importhtml'), $url, navigation_node::TYPE_SETTING, null, null, null);
                                +    }
                                 }
                                diff --git a/mod/book/tool/importhtml/locallib.php b/mod/book/tool/importhtml/locallib.php
                                index b8c44c00174..7aa04cab1a5 100644
                                --- a/mod/book/tool/importhtml/locallib.php
                                +++ b/mod/book/tool/importhtml/locallib.php
                                @@ -98,7 +98,7 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $
                                         $matches = null;
                                         if (preg_match_all('/(src|codebase|name|href)\s*=\s*"([^"]+)"/i', $chapter->content, $matches)) {
                                             $file_record = array('contextid'=>$context->id, 'component'=>'mod_book', 'filearea'=>'chapter', 'itemid'=>$chapter->id);
                                -            foreach ($matches[0] as $i=>$match) {
                                +            foreach ($matches[0] as $i => $match) {
                                                 $filepath = dirname($chapter->importsrc).'/'.$matches[2][$i];
                                                 $filepath = toolbook_importhtml_fix_path($filepath);
                                 
                                @@ -128,7 +128,7 @@ function toolbook_importhtml_import_chapters($package, $type, $book, $context, $
                                         $newcontent = $chapter->content;
                                         $matches = null;
                                         if (preg_match_all('/(href)\s*=\s*"([^"]+)"/i', $chapter->content, $matches)) {
                                -            foreach ($matches[0] as $i=>$match) {
                                +            foreach ($matches[0] as $i => $match) {
                                                 if (strpos($matches[2][$i], ':') !== false or strpos($matches[2][$i], '@') !== false) {
                                                     // it is either absolute or pluginfile link
                                                     continue;
                                @@ -177,7 +177,7 @@ function toolbook_importhtml_parse_styles($html) {
                                     if (preg_match('/]*>(.+)<\/head>/is', $html, $matches)) {
                                         $head = $matches[1];
                                         if (preg_match_all('/]+rel="stylesheet"[^>]*>/i', $head, $matches)) { // Extract links to css.
                                -            for($i=0; $i$htmlfiles) {
                                +        foreach ($topdirs as $dir => $htmlfiles) {
                                             if (empty($htmlfiles)) {
                                                 continue;
                                             }
                                diff --git a/mod/book/tool/print/index.php b/mod/book/tool/print/index.php
                                index c793ad97bbb..5205435375e 100644
                                --- a/mod/book/tool/print/index.php
                                +++ b/mod/book/tool/print/index.php
                                @@ -143,7 +143,7 @@ if ($chapter) {
                                     
                            :
                            ::
                        • diff --git a/mod/book/tool/print/locallib.php b/mod/book/tool/print/locallib.php index 2cae0484168..821c278787e 100644 --- a/mod/book/tool/print/locallib.php +++ b/mod/book/tool/print/locallib.php @@ -44,18 +44,18 @@ function booktool_print_get_toc($chapters, $book, $cm) { $toc = ''; // Representation of toc (HTML). switch ($book->numbering) { - case BOOK_NUM_NONE: - $toc .= '
                          '; - break; - case BOOK_NUM_NUMBERS: - $toc .= '
                          '; - break; - case BOOK_NUM_BULLETS: - $toc .= '
                          '; - break; - case BOOK_NUM_INDENTED: - $toc .= '
                          '; - break; + case BOOK_NUM_NONE: + $toc .= '
                          '; + break; + case BOOK_NUM_NUMBERS: + $toc .= '
                          '; + break; + case BOOK_NUM_BULLETS: + $toc .= '
                          '; + break; + case BOOK_NUM_INDENTED: + $toc .= '
                          '; + break; } $toc .= ''; // Representation of toc (HTML). @@ -66,7 +66,7 @@ function booktool_print_get_toc($chapters, $book, $cm) { $toc .= '

                          '.get_string('toc', 'mod_book').'

                          '; } $toc .= '
                            '; - foreach($chapters as $ch) { + foreach ($chapters as $ch) { if (!$ch->hidden) { $title = book_get_chapter_title($ch->id, $chapters, $book, $context); if (!$ch->subchapter) { From 2cd972c1c60e6780140092106c44b5e216335a7a Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Mon, 21 May 2012 14:06:00 +1200 Subject: [PATCH 221/455] MDL-32709 Pre-integration trivial clean up * Added a comment for the BOOK_NUM_* defines. * Fixed broken redirects in tool/importhtml/index.php * Fixed typo in book_preload_chapters [subchpaters => subchapters] * Fixed copy paste docblock error in tool/print/locallib.php * Removed the .gitignore file as Eloy had previously mentioned that. --- mod/book/.gitignore | 16 ---------------- mod/book/locallib.php | 11 +++++++++-- mod/book/tool/importhtml/index.php | 4 ++-- mod/book/tool/print/locallib.php | 2 +- 4 files changed, 12 insertions(+), 21 deletions(-) delete mode 100644 mod/book/.gitignore diff --git a/mod/book/.gitignore b/mod/book/.gitignore deleted file mode 100644 index 043a39ba30d..00000000000 --- a/mod/book/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -# See gitignore(5) man page for more details -# -*~ -*.swp -/tags -/TAGS -/cscope.* -/.patches/ -/.idea/ -/nbproject/ -CVS -.DS_Store -/.settings/ -/.project -/.buildpath -/.cache diff --git a/mod/book/locallib.php b/mod/book/locallib.php index 3ba4af5100b..96f9f456aad 100644 --- a/mod/book/locallib.php +++ b/mod/book/locallib.php @@ -27,6 +27,13 @@ defined('MOODLE_INTERNAL') || die; require_once(dirname(__FILE__).'/lib.php'); require_once($CFG->libdir.'/filelib.php'); +/** + * The following defines are used to define how the chapters and subchapters of a book should be displayed in that table of contents. + * BOOK_NUM_NONE No special styling will applied and the editor will be able to do what ever thay want in the title + * BOOK_NUM_NUMBERS Chapters and subchapters are numbered (1, 1.1, 1.2, 2, ...) + * BOOK_NUM_BULLETS Subchapters are indented and displayed with bullets + * BOOK_NUM_INDENTED Subchapters are indented + */ define('BOOK_NUM_NONE', '0'); define('BOOK_NUM_NUMBERS', '1'); define('BOOK_NUM_BULLETS', '2'); @@ -88,7 +95,7 @@ function book_preload_chapters($book) { $hidesub = $ch->hidden; $parent = $ch->id; $ch->parent = null; - $ch->subchpaters = array(); + $ch->subchapters = array(); } else { $ch->prev = $prevsub; $ch->next = null; @@ -96,7 +103,7 @@ function book_preload_chapters($book) { $chapters[$prevsub]->next = $ch->id; } $ch->parent = $parent; - $ch->subchpaters = null; + $ch->subchapters = null; $chapters[$parent]->subchapters[$ch->id] = $ch->id; if ($hidesub) { // all subchapters in hidden chapter must be hidden too diff --git a/mod/book/tool/importhtml/index.php b/mod/book/tool/importhtml/index.php index f28bd445b17..95bdd381566 100644 --- a/mod/book/tool/importhtml/index.php +++ b/mod/book/tool/importhtml/index.php @@ -61,9 +61,9 @@ $mform = new booktool_importhtml_form(null, array('id'=>$id, 'chapterid'=>$chapt // If data submitted, then process and store. if ($mform->is_cancelled()) { if (empty($chapter->id)) { - redirect("view.php?id=$cm->id"); + redirect("/mod/book/view.php?id=$cm->id"); } else { - redirect("view.php?id=$cm->id&chapterid=$chapter->id"); + redirect("/mod/book/view.php?id=$cm->id&chapterid=$chapter->id"); } } else if ($data = $mform->get_data()) { diff --git a/mod/book/tool/print/locallib.php b/mod/book/tool/print/locallib.php index 821c278787e..524ad16f2d7 100644 --- a/mod/book/tool/print/locallib.php +++ b/mod/book/tool/print/locallib.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * HTML import lib + * Book print lib * * @package booktool_print * @copyright 2011 Petr Skoda {@link http://skodak.org} From 728ff21b9fd6342acc927ab4496f640cd1e7a709 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Tue, 15 May 2012 07:46:45 +0700 Subject: [PATCH 222/455] MDL-32860 grade: refactored graded_users_iterator --- grade/lib.php | 80 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/grade/lib.php b/grade/lib.php index 8c969f28994..7f13b7fbf0f 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -32,16 +32,56 @@ require_once $CFG->libdir.'/gradelib.php'; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class graded_users_iterator { - public $course; - public $grade_items; - public $groupid; - public $users_rs; - public $grades_rs; - public $gradestack; - public $sortfield1; - public $sortorder1; - public $sortfield2; - public $sortorder2; + + /** + * The couse whose users we are interested in + */ + protected $course; + + /** + * An array of grade items or null if only user data was requested + */ + protected $grade_items; + + /** + * The group ID we are interested in. 0 means all groups. + */ + protected $groupid; + + /** + * A recordset of graded users + */ + protected $users_rs; + + /** + * A recordset of user grades (grade_grade instances) + */ + protected $grades_rs; + + /** + * Array used when moving to next user while iterating through the grades recordset + */ + protected $gradestack; + + /** + * The first field of the users table by which the array of users will be sorted + */ + protected $sortfield1; + + /** + * Should sortfield1 be ASC or DESC + */ + protected $sortorder1; + + /** + * The second field of the users table by which the array of users will be sorted + */ + protected $sortfield2; + + /** + * Should sortfield2 be ASC or DESC + */ + protected $sortorder2; /** * Constructor @@ -54,7 +94,7 @@ class graded_users_iterator { * @param string $sortfield2 The second field of the users table by which the array of users will be sorted * @param string $sortorder2 The order in which the second sorting field will be sorted (ASC or DESC) */ - public function graded_users_iterator($course, $grade_items=null, $groupid=0, + public function __construct($course, $grade_items=null, $groupid=0, $sortfield1='lastname', $sortorder1='ASC', $sortfield2='firstname', $sortorder2='ASC') { $this->course = $course; @@ -70,6 +110,7 @@ class graded_users_iterator { /** * Initialise the iterator + * * @return boolean success */ public function init() { @@ -174,7 +215,7 @@ class graded_users_iterator { * Returns information about the next user * @return mixed array of user info, all grades and feedback or null when no more users found */ - function next_user() { + public function next_user() { if (!$this->users_rs) { return false; // no users present } @@ -238,10 +279,9 @@ class graded_users_iterator { } /** - * Close the iterator, do not forget to call this function. - * @return void + * Close the iterator, do not forget to call this function */ - function close() { + public function close() { if ($this->users_rs) { $this->users_rs->close(); $this->users_rs = null; @@ -255,23 +295,23 @@ class graded_users_iterator { /** - * _push + * Add a grade_grade instance to the grade stack * * @param grade_grade $grade Grade object * * @return void */ - function _push($grade) { + private function _push($grade) { array_push($this->gradestack, $grade); } /** - * _pop + * Remove a grade_grade instance from the grade stack * - * @return object current grade object + * @return grade_grade current grade object */ - function _pop() { + private function _pop() { global $DB; if (empty($this->gradestack)) { if (empty($this->grades_rs) || !$this->grades_rs->valid()) { From 9e4b9a00cc1b1ceb8ca5314b9c9cac71e2a3944d Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Thu, 7 Apr 2011 14:16:07 +0930 Subject: [PATCH 223/455] MDL-27120 backup: replace sequential scan search with hash-based lookup. --- backup/util/plan/base_plan.class.php | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/backup/util/plan/base_plan.class.php b/backup/util/plan/base_plan.class.php index 3ed176b0bbf..24becc6969b 100644 --- a/backup/util/plan/base_plan.class.php +++ b/backup/util/plan/base_plan.class.php @@ -61,7 +61,12 @@ abstract class base_plan implements checksumable, executable { // Append task settings to plan array, if not present, for comodity foreach ($task->get_settings() as $key => $setting) { if (!in_array($setting, $this->settings)) { - $this->settings[] = $setting; + $name = $setting->get_name(); + if(!isset($this->settings[$name])) { + $this->settings[$name] = $setting; + } else { + throw new base_plan_exception('multiple_settings_by_name_found', $name); + } } } } @@ -91,17 +96,10 @@ abstract class base_plan implements checksumable, executable { */ public function get_setting($name) { $result = null; - foreach ($this->settings as $key => $setting) { - if ($setting->get_name() == $name) { - if ($result != null) { - throw new base_plan_exception('multiple_settings_by_name_found', $name); - } else { - $result = $setting; - } - } - } - if (!$result) { - throw new base_plan_exception('setting_by_name_not_found', $name); + if(isset($this->settings[$name])) { + $result = $this->settings[$name]; + } else { + throw new base_plan_exception('setting_by_name_not_found', $name); } return $result; } From 01ab87feda2946bb6ce52bdf4084a3af0a83872a Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Thu, 7 Apr 2011 15:38:10 +0930 Subject: [PATCH 224/455] MDL-27120 More efficient use of QuickForms in backup UI --- backup/util/ui/backup_ui_stage.class.php | 22 ++++++++++++--- backup/util/ui/base_moodleform.class.php | 34 +++++++++++++++++++++++- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index 2cc20455259..fdf48c2b3f3 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -124,6 +124,8 @@ class backup_ui_stage_initial extends backup_ui_stage { // Store as a variable so we can iterate by reference $tasks = $this->ui->get_tasks(); // Iterate all tasks by reference + $add_settings = array(); + $dependencies = array(); foreach ($tasks as &$task) { // For the initial stage we are only interested in the root settings if ($task instanceof backup_root_task) { @@ -134,17 +136,23 @@ class backup_ui_stage_initial extends backup_ui_stage { if ($setting->get_name() == 'filename') { continue; } - $form->add_setting($setting, $task); + $add_settings[] = array($setting, $task); } // Then add all dependencies foreach ($settings as &$setting) { if ($setting->get_name() == 'filename') { continue; } - $form->add_dependencies($setting); + $dependencies[] = $setting; } } } + // Add all settings at once + $form->add_settings($add_settings); + // Add dependencies + foreach ($dependencies as $depsetting) { + $form->add_dependencies($setting); + } $this->stageform = $form; } // Return the form @@ -226,6 +234,8 @@ class backup_ui_stage_schema extends backup_ui_stage { $tasks = $this->ui->get_tasks(); $content = ''; $courseheading = false; + $add_settings = array(); + $dependencies = array(); foreach ($tasks as $task) { if (!($task instanceof backup_root_task)) { if (!$courseheading) { @@ -235,11 +245,11 @@ class backup_ui_stage_schema extends backup_ui_stage { } // First add each setting foreach ($task->get_settings() as $setting) { - $form->add_setting($setting, $task); + $add_settings[] = array($setting, $task); } // The add all the dependencies foreach ($task->get_settings() as $setting) { - $form->add_dependencies($setting); + $dependencies[] = $setting; } } else if ($this->ui->enforce_changed_dependencies()) { // Only show these settings if dependencies changed them. @@ -254,6 +264,10 @@ class backup_ui_stage_schema extends backup_ui_stage { } } } + $form->add_settings($add_settings); + foreach($dependencies as $depsetting) { + $form->add_dependencies($depsetting); + } $this->stageform = $form; } return $this->stageform; diff --git a/backup/util/ui/base_moodleform.class.php b/backup/util/ui/base_moodleform.class.php index ad992602083..652d5806470 100644 --- a/backup/util/ui/base_moodleform.class.php +++ b/backup/util/ui/base_moodleform.class.php @@ -156,6 +156,38 @@ abstract class base_moodleform extends moodleform { $this->_form->addElement('html', html_writer::end_tag('div')); return true; } + /** + * Adds multiple backup_settings as elements to the form + * @param array $settingstasks Consists of array($setting, $task) elements + * @return bool + */ + function add_settings(array $settingstasks) { + global $OUTPUT; + + $defaults = array(); + foreach ($settingstasks as $st) { + list($setting, $task) = $st; + // If the setting cant be changed or isn't visible then add it as a fixed setting. + if (!$setting->get_ui()->is_changeable() || $setting->get_visibility() != backup_setting::VISIBLE) { + $this->add_fixed_setting($setting, $task); + continue; + } + + // First add the formatting for this setting + $this->add_html_formatting($setting); + + // Then call the add method with the get_element_properties array + call_user_func_array(array($this->_form, 'addElement'), $setting->get_ui()->get_element_properties($task, $OUTPUT)); + $defaults[$setting->get_ui_name()] = $setting->get_value(); + if ($setting->has_help()) { + list($identifier, $component) = $setting->get_help(); + $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component); + } + $this->_form->addElement('html', html_writer::end_tag('div')); + } + $this->_form->setDefaults($defaults); + return true; + } /** * Adds a heading to the form * @param string $name @@ -317,4 +349,4 @@ abstract class base_moodleform extends moodleform { $this->definition_after_data(); } } -} \ No newline at end of file +} From 588605efa6c4e82f7a28fab55bfda642534486e3 Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Thu, 7 Apr 2011 18:36:43 +0930 Subject: [PATCH 225/455] MDL-27120 Add global cache to backup_xml_transformer::register_link_encoders() --- backup/moodle2/backup_xml_transformer.class.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index a3770d03528..fec3c591d39 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -32,6 +32,12 @@ defined('MOODLE_INTERNAL') || die(); * * TODO: Finish phpdocs */ + +// cache for storing link encoders, so that we don't need to call +// register_link_encoders each time backup_xml_transformer is constructed +global $LINKS_ENCODERS_CACHE; +$LINKS_ENCODERS_CACHE = array(); + class backup_xml_transformer extends xml_contenttransformer { private $absolute_links_encoders; // array of static methods to be called in order to @@ -41,13 +47,18 @@ class backup_xml_transformer extends xml_contenttransformer { private $unicoderegexp; // to know if the site supports unicode regexp public function __construct($courseid) { + global $LINKS_ENCODERS_CACHE; + $this->absolute_links_encoders = array(); $this->courseid = $courseid; // Check if we support unicode modifiers in regular expressions $this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false, // if regexp libraries don't support unicode // Register all the available content link encoders - $this->absolute_links_encoders = $this->register_link_encoders(); + if (!empty($LINKS_ENCODERS_CACHE)) { + $LINKS_ENCODERS_CACHE = $this->register_link_encoders(); + } + $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE; } public function process($content) { From 67bf69416e10cb26e155fb630bc9233ca16717eb Mon Sep 17 00:00:00 2001 From: Jason Ilicic Date: Tue, 22 Nov 2011 10:34:56 +1030 Subject: [PATCH 226/455] mdl-27120 Fixed incorrect variable in parameter when adding form dependencies. --- backup/util/ui/backup_ui_stage.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index fdf48c2b3f3..6332102e25d 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -151,7 +151,7 @@ class backup_ui_stage_initial extends backup_ui_stage { $form->add_settings($add_settings); // Add dependencies foreach ($dependencies as $depsetting) { - $form->add_dependencies($setting); + $form->add_dependencies($depsetting); } $this->stageform = $form; } From 16bf868513341cd2efe3a9a694eb191f4b5a1ee6 Mon Sep 17 00:00:00 2001 From: Adam Olley Date: Wed, 14 Sep 2011 11:42:03 +0930 Subject: [PATCH 227/455] mdl-27120 Fix static cache for backup_xml_transformer::register_link_encoders() --- backup/moodle2/backup_xml_transformer.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index fec3c591d39..7c3cd5515d7 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -55,7 +55,7 @@ class backup_xml_transformer extends xml_contenttransformer { $this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false, // if regexp libraries don't support unicode // Register all the available content link encoders - if (!empty($LINKS_ENCODERS_CACHE)) { + if (empty($LINKS_ENCODERS_CACHE)) { $LINKS_ENCODERS_CACHE = $this->register_link_encoders(); } $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE; From 55f6d9d3788b68ffedb082edc7ac4aed10a0491e Mon Sep 17 00:00:00 2001 From: Tony Levi Date: Mon, 11 Apr 2011 15:34:02 +0930 Subject: [PATCH 228/455] MDL-27120: Cache dirname transformations in progressive_parser::dirname --- backup/util/xml/parser/progressive_parser.class.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backup/util/xml/parser/progressive_parser.class.php b/backup/util/xml/parser/progressive_parser.class.php index 91bc85fc4b2..8b6df4b5ee9 100644 --- a/backup/util/xml/parser/progressive_parser.class.php +++ b/backup/util/xml/parser/progressive_parser.class.php @@ -149,7 +149,15 @@ class progressive_parser { * handling parser paths, see MDL-24381 */ public static function dirname($path) { - return str_replace('\\', '/', dirname($path)); + static $cache = array(); + + if (!isset($cache[$path])) { + if (count($cache) > 4096) + $cache = array(); + $cache[$path] = str_replace('\\', '/', dirname($path)); + } + + return $cache[$path]; } // Protected API starts here From 0c99b72299b1c9660f28aab22b8c5f6a58f8bd21 Mon Sep 17 00:00:00 2001 From: Tony Levi Date: Sat, 16 Apr 2011 13:33:33 +0930 Subject: [PATCH 229/455] MDL-27120: Cache DB operations in restore_dbops --- backup/util/dbops/restore_dbops.class.php | 98 +++++++++++++++-------- 1 file changed, 66 insertions(+), 32 deletions(-) diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index 25f2e533d1c..c6319a4551c 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -28,6 +28,8 @@ * TODO: Finish phpdocs */ abstract class restore_dbops { + static $BACKUP_IDS_CACHE = array(); + static $BACKUP_IDS_EXIST = array(); /** * Return one array containing all the tasks that have been included @@ -151,6 +153,65 @@ abstract class restore_dbops { return $problems; } + protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) { + global $DB; + + $key = "$itemid $itemname $restoreid"; + + if (!isset(self::$BACKUP_IDS_EXIST[$key])) { + return false; + } + + if (isset(self::$BACKUP_IDS_CACHE[$key])) { + return self::$BACKUP_IDS_CACHE[$key]; + } + + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid + ); + + if (count(self::$BACKUP_IDS_CACHE) > 2048) { + $BACKUP_IDS_CACHE = array(); + } + + return self::$BACKUP_IDS_CACHE[$key] = $DB->get_record('backup_ids_temp', $record); + } + + protected static function set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord) { + global $DB; + + $key = "$itemid $itemname $restoreid"; + + if (!isset(self::$BACKUP_IDS_EXIST[$key])) { + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid, + 'newitemid' => 0, + 'parentitemid' => null, + 'info' => null + ); + $record = array_merge($record, $extrarecord); + $record['id'] = $DB->insert_record_raw('backup_ids_temp', $record); + self::$BACKUP_IDS_EXIST[$key] = $record['id']; + if (count(self::$BACKUP_IDS_CACHE) < 2048) { + // cache new records if we haven't got many yet + self::$BACKUP_IDS_CACHE[$key] = (object) $record; + } + } else { + if (!empty($extrarecord)) { + $extrarecord['id'] = self::$BACKUP_IDS_EXIST[$key]; + $DB->update_record('backup_ids_temp', $extrarecord); + if (isset(self::$BACKUP_IDS_CACHE[$key])) { + $record = array_merge((array)self::$BACKUP_IDS_CACHE[$key], $extrarecord); + self::$BACKUP_IDS_CACHE[$key] = (object) $record; + } + } + } + } + /** * Given one role, as loaded from XML, perform the best possible matching against the assignable * roles, using different fallback alternatives (shortname, archetype, editingteacher => teacher, defaultcourseroleid) @@ -1209,16 +1270,7 @@ abstract class restore_dbops { $DB->insert_record('backup_files_temp', $filerec); } - public static function set_backup_ids_record($restoreid, $itemname, $itemid, $newitemid = 0, $parentitemid = null, $info = null) { - global $DB; - - // Build the basic (mandatory) record info - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid - ); // Build conditionally the extra record info $extrarecord = array(); if ($newitemid != 0) { @@ -1231,34 +1283,16 @@ abstract class restore_dbops { $extrarecord['info'] = base64_encode(serialize($info)); } - // TODO: Analyze if some static (and limited) cache by the 3 params could save us a bunch of get_record() calls - // Note: Sure it will! And also will improve getter - if (!$dbrec = $DB->get_record('backup_ids_temp', $record)) { // Need to insert the complete record - $DB->insert_record('backup_ids_temp', array_merge($record, $extrarecord)); - - } else { // Need to update the extra record info if there is something to - if (!empty($extrarecord)) { - $extrarecord['id'] = $dbrec->id; - $DB->update_record('backup_ids_temp', $extrarecord); - } - } + self::set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord); } public static function get_backup_ids_record($restoreid, $itemname, $itemid) { - global $DB; + $dbrec = self::get_backup_ids_cached($restoreid, $itemname, $itemid); - // Build the basic (mandatory) record info to look for - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid - ); - // TODO: Analyze if some static (and limited) cache by the 3 params could save us a bunch of get_record() calls - if ($dbrec = $DB->get_record('backup_ids_temp', $record)) { - if ($dbrec->info != null) { - $dbrec->info = unserialize(base64_decode($dbrec->info)); - } + if ($dbrec && isset($dbrec->info) && is_string($dbrec->info)) { + $dbrec->info = unserialize(base64_decode($dbrec->info)); } + return $dbrec; } From f2bfe26aea52b918df5147d7b2b911b0eca12f59 Mon Sep 17 00:00:00 2001 From: Rajesh Taneja Date: Tue, 17 Apr 2012 11:32:15 +0800 Subject: [PATCH 230/455] MDL-27120 backup: fixed docblock and code cleanup --- .../moodle2/backup_xml_transformer.class.php | 33 ++-- backup/util/dbops/restore_dbops.class.php | 163 ++++++++++++++---- backup/util/plan/base_plan.class.php | 14 +- backup/util/ui/backup_ui_stage.class.php | 8 +- backup/util/ui/base_moodleform.class.php | 22 +-- .../xml/parser/progressive_parser.class.php | 10 +- 6 files changed, 166 insertions(+), 84 deletions(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index 7c3cd5515d7..25c8503bcf7 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -27,17 +27,18 @@ defined('MOODLE_INTERNAL') || die(); +// Cache for storing link encoders, so that we don't need to call +// register_link_encoders each time backup_xml_transformer is constructed +// TODO MDL-25290 replace global with MUC code. +global $LINKS_ENCODERS_CACHE; + +$LINKS_ENCODERS_CACHE = array(); + /** * Class implementing the @xml_contenttrasnformed logic to be applied in moodle2 backups * * TODO: Finish phpdocs */ - -// cache for storing link encoders, so that we don't need to call -// register_link_encoders each time backup_xml_transformer is constructed -global $LINKS_ENCODERS_CACHE; -$LINKS_ENCODERS_CACHE = array(); - class backup_xml_transformer extends xml_contenttransformer { private $absolute_links_encoders; // array of static methods to be called in order to @@ -47,18 +48,13 @@ class backup_xml_transformer extends xml_contenttransformer { private $unicoderegexp; // to know if the site supports unicode regexp public function __construct($courseid) { - global $LINKS_ENCODERS_CACHE; - $this->absolute_links_encoders = array(); $this->courseid = $courseid; // Check if we support unicode modifiers in regular expressions $this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false, // if regexp libraries don't support unicode // Register all the available content link encoders - if (empty($LINKS_ENCODERS_CACHE)) { - $LINKS_ENCODERS_CACHE = $this->register_link_encoders(); - } - $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE; + $this->absolute_links_encoders = $this->register_link_encoders(); } public function process($content) { @@ -142,7 +138,19 @@ class backup_xml_transformer extends xml_contenttransformer { return $result; } + /** + * Register all available content link encoders + * + * @return array encoder + * @todo MDL-25290 replace LINKS_ENCODERS_CACHE global with MUC code + */ private function register_link_encoders() { + global $LINKS_ENCODERS_CACHE; + // If encoder is linked, then return cached encoder. + if (!empty($LINKS_ENCODERS_CACHE)) { + return $LINKS_ENCODERS_CACHE; + } + $encoders = array(); // Add the course encoder @@ -171,6 +179,7 @@ class backup_xml_transformer extends xml_contenttransformer { // Add local encodes // TODO: Any interest? 1.9 never had that. + $LINKS_ENCODERS_CACHE = $encoders; return $encoders; } } diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index c6319a4551c..08c593ebc6a 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -28,8 +28,38 @@ * TODO: Finish phpdocs */ abstract class restore_dbops { - static $BACKUP_IDS_CACHE = array(); - static $BACKUP_IDS_EXIST = array(); + /** + * Keep cache of backup records. + * @var array + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidscache = array(); + /** + * Keep track of backup ids which are cached. + * @var array + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidsexist = array(); + /** + * Count is expensive, so manually keeping track of + * backupidscache, to avoid memory issues. + * @var int + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidscachesize = 2048; + /** + * Count is expensive, so manually keeping track of + * backupidsexist, to avoid memory issues. + * @var int + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidsexistsize = 10240; + /** + * Slice backupids cache to add more data. + * @var int + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidsslice = 512; /** * Return one array containing all the tasks that have been included @@ -153,61 +183,130 @@ abstract class restore_dbops { return $problems; } + /** + * Return cached backup id's + * + * @param int $restoreid id of backup + * @param string $itemname name of the item + * @param int $itemid id of item + * @return array backup id's + * @todo MDL-25290 replace static backupids* with MUC code + */ protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) { global $DB; $key = "$itemid $itemname $restoreid"; - if (!isset(self::$BACKUP_IDS_EXIST[$key])) { - return false; + // If record exists in cache then return. + if (isset(self::$backupidsexist[$key]) && isset(self::$backupidscache[$key])) { + return self::$backupidscache[$key]; } - if (isset(self::$BACKUP_IDS_CACHE[$key])) { - return self::$BACKUP_IDS_CACHE[$key]; + // Clean cache, if it's full. + if (self::$backupidscachesize <= 0) { + // Remove some records, to keep memory in limit. + self::$backupidscache = array_slice(self::$backupidscache, self::$backupidsslice, null, true); + self::$backupidscachesize = self::$backupidscachesize + self::$backupidsslice; + } + if (self::$backupidsexistsize <= 0) { + self::$backupidsexist = array_slice(self::$backupidsexist, self::$backupidsslice, null, true); + self::$backupidsexistsize = self::$backupidsexistsize + self::$backupidsslice; } + // Retrive record from database. $record = array( 'backupid' => $restoreid, 'itemname' => $itemname, 'itemid' => $itemid ); - - if (count(self::$BACKUP_IDS_CACHE) > 2048) { - $BACKUP_IDS_CACHE = array(); + if ($dbrec = $DB->get_record('backup_ids_temp', $record)) { + self::$backupidsexist[$key] = $dbrec->id; + self::$backupidscache[$key] = $dbrec; + self::$backupidscachesize--; + self::$backupidsexistsize--; + return self::$backupidscache[$key]; + } else { + return false; } - - return self::$BACKUP_IDS_CACHE[$key] = $DB->get_record('backup_ids_temp', $record); } + /** + * Cache backup ids' + * + * @param int $restoreid id of backup + * @param string $itemname name of the item + * @param int $itemid id of item + * @param array $extrarecord extra record which needs to be updated + * @return void + * @todo MDL-25290 replace static BACKUP_IDS_* with MUC code + */ protected static function set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord) { global $DB; $key = "$itemid $itemname $restoreid"; - if (!isset(self::$BACKUP_IDS_EXIST[$key])) { - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid, - 'newitemid' => 0, - 'parentitemid' => null, - 'info' => null - ); - $record = array_merge($record, $extrarecord); - $record['id'] = $DB->insert_record_raw('backup_ids_temp', $record); - self::$BACKUP_IDS_EXIST[$key] = $record['id']; - if (count(self::$BACKUP_IDS_CACHE) < 2048) { - // cache new records if we haven't got many yet - self::$BACKUP_IDS_CACHE[$key] = (object) $record; + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid, + ); + + // If record is not cached then add one. + if (!isset(self::$backupidsexist[$key])) { + // If we have this record in db, then just update this. + if ($existingrecord = $DB->get_record('backup_ids_temp', $record)) { + self::$backupidsexist[$key] = $existingrecord->id; + self::$backupidsexistsize--; + self::update_backup_cached_record($record, $extrarecord, $key, $existingrecord); + } else { + // Add new record to cache and db. + $recorddefault = array ( + 'newitemid' => 0, + 'parentitemid' => null, + 'info' => null); + $record = array_merge($record, $recorddefault, $extrarecord); + $record['id'] = $DB->insert_record('backup_ids_temp', $record); + self::$backupidsexist[$key] = $record['id']; + self::$backupidsexistsize--; + if (self::$backupidscachesize > 0) { + // Cache new records if we haven't got many yet. + self::$backupidscache[$key] = (object) $record; + self::$backupidscachesize--; + } } } else { - if (!empty($extrarecord)) { - $extrarecord['id'] = self::$BACKUP_IDS_EXIST[$key]; - $DB->update_record('backup_ids_temp', $extrarecord); - if (isset(self::$BACKUP_IDS_CACHE[$key])) { - $record = array_merge((array)self::$BACKUP_IDS_CACHE[$key], $extrarecord); - self::$BACKUP_IDS_CACHE[$key] = (object) $record; + self::update_backup_cached_record($record, $extrarecord, $key); + } + } + + /** + * Updates existing backup record + * + * @param array $record record which needs to be updated + * @param array $extrarecord extra record which needs to be updated + * @param string $key unique key which is used to identify cached record + * @param stdClass $existingrecord (optional) existing record + */ + protected static function update_backup_cached_record($record, $extrarecord, $key, $existingrecord = null) { + global $DB; + // Update only if extrarecord is not empty. + if (!empty($extrarecord)) { + $extrarecord['id'] = self::$backupidsexist[$key]; + $DB->update_record('backup_ids_temp', $extrarecord); + // Update existing cache or add new record to cache. + if (isset(self::$backupidscache[$key])) { + $record = array_merge((array)self::$backupidscache[$key], $extrarecord); + self::$backupidscache[$key] = (object) $record; + } else if (self::$backupidscachesize > 0) { + if ($existingrecord) { + self::$backupidscache[$key] = $existingrecord; + } else { + // Retrive record from database and cache updated records. + self::$backupidscache[$key] = $DB->get_record('backup_ids_temp', $record); } + $record = array_merge((array)self::$backupidscache[$key], $extrarecord); + self::$backupidscache[$key] = (object) $record; + self::$backupidscachesize--; } } } diff --git a/backup/util/plan/base_plan.class.php b/backup/util/plan/base_plan.class.php index 24becc6969b..eab1869d6d3 100644 --- a/backup/util/plan/base_plan.class.php +++ b/backup/util/plan/base_plan.class.php @@ -62,7 +62,7 @@ abstract class base_plan implements checksumable, executable { foreach ($task->get_settings() as $key => $setting) { if (!in_array($setting, $this->settings)) { $name = $setting->get_name(); - if(!isset($this->settings[$name])) { + if (!isset($this->settings[$name])) { $this->settings[$name] = $setting; } else { throw new base_plan_exception('multiple_settings_by_name_found', $name); @@ -89,17 +89,17 @@ abstract class base_plan implements checksumable, executable { /** * return one setting by name, useful to request root/course settings - * that are, by definition, unique by name. Throws exception if multiple - * are found + * that are, by definition, unique by name. * - * TODO: Change this to string indexed array for quicker lookup. Not critical + * @param string $name name of the setting + * @throws base_plan_exception if setting name is not found. */ public function get_setting($name) { $result = null; - if(isset($this->settings[$name])) { - $result = $this->settings[$name]; + if (isset($this->settings[$name])) { + $result = $this->settings[$name]; } else { - throw new base_plan_exception('setting_by_name_not_found', $name); + throw new base_plan_exception('setting_by_name_not_found', $name); } return $result; } diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index 6332102e25d..fbff601dba7 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -147,9 +147,9 @@ class backup_ui_stage_initial extends backup_ui_stage { } } } - // Add all settings at once + // Add all settings at once. $form->add_settings($add_settings); - // Add dependencies + // Add dependencies. foreach ($dependencies as $depsetting) { $form->add_dependencies($depsetting); } @@ -265,8 +265,8 @@ class backup_ui_stage_schema extends backup_ui_stage { } } $form->add_settings($add_settings); - foreach($dependencies as $depsetting) { - $form->add_dependencies($depsetting); + foreach ($dependencies as $depsetting) { + $form->add_dependencies($depsetting); } $this->stageform = $form; } diff --git a/backup/util/ui/base_moodleform.class.php b/backup/util/ui/base_moodleform.class.php index 652d5806470..e0ffc0f9fcf 100644 --- a/backup/util/ui/base_moodleform.class.php +++ b/backup/util/ui/base_moodleform.class.php @@ -136,32 +136,14 @@ abstract class base_moodleform extends moodleform { * @return bool */ function add_setting(backup_setting $setting, base_task $task=null) { - global $OUTPUT; - - // If the setting cant be changed or isn't visible then add it as a fixed setting. - if (!$setting->get_ui()->is_changeable() || $setting->get_visibility() != backup_setting::VISIBLE) { - return $this->add_fixed_setting($setting, $task); - } - - // First add the formatting for this setting - $this->add_html_formatting($setting); - - // The call the add method with the get_element_properties array - call_user_func_array(array($this->_form, 'addElement'), $setting->get_ui()->get_element_properties($task, $OUTPUT)); - $this->_form->setDefault($setting->get_ui_name(), $setting->get_value()); - if ($setting->has_help()) { - list($identifier, $component) = $setting->get_help(); - $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component); - } - $this->_form->addElement('html', html_writer::end_tag('div')); - return true; + return $this->add_settings(array(array($setting, $task))); } /** * Adds multiple backup_settings as elements to the form * @param array $settingstasks Consists of array($setting, $task) elements * @return bool */ - function add_settings(array $settingstasks) { + public function add_settings(array $settingstasks) { global $OUTPUT; $defaults = array(); diff --git a/backup/util/xml/parser/progressive_parser.class.php b/backup/util/xml/parser/progressive_parser.class.php index 8b6df4b5ee9..91bc85fc4b2 100644 --- a/backup/util/xml/parser/progressive_parser.class.php +++ b/backup/util/xml/parser/progressive_parser.class.php @@ -149,15 +149,7 @@ class progressive_parser { * handling parser paths, see MDL-24381 */ public static function dirname($path) { - static $cache = array(); - - if (!isset($cache[$path])) { - if (count($cache) > 4096) - $cache = array(); - $cache[$path] = str_replace('\\', '/', dirname($path)); - } - - return $cache[$path]; + return str_replace('\\', '/', dirname($path)); } // Protected API starts here From 6723372514e0bf8b44b945b4a625ac43e08dc382 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Sat, 12 May 2012 04:14:53 +0800 Subject: [PATCH 231/455] MDL-28666 Extends repository to support references 1. Allow repository to create references to external contents 2. Extends files API to handle file references 3. Generic file caching 4. Backup/restore file references 5. Download external contents if repository uninstalled 6. Allow filepicker to display iframe 7. PHPUnit test suits --- admin/repository.php | 73 +- admin/repositoryinstance.php | 93 ++- backup/backupfilesedit_form.php | 2 +- backup/moodle2/backup_stepslib.php | 19 +- backup/moodle2/restore_stepslib.php | 15 +- .../dbops/backup_controller_dbops.class.php | 21 + backup/util/dbops/restore_dbops.class.php | 14 +- .../util/helper/backup_file_manager.class.php | 4 + .../helper/backup_general_helper.class.php | 1 + backup/util/ui/backup_ui_stage.class.php | 3 + backup/util/ui/renderer.php | 10 + blocks/private_files/edit.php | 2 +- files/coursefilesedit_form.php | 2 +- lang/en/backup.php | 4 + lang/en/error.php | 1 + lang/en/repository.php | 8 +- lib/cronlib.php | 7 +- lib/db/install.xml | 27 +- lib/db/upgrade.php | 54 ++ lib/filelib.php | 288 +++++++- lib/filestorage/file_exceptions.php | 29 +- lib/filestorage/file_storage.php | 664 +++++++++++++---- lib/filestorage/stored_file.php | 319 ++++++++- lib/filestorage/tests/file_storage_test.php | 124 ++++ lib/form/editor.php | 4 +- lib/form/filemanager.php | 10 +- lib/form/filepicker.php | 10 +- lib/outputrequirementslib.php | 4 +- lib/tests/filelib_test.php | 81 ++- lib/tests/repositorylib_test.php | 57 -- mod/folder/edit.php | 2 +- mod/folder/mod_form.php | 2 +- mod/resource/mod_form.php | 4 +- mod/wiki/filesedit.php | 2 +- mod/workshop/submission.php | 2 +- repository/alfresco/lib.php | 19 +- repository/boxnet/lib.php | 94 ++- repository/coursefiles/lib.php | 123 +++- repository/dropbox/lib.php | 187 ++++- repository/dropbox/locallib.php | 20 + repository/filepicker.js | 91 ++- repository/filesystem/lib.php | 79 +- repository/flickr/lib.php | 17 +- repository/flickr_public/lib.php | 22 +- repository/googledocs/lib.php | 18 +- repository/lib.php | 672 ++++++++++++------ repository/local/lib.php | 16 +- repository/merlot/lib.php | 17 +- repository/picasa/lib.php | 15 +- repository/recent/lib.php | 16 +- repository/repository_ajax.php | 134 +++- repository/s3/lib.php | 19 +- repository/tests/repository_test.php | 61 ++ repository/upload/lib.php | 16 +- repository/url/lib.php | 20 +- repository/user/lib.php | 133 +++- repository/webdav/lib.php | 20 +- repository/wikimedia/lib.php | 17 +- repository/youtube/lib.php | 17 +- user/filesedit.php | 2 +- version.php | 2 +- 61 files changed, 3112 insertions(+), 697 deletions(-) delete mode 100644 lib/tests/repositorylib_test.php create mode 100644 repository/tests/repository_test.php diff --git a/admin/repository.php b/admin/repository.php index c3409a5b5a0..a3af2ddc588 100644 --- a/admin/repository.php +++ b/admin/repository.php @@ -1,12 +1,27 @@ . require_once(dirname(dirname(__FILE__)) . '/config.php'); require_once($CFG->dirroot . '/repository/lib.php'); require_once($CFG->libdir . '/adminlib.php'); -$repository = optional_param('repos', '', PARAM_FORMAT); -$action = optional_param('action', '', PARAM_ALPHA); -$sure = optional_param('sure', '', PARAM_ALPHA); +$repository = optional_param('repos', '', PARAM_ALPHANUMEXT); +$action = optional_param('action', '', PARAM_ACTION); +$sure = optional_param('sure', '', PARAM_ALPHA); +$downloadcontents = optional_param('downloadcontents', '', PARAM_ALPHA); $display = true; // fall through to normal display @@ -42,6 +57,10 @@ $configstr = get_string('manage', 'repository'); $return = true; +if (!empty($action)) { + require_sesskey(); +} + /** * Helper function that generates a moodle_url object * relevant to the repository @@ -152,10 +171,10 @@ if (($action == 'edit') || ($action == 'new')) { // Display instances list and creation form if ($action == 'edit') { - $instanceoptionnames = repository::static_function($repository, 'get_instance_option_names'); - if (!empty($instanceoptionnames)) { - repository::display_instances_list(get_context_instance(CONTEXT_SYSTEM), $repository); - } + $instanceoptionnames = repository::static_function($repository, 'get_instance_option_names'); + if (!empty($instanceoptionnames)) { + repository::display_instances_list(context_system::instance(), $repository); + } } } } else if ($action == 'show') { @@ -185,7 +204,14 @@ if (($action == 'edit') || ($action == 'new')) { if (!confirm_sesskey()) { print_error('confirmsesskeybad', '', $baseurl); } - if ($repositorytype->delete()) { + + if (!empty($downloadcontents) and $downloadcontents == 'yes') { + $downloadcontents = true; + } else { + $downloadcontents = false; + } + + if ($repositorytype->delete($downloadcontents)) { redirect($baseurl); } else { print_error('instancenotdeleted', 'repository', $baseurl); @@ -193,7 +219,34 @@ if (($action == 'edit') || ($action == 'new')) { exit; } else { echo $OUTPUT->header(); - echo $OUTPUT->confirm(get_string('confirmremove', 'repository', $repositorytype->get_readablename()), $sesskeyurl . '&action=delete&repos=' . $repository . '&sure=yes', $baseurl); + + $message = get_string('confirmremove', 'repository', $repositorytype->get_readablename()); + + $output = $OUTPUT->box_start('generalbox', 'notice'); + $output .= html_writer::tag('p', $message); + + $removeurl = new moodle_url($sesskeyurl); + $removeurl->params(array( + 'action' =>'delete', + 'repos' => $repository, + 'sure' => 'yes', + )); + + $removeanddownloadurl = new moodle_url($sesskeyurl); + $removeanddownloadurl->params(array( + 'action' =>'delete', + 'repos'=> $repository, + 'sure' => 'yes', + 'downloadcontents' => 'yes', + )); + + $output .= $OUTPUT->single_button($removeurl, get_string('continueuninstall', 'repository')); + $output .= $OUTPUT->single_button($removeanddownloadurl, get_string('continueuninstallanddownload', 'repository')); + $output .= $OUTPUT->single_button($baseurl, get_string('cancel')); + $output .= $OUTPUT->box_end(); + + echo $output; + $return = false; } } else if ($action == 'moveup') { @@ -255,7 +308,7 @@ if (($action == 'edit') || ($action == 'new')) { // Calculate number of instances in order to display them for the Moodle administrator if (!empty($instanceoptionnames)) { $params = array(); - $params['context'] = array(get_system_context()); + $params['context'] = array(context_system::instance()); $params['onlyvisible'] = false; $params['type'] = $typename; $admininstancenumber = count(repository::static_function($typename, 'get_instances', $params)); diff --git a/admin/repositoryinstance.php b/admin/repositoryinstance.php index e75193d0be4..ce903e843a9 100644 --- a/admin/repositoryinstance.php +++ b/admin/repositoryinstance.php @@ -1,18 +1,35 @@ . require_once(dirname(dirname(__FILE__)) . '/config.php'); require_once($CFG->dirroot . '/repository/lib.php'); require_once($CFG->libdir . '/adminlib.php'); +require_sesskey(); + // id of repository $edit = optional_param('edit', 0, PARAM_INT); -$new = optional_param('new', '', PARAM_FORMAT); +$new = optional_param('new', '', PARAM_PLUGIN); $hide = optional_param('hide', 0, PARAM_INT); $delete = optional_param('delete', 0, PARAM_INT); $sure = optional_param('sure', '', PARAM_ALPHA); $type = optional_param('type', '', PARAM_PLUGIN); +$downloadcontents = optional_param('downloadcontents', '', PARAM_ALPHA); -$context = get_context_instance(CONTEXT_SYSTEM); +$context = context_system::instance(); $pagename = 'repositorycontroller'; @@ -25,15 +42,19 @@ if ($edit){ } admin_externalpage_setup($pagename); -require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); +require_capability('moodle/site:config', $context); + +$baseurl = new moodle_url("/$CFG->admin/repositoryinstance.php", array('sesskey'=>sesskey())); + +$parenturl = new moodle_url("/$CFG->admin/repository.php", array( + 'sesskey'=>sesskey(), + 'action'=>'edit', +)); -$sesskeyurl = "$CFG->wwwroot/$CFG->admin/repositoryinstance.php?sesskey=" . sesskey(); -$baseurl = "$CFG->wwwroot/$CFG->admin/repository.php?session=". sesskey() .'&action=edit&repos='; if ($new) { - $baseurl .= $new; -} -else { - $baseurl .= $type; + $parenturl->param('repos', $new); +} else { + $parenturl->param('repos', $type); } $return = true; @@ -48,7 +69,7 @@ if (!empty($edit) || !empty($new)) { $typeid = $instance->options['typeid']; } else { $plugin = $new; - $typeid = $new; + $typeid = null; $instance = null; } @@ -57,12 +78,9 @@ if (!empty($edit) || !empty($new)) { // end setup, begin output if ($mform->is_cancelled()){ - redirect($baseurl); + redirect($parenturl); exit; } else if ($fromform = $mform->get_data()){ - if (!confirm_sesskey()) { - print_error('confirmsesskeybad', '', $baseurl); - } if ($edit) { $settings = array(); $settings['name'] = $fromform->name; @@ -77,13 +95,13 @@ if (!empty($edit) || !empty($new)) { } $success = $instance->set_option($settings); } else { - $success = repository::static_function($plugin, 'create', $plugin, 0, get_system_context(), $fromform); + $success = repository::static_function($plugin, 'create', $plugin, 0, $context, $fromform); $data = data_submitted(); } if ($success) { - redirect($baseurl); + redirect($parenturl); } else { - print_error('instancenotsaved', 'repository', $baseurl); + print_error('instancenotsaved', 'repository', $parenturl); } exit; } else { @@ -95,9 +113,6 @@ if (!empty($edit) || !empty($new)) { $return = false; } } else if (!empty($hide)) { - if (!confirm_sesskey()) { - print_error('confirmsesskeybad', '', $baseurl); - } $instance = repository::get_type_by_typename($hide); $instance->hide(); $return = true; @@ -108,25 +123,43 @@ if (!empty($edit) || !empty($new)) { throw new repository_exception('readonlyinstance', 'repository'); } if ($sure) { - if (!confirm_sesskey()) { - print_error('confirmsesskeybad', '', $baseurl); - } - if ($instance->delete()) { - $deletedstr = get_string('instancedeleted', 'repository'); - redirect($baseurl, $deletedstr, 3); + if (!empty($downloadcontents) and $downloadcontents == 'yes') { + $downloadcontents = true; } else { - print_error('instancenotdeleted', 'repository', $baseurl); + $downloadcontents = false; + } + if ($instance->delete($downloadcontents)) { + $deletedstr = get_string('instancedeleted', 'repository'); + redirect($parenturl, $deletedstr, 3); + } else { + print_error('instancenotdeleted', 'repository', $parenturl); } exit; } echo $OUTPUT->header(); - echo $OUTPUT->confirm(get_string('confirmdelete', 'repository', $instance->name), "$sesskeyurl&type=$type'&delete=$delete'&sure=yes", "$CFG->wwwroot/$CFG->admin/repositoryinstance.php?session=". sesskey()); + echo $OUTPUT->box_start('generalbox', 'notice'); + $continueurl = new moodle_url($baseurl, array( + 'type' => $type, + 'delete' => $delete, + 'sure' => 'yes', + )); + $continueanddownloadurl = new moodle_url($continueurl, array( + 'downloadcontents' => 'yes' + )); + $message = get_string('confirmdelete', 'repository', $instance->name); + echo html_writer::tag('p', $message); + + echo $OUTPUT->single_button($continueurl, get_string('continueuninstall', 'repository')); + echo $OUTPUT->single_button($continueanddownloadurl, get_string('continueuninstallanddownload', 'repository')); + echo $OUTPUT->single_button($parenturl, get_string('cancel')); + + echo $OUTPUT->box_end(); + $return = false; } if (!empty($return)) { - - redirect($baseurl); + redirect($parenturl); } echo $OUTPUT->footer(); diff --git a/backup/backupfilesedit_form.php b/backup/backupfilesedit_form.php index 7906a080d1a..36a4030da07 100644 --- a/backup/backupfilesedit_form.php +++ b/backup/backupfilesedit_form.php @@ -27,7 +27,7 @@ class backup_files_edit_form extends moodleform { function definition() { $mform =& $this->_form; $contextid = $this->_customdata['contextid']; - $options = array('subdirs'=>0, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); + $options = array('subdirs'=>0, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL | FILE_REFERENCE); $mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options); $mform->addElement('hidden', 'contextid', $this->_customdata['contextid']); $mform->addElement('hidden', 'currentcontext', $this->_customdata['currentcontext']); diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index e7b6018cdf3..d1be602bc8f 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1404,7 +1404,7 @@ class backup_final_files_structure_step extends backup_structure_step { 'contenthash', 'contextid', 'component', 'filearea', 'itemid', 'filepath', 'filename', 'userid', 'filesize', 'mimetype', 'status', 'timecreated', 'timemodified', - 'source', 'author', 'license', 'sortorder')); + 'source', 'author', 'license', 'sortorder', 'reference', 'repositoryid')); // Build the tree @@ -1412,9 +1412,12 @@ class backup_final_files_structure_step extends backup_structure_step { // Define sources - $file->set_source_sql("SELECT f.* + $file->set_source_sql("SELECT f.*, r.repositoryid, r.reference FROM {files} f - JOIN {backup_ids_temp} bi ON f.id = bi.itemid + JOIN {files_reference} r + ON r.id = f.referencefileid + JOIN {backup_ids_temp} bi + ON f.id = bi.itemid WHERE bi.backupid = ? AND bi.itemname = 'filefinal'", array(backup::VAR_BACKUPID)); @@ -1442,6 +1445,8 @@ class backup_main_structure_step extends backup_structure_step { $info['backup_date'] = time(); $info['backup_uniqueid']= $this->get_backupid(); $info['mnet_remoteusers']=backup_controller_dbops::backup_includes_mnet_remote_users($this->get_backupid()); + $info['include_file_references_to_external_content'] = + backup_controller_dbops::backup_includes_file_references($this->get_backupid()); $info['original_wwwroot']=$CFG->wwwroot; $info['original_site_identifier_hash'] = md5(get_site_identifier()); $info['original_course_id'] = $this->get_courseid(); @@ -1461,7 +1466,7 @@ class backup_main_structure_step extends backup_structure_step { $information = new backup_nested_element('information', null, array( 'name', 'moodle_version', 'moodle_release', 'backup_version', - 'backup_release', 'backup_date', 'mnet_remoteusers', 'original_wwwroot', + 'backup_release', 'backup_date', 'mnet_remoteusers', 'include_file_references_to_external_content', 'original_wwwroot', 'original_site_identifier_hash', 'original_course_id', 'original_course_fullname', 'original_course_shortname', 'original_course_startdate', 'original_course_contextid', 'original_system_contextid')); @@ -1584,8 +1589,12 @@ class backup_store_backup_file extends backup_execution_step { // Calculate the zip fullpath (in OS temp area it's always backup.mbz) $zipfile = $basepath . '/backup.mbz'; + $has_file_references = backup_controller_dbops::backup_includes_file_references($this->get_backupid()); // Perform storage and return it (TODO: shouldn't be array but proper result object) - return array('backup_destination' => backup_helper::store_backup_file($this->get_backupid(), $zipfile)); + return array( + 'backup_destination' => backup_helper::store_backup_file($this->get_backupid(), $zipfile), + 'include_file_references_to_external_content' => $has_file_references + ); } } diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index fda860c9cf1..4d610e5cafb 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -586,11 +586,23 @@ class restore_load_included_files extends restore_structure_step { return array($file); } - // Processing functions go here + /** + * Processing functions go here + * + * @param array $data one file record including repositoryid and reference + */ public function process_file($data) { $data = (object)$data; // handy + $isreference = !empty($data->repositoryid); + $issamesite = $this->task->is_samesite(); + + // If it's not samesite, we skip file refernces + if (!$issamesite && $isreference) { + return; + } + // load it if needed: // - it it is one of the annotated inforef files (course/section/activity/block) // - it is one "user", "group", "grouping", "grade", "question" or "qtype_xxxx" component file (that aren't sent to inforef ever) @@ -601,6 +613,7 @@ class restore_load_included_files extends restore_structure_step { $data->component == 'grouping' || $data->component == 'grade' || $data->component == 'question' || substr($data->component, 0, 5) == 'qtype'); if ($isfileref || $iscomponent) { + // Process files restore_dbops::set_backup_files_record($this->get_restoreid(), $data); } } diff --git a/backup/util/dbops/backup_controller_dbops.class.php b/backup/util/dbops/backup_controller_dbops.class.php index c77aeb6e4c4..ee98987a41d 100644 --- a/backup/util/dbops/backup_controller_dbops.class.php +++ b/backup/util/dbops/backup_controller_dbops.class.php @@ -409,6 +409,27 @@ abstract class backup_controller_dbops extends backup_dbops { return (int)(bool)$count; } + /** + * Given the backupid, detect if the backup contains references to external contents + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @return int + */ + public static function backup_includes_file_references($backupid) { + global $CFG, $DB; + + $sql = "SELECT count(r.repositoryid) + FROM {files} f + JOIN {files_reference} r + ON r.id = f.referencefileid + JOIN {backup_ids_temp} bi + ON f.id = bi.itemid + WHERE bi.backupid = ? + AND bi.itemname = 'filefinal'"; + $count = $DB->count_records_sql($sql, array($backupid)); + return (int)(bool)$count; + } + /** * Given the courseid, return some course related information we want to transport * diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index 25f2e533d1c..e50c6e607df 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -685,6 +685,9 @@ abstract class restore_dbops { $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $rec) { $file = (object)unserialize(base64_decode($rec->info)); + + $isreference = !empty($file->repositoryid); + // ignore root dirs (they are created automatically) if ($file->filepath == '/' && $file->filename == '.') { continue; @@ -697,10 +700,12 @@ abstract class restore_dbops { $fs->create_directory($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->userid); continue; } + // arrived here, file found // Find file in backup pool $backuppath = $basepath . backup_file_manager::get_backup_content_file_location($file->contenthash); - if (!file_exists($backuppath)) { + + if (!file_exists($backuppath) && !$isreference) { throw new restore_dbops_exception('file_not_found_in_pool', $file); } if (!$fs->file_exists($newcontextid, $component, $filearea, $rec->newitemid, $file->filepath, $file->filename)) { @@ -717,7 +722,11 @@ abstract class restore_dbops { 'author' => $file->author, 'license' => $file->license, 'sortorder' => $file->sortorder); - $fs->create_file_from_pathname($file_record, $backuppath); + if ($isreference) { + $fs->create_file_from_reference($file_record, $file->repositoryid, $file->reference); + } else { + $fs->create_file_from_pathname($file_record, $backuppath); + } } } $rs->close(); @@ -1204,6 +1213,7 @@ abstract class restore_dbops { public static function set_backup_files_record($restoreid, $filerec) { global $DB; + // Store external files info in `info` field $filerec->info = base64_encode(serialize($filerec)); // Serialize the whole rec in info $filerec->backupid = $restoreid; $DB->insert_record('backup_files_temp', $filerec); diff --git a/backup/util/helper/backup_file_manager.class.php b/backup/util/helper/backup_file_manager.class.php index fb6477a6996..9941af7f4b6 100644 --- a/backup/util/helper/backup_file_manager.class.php +++ b/backup/util/helper/backup_file_manager.class.php @@ -73,6 +73,10 @@ class backup_file_manager { $fs = get_file_storage(); $file = $fs->get_file_instance($filerecorid); + // If the file is external file, skip copying. + if ($file->is_external_file()) { + return; + } // Calculate source and target paths (use same subdirs strategy for both) $targetfilepath = self::get_backup_storage_base_dir($backupid) . '/' . diff --git a/backup/util/helper/backup_general_helper.class.php b/backup/util/helper/backup_general_helper.class.php index 73b5d3b4014..b0eb2e237d2 100644 --- a/backup/util/helper/backup_general_helper.class.php +++ b/backup/util/helper/backup_general_helper.class.php @@ -145,6 +145,7 @@ abstract class backup_general_helper extends backup_helper { $info->original_course_startdate= $infoarr['original_course_startdate']; $info->original_course_contextid= $infoarr['original_course_contextid']; $info->original_system_contextid= $infoarr['original_system_contextid']; + $info->include_file_references_to_external_content = $infoarr['include_file_references_to_external_content']; $info->type = $infoarr['details']['detail'][0]['type']; $info->format = $infoarr['details']['detail'][0]['format']; $info->mode = $infoarr['details']['detail'][0]['mode']; diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index 2cc20455259..1ce9053dd52 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -470,6 +470,9 @@ class backup_ui_stage_complete extends backup_ui_stage_final { $output = ''; $output .= $renderer->box_start(); + if (!empty($this->results['include_file_references_to_external_content'])) { + $output .= $renderer->notification(get_string('filereferencesincluded', 'backup'), 'notifyproblem'); + } $output .= $renderer->notification(get_string('executionsuccess', 'backup'), 'notifysuccess'); $output .= $renderer->continue_button($restorerul); $output .= $renderer->box_end(); diff --git a/backup/util/ui/renderer.php b/backup/util/ui/renderer.php index 7afcdfd368a..9e0ab9dd4f9 100644 --- a/backup/util/ui/renderer.php +++ b/backup/util/ui/renderer.php @@ -92,6 +92,16 @@ class core_backup_renderer extends plugin_renderer_base { $html .= $this->backup_detail_pair(get_string('originalwwwroot', 'backup'), html_writer::tag('span', $details->original_wwwroot, array('class'=>'originalwwwroot')). html_writer::tag('span', '['.$details->original_site_identifier_hash.']', array('class'=>'sitehash sub-detail'))); + if (!empty($details->include_file_references_to_external_content)) { + $message = ''; + if (backup_general_helper::backup_is_samesite($details)) { + $message = $yestick . ' ' . get_string('filereferencessamesite', 'backup'); + } else { + $message = $notick . ' ' . get_string('filereferencesnotsamesite', 'backup'); + } + $html .= $this->backup_detail_pair(get_string('includefilereferences', 'backup'), $message); + } + $html .= html_writer::end_tag('div'); $html .= html_writer::start_tag('div', array('class'=>'backup-section settings-section')); diff --git a/blocks/private_files/edit.php b/blocks/private_files/edit.php index 5a7667bbd76..67b1e70d5bc 100644 --- a/blocks/private_files/edit.php +++ b/blocks/private_files/edit.php @@ -45,7 +45,7 @@ $PAGE->set_pagelayout('mydashboard'); $PAGE->set_pagetype('user-private-files'); $data = new stdClass(); -$options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); +$options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*'); file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0); $mform = new block_private_files_form(null, array('data'=>$data, 'options'=>$options)); diff --git a/files/coursefilesedit_form.php b/files/coursefilesedit_form.php index e5498dcec18..fadd387413d 100644 --- a/files/coursefilesedit_form.php +++ b/files/coursefilesedit_form.php @@ -21,7 +21,7 @@ class coursefiles_edit_form extends moodleform { function definition() { $mform =& $this->_form; $contextid = $this->_customdata['contextid']; - $options = array('subdirs'=>1, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); + $options = array('subdirs'=>1, 'maxfiles'=>-1, 'accepted_types'=>'*'); $mform->addElement('filemanager', 'files_filemanager', '', null, $options); $mform->addElement('hidden', 'contextid', $this->_customdata['contextid']); $this->set_data($this->_customdata['data']); diff --git a/lang/en/backup.php b/lang/en/backup.php index 3cb7ec138f9..fa809254ddb 100644 --- a/lang/en/backup.php +++ b/lang/en/backup.php @@ -117,6 +117,9 @@ $string['errorinvalidformat'] = 'Unknown backup format'; $string['errorinvalidformatinfo'] = 'The selected file is not a valid Moodle backup file and can\'t be restored.'; $string['executionsuccess'] = 'The backup file was successfully created.'; $string['filename'] = 'Filename'; +$string['filereferencesincluded'] = 'File references to external contents included in backup package, they won\'t work on other sites.'; +$string['filereferencessamesite'] = 'Backup is from the same site, file references can be restored'; +$string['filereferencesnotsamesite'] = 'Backup is from other site, file references cannot be restored'; $string['generalactivities'] = 'Include activities'; $string['generalanonymize'] = 'Anonymise information'; $string['generalbackdefaults'] = 'General backup defaults'; @@ -148,6 +151,7 @@ $string['includeditems'] = 'Included items:'; $string['includesection'] = 'Section {$a}'; $string['includeuserinfo'] = 'User data'; $string['loglifetime'] = 'Keep logs for'; +$string['includefilereferences'] = 'File references to external contents'; $string['locked'] = 'Locked'; $string['lockedbypermission'] = 'You don\'t have sufficient permissions to change this setting'; $string['lockedbyconfig'] = 'This setting has been locked by the default backup settings'; diff --git a/lang/en/error.php b/lang/en/error.php index 75fb0be028c..371cf469fd3 100644 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -224,6 +224,7 @@ $string['errorsettinguserpref'] = 'Error setting user preference'; $string['errorunzippingfiles'] = 'Error unzipping files'; $string['expiredkey'] = 'Expired key'; $string['externalauthpassworderror'] = 'Non-empty password for external authentication'; +$string['externalfilenolocation'] = 'External file has no location path'; $string['failtoloadblocks'] = 'One or more blocks are registered in the database, but they all failed to load!'; $string['fieldrequired'] = '"{$a}" is a required field'; $string['fileexists'] = 'File exists'; diff --git a/lang/en/repository.php b/lang/en/repository.php index 0e84fcd4c64..b288e85f0f0 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -61,9 +61,11 @@ $string['commonrepositorysettings'] = 'Common repository settings'; $string['configallowexternallinks'] = 'This option enables all users to choose whether or not external media is copied into Moodle or not. If this is off then media is always copied into Moodle (this is usually best for overall data integrity and security). If this is on then users can choose each time they add media to a text.'; $string['configcacheexpire'] = 'The amount of time that file listings are cached locally (in seconds) when browsing external repositories.'; $string['configsaved'] = 'Configuration saved!'; -$string['confirmdelete'] = 'Are you sure you want to delete this repository - {$a}?'; +$string['confirmdelete'] = 'Are you sure you want to delete this repository - {$a}? If you choose "Continue and download", file references to external contents will be downloaded to moodle, but it could take long time to process.'; $string['confirmdeletefile'] = 'Are you sure you want to delete this file?'; -$string['confirmremove'] = 'Are you sure you want to remove this repository plugin, its options and all of its instances - {$a}?'; +$string['confirmremove'] = 'Are you sure you want to remove this repository plugin, its options and all of its instances - {$a}? If you choose "Continue and download", file references to external contents will be downloaded to moodle, but it could take long time to process.'; +$string['continueuninstall'] = 'Continue'; +$string['continueuninstallanddownload'] = 'Continue and download'; $string['copying'] = 'Copying'; $string['create'] = 'Create'; $string['createfolderfail'] = 'Fail to create this folder'; @@ -117,6 +119,7 @@ $string['invalidjson'] = 'Invalid JSON string'; $string['invalidplugin'] = 'Invalid repository {$a} plug-in'; $string['invalidfiletype'] = '{$a} filetype cannot be accepted.'; $string['invalidrepositoryid'] = 'Invalid repository ID'; +$string['invalidparams'] = 'Invalid parameters'; $string['isactive'] = 'Active?'; $string['keyword'] = 'Keyword'; $string['linkexternal'] = 'Link external'; @@ -179,6 +182,7 @@ $string['typenotvisible'] = 'Type not visible'; $string['upload'] = 'Upload this file'; $string['uploading'] = 'Uploading...'; $string['uploadsucc'] = 'The file has been uploaded successfully'; +$string['uselatestfile'] = 'Use latest file'; $string['usercontextrepositorydisabled'] = 'You cannot edit this repository in user context'; $string['usenonjsfilemanager'] = 'Open file manager in new window'; $string['usenonjsfilepicker'] = 'Open file picker in new window'; diff --git a/lib/cronlib.php b/lib/cronlib.php index b05e34f87c9..0e47a655c32 100644 --- a/lib/cronlib.php +++ b/lib/cronlib.php @@ -403,9 +403,7 @@ function cron_run() { cron_execute_plugin_type('format', 'course formats'); cron_execute_plugin_type('profilefield', 'profile fields'); cron_execute_plugin_type('webservice', 'webservices'); - // TODO: Repository lib.php files are messed up (include many other files, etc), so it is - // currently not possible to implement repository plugin cron using this infrastructure - // cron_execute_plugin_type('repository', 'repository plugins'); + cron_execute_plugin_type('repository', 'repository plugins'); cron_execute_plugin_type('qbehaviour', 'question behaviours'); cron_execute_plugin_type('qformat', 'question import/export formats'); cron_execute_plugin_type('qtype', 'question types'); @@ -462,6 +460,9 @@ function cron_run() { $fs = get_file_storage(); $fs->cron(); + mtrace("Clean up cached external files"); + // 1 week + cache_file::cleanup(array(), 60 * 60 * 24 * 7); mtrace("Cron script completed correctly"); diff --git a/lib/db/install.xml b/lib/db/install.xml index 1d83d84ead5..0463430e996 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -2326,7 +2326,7 @@ - +
                            @@ -2346,12 +2346,16 @@ - + + + + - + + @@ -2359,7 +2363,20 @@
                            - +
                            + + + + + + + + + + + +
                            + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index b263a39e735..29af2df5f5d 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -592,5 +592,59 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2012051100.03); } + if ($oldversion < 2012052100.00) { + + // Define field referencefileid to be added to files + $table = new xmldb_table('files'); + + // Define field referencefileid to be added to files + $field = new xmldb_field('referencefileid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'sortorder'); + // Conditionally launch add field referencefileid + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define field referencelastsync to be added to files + $field = new xmldb_field('referencelastsync', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'referencefileid'); + // Conditionally launch add field referencelastsync + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define field referencelifetime to be added to files + $field = new xmldb_field('referencelastsync', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'referencefileid'); + // Conditionally launch add field referencelifetime + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $key = new xmldb_key('referencefileid', XMLDB_KEY_FOREIGN, array('referencefileid'), 'files_reference', array('id')); + // Launch add key referencefileid + $dbman->add_key($table, $key); + + // Define table files_reference to be created. + $table = new xmldb_table('files_reference'); + + // Adding fields to table files_reference. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('fileid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('repositoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('lastsync', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + $table->add_field('lifetime', XMLDB_TYPE_INTEGER, '10', null, null, null, null); + $table->add_field('reference', XMLDB_TYPE_TEXT, null, null, null, null, null); + + // Adding keys to table files_reference. + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); + $table->add_key('repositoryid', XMLDB_KEY_FOREIGN, array('repositoryid'), 'repository_instances', array('id')); + + // Conditionally launch create table for files_reference + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Main savepoint reached + upgrade_main_savepoint(true, 2012052100.00); + } + return true; } diff --git a/lib/filelib.php b/lib/filelib.php index f10d8ca5d63..78af2871e18 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -374,7 +374,25 @@ function file_prepare_draft_area(&$draftitemid, $contextid, $component, $fileare if (!$options['subdirs'] and ($file->is_directory() or $file->get_filepath() !== '/')) { continue; } - $fs->create_file_from_storedfile($file_record, $file); + $draftfile = $fs->create_file_from_storedfile($file_record, $file); + // XXX: This is a hack for file manager + // File manager needs to know the original file information before copying + // to draft area, so we append these information in mdl_files.source field + // {@link file_storage::search_references()} + // {@link file_storage::search_references_count()} + $sourcefield = $file->get_source(); + $newsourcefield = new stdClass; + $newsourcefield->source = $sourcefield; + $original = new stdClass; + $original->contextid = $contextid; + $original->component = $component; + $original->filearea = $filearea; + $original->itemid = $itemid; + $original->filename = $file->get_filename(); + $original->filepath = $file->get_filepath(); + $newsourcefield->original = file_storage::pack_reference($original); + $draftfile->set_source(serialize($newsourcefield)); + // End of file manager hack } } if (!is_null($text)) { @@ -631,6 +649,20 @@ function file_get_submitted_draft_itemid($elname) { return $param; } +/** + * Restore the original source field from draft files + * + * @param stored_file $storedfile This only works with draft files + * @return stored_file + */ +function file_restore_source_field_from_draft_file($storedfile) { + $source = unserialize($storedfile->get_source()); + if (!empty($source) && is_object($source)) { + $restoredsource = $source->source; + $storedfile->set_source($restoredsource); + } + return $storedfile; +} /** * Saves files from a draft file area to a real one (merging the list of files). * Can rewrite URLs in some content at the same time if desired. @@ -694,6 +726,16 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea if (!$file->is_directory()) { $filecount++; } + + if ($file->is_external_file()) { + $repoid = $file->get_repository_id(); + if (!empty($repoid)) { + $file_record['repositoryid'] = $repoid; + $file_record['reference'] = $file->get_reference(); + } + } + file_restore_source_field_from_draft_file($file); + $fs->create_file_from_storedfile($file_record, $file); } @@ -715,14 +757,40 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea $oldfile->delete(); continue; } + $newfile = $newhashes[$oldhash]; - if ($oldfile->get_contenthash() != $newfile->get_contenthash() or $oldfile->get_sortorder() != $newfile->get_sortorder() - or $oldfile->get_status() != $newfile->get_status() or $oldfile->get_license() != $newfile->get_license() - or $oldfile->get_author() != $newfile->get_author() or $oldfile->get_source() != $newfile->get_source()) { + // status changed, we delete old file, and create a new one + if ($oldfile->get_status() != $newfile->get_status()) { // file was changed, use updated with new timemodified data $oldfile->delete(); + // This file will be added later continue; } + + file_restore_source_field_from_draft_file($newfile); + // Replaced file content + if ($oldfile->get_contenthash() != $newfile->get_contenthash()) { + $oldfile->replace_content_with($newfile); + } + // Updated author + if ($oldfile->get_author() != $newfile->get_author()) { + $oldfile->set_author($newfile->get_author()); + } + // Updated license + if ($oldfile->get_license() != $newfile->get_license()) { + $oldfile->set_license($newfile->get_license()); + } + + // Updated file source + if ($oldfile->get_source() != $newfile->get_source()) { + $oldfile->set_source($newfile->get_source()); + } + + // Updated sort order + if ($oldfile->get_sortorder() != $newfile->get_sortorder()) { + $oldfile->set_sortorder($newfile->get_sortorder()); + } + // unchanged file or directory - we keep it as is unset($newhashes[$oldhash]); if (!$oldfile->is_directory()) { @@ -730,7 +798,7 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea } } - // now add new/changed files + // Add fresh file or the file which has changed status // the size and subdirectory tests are extra safety only, the UI should prevent it foreach ($newhashes as $file) { if (!$options['subdirs']) { @@ -749,6 +817,15 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea if (!$file->is_directory()) { $filecount++; } + + if ($file->is_external_file()) { + $repoid = $file->get_repository_id(); + if (!empty($repoid)) { + $file_record['repositoryid'] = $repoid; + $file_record['reference'] = $file->get_reference(); + } + } + $fs->create_file_from_storedfile($file_record, $file); } } @@ -2005,6 +2082,12 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl } } + // handle external resource + if ($stored_file->is_external_file()) { + $stored_file->send_file($lifetime, $filter, $forcedownload, $options); + die; + } + if (!$stored_file or $stored_file->is_directory()) { // nothing to serve if ($dontdie) { @@ -2943,7 +3026,7 @@ class curl_cache { * @global stdClass $CFG * @param string $module which module is using curl_cache */ - function __construct($module = 'repository'){ + public function __construct($module = 'repository') { global $CFG; if (!empty($module)) { $this->dir = $CFG->cachedir.'/'.$module.'/'; @@ -2974,14 +3057,13 @@ class curl_cache { * @param mixed $param * @return bool|string */ - public function get($param){ + public function get($param) { global $CFG, $USER; $this->cleanup($this->ttl); $filename = 'u'.$USER->id.'_'.md5(serialize($param)); if(file_exists($this->dir.$filename)) { $lasttime = filemtime($this->dir.$filename); - if(time()-$lasttime > $this->ttl) - { + if (time()-$lasttime > $this->ttl) { return false; } else { $fp = fopen($this->dir.$filename, 'r'); @@ -3001,7 +3083,7 @@ class curl_cache { * @param mixed $param * @param mixed $val */ - public function set($param, $val){ + public function set($param, $val) { global $CFG, $USER; $filename = 'u'.$USER->id.'_'.md5(serialize($param)); $fp = fopen($this->dir.$filename, 'w'); @@ -3012,18 +3094,19 @@ class curl_cache { /** * Remove cache files * - * @param int $expire The number os seconds before expiry + * @param int $expire The number of seconds before expiry */ - public function cleanup($expire){ - if($dir = opendir($this->dir)){ + public function cleanup($expire) { + if ($dir = opendir($this->dir)) { while (false !== ($file = readdir($dir))) { if(!is_dir($file) && $file != '.' && $file != '..') { $lasttime = @filemtime($this->dir.$file); - if(time() - $lasttime > $expire){ + if (time() - $lasttime > $expire) { @unlink($this->dir.$file); } } } + closedir($dir); } } /** @@ -3032,12 +3115,12 @@ class curl_cache { * @global object $CFG * @global object $USER */ - public function refresh(){ + public function refresh() { global $CFG, $USER; - if($dir = opendir($this->dir)){ + if ($dir = opendir($this->dir)) { while (false !== ($file = readdir($dir))) { - if(!is_dir($file) && $file != '.' && $file != '..') { - if(strpos($file, 'u'.$USER->id.'_')!==false){ + if (!is_dir($file) && $file != '.' && $file != '..') { + if (strpos($file, 'u'.$USER->id.'_') !== false) { @unlink($this->dir.$file); } } @@ -3923,3 +4006,172 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) { } } + +/** + * Universe file cacheing class + * + * @package core_files + * @category files + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class cache_file { + /** @var string */ + public $cachedir = ''; + + /** + * static method to create cache_file class instance + * + * @param array $options caching ooptions + */ + public static function get_instance($options = array()) { + return new cache_file($options); + } + + /** + * Constructor + * + * @param array $options + */ + private function __construct($options = array()) { + global $CFG; + + // Path to file caches. + if (isset($options['cachedir'])) { + $this->cachedir = $options['cachedir']; + } else { + $this->cachedir = $CFG->cachedir . '/filedir'; + } + + // Create cache directory. + if (!file_exists($this->cachedir)) { + mkdir($this->cachedir, $CFG->directorypermissions, true); + } + + // When use cache_file::get, it will check ttl. + if (isset($options['ttl']) && is_numeric($options['ttl'])) { + $this->ttl = $options['ttl']; + } else { + // One day. + $this->ttl = 60 * 60 * 24; + } + } + + /** + * Get cached file, false if file expires + * + * @param mixed $param + * @param array $options caching options + * @return bool|string + */ + public static function get($param, $options = array()) { + $instance = self::get_instance($options); + $filepath = $instance->generate_filepath($param); + if (file_exists($filepath)) { + $lasttime = filemtime($filepath); + if (time() - $lasttime > $instance->ttl) { + // Remove cache file. + unlink($filepath); + return false; + } else { + return $filepath; + } + } else { + return false; + } + } + + /** + * Static method to create cache from a file + * + * @param mixed $ref + * @param string $srcfile + * @param array $options + * @return string cached file path + */ + public static function create_from_file($ref, $srcfile, $options = array()) { + $instance = self::get_instance($options); + $cachedfilepath = $instance->generate_filepath($ref); + copy($srcfile, $cachedfilepath); + return $cachedfilepath; + } + + /** + * Static method to create cache from url + * + * @param mixed $ref file reference + * @param string $url file url + * @param array $options options + * @return string cached file path + */ + public static function create_from_url($ref, $url, $options = array()) { + global $CFG; + $instance = self::get_instance($options); + $cachedfilepath = $instance->generate_filepath($ref); + $fp = fopen($cachedfilepath, 'w'); + $curl = new curl; + $curl->download(array(array('url'=>$url, 'file'=>$fp))); + // Must close file handler. + fclose($fp); + return $cachedfilepath; + } + + /** + * Static method to create cache from string + * + * @param mixed $ref file reference + * @param string $url file url + * @param array $options options + * @return string cached file path + */ + public static function create_from_string($ref, $string, $options = array()) { + global $CFG; + $instance = self::get_instance($options); + $cachedfilepath = $instance->generate_filepath($ref); + $fp = fopen($cachedfilepath, 'w'); + fwrite($fp, $string); + // Must close file handler. + fclose($fp); + return $cachedfilepath; + } + + /** + * Build path to cache file + * + * @param mixed $ref + * @return string + */ + private function generate_filepath($ref) { + global $CFG; + $hash = sha1(serialize($ref)); + $l1 = $hash[0].$hash[1]; + $l2 = $hash[2].$hash[3]; + $dir = $this->cachedir . "/$l1/$l2"; + if (!file_exists($dir)) { + mkdir($dir, $CFG->directorypermissions, true); + } + return "$dir/$hash"; + } + + /** + * Remove cache files + * + * @param array $options options + * @param int $expire The number of seconds before expiry + */ + public static function cleanup($options = array(), $expire) { + global $CFG; + $instance = self::get_instance($options); + if ($dir = opendir($instance->cachedir)) { + while (($file = readdir($dir)) !== false) { + if (!is_dir($file) && $file != '.' && $file != '..') { + $lasttime = @filemtime($instance->cachedir . $file); + if(time() - $lasttime > $expire){ + @unlink($instance->cachedir . $file); + } + } + } + closedir($dir); + } + } +} diff --git a/lib/filestorage/file_exceptions.php b/lib/filestorage/file_exceptions.php index 93eef5b0164..68c01de2e39 100644 --- a/lib/filestorage/file_exceptions.php +++ b/lib/filestorage/file_exceptions.php @@ -65,7 +65,7 @@ class stored_file_creation_exception extends file_exception { * @param string $filename file name * @param string $debuginfo extra debug info */ - function __construct($contextid, $component, $filearea, $itemid, $filepath, $filename, $debuginfo = NULL) { + function __construct($contextid, $component, $filearea, $itemid, $filepath, $filename, $debuginfo = null) { $a = new stdClass(); $a->contextid = $contextid; $a->component = $component; @@ -91,8 +91,8 @@ class file_access_exception extends file_exception { * * @param string $debuginfo extra debug info */ - function __construct($debuginfo = NULL) { - parent::__construct('nopermissions', NULL, $debuginfo); + public function __construct($debuginfo = null) { + parent::__construct('nopermissions', null, $debuginfo); } } @@ -111,7 +111,28 @@ class file_pool_content_exception extends file_exception { * @param string $contenthash content hash * @param string $debuginfo extra debug info */ - function __construct($contenthash, $debuginfo = NULL) { + public function __construct($contenthash, $debuginfo = null) { parent::__construct('hashpoolproblem', $contenthash, $debuginfo); } } + +/** + * Exception related to external file support + * + * @package core_files + * @category files + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class external_file_exception extends file_exception { + /** + * Constructor + * + * @param string $errorcode error code + * @param stdClass $a extra information + * @param string $debuginfo extra debug info + */ + public function __construct($errorcode, $a = null, $debuginfo = null) { + parent::__construct($errorcode, '', '', $a, $debuginfo); + } +} diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index 9855a6d0973..55a6307f76a 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -145,11 +145,12 @@ class file_storage { /** * Create instance of file class from database record. * - * @param stdClass $file_record record from the files table + * @param stdClass $filerecord record from the files table * @return stored_file instance of file abstraction class */ - public function get_file_instance(stdClass $file_record) { - return new stored_file($this, $file_record, $this->filedir); + public function get_file_instance(stdClass $filerecord) { + $storedfile = new stored_file($this, $filerecord, $this->filedir); + return $storedfile; } /** @@ -271,8 +272,13 @@ class file_storage { public function get_file_by_id($fileid) { global $DB; - if ($file_record = $DB->get_record('files', array('id'=>$fileid))) { - return $this->get_file_instance($file_record); + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE f.id = ?"; + if ($filerecord = $DB->get_record_sql($sql, array($fileid))) { + return $this->get_file_instance($filerecord); } else { return false; } @@ -287,8 +293,13 @@ class file_storage { public function get_file_by_hash($pathnamehash) { global $DB; - if ($file_record = $DB->get_record('files', array('pathnamehash'=>$pathnamehash))) { - return $this->get_file_instance($file_record); + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE f.pathnamehash = ?"; + if ($filerecord = $DB->get_record_sql($sql, array($pathnamehash))) { + return $this->get_file_instance($filerecord); } else { return false; } @@ -351,6 +362,29 @@ class file_storage { return !$DB->record_exists_sql($sql, $params); } + /** + * Returns all files belonging to given repository + * + * @param int $repositoryid + * @param string $sort + */ + public function get_external_files($repositoryid, $sort = 'sortorder, itemid, filepath, filename') { + global $DB; + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE r.repositoryid = ? + ORDER BY $sort"; + + $result = array(); + $filerecords = $DB->get_records_sql($sql, array($repositoryid)); + foreach ($filerecords as $filerecord) { + $result[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); + } + return $result; + } + /** * Returns all area files (optionally limited by itemid) * @@ -367,16 +401,29 @@ class file_storage { $conditions = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea); if ($itemid !== false) { + $itemidsql = ' AND f.itemid = :itemid '; $conditions['itemid'] = $itemid; + } else { + $itemidsql = ''; } + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE f.contextid = :contextid + AND f.component = :component + AND f.filearea = :filearea + $itemidsql + ORDER BY $sort"; + $result = array(); - $file_records = $DB->get_records('files', $conditions, $sort); - foreach ($file_records as $file_record) { - if (!$includedirs and $file_record->filename === '.') { + $filerecords = $DB->get_records_sql($sql, $conditions); + foreach ($filerecords as $filerecord) { + if (!$includedirs and $filerecord->filename === '.') { continue; } - $result[$file_record->pathnamehash] = $this->get_file_instance($file_record); + $result[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } return $result; } @@ -468,12 +515,12 @@ class file_storage { $files = array(); $dirs = array(); - $file_records = $DB->get_records_sql($sql, $params); - foreach ($file_records as $file_record) { - if ($file_record->filename == '.') { - $dirs[$file_record->pathnamehash] = $this->get_file_instance($file_record); + $filerecords = $DB->get_records_sql($sql, $params); + foreach ($filerecords as $filerecord) { + if ($filerecord->filename == '.') { + $dirs[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } else { - $files[$file_record->pathnamehash] = $this->get_file_instance($file_record); + $files[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } } $result = array_merge($dirs, $files); @@ -493,12 +540,12 @@ class file_storage { AND id <> :dirid ORDER BY $sort"; $reqlevel = substr_count($filepath, '/') + 1; - $file_records = $DB->get_records_sql($sql, $params); - foreach ($file_records as $file_record) { - if (substr_count($file_record->filepath, '/') !== $reqlevel) { + $filerecords = $DB->get_records_sql($sql, $params); + foreach ($filerecords as $filerecord) { + if (substr_count($filerecord->filepath, '/') !== $reqlevel) { continue; } - $result[$file_record->pathnamehash] = $this->get_file_instance($file_record); + $result[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } } @@ -508,9 +555,9 @@ class file_storage { AND filepath = :filepath AND filename <> '.' ORDER BY $sort"; - $file_records = $DB->get_records_sql($sql, $params); - foreach ($file_records as $file_record) { - $result[$file_record->pathnamehash] = $this->get_file_instance($file_record); + $filerecords = $DB->get_records_sql($sql, $params); + foreach ($filerecords as $filerecord) { + $result[$filerecord->pathnamehash] = $this->get_file_instance($filerecord); } } @@ -540,9 +587,9 @@ class file_storage { $conditions['itemid'] = $itemid; } - $file_records = $DB->get_records('files', $conditions); - foreach ($file_records as $file_record) { - $this->get_file_instance($file_record)->delete(); + $filerecords = $DB->get_records('files', $conditions); + foreach ($filerecords as $filerecord) { + $this->get_file_instance($filerecord)->delete(); } return true; // BC only @@ -572,11 +619,11 @@ class file_storage { $params['component'] = $component; $params['filearea'] = $filearea; - $file_records = $DB->get_recordset_select('files', $where, $params); - foreach ($file_records as $file_record) { - $this->get_file_instance($file_record)->delete(); + $filerecords = $DB->get_recordset_select('files', $where, $params); + foreach ($filerecords as $filerecord) { + $this->get_file_instance($filerecord)->delete(); } - $file_records->close(); + $filerecords->close(); } /** @@ -699,11 +746,11 @@ class file_storage { /** * Add new local file based on existing local file. * - * @param stdClass|array $file_record object or array describing changes + * @param stdClass|array $filerecord object or array describing changes * @param stored_file|int $fileorid id or stored_file instance of the existing local file * @return stored_file instance of newly created file */ - public function create_file_from_storedfile($file_record, $fileorid) { + public function create_file_from_storedfile($filerecord, $fileorid) { global $DB; if ($fileorid instanceof stored_file) { @@ -712,20 +759,26 @@ class file_storage { $fid = $fileorid; } - $file_record = (array)$file_record; // we support arrays too, do not modify the submitted record! + $filerecord = (array)$filerecord; // We support arrays too, do not modify the submitted record! - unset($file_record['id']); - unset($file_record['filesize']); - unset($file_record['contenthash']); - unset($file_record['pathnamehash']); + unset($filerecord['id']); + unset($filerecord['filesize']); + unset($filerecord['contenthash']); + unset($filerecord['pathnamehash']); - if (!$newrecord = $DB->get_record('files', array('id'=>$fid))) { + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE f.id = ?"; + + if (!$newrecord = $DB->get_record_sql($sql, array($fid))) { throw new file_exception('storedfileproblem', 'File does not exist'); } unset($newrecord->id); - foreach ($file_record as $key=>$value) { + foreach ($filerecord as $key => $value) { // validate all parameters, we do not want any rubbish stored in database, right? if ($key == 'contextid' and (!is_number($value) or $value < 1)) { throw new file_exception('storedfileproblem', 'Invalid contextid'); @@ -776,6 +829,10 @@ class file_storage { } } + if ($key == 'referencefileid' or $key == 'referencelastsync' or $key == 'referencelifetime') { + $value = clean_param($value, PARAM_INT); + } + $newrecord->$key = $value; } @@ -790,6 +847,21 @@ class file_storage { return $this->get_file_instance($newrecord); } + if (!empty($newrecord->repositoryid)) { + try { + $referencerecord = new stdClass; + $referencerecord->repositoryid = $newrecord->repositoryid; + $referencerecord->reference = $newrecord->reference; + $referencerecord->lastsync = $newrecord->referencelastsync; + $referencerecord->lifetime = $newrecord->referencelifetime; + $referencerecord->id = $DB->insert_record('files_reference', $referencerecord); + } catch (dml_exception $e) { + throw new stored_file_creation_exception($newrecord->contextid, $newrecord->component, $newrecord->filearea, $newrecord->itemid, + $newrecord->filepath, $newrecord->filename, $e->debuginfo); + } + $newrecord->referencefileid = $referencerecord->id; + } + try { $newrecord->id = $DB->insert_record('files', $newrecord); } catch (dml_exception $e) { @@ -797,6 +869,7 @@ class file_storage { $newrecord->filepath, $newrecord->filename, $e->debuginfo); } + $this->create_directory($newrecord->contextid, $newrecord->component, $newrecord->filearea, $newrecord->itemid, $newrecord->filepath, $newrecord->userid); return $this->get_file_instance($newrecord); @@ -805,16 +878,16 @@ class file_storage { /** * Add new local file. * - * @param stdClass|array $file_record object or array describing file + * @param stdClass|array $filerecord object or array describing file * @param string $url the URL to the file * @param array $options {@link download_file_content()} options * @param bool $usetempfile use temporary file for download, may prevent out of memory problems * @return stored_file */ - public function create_file_from_url($file_record, $url, array $options = NULL, $usetempfile = false) { + public function create_file_from_url($filerecord, $url, array $options = null, $usetempfile = false) { - $file_record = (array)$file_record; //do not modify the submitted record, this cast unlinks objects - $file_record = (object)$file_record; // we support arrays too + $filerecord = (array)$filerecord; // Do not modify the submitted record, this cast unlinks objects. + $filerecord = (object)$filerecord; // We support arrays too. $headers = isset($options['headers']) ? $options['headers'] : null; $postdata = isset($options['postdata']) ? $options['postdata'] : null; @@ -824,13 +897,13 @@ class file_storage { $skipcertverify = isset($options['skipcertverify']) ? $options['skipcertverify'] : false; $calctimeout = isset($options['calctimeout']) ? $options['calctimeout'] : false; - if (!isset($file_record->filename)) { + if (!isset($filerecord->filename)) { $parts = explode('/', $url); $filename = array_pop($parts); - $file_record->filename = clean_param($filename, PARAM_FILE); + $filerecord->filename = clean_param($filename, PARAM_FILE); } - $source = !empty($file_record->source) ? $file_record->source : $url; - $file_record->source = clean_param($source, PARAM_URL); + $source = !empty($filerecord->source) ? $filerecord->source : $url; + $filerecord->source = clean_param($source, PARAM_URL); if ($usetempfile) { check_dir_exists($this->tempdir); @@ -840,7 +913,7 @@ class file_storage { throw new file_exception('storedfileproblem', 'Can not fetch file form URL'); } try { - $newfile = $this->create_file_from_pathname($file_record, $tmpfile); + $newfile = $this->create_file_from_pathname($filerecord, $tmpfile); @unlink($tmpfile); return $newfile; } catch (Exception $e) { @@ -853,104 +926,108 @@ class file_storage { if ($content === false) { throw new file_exception('storedfileproblem', 'Can not fetch file form URL'); } - return $this->create_file_from_string($file_record, $content); + return $this->create_file_from_string($filerecord, $content); } } /** * Add new local file. * - * @param stdClass|array $file_record object or array describing file + * @param stdClass|array $filerecord object or array describing file * @param string $pathname path to file or content of file * @return stored_file */ - public function create_file_from_pathname($file_record, $pathname) { + public function create_file_from_pathname($filerecord, $pathname) { global $DB; - $file_record = (array)$file_record; //do not modify the submitted record, this cast unlinks objects - $file_record = (object)$file_record; // we support arrays too + $filerecord = (array)$filerecord; // Do not modify the submitted record, this cast unlinks objects. + $filerecord = (object)$filerecord; // We support arrays too. // validate all parameters, we do not want any rubbish stored in database, right? - if (!is_number($file_record->contextid) or $file_record->contextid < 1) { + if (!is_number($filerecord->contextid) or $filerecord->contextid < 1) { throw new file_exception('storedfileproblem', 'Invalid contextid'); } - $file_record->component = clean_param($file_record->component, PARAM_COMPONENT); - if (empty($file_record->component)) { + $filerecord->component = clean_param($filerecord->component, PARAM_COMPONENT); + if (empty($filerecord->component)) { throw new file_exception('storedfileproblem', 'Invalid component'); } - $file_record->filearea = clean_param($file_record->filearea, PARAM_AREA); - if (empty($file_record->filearea)) { + $filerecord->filearea = clean_param($filerecord->filearea, PARAM_AREA); + if (empty($filerecord->filearea)) { throw new file_exception('storedfileproblem', 'Invalid filearea'); } - if (!is_number($file_record->itemid) or $file_record->itemid < 0) { + if (!is_number($filerecord->itemid) or $filerecord->itemid < 0) { throw new file_exception('storedfileproblem', 'Invalid itemid'); } - if (!empty($file_record->sortorder)) { - if (!is_number($file_record->sortorder) or $file_record->sortorder < 0) { - $file_record->sortorder = 0; + if (!empty($filerecord->sortorder)) { + if (!is_number($filerecord->sortorder) or $filerecord->sortorder < 0) { + $filerecord->sortorder = 0; } } else { - $file_record->sortorder = 0; + $filerecord->sortorder = 0; } - $file_record->filepath = clean_param($file_record->filepath, PARAM_PATH); - if (strpos($file_record->filepath, '/') !== 0 or strrpos($file_record->filepath, '/') !== strlen($file_record->filepath)-1) { + $filerecord->referencefileid = !isset($filerecord->referencefileid) ? 0 : $filerecord->referencefileid; + $filerecord->referencelastsync = !isset($filerecord->referencelastsync) ? 0 : $filerecord->referencelastsync; + $filerecord->referencelifetime = !isset($filerecord->referencelifetime) ? 0 : $filerecord->referencelifetime; + + $filerecord->filepath = clean_param($filerecord->filepath, PARAM_PATH); + if (strpos($filerecord->filepath, '/') !== 0 or strrpos($filerecord->filepath, '/') !== strlen($filerecord->filepath)-1) { // path must start and end with '/' throw new file_exception('storedfileproblem', 'Invalid file path'); } - $file_record->filename = clean_param($file_record->filename, PARAM_FILE); - if ($file_record->filename === '') { + $filerecord->filename = clean_param($filerecord->filename, PARAM_FILE); + if ($filerecord->filename === '') { // filename must not be empty throw new file_exception('storedfileproblem', 'Invalid file name'); } $now = time(); - if (isset($file_record->timecreated)) { - if (!is_number($file_record->timecreated)) { + if (isset($filerecord->timecreated)) { + if (!is_number($filerecord->timecreated)) { throw new file_exception('storedfileproblem', 'Invalid file timecreated'); } - if ($file_record->timecreated < 0) { + if ($filerecord->timecreated < 0) { //NOTE: unfortunately I make a mistake when creating the "files" table, we can not have negative numbers there, on the other hand no file should be older than 1970, right? (skodak) - $file_record->timecreated = 0; + $filerecord->timecreated = 0; } } else { - $file_record->timecreated = $now; + $filerecord->timecreated = $now; } - if (isset($file_record->timemodified)) { - if (!is_number($file_record->timemodified)) { + if (isset($filerecord->timemodified)) { + if (!is_number($filerecord->timemodified)) { throw new file_exception('storedfileproblem', 'Invalid file timemodified'); } - if ($file_record->timemodified < 0) { + if ($filerecord->timemodified < 0) { //NOTE: unfortunately I make a mistake when creating the "files" table, we can not have negative numbers there, on the other hand no file should be older than 1970, right? (skodak) - $file_record->timemodified = 0; + $filerecord->timemodified = 0; } } else { - $file_record->timemodified = $now; + $filerecord->timemodified = $now; } $newrecord = new stdClass(); - $newrecord->contextid = $file_record->contextid; - $newrecord->component = $file_record->component; - $newrecord->filearea = $file_record->filearea; - $newrecord->itemid = $file_record->itemid; - $newrecord->filepath = $file_record->filepath; - $newrecord->filename = $file_record->filename; + $newrecord->contextid = $filerecord->contextid; + $newrecord->component = $filerecord->component; + $newrecord->filearea = $filerecord->filearea; + $newrecord->itemid = $filerecord->itemid; + $newrecord->filepath = $filerecord->filepath; + $newrecord->filename = $filerecord->filename; - $newrecord->timecreated = $file_record->timecreated; - $newrecord->timemodified = $file_record->timemodified; - $newrecord->mimetype = empty($file_record->mimetype) ? mimeinfo('type', $file_record->filename) : $file_record->mimetype; - $newrecord->userid = empty($file_record->userid) ? null : $file_record->userid; - $newrecord->source = empty($file_record->source) ? null : $file_record->source; - $newrecord->author = empty($file_record->author) ? null : $file_record->author; - $newrecord->license = empty($file_record->license) ? null : $file_record->license; - $newrecord->sortorder = $file_record->sortorder; + $newrecord->timecreated = $filerecord->timecreated; + $newrecord->timemodified = $filerecord->timemodified; + $newrecord->mimetype = empty($filerecord->mimetype) ? mimeinfo('type', $filerecord->filename) : $filerecord->mimetype; + $newrecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; + $newrecord->source = empty($filerecord->source) ? null : $filerecord->source; + $newrecord->author = empty($filerecord->author) ? null : $filerecord->author; + $newrecord->license = empty($filerecord->license) ? null : $filerecord->license; + $newrecord->sortorder = $filerecord->sortorder; list($newrecord->contenthash, $newrecord->filesize, $newfile) = $this->add_file_to_pool($pathname); @@ -974,97 +1051,100 @@ class file_storage { /** * Add new local file. * - * @param stdClass|array $file_record object or array describing file + * @param stdClass|array $filerecord object or array describing file * @param string $content content of file * @return stored_file */ - public function create_file_from_string($file_record, $content) { + public function create_file_from_string($filerecord, $content) { global $DB; - $file_record = (array)$file_record; //do not modify the submitted record, this cast unlinks objects - $file_record = (object)$file_record; // we support arrays too + $filerecord = (array)$filerecord; // Do not modify the submitted record, this cast unlinks objects. + $filerecord = (object)$filerecord; // We support arrays too. // validate all parameters, we do not want any rubbish stored in database, right? - if (!is_number($file_record->contextid) or $file_record->contextid < 1) { + if (!is_number($filerecord->contextid) or $filerecord->contextid < 1) { throw new file_exception('storedfileproblem', 'Invalid contextid'); } - $file_record->component = clean_param($file_record->component, PARAM_COMPONENT); - if (empty($file_record->component)) { + $filerecord->component = clean_param($filerecord->component, PARAM_COMPONENT); + if (empty($filerecord->component)) { throw new file_exception('storedfileproblem', 'Invalid component'); } - $file_record->filearea = clean_param($file_record->filearea, PARAM_AREA); - if (empty($file_record->filearea)) { + $filerecord->filearea = clean_param($filerecord->filearea, PARAM_AREA); + if (empty($filerecord->filearea)) { throw new file_exception('storedfileproblem', 'Invalid filearea'); } - if (!is_number($file_record->itemid) or $file_record->itemid < 0) { + if (!is_number($filerecord->itemid) or $filerecord->itemid < 0) { throw new file_exception('storedfileproblem', 'Invalid itemid'); } - if (!empty($file_record->sortorder)) { - if (!is_number($file_record->sortorder) or $file_record->sortorder < 0) { - $file_record->sortorder = 0; + if (!empty($filerecord->sortorder)) { + if (!is_number($filerecord->sortorder) or $filerecord->sortorder < 0) { + $filerecord->sortorder = 0; } } else { - $file_record->sortorder = 0; + $filerecord->sortorder = 0; } + $filerecord->referencefileid = !isset($filerecord->referencefileid) ? 0 : $filerecord->referencefileid; + $filerecord->referencelastsync = !isset($filerecord->referencelastsync) ? 0 : $filerecord->referencelastsync; + $filerecord->referencelifetime = !isset($filerecord->referencelifetime) ? 0 : $filerecord->referencelifetime; - $file_record->filepath = clean_param($file_record->filepath, PARAM_PATH); - if (strpos($file_record->filepath, '/') !== 0 or strrpos($file_record->filepath, '/') !== strlen($file_record->filepath)-1) { + $filerecord->filepath = clean_param($filerecord->filepath, PARAM_PATH); + if (strpos($filerecord->filepath, '/') !== 0 or strrpos($filerecord->filepath, '/') !== strlen($filerecord->filepath)-1) { // path must start and end with '/' throw new file_exception('storedfileproblem', 'Invalid file path'); } - $file_record->filename = clean_param($file_record->filename, PARAM_FILE); - if ($file_record->filename === '') { + $filerecord->filename = clean_param($filerecord->filename, PARAM_FILE); + if ($filerecord->filename === '') { // path must start and end with '/' throw new file_exception('storedfileproblem', 'Invalid file name'); } $now = time(); - if (isset($file_record->timecreated)) { - if (!is_number($file_record->timecreated)) { + if (isset($filerecord->timecreated)) { + if (!is_number($filerecord->timecreated)) { throw new file_exception('storedfileproblem', 'Invalid file timecreated'); } - if ($file_record->timecreated < 0) { + if ($filerecord->timecreated < 0) { //NOTE: unfortunately I make a mistake when creating the "files" table, we can not have negative numbers there, on the other hand no file should be older than 1970, right? (skodak) - $file_record->timecreated = 0; + $filerecord->timecreated = 0; } } else { - $file_record->timecreated = $now; + $filerecord->timecreated = $now; } - if (isset($file_record->timemodified)) { - if (!is_number($file_record->timemodified)) { + if (isset($filerecord->timemodified)) { + if (!is_number($filerecord->timemodified)) { throw new file_exception('storedfileproblem', 'Invalid file timemodified'); } - if ($file_record->timemodified < 0) { + if ($filerecord->timemodified < 0) { //NOTE: unfortunately I make a mistake when creating the "files" table, we can not have negative numbers there, on the other hand no file should be older than 1970, right? (skodak) - $file_record->timemodified = 0; + $filerecord->timemodified = 0; } } else { - $file_record->timemodified = $now; + $filerecord->timemodified = $now; } $newrecord = new stdClass(); - $newrecord->contextid = $file_record->contextid; - $newrecord->component = $file_record->component; - $newrecord->filearea = $file_record->filearea; - $newrecord->itemid = $file_record->itemid; - $newrecord->filepath = $file_record->filepath; - $newrecord->filename = $file_record->filename; + $newrecord->contextid = $filerecord->contextid; + $newrecord->component = $filerecord->component; + $newrecord->filearea = $filerecord->filearea; + $newrecord->itemid = $filerecord->itemid; + $newrecord->filepath = $filerecord->filepath; + $newrecord->filename = $filerecord->filename; - $newrecord->timecreated = $file_record->timecreated; - $newrecord->timemodified = $file_record->timemodified; - $newrecord->mimetype = empty($file_record->mimetype) ? mimeinfo('type', $file_record->filename) : $file_record->mimetype; - $newrecord->userid = empty($file_record->userid) ? null : $file_record->userid; - $newrecord->source = empty($file_record->source) ? null : $file_record->source; - $newrecord->author = empty($file_record->author) ? null : $file_record->author; - $newrecord->license = empty($file_record->license) ? null : $file_record->license; - $newrecord->sortorder = $file_record->sortorder; + $newrecord->timecreated = $filerecord->timecreated; + $newrecord->timemodified = $filerecord->timemodified; + $newrecord->mimetype = empty($filerecord->mimetype) ? mimeinfo('type', $filerecord->filename) : $filerecord->mimetype; + $newrecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; + $newrecord->source = empty($filerecord->source) ? null : $filerecord->source; + $newrecord->author = empty($filerecord->author) ? null : $filerecord->author; + $newrecord->license = empty($filerecord->license) ? null : $filerecord->license; + $newrecord->sortorder = $filerecord->sortorder; list($newrecord->contenthash, $newrecord->filesize, $newfile) = $this->add_string_to_pool($content); @@ -1085,10 +1165,135 @@ class file_storage { return $this->get_file_instance($newrecord); } + /** + * Create a moodle file from file reference information + * + * @param stdClass $filerecord + * @param int $repositoryid + * @param string $reference + * @param array $options options for creating external file + * @return stored_file + */ + public function create_file_from_reference($filerecord, $repositoryid, $reference, $options = array()) { + global $DB; + + $filerecord = (array)$filerecord; // Do not modify the submitted record, this cast unlinks objects. + $filerecord = (object)$filerecord; // We support arrays too. + + // validate all parameters, we do not want any rubbish stored in database, right? + if (!is_number($filerecord->contextid) or $filerecord->contextid < 1) { + throw new file_exception('storedfileproblem', 'Invalid contextid'); + } + + $filerecord->component = clean_param($filerecord->component, PARAM_COMPONENT); + if (empty($filerecord->component)) { + throw new file_exception('storedfileproblem', 'Invalid component'); + } + + $filerecord->filearea = clean_param($filerecord->filearea, PARAM_AREA); + if (empty($filerecord->filearea)) { + throw new file_exception('storedfileproblem', 'Invalid filearea'); + } + + if (!is_number($filerecord->itemid) or $filerecord->itemid < 0) { + throw new file_exception('storedfileproblem', 'Invalid itemid'); + } + + if (!empty($filerecord->sortorder)) { + if (!is_number($filerecord->sortorder) or $filerecord->sortorder < 0) { + $filerecord->sortorder = 0; + } + } else { + $filerecord->sortorder = 0; + } + + $filerecord->referencefileid = empty($filerecord->referencefileid) ? 0 : $filerecord->referencefileid; + $filerecord->referencelastsync = empty($filerecord->referencelastsync) ? 0 : $filerecord->referencelastsync; + $filerecord->referencelifetime = empty($filerecord->referencelifetime) ? 0 : $filerecord->referencelifetime; + $filerecord->mimetype = empty($filerecord->mimetype) ? mimeinfo('type', $filerecord->filename) : $filerecord->mimetype; + $filerecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; + $filerecord->source = empty($filerecord->source) ? null : $filerecord->source; + $filerecord->author = empty($filerecord->author) ? null : $filerecord->author; + $filerecord->license = empty($filerecord->license) ? null : $filerecord->license; + $filerecord->filepath = clean_param($filerecord->filepath, PARAM_PATH); + if (strpos($filerecord->filepath, '/') !== 0 or strrpos($filerecord->filepath, '/') !== strlen($filerecord->filepath)-1) { + // Path must start and end with '/'. + throw new file_exception('storedfileproblem', 'Invalid file path'); + } + + $filerecord->filename = clean_param($filerecord->filename, PARAM_FILE); + if ($filerecord->filename === '') { + // Path must start and end with '/'. + throw new file_exception('storedfileproblem', 'Invalid file name'); + } + + $now = time(); + if (isset($filerecord->timecreated)) { + if (!is_number($filerecord->timecreated)) { + throw new file_exception('storedfileproblem', 'Invalid file timecreated'); + } + if ($filerecord->timecreated < 0) { + // NOTE: unfortunately I make a mistake when creating the "files" table, we can not have negative numbers there, on the other hand no file should be older than 1970, right? (skodak) + $filerecord->timecreated = 0; + } + } else { + $filerecord->timecreated = $now; + } + + if (isset($filerecord->timemodified)) { + if (!is_number($filerecord->timemodified)) { + throw new file_exception('storedfileproblem', 'Invalid file timemodified'); + } + if ($filerecord->timemodified < 0) { + // NOTE: unfortunately I make a mistake when creating the "files" table, we can not have negative numbers there, on the other hand no file should be older than 1970, right? (skodak) + $filerecord->timemodified = 0; + } + } else { + $filerecord->timemodified = $now; + } + + // Insert file reference record. + try { + $referencerecord = new stdClass; + $referencerecord->repositoryid = $repositoryid; + $referencerecord->reference = $reference; + $referencerecord->lastsync = $filerecord->referencelastsync; + $referencerecord->lifetime = $filerecord->referencelifetime; + $referencerecord->id = $DB->insert_record('files_reference', $referencerecord); + } catch (dml_exception $e) { + throw $e; + } + + $filerecord->referencefileid = $referencerecord->id; + + // External file doesn't have content in moodle. + // So we create an empty file for it. + list($filerecord->contenthash, $filerecord->filesize, $newfile) = $this->add_string_to_pool(null); + + $filerecord->pathnamehash = $this->get_pathname_hash($filerecord->contextid, $filerecord->component, $filerecord->filearea, $filerecord->itemid, $filerecord->filepath, $filerecord->filename); + + try { + $filerecord->id = $DB->insert_record('files', $filerecord); + } catch (dml_exception $e) { + if ($newfile) { + $this->deleted_file_cleanup($filerecord->contenthash); + } + throw new stored_file_creation_exception($filerecord->contextid, $filerecord->component, $filerecord->filearea, $filerecord->itemid, + $filerecord->filepath, $filerecord->filename, $e->debuginfo); + } + + $this->create_directory($filerecord->contextid, $filerecord->component, $filerecord->filearea, $filerecord->itemid, $filerecord->filepath, $filerecord->userid); + + // Adding repositoryid and reference to file record to create stored_file instance + $filerecord->repositoryid = $repositoryid; + $filerecord->reference = $reference; + return $this->get_file_instance($filerecord); + } + /** * Creates new image file from existing. * - * @param stdClass|array $file_record object or array describing new file + * @param stdClass|array $filerecord object or array describing new file * @param int|stored_file $fid file id or stored file object * @param int $newwidth in pixels * @param int $newheight in pixels @@ -1096,7 +1301,7 @@ class file_storage { * @param int $quality depending on image type 0-100 for jpeg, 0-9 (0 means no compression) for png * @return stored_file */ - public function convert_image($file_record, $fid, $newwidth = NULL, $newheight = NULL, $keepaspectratio = true, $quality = NULL) { + public function convert_image($filerecord, $fid, $newwidth = null, $newheight = null, $keepaspectratio = true, $quality = null) { if (!function_exists('imagecreatefromstring')) { //Most likely the GD php extension isn't installed //image conversion cannot succeed @@ -1107,9 +1312,9 @@ class file_storage { $fid = $fid->get_id(); } - $file_record = (array)$file_record; // we support arrays too, do not modify the submitted record! + $filerecord = (array)$filerecord; // We support arrays too, do not modify the submitted record! - if (!$file = $this->get_file_by_id($fid)) { // make sure file really exists and we we correct data + if (!$file = $this->get_file_by_id($fid)) { // Make sure file really exists and we we correct data. throw new file_exception('storedfileproblem', 'File does not exist'); } @@ -1117,12 +1322,12 @@ class file_storage { throw new file_exception('storedfileproblem', 'File is not an image'); } - if (!isset($file_record['filename'])) { - $file_record['filename'] = $file->get_filename(); + if (!isset($filerecord['filename'])) { + $filerecord['filename'] = $file->get_filename(); } - if (!isset($file_record['mimetype'])) { - $file_record['mimetype'] = mimeinfo('type', $file_record['filename']); + if (!isset($filerecord['mimetype'])) { + $filerecord['mimetype'] = mimeinfo('type', $filerecord['filename']); } $width = $imageinfo['width']; @@ -1171,7 +1376,7 @@ class file_storage { } ob_start(); - switch ($file_record['mimetype']) { + switch ($filerecord['mimetype']) { case 'image/gif': imagegif($img); break; @@ -1201,7 +1406,7 @@ class file_storage { throw new file_exception('storedfileproblem', 'Can not convert image'); } - return $this->create_file_from_string($file_record, $content); + return $this->create_file_from_string($filerecord, $content); } /** @@ -1310,6 +1515,18 @@ class file_storage { return xsendfile("$hashpath/$contenthash"); } + /** + * Content exists + * + * @param string $contenthash + * @return bool + */ + public function content_exists($contenthash) { + $dir = $this->path_from_hash($contenthash); + $filepath = $dir . '/' . $contenthash; + return file_exists($filepath); + } + /** * Return path to file with given hash. * @@ -1408,6 +1625,167 @@ class file_storage { chmod($trashfile, $this->filepermissions); // fix permissions if needed } + /** + * When user referring to a moodle file, we build the reference field + * + * @param array $params + * @return string + */ + public static function pack_reference($params) { + $params = (array)$params; + $reference = array(); + $reference['contextid'] = is_null($params['contextid']) ? null : clean_param($params['contextid'], PARAM_INT); + $reference['component'] = is_null($params['component']) ? null : clean_param($params['component'], PARAM_COMPONENT); + $reference['itemid'] = is_null($params['itemid']) ? null : clean_param($params['itemid'], PARAM_INT); + $reference['filearea'] = is_null($params['filearea']) ? null : clean_param($params['filearea'], PARAM_AREA); + $reference['filepath'] = is_null($params['filepath']) ? null : clean_param($params['filepath'], PARAM_PATH);; + $reference['filename'] = is_null($params['filename']) ? null : clean_param($params['filename'], PARAM_FILE); + return base64_encode(serialize($reference)); + } + + /** + * Unpack reference field + * + * @param string $str + * @return array + */ + public static function unpack_reference($str) { + return unserialize(base64_decode($str)); + } + + /** + * Search references by providing reference content + * + * @param string $str + * @return array + */ + public function search_references($str) { + global $DB; + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE r.reference = ?"; + + $rs = $DB->get_recordset_sql($sql, array($str)); + $files = array(); + foreach ($rs as $filerecord) { + $file = $this->get_file_instance($filerecord); + if ($file->is_external_file()) { + $files[$filerecord->pathnamehash] = $file; + } + } + + return $files; + } + + /** + * Search references count by providing reference content + * + * @param string $str + * @return int + */ + public function search_references_count($str) { + global $DB; + $sql = "SELECT COUNT(f.id) + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE r.reference = ?"; + + $count = $DB->count_records_sql($sql, array($str)); + return $count; + } + + /** + * Return all files referring to provided stored_file instance + * This won't work for draft files + * + * @param stored_file $storedfile + * @return array + */ + public function get_references_by_storedfile($storedfile) { + global $DB; + + $params = array(); + $params['contextid'] = $storedfile->get_contextid(); + $params['component'] = $storedfile->get_component(); + $params['filearea'] = $storedfile->get_filearea(); + $params['itemid'] = $storedfile->get_itemid(); + $params['filename'] = $storedfile->get_filename(); + $params['filepath'] = $storedfile->get_filepath(); + $params['userid'] = $storedfile->get_userid(); + + $reference = self::pack_reference($params); + + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE r.reference = ?"; + + $rs = $DB->get_recordset_sql($sql, array($reference)); + $files = array(); + foreach ($rs as $filerecord) { + $file = $this->get_file_instance($filerecord); + if ($file->is_external_file()) { + $files[$filerecord->pathnamehash] = $file; + } + } + + return $files; + } + + /** + * Return the count files referring to provided stored_file instance + * This won't work for draft files + * + * @param stored_file $storedfile + * @return int + */ + public function get_references_count_by_storedfile($storedfile) { + global $DB; + + $params = array(); + $params['contextid'] = $storedfile->get_contextid(); + $params['component'] = $storedfile->get_component(); + $params['filearea'] = $storedfile->get_filearea(); + $params['itemid'] = $storedfile->get_itemid(); + $params['filename'] = $storedfile->get_filename(); + $params['filepath'] = $storedfile->get_filepath(); + $params['userid'] = $storedfile->get_userid(); + + $reference = self::pack_reference($params); + + $sql = "SELECT COUNT(f.id) + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE r.reference = ?"; + + $count = $DB->count_records_sql($sql, array($reference)); + return $count; + } + + /** + * Convert file alias to local file + * + * @param stored_file $storedfile a stored_file instances + * @return stored_file|bool stored_file or return false when fail + */ + public function import_external_file($storedfile) { + global $CFG; + require_once($CFG->dirroot.'/repository/lib.php'); + // sync external file + if (repository::sync_external_file($storedfile)) { + // Remove file references + $storedfile->delete_reference(); + return $storedfile; + } else { + return false; + } + } + /** * Cron cleanup job. */ diff --git a/lib/filestorage/stored_file.php b/lib/filestorage/stored_file.php index bc19c0ba78b..fabf9480c71 100644 --- a/lib/filestorage/stored_file.php +++ b/lib/filestorage/stored_file.php @@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/filestorage/stored_file.php"); +require_once("$CFG->dirroot/repository/lib.php"); /** * Class representing local files stored in a sha1 file pool. @@ -46,6 +47,8 @@ class stored_file { private $file_record; /** @var string location of content files */ private $filedir; + /** @var repository repository plugin instance */ + public $repository; /** * Constructor, this constructor should be called ONLY from the file_storage class! @@ -55,9 +58,142 @@ class stored_file { * @param string $filedir location of file directory with sh1 named content files */ public function __construct(file_storage $fs, stdClass $file_record, $filedir) { + global $DB, $CFG; $this->fs = $fs; $this->file_record = clone($file_record); // prevent modifications $this->filedir = $filedir; // keep secret, do not expose! + + if (!empty($file_record->repositoryid)) { + $this->repository = repository::get_repository_by_id($file_record->repositoryid, SYSCONTEXTID); + if ($this->repository->supported_returntypes() & FILE_REFERENCE != FILE_REFERENCE) { + // Repository cannot do file reference. + throw new moodle_exception('error'); + } + } else { + $this->repository = null; + } + } + + /** + * Whether or not this is a external resource + * + * @return bool + */ + public function is_external_file() { + return !empty($this->repository); + } + + /** + * Update some file record fields + * NOTE: Must remain protected + * + * @param stdClass $dataobject + */ + protected function update($dataobject) { + global $DB; + $keys = array_keys((array)$this->file_record); + foreach ($dataobject as $field => $value) { + if (in_array($field, $keys)) { + if ($field == 'contextid' and (!is_number($value) or $value < 1)) { + throw new file_exception('storedfileproblem', 'Invalid contextid'); + } + + if ($field == 'component') { + $value = clean_param($value, PARAM_COMPONENT); + if (empty($value)) { + throw new file_exception('storedfileproblem', 'Invalid component'); + } + } + + if ($field == 'filearea') { + $value = clean_param($value, PARAM_AREA); + if (empty($value)) { + throw new file_exception('storedfileproblem', 'Invalid filearea'); + } + } + + if ($field == 'itemid' and (!is_number($value) or $value < 0)) { + throw new file_exception('storedfileproblem', 'Invalid itemid'); + } + + + if ($field == 'filepath') { + $value = clean_param($value, PARAM_PATH); + if (strpos($value, '/') !== 0 or strrpos($value, '/') !== strlen($value)-1) { + // path must start and end with '/' + throw new file_exception('storedfileproblem', 'Invalid file path'); + } + } + + if ($field == 'filename') { + $value = clean_param($value, PARAM_FILE); + if ($value === '') { + throw new file_exception('storedfileproblem', 'Invalid file name'); + } + } + + if ($field === 'timecreated' or $field === 'timemodified') { + if (!is_number($value)) { + throw new file_exception('storedfileproblem', 'Invalid timestamp'); + } + if ($value < 0) { + $value = 0; + } + } + + if ($field == 'referencefileid' or $field == 'referencelastsync' or $field == 'referencelifetime') { + $value = clean_param($value, PARAM_INT); + } + + // adding the field + $this->file_record->$field = $value; + } else { + throw new coding_exception("Invalid field name, $field doesn't exist in file record"); + } + } + $DB->update_record('files', $this->file_record); + } + + /** + * Rename filename + * + * @param string $filepath file path + * @param string $filename file name + */ + public function rename($filepath, $filename) { + $filerecord = new stdClass; + $filerecord->filepath = $filepath; + $filerecord->filename = $filename; + // populate the pathname hash + $filerecord->pathnamehash = $this->fs->get_pathname_hash($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath, $filename); + $this->update($filerecord); + } + + /** + * Replace the content by providing another stored_file instance + * + * @param stored_file $storedfile + */ + public function replace_content_with(stored_file $storedfile) { + $contenthash = $storedfile->get_contenthash(); + $this->set_contenthash($contenthash); + } + + /** + * Delete file reference + * + */ + public function delete_reference() { + global $DB; + // Remove repository info. + $this->repository = null; + unset($this->file_record->repositoryid); + unset($this->file_record->reference); + unset($this->file_record->referencelastsync); + unset($this->file_record->referencelifetime); + + // Remove reference info from DB. + $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid)); } /** @@ -83,7 +219,15 @@ class stored_file { */ public function delete() { global $DB; + // If other files referring to this file, we need convert them + if ($files = $this->fs->get_references_by_storedfile($this)) { + foreach ($files as $file) { + $this->fs->import_external_file($file); + } + } + // Now delete file records in DB $DB->delete_records('files', array('id'=>$this->file_record->id)); + $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid)); // moves pool file to trash if content not needed any more $this->fs->deleted_file_cleanup($this->file_record->contenthash); return true; // BC only @@ -97,9 +241,12 @@ class stored_file { * @return string full path to pool file with file content **/ protected function get_content_file_location() { + $this->sync_external_file(); + // Detect is local file or not. $contenthash = $this->file_record->contenthash; $l1 = $contenthash[0].$contenthash[1]; $l2 = $contenthash[2].$contenthash[3]; + $path = "$this->filedir/$l1/$l2/$contenthash"; return "$this->filedir/$l1/$l2/$contenthash"; } @@ -128,7 +275,7 @@ class stored_file { throw new file_exception('storedfilecannotread', '', $path); } } - return fopen($path, 'rb'); //binary reading only!! + return fopen($path, 'rb'); // Binary reading only!! } /** @@ -300,7 +447,33 @@ class stored_file { } /** - * Returns context id of the file- + * Sync external files + * + * @return bool true if file content changed, false if not + */ + public function sync_external_file() { + global $CFG, $DB; + if (empty($this->file_record->referencefileid)) { + return false; + } + if (empty($this->file_record->referencelastsync) or ($this->file_record->referencelastsync + $this->file_record->referencelifetime < time())) { + require_once($CFG->dirroot.'/repository/lib.php'); + if (repository::sync_external_file($this)) { + $prevcontent = $this->file_record->contenthash; + $sql = "SELECT f.*, r.repositoryid, r.reference + FROM {files} f + LEFT JOIN {files_reference} r + ON f.referencefileid = r.id + WHERE f.id = ?"; + $this->file_record = $DB->get_record_sql($sql, array($this->file_record->id), MUST_EXIST); + return ($prevcontent !== $this->file_record->contenthash); + } + } + return false; + } + + /** + * Returns context id of the file * * @return int context id */ @@ -370,6 +543,7 @@ class stored_file { * @return int bytes */ public function get_filesize() { + $this->sync_external_file(); return $this->file_record->filesize; } @@ -397,9 +571,21 @@ class stored_file { * @return int */ public function get_timemodified() { + $this->sync_external_file(); return $this->file_record->timemodified; } + /** + * set timemodified + * + * @param int $timemodified + */ + public function set_timemodified($timemodified) { + $filerecord = new stdClass; + $filerecord->timemodified = $timemodified; + $this->update($filerecord); + } + /** * Returns file status flag. * @@ -424,9 +610,26 @@ class stored_file { * @return string */ public function get_contenthash() { + $this->sync_external_file(); return $this->file_record->contenthash; } + /** + * Set contenthash + * + * @param string $contenthash + */ + protected function set_contenthash($contenthash) { + // make sure the content exists in moodle file pool + if ($this->fs->content_exists($contenthash)) { + $filerecord = new stdClass; + $filerecord->contenthash = $contenthash; + $this->update($filerecord); + } else { + throw new file_exception('storedfileproblem', 'Invalid contenthash, content must be already in filepool', $contenthash); + } + } + /** * Returns sha1 hash of all file path components sha1("contextid/component/filearea/itemid/dir/dir/filename.ext"). * @@ -445,6 +648,17 @@ class stored_file { return $this->file_record->license; } + /** + * Set license + * + * @param string $license license + */ + public function set_license($license) { + $filerecord = new stdClass; + $filerecord->license = $license; + $this->update($filerecord); + } + /** * Returns the author name of the file. * @@ -454,6 +668,17 @@ class stored_file { return $this->file_record->author; } + /** + * Set author + * + * @param string $author + */ + public function set_author($author) { + $filerecord = new stdClass; + $filerecord->author = $author; + $this->update($filerecord); + } + /** * Returns the source of the file, usually it is a url. * @@ -463,6 +688,18 @@ class stored_file { return $this->file_record->source; } + /** + * Set license + * + * @param string $license license + */ + public function set_source($source) { + $filerecord = new stdClass; + $filerecord->source = $source; + $this->update($filerecord); + } + + /** * Returns the sort order of file * @@ -471,4 +708,82 @@ class stored_file { public function get_sortorder() { return $this->file_record->sortorder; } + + /** + * Set file sort order + * + * @param int $sortorder + * @return int + */ + public function set_sortorder($sortorder) { + $filerecord = new stdClass; + $filerecord->sortorder = $sortorder; + $this->update($filerecord); + } + + /** + * Returns repository id + * + * @return int|null + */ + public function get_repository_id() { + if (!empty($this->repository)) { + return $this->repository->id; + } else { + return null; + } + } + + /** + * get reference file id + * @return int + */ + public function get_referencefileid() { + return $this->file_record->referencefileid; + } + + /** + * Get reference last sync time + * @return int + */ + public function get_referencelastsync() { + return $this->file_record->referencelastsync; + } + + /** + * Get reference last sync time + * @return int + */ + public function get_referencelifetime() { + return $this->file_record->referencelifetime; + } + /** + * Returns file reference + * + * @return string + */ + public function get_reference() { + return $this->file_record->reference; + } + + /** + * Get human readable file reference information + * + * @return string + */ + public function get_reference_details() { + return $this->repository->get_reference_details($this->get_reference()); + } + + /** + * Send file references + * + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($lifetime, $filter, $forcedownload, $options) { + $this->repository->send_file($this, $lifetime, $filter, $forcedownload, $options); + } } diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index ba31f8043a9..d52533278c4 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -77,4 +77,128 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertInstanceOf('stored_file', $previewtinyicon); $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename()); } + + /** + * Make sure renaming is working + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + */ + public function test_file_renaming() { + global $CFG; + + $this->resetAfterTest(true); + $fs = get_file_storage(); + $syscontext = context_system::instance(); + $component = 'core'; + $filearea = 'unittest'; + $itemid = 0; + $filepath = '/'; + $filename = 'test.txt'; + + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => $component, + 'filearea' => $filearea, + 'itemid' => $itemid, + 'filepath' => $filepath, + 'filename' => $filename, + ); + + $originalfile = $fs->create_file_from_string($filerecord, 'Test content'); + $this->assertInstanceOf('stored_file', $originalfile); + $contenthash = $originalfile->get_contenthash(); + $newpath = '/test/'; + $newname = 'newtest.txt'; + $originalfile->rename($newpath, $newname); + + $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname); + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($contenthash, $file->get_contenthash()); + } + + /** + * Create file from reference tests + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + */ + public function test_create_file_from_reference() { + global $CFG, $DB; + + $this->resetAfterTest(true); + // create user + $generator = $this->getDataGenerator(); + $user = $generator->create_user(); + $usercontext = context_user::instance($user->id); + $syscontext = context_system::instance(); + $USER = $DB->get_record('user', array('id'=>$user->id)); + + $fs = get_file_storage(); + + $repositorypluginname = 'user'; + // override repository permission + $capability = 'repository/' . $repositorypluginname . ':view'; + $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id'); + assign_capability($capability, CAP_ALLOW, $allroles['guest'], $syscontext->id, true); + + + $args = array(); + $args['type'] = $repositorypluginname; + $repos = repository::get_instances($args); + $userrepository = reset($repos); + $this->assertInstanceOf('repository', $userrepository); + + $component = 'user'; + $filearea = 'private'; + $itemid = 0; + $filepath = '/'; + $filename = 'userfile.txt'; + + $filerecord = array( + 'contextid' => $usercontext->id, + 'component' => $component, + 'filearea' => $filearea, + 'itemid' => $itemid, + 'filepath' => $filepath, + 'filename' => $filename, + ); + + $content = 'Test content'; + $originalfile = $fs->create_file_from_string($filerecord, $content); + $this->assertInstanceOf('stored_file', $originalfile); + + $newfilerecord = array( + 'contextid' => $syscontext->id, + 'component' => 'core', + 'filearea' => 'phpunit', + 'itemid' => 0, + 'filepath' => $filepath, + 'filename' => $filename, + ); + $ref = $fs->pack_reference($filerecord); + $newstoredfile = $fs->create_file_from_reference($newfilerecord, $userrepository->id, $ref); + $this->assertInstanceOf('stored_file', $newstoredfile); + $this->assertEquals($userrepository->id, $newstoredfile->repository->id); + $this->assertEquals($originalfile->get_contenthash(), $newstoredfile->get_contenthash()); + $this->assertEquals($originalfile->get_filesize(), $newstoredfile->get_filesize()); + $this->assertRegExp('#' . $filename. '$#', $newstoredfile->get_reference_details()); + + // Test looking for references + $count = $fs->get_references_count_by_storedfile($originalfile); + $this->assertEquals(1, $count); + $files = $fs->get_references_by_storedfile($originalfile); + $file = reset($files); + $this->assertEquals($file, $newstoredfile); + + // Look for references by repository ID + $files = $fs->get_external_files($userrepository->id); + $file = reset($files); + $this->assertEquals($file, $newstoredfile); + + // Try convert reference to local file + $importedfile = $fs->import_external_file($newstoredfile); + $this->assertFalse($importedfile->is_external_file()); + $this->assertInstanceOf('stored_file', $importedfile); + // still readable? + $this->assertEquals($content, $importedfile->get_content()); + } } diff --git a/lib/form/editor.php b/lib/form/editor.php index a993ffd467a..fdbbaf9faad 100644 --- a/lib/form/editor.php +++ b/lib/form/editor.php @@ -303,7 +303,7 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element { $args = new stdClass(); // need these three to filter repositories list $args->accepted_types = array('image'); - $args->return_types = (FILE_INTERNAL | FILE_EXTERNAL); + $args->return_types = (FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE); $args->context = $ctx; $args->env = 'filepicker'; // advimage plugin @@ -407,4 +407,4 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element { return ''; } -} \ No newline at end of file +} diff --git a/lib/form/filemanager.php b/lib/form/filemanager.php index 213ecc675f6..beceb6317e4 100644 --- a/lib/form/filemanager.php +++ b/lib/form/filemanager.php @@ -45,7 +45,10 @@ class MoodleQuickForm_filemanager extends HTML_QuickForm_element { public $_helpbutton = ''; /** @var array options provided to initalize filemanager */ - protected $_options = array('mainfile'=>'', 'subdirs'=>1, 'maxbytes'=>-1, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); + // PHP doesn't support 'key' => $value1 | $value2 in class definition + // We cannot do $_options = array('return_types'=> FILE_INTERNAL | FILE_REFERENCE); + // So I have to set null here, and do it in constructor + protected $_options = array('mainfile'=>'', 'subdirs'=>1, 'maxbytes'=>-1, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=> null); /** * Constructor @@ -68,6 +71,9 @@ class MoodleQuickForm_filemanager extends HTML_QuickForm_element { if (!empty($options['maxbytes'])) { $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']); } + if (empty($options['return_types'])) { + $this->_options['return_types'] = (FILE_INTERNAL | FILE_REFERENCE); + } $this->_type = 'filemanager'; parent::HTML_QuickForm_element($elementName, $elementLabel, $attributes); } @@ -242,7 +248,7 @@ class MoodleQuickForm_filemanager extends HTML_QuickForm_element { $options->subdirs = $this->_options['subdirs']; $options->target = $id; $options->accepted_types = $accepted_types; - $options->return_types = FILE_INTERNAL; + $options->return_types = $this->_options['return_types']; $options->context = $PAGE->context; $html = $this->_getTabs(); diff --git a/lib/form/filepicker.php b/lib/form/filepicker.php index 4436cebb016..09071fb3cea 100644 --- a/lib/form/filepicker.php +++ b/lib/form/filepicker.php @@ -45,7 +45,10 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { public $_helpbutton = ''; /** @var array options provided to initalize filemanager */ - protected $_options = array('maxbytes'=>0, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); + // PHP doesn't support 'key' => $value1 | $value2 in class definition + // We cannot do $_options = array('return_types'=> FILE_INTERNAL | FILE_REFERENCE); + // So I have to set null here, and do it in constructor + protected $_options = array('maxbytes'=>0, 'accepted_types'=>'*', 'return_types'=>null); /** * Constructor @@ -65,6 +68,9 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { $this->_options[$name] = $value; } } + if (!empty($options['return_types'])) { + $this->_options['return_types'] = FILE_INTERNAL | FILE_REFERENCE; + } if (!empty($options['maxbytes'])) { $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']); } @@ -137,7 +143,7 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { $args = new stdClass(); // need these three to filter repositories list $args->accepted_types = $this->_options['accepted_types']?$this->_options['accepted_types']:'*'; - $args->return_types = FILE_INTERNAL; + $args->return_types = FILE_INTERNAL | FILE_REFERENCE; $args->itemid = $draftitemid; $args->maxbytes = $this->_options['maxbytes']; $args->context = $PAGE->context; diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 961f8eb8a5d..25711c7ae46 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -457,7 +457,7 @@ class page_requirements_manager { array('nofilesavailable', 'repository'), array('overwrite', 'repository'), array('renameto', 'repository'), array('fileexists', 'repository'), array('fileexistsdialogheader', 'repository'), array('fileexistsdialog_editor', 'repository'), - array('fileexistsdialog_filemanager', 'repository') + array('fileexistsdialog_filemanager', 'repository'), array('uselatestfile', 'repository') )); break; case 'core_comment': @@ -1277,4 +1277,4 @@ function js_reset_all_caches() { set_config('jsrev', empty($CFG->jsrev) ? 1 : $CFG->jsrev+1); fulldelete("$CFG->cachedir/js"); -} \ No newline at end of file +} diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 5ef866a6a5c..667007e0b19 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir . '/filelib.php'); -class filelib_testcase extends basic_testcase { +class filelib_testcase extends advanced_testcase { public function test_format_postdata_for_curlcall() { //POST params with just simple types @@ -85,4 +85,83 @@ class filelib_testcase extends basic_testcase { $contents = download_file_content($testhtml); $this->assertEquals('47250a973d1b88d9445f94db4ef2c97a', md5($contents)); } + + /** + * Testing prepare draft area + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + public function test_prepare_draft_area() { + global $USER, $DB; + + $this->resetAfterTest(true); + + $generator = $this->getDataGenerator(); + $user = $generator->create_user(); + $usercontext = context_user::instance($user->id); + $USER = $DB->get_record('user', array('id'=>$user->id)); + + + $fs = get_file_storage(); + $syscontext = context_system::instance(); + $component = 'core'; + $filearea = 'unittest'; + $itemid = 0; + $filepath = '/'; + $filename = 'test.txt'; + $sourcefield = 'Copyright stuff'; + + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => $component, + 'filearea' => $filearea, + 'itemid' => $itemid, + 'filepath' => $filepath, + 'filename' => $filename, + 'source' => $sourcefield, + ); + $ref = $fs->pack_reference($filerecord); + + $originalfile = $fs->create_file_from_string($filerecord, 'Test content'); + + $fileid = $originalfile->get_id(); + $this->assertInstanceOf('stored_file', $originalfile); + + $draftitemid = 0; + file_prepare_draft_area($draftitemid, $syscontext->id, $component, $filearea, $itemid); + + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid); + $this->assertEquals(2, count($draftfiles)); + + $draftfile = $fs->get_file($usercontext->id, 'user', 'draft', $draftitemid, $filepath, $filename); + $source = unserialize($draftfile->get_source()); + $this->assertEquals($ref, $source->original); + $this->assertEquals($sourcefield, $source->source); + + + // change some information + $author = 'Dongsheng Cai'; + $draftfile->set_author($author); + $newsourcefield = 'Get from flickr'; + $license = 'GPLv3'; + $draftfile->set_license($license); + // if you want to really just change source field, do this: + $source = unserialize($draftfile->get_source()); + $newsourcefield = 'From flickr'; + $source->source = $newsourcefield; + $draftfile->set_source(serialize($source)); + + // Save changed file + file_save_draft_area_files($draftitemid, $syscontext->id, $component, $filearea, $itemid); + + $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $filepath, $filename); + + // Make sure it's the original file id + $this->assertEquals($fileid, $file->get_id()); + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($author, $file->get_author()); + $this->assertEquals($license, $file->get_license()); + $this->assertEquals($newsourcefield, $file->get_source()); + } } diff --git a/lib/tests/repositorylib_test.php b/lib/tests/repositorylib_test.php deleted file mode 100644 index 55ca73120d0..00000000000 --- a/lib/tests/repositorylib_test.php +++ /dev/null @@ -1,57 +0,0 @@ -. - -/** - * Unit tests for ../repositorylib.php. - * - * @package core_repository - * @category phpunit - * @author nicolasconnault@gmail.com - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - */ - -defined('MOODLE_INTERNAL') || die(); - -global $CFG; -require_once("$CFG->dirroot/repository/lib.php"); - - -class repositorylib_testcase extends advanced_testcase { - - public function test_initialise_filepicker() { - global $PAGE, $SITE; - - $this->resetAfterTest(true); - - $PAGE->set_url('/'); - $PAGE->set_course($SITE); - - $this->setAdminUser(); - - $args = new stdClass(); - $args->accepted_types = '*'; - $args->return_types = array(FILE_EXTERNAL); - $info = initialise_filepicker($args); - - $this->assertInstanceOf('stdClass', $info); - $this->assertObjectHasAttribute('defaultlicense', $info); - $this->assertObjectHasAttribute('licenses', $info); - $this->assertObjectHasAttribute('author', $info); - $this->assertObjectHasAttribute('externallink', $info); - $this->assertObjectHasAttribute('accepted_types', $info); - $this->assertObjectHasAttribute('return_types', $info); - } -} diff --git a/mod/folder/edit.php b/mod/folder/edit.php index 161745c70ef..918568575ba 100644 --- a/mod/folder/edit.php +++ b/mod/folder/edit.php @@ -48,7 +48,7 @@ $PAGE->set_activity_record($folder); $data = new stdClass(); $data->id = $cm->id; -$options = array('mainfile'=>true, 'subdirs'=>1, 'maxbytes'=>$CFG->maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); +$options = array('mainfile'=>true, 'subdirs'=>1, 'maxbytes'=>$CFG->maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*'); file_prepare_standard_filemanager($data, 'files', $options, $context, 'mod_folder', 'content', 0); $mform = new mod_folder_edit_form(null, array('data'=>$data, 'options'=>$options)); diff --git a/mod/folder/mod_form.php b/mod/folder/mod_form.php index 3fe54d53488..212cb125120 100644 --- a/mod/folder/mod_form.php +++ b/mod/folder/mod_form.php @@ -48,7 +48,7 @@ class mod_folder_mod_form extends moodleform_mod { //------------------------------------------------------- $mform->addElement('header', 'content', get_string('contentheader', 'folder')); - $mform->addElement('filemanager', 'files', get_string('files'), null, array('subdirs'=>1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL)); + $mform->addElement('filemanager', 'files', get_string('files'), null, array('subdirs'=>1, 'accepted_types'=>'*')); //------------------------------------------------------- $this->standard_coursemodule_elements(); diff --git a/mod/resource/mod_form.php b/mod/resource/mod_form.php index d0f5a28eaa5..01560dd471f 100644 --- a/mod/resource/mod_form.php +++ b/mod/resource/mod_form.php @@ -61,9 +61,9 @@ class mod_resource_mod_form extends moodleform_mod { $mform->addElement('header', 'contentsection', get_string('contentheader', 'resource')); $filemanager_options = array(); - // 3 == FILE_EXTERNAL & FILE_INTERNAL + // 3 == FILE_EXTERNAL | FILE_INTERNAL | FILE_REFERENCE // These two constant names are defined in repository/lib.php - $filemanager_options['return_types'] = 3; + $filemanager_options['return_types'] = 7; $filemanager_options['accepted_types'] = '*'; $filemanager_options['maxbytes'] = 0; $filemanager_options['maxfiles'] = -1; diff --git a/mod/wiki/filesedit.php b/mod/wiki/filesedit.php index 0982095e5ea..e70fe95ff28 100644 --- a/mod/wiki/filesedit.php +++ b/mod/wiki/filesedit.php @@ -78,7 +78,7 @@ $data = new stdClass(); $data->returnurl = $returnurl; $data->subwikiid = $subwiki->id; $maxbytes = get_max_upload_file_size($CFG->maxbytes, $COURSE->maxbytes); -$options = array('subdirs'=>0, 'maxbytes'=>$maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); +$options = array('subdirs'=>0, 'maxbytes'=>$maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL | FILE_REFERENCE); file_prepare_standard_filemanager($data, 'files', $options, $context, 'mod_wiki', 'attachments', $subwiki->id); $mform = new mod_wiki_filesedit_form(null, array('data'=>$data, 'options'=>$options)); diff --git a/mod/workshop/submission.php b/mod/workshop/submission.php index eb10b8fd90d..efcff41f930 100644 --- a/mod/workshop/submission.php +++ b/mod/workshop/submission.php @@ -147,7 +147,7 @@ if ($edit) { 'context' => $workshop->context ); - $attachmentopts = array('subdirs' => true, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes); + $attachmentopts = array('subdirs' => true, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes, 'return_types' => FILE_INTERNAL); $submission = file_prepare_standard_editor($submission, 'content', $contentopts, $workshop->context, 'mod_workshop', 'submission_content', $submission->id); $submission = file_prepare_standard_filemanager($submission, 'attachment', $attachmentopts, $workshop->context, diff --git a/repository/alfresco/lib.php b/repository/alfresco/lib.php index 1bda70d5748..8b8e1d8716e 100644 --- a/repository/alfresco/lib.php +++ b/repository/alfresco/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access alfresco repository + * + * @since 2.0 + * @package repository_alfresco + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); + /** * repository_alfresco class * This is a class used to browse files from alfresco * * @since 2.0 - * @package repository - * @subpackage alfresco - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_alfresco + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - class repository_alfresco extends repository { private $ticket = null; private $user_session = null; @@ -292,4 +298,3 @@ class repository_alfresco extends repository { return (FILE_INTERNAL | FILE_EXTERNAL); } } - diff --git a/repository/boxnet/lib.php b/repository/boxnet/lib.php index 65a5575822b..3ff8f347e53 100644 --- a/repository/boxnet/lib.php +++ b/repository/boxnet/lib.php @@ -1,5 +1,4 @@ . -require_once($CFG->libdir.'/boxlib.php'); - /** - * repository_boxnet class - * This is a subclass of repository class + * This plugin is used to access box.net repository * * @since 2.0 - * @package repository - * @subpackage boxnet - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_boxnet + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once($CFG->libdir . '/boxlib.php'); + +/** + * repository_boxnet class implements box.net client + * + * @since 2.0 + * @package repository_boxnet + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_boxnet extends repository { @@ -33,8 +38,9 @@ class repository_boxnet extends repository { /** * Constructor + * * @param int $repositoryid - * @param object $context + * @param stdClass $context * @param array $options */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { @@ -59,6 +65,7 @@ class repository_boxnet extends repository { /** * check if user logged + * * @return boolean */ public function check_login() { @@ -110,7 +117,6 @@ class repository_boxnet extends repository { /** * Search files from box.net * - * @global object $OUTPUT * @param string $search_text * @return mixed */ @@ -144,6 +150,7 @@ class repository_boxnet extends repository { * Get file listing * * @param string $path + * @param string $page * @return mixed */ public function get_listing($path = '/', $page = ''){ @@ -188,6 +195,7 @@ class repository_boxnet extends repository { /** * Names of the plugin settings + * * @return array */ public static function get_type_option_names() { @@ -204,7 +212,9 @@ class repository_boxnet extends repository { /** * Add Plugin settings input to Moodle form - * @param object $mform + * + * @param moodleform $mform + * @param string $classname */ public static function type_config_form($mform, $classname = 'repository') { global $CFG; @@ -235,12 +245,66 @@ class repository_boxnet extends repository { $mform->addElement('static', 'callbackurl', '', get_string('callbackurltext', 'repository_boxnet', $callbackurl)); } } + /** * Box.net supports file linking and copying - * @return string + * + * @return int */ public function supported_returntypes() { - return FILE_INTERNAL | FILE_EXTERNAL; + return FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE; + } + + /** + * Prepare file reference information + * + * @param string $source + * @return string file referece + */ + public function get_file_reference($source) { + // Box.net returns a url. + return $source; + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param stdClass $reference file reference db record + * @return stdClass|null|false + */ + public function get_file_by_reference($reference) { + $fileinfo = new stdClass; + $boxnetfile = $this->get_file($reference->reference); + $fileinfo->filepath = $boxnetfile['path']; + return $fileinfo; + } + + /** + * Return human readable reference information + * {@link stored_file::get_reference()} + * + * @param string $reference + * @return string|null + */ + public function get_reference_details($reference) { + // Indicate it's from box.net repository + secure URL + return $this->get_name() . ': ' . $reference; + } + + /** + * Repository method to serve file + * + * @param stored_file $storedfile + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + $ref = $storedfile->get_reference(); + // Let box.net serve the file. + header('Location: ' . $ref); } } - diff --git a/repository/coursefiles/lib.php b/repository/coursefiles/lib.php index 9a12e85ae11..6cf0622c3dc 100644 --- a/repository/coursefiles/lib.php +++ b/repository/coursefiles/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access coursefiles repository + * + * @since 2.0 + * @package repository_coursefiles + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); + /** * repository_coursefiles class is used to browse course files * * @since 2.0 - * @package repository - * @subpackage coursefiles - * @copyright 2010 Dongsheng Cai + * @package repository_coursefiles + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - class repository_coursefiles extends repository { /** * coursefiles plugin doesn't require login, so list all files + * * @return mixed */ public function print_login() { @@ -145,6 +153,7 @@ class repository_coursefiles extends repository { /** * Return is the instance is visible * (is the type visible ? is the context enable ?) + * * @return boolean */ public function is_visible() { @@ -167,8 +176,9 @@ class repository_coursefiles extends repository { } public function supported_returntypes() { - return (FILE_INTERNAL | FILE_EXTERNAL); + return (FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE); } + public static function get_type_option_names() { return array(); } @@ -181,4 +191,105 @@ class repository_coursefiles extends repository { public function has_moodle_files() { return true; } + + /** + * Unpack file info and pack it, mainly for data validation + * + * @param string $source + * @return string file referece + */ + public function get_file_reference($source) { + $params = unserialize(base64_decode($source)); + + if (!is_array($params)) { + throw new repository_exception('invalidparams', 'repository'); + } + + $filename = is_null($params['filename']) ? null : clean_param($params['filename'], PARAM_FILE); + $filepath = is_null($params['filepath']) ? null : clean_param($params['filepath'], PARAM_PATH);; + $contextid = is_null($params['contextid']) ? null : clean_param($params['contextid'], PARAM_INT); + + $reference = array(); + // hard coded filearea, component and itemid for security + $reference['component'] = 'course'; + $reference['filearea'] = 'legacy'; + $reference['itemid'] = 0; + $reference['contextid'] = $contextid; + $reference['filepath'] = $filepath; + $reference['filename'] = $filename; + + return file_storage::pack_reference($reference); + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param stdClass $reference file reference db record + * @return stdClass|null|false + */ + public function get_file_by_reference($reference) { + $ref = $reference->reference; + $params = file_storage::unpack_reference($ref); + if (!is_array($params)) { + throw new repository_exception('invalidparams', 'repository'); + } + $filename = is_null($params['filename']) ? null : clean_param($params['filename'], PARAM_FILE); + $filepath = is_null($params['filepath']) ? null : clean_param($params['filepath'], PARAM_PATH);; + $contextid = is_null($params['contextid']) ? null : clean_param($params['contextid'], PARAM_INT); + + // hard coded filearea, component and itemid for security + $storedfile = $fs->get_file($contextid, 'course', 'legacy', 0, $filepath, $filename); + + $fileinfo = new stdClass; + $fileinfo->contenthash = $storedfile->get_contenthash(); + $fileinfo->filesize = $storedfile->get_filesize(); + return $fileinfo; + } + + /** + * Return human readable reference information + * {@link stored_file::get_reference()} + * + * @param string $reference + * @return string|null + */ + public function get_reference_details($reference) { + $params = file_storage::unpack_reference($reference); + list($context, $course, $cm) = get_context_info_array($params['contextid']); + $coursename = ''; + if (!empty($course)) { + $coursename = '"' . format_string($course->shortname, true, array('context' => get_course_context($context))) . '" ' . get_string('courselegacyfiles'); + } else { + $coursename = get_string('courselegacyfiles'); + } + // Indicate this is from user private area + return $coursename . ': ' . $params['filepath'] . $params['filename']; + } + + /** + * Repository method to serve file + * + * @param stored_file $storedfile + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + $fs = get_file_storage(); + + $reference = $storedfile->get_reference(); + $params = file_storage::unpack_reference($reference); + + $filename = is_null($params['filename']) ? null : clean_param($params['filename'], PARAM_FILE); + $filepath = is_null($params['filepath']) ? null : clean_param($params['filepath'], PARAM_PATH);; + $contextid = is_null($params['contextid']) ? null : clean_param($params['contextid'], PARAM_INT); + + // hard coded file area and component for security + $srcfile = $fs->get_file($contextid, 'course', 'legacy', 0, $filepath, $filename); + + send_stored_file($srcfile, $lifetime, $filter, $forcedownload, $options); + } } diff --git a/repository/dropbox/lib.php b/repository/dropbox/lib.php index 2c1003c5c2c..659b91a8f11 100644 --- a/repository/dropbox/lib.php +++ b/repository/dropbox/lib.php @@ -1,5 +1,4 @@ . /** - * repository_dropbox class * This plugin is used to access user's dropbox files * * @since 2.0 - * @package repository - * @subpackage dropbox - * @copyright 2010 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_dropbox + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - +require_once($CFG->dirroot . '/repository/lib.php'); require_once(dirname(__FILE__).'/locallib.php'); class repository_dropbox extends repository { + /** @var dropbox the instance of dropbox client */ private $dropbox; + /** @var array files */ public $files; + /** @var bool flag of login status */ public $logged=false; + /** @var int cached file ttl */ + private $cachedfilettl = null; + /** * Constructor of dropbox plugin + * * @param int $repositoryid - * @param object $context + * @param stdClass $context * @param array $options */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { - global $SESSION, $CFG; + global $CFG; $options['page'] = optional_param('p', 1, PARAM_INT); parent::__construct($repositoryid, $context, $options); @@ -50,14 +53,25 @@ class repository_dropbox extends repository { $this->dropbox_key = $this->get_option('dropbox_key'); $this->dropbox_secret = $this->get_option('dropbox_secret'); - $this->access_key = get_user_preferences($this->setting.'_access_key', ''); - $this->access_secret = get_user_preferences($this->setting.'_access_secret', ''); + // one day + $this->cachedfilettl = 60 * 60 * 24; + + if (isset($options['access_key'])) { + $this->access_key = $options['access_key']; + } else { + $this->access_key = get_user_preferences($this->setting.'_access_key', ''); + } + if (isset($options['access_secret'])) { + $this->access_secret = $options['access_secret']; + } else { + $this->access_secret = get_user_preferences($this->setting.'_access_secret', ''); + } if (!empty($this->access_key) && !empty($this->access_secret)) { $this->logged = true; } - $this->callback = new moodle_url($CFG->wwwroot.'/repository/repository_callback.php', array( + $callbackurl = new moodle_url($CFG->wwwroot.'/repository/repository_callback.php', array( 'callback'=>'yes', 'repo_id'=>$repositoryid )); @@ -65,15 +79,35 @@ class repository_dropbox extends repository { $args = array( 'oauth_consumer_key'=>$this->dropbox_key, 'oauth_consumer_secret'=>$this->dropbox_secret, - 'oauth_callback' => $this->callback->out(false), + 'oauth_callback' => $callbackurl->out(false), 'api_root' => 'https://www.dropbox.com/1/oauth', ); $this->dropbox = new dropbox($args); } + /** + * Set access key + * + * @param string $access_key + */ + public function set_access_key($access_key) { + $this->access_key = $access_key; + } + + /** + * Set access secret + * + * @param string $access_secret + */ + public function set_access_secret($access_secret) { + $this->access_secret = $access_secret; + } + + /** * Check if moodle has got access token and secret + * * @return bool */ public function check_login() { @@ -82,6 +116,7 @@ class repository_dropbox extends repository { /** * Generate dropbox login url + * * @return array */ public function print_login() { @@ -102,6 +137,7 @@ class repository_dropbox extends repository { /** * Request access token + * * @return array */ public function callback() { @@ -114,6 +150,7 @@ class repository_dropbox extends repository { /** * Get dropbox files + * * @param string $path * @param int $page * @return array @@ -256,6 +293,7 @@ class repository_dropbox extends repository { } /** * Add Plugin settings input to Moodle form + * * @param object $mform */ public static function type_config_form($mform, $classname = 'repository') { @@ -284,6 +322,7 @@ class repository_dropbox extends repository { /** * Option names of dropbox plugin + * * @return array */ public static function get_type_option_names() { @@ -292,6 +331,7 @@ class repository_dropbox extends repository { /** * Dropbox plugin supports all kinds of files + * * @return array */ public function supported_filetypes() { @@ -300,9 +340,128 @@ class repository_dropbox extends repository { /** * User cannot use the external link to dropbox + * * @return int */ public function supported_returntypes() { - return FILE_INTERNAL; + return FILE_INTERNAL | FILE_REFERENCE; + } + + /** + * Prepare file reference information + * + * @param string $source + * @return string file referece + */ + public function get_file_reference($source) { + $reference = new stdClass; + $reference->path = $source; + $reference->access_key = get_user_preferences($this->setting.'_access_key', ''); + $reference->access_secret = get_user_preferences($this->setting.'_access_secret', ''); + return serialize($reference); + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param stdClass $reference file reference db record + * @return stdClass|null|false + */ + public function get_file_by_reference($reference) { + $reference = unserialize($reference->reference); + $cachedfilepath = cache_file::get($reference, array('ttl' => $this->cachedfilettl)); + if ($cachedfilepath === false) { + // Cache the file. + $this->set_access_key($reference->access_key); + $this->set_access_secret($reference->access_secret); + $path = $this->get_file($reference->path); + $cachedfilepath = cache_file::create_from_file($reference, $path['path']); + } + + $fileinfo = new stdClass; + $fileinfo->filepath = $cachedfilepath; + + return $fileinfo; + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param string $reference this reference is generated by + * repository::get_file_reference() + * @param stored_file $storedfile created file reference + */ + public function cache_file_by_reference($reference, $storedfile) { + $reference = unserialize($reference); + $path = $this->get_file($reference->path); + cache_file::create_from_file($reference, $path['path']); + } + + /** + * Return human readable reference information + * {@link stored_file::get_reference()} + * + * @param string $reference + * @return string|null + */ + public function get_reference_details($reference) { + $ref = unserialize($reference); + // Indicate this is from dropbox with path + return $this->get_name() . ': ' . $ref->path; + } + + /** + * Repository method to serve file + * + * @param stored_file $storedfile + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + $reference = unserialize($storedfile->get_reference()); + + $cachedfilepath = cache_file::get($reference, array('ttl' => $this->cachedfilettl)); + if ($cachedfilepath === false) { + // Cache the file. + $this->set_access_key($reference->access_key); + $this->set_access_secret($reference->access_secret); + $path = $this->get_file($reference->path); + $cachedfilepath = cache_file::create_from_file($reference, $path['path']); + } + + send_file($cachedfilepath, $storedfile->get_filename(), 'default' , $filter, false, $forcedownload); + } + + public function cron() { + $fs = get_file_storage(); + $files = $fs->get_external_files($this->id); + foreach ($files as $file) { + $reference = unserialize($file->get_reference()); + + $cachedfile = cache_file::get($reference); + if ($cachedfile === false) { + // Re-fetch resource. + $this->set_access_key($reference->access_key); + $this->set_access_secret($reference->access_secret); + $path = $this->get_file($reference->path); + cache_file::create_from_file($reference, $path['path']); + } + } + } +} + +/** + * Dropbox plugin cron task + */ +function repository_dropbox_cron() { + $instances = repository::get_instances(array('type'=>'dropbox')); + foreach ($instances as $instance) { + $instance->cron(); } } diff --git a/repository/dropbox/locallib.php b/repository/dropbox/locallib.php index a86899c41a3..2fb322ae247 100644 --- a/repository/dropbox/locallib.php +++ b/repository/dropbox/locallib.php @@ -71,6 +71,26 @@ class dropbox extends oauth_helper { return array('path'=>$saveas, 'url'=>$url); } + /** + * Get file url + * + * @param string $filepath file path + * @return string file url + */ + public function get_file_url($filepath) { + $info = pathinfo($filepath); + $dirname = $info['dirname']; + $basename = $info['basename']; + $filepath = $dirname . rawurlencode($basename); + if ($dirname != '/') { + $filepath = $dirname . '/' . $basename; + $filepath = str_replace("%2F", "/", rawurlencode($filepath)); + } + + $url = $this->dropbox_content_api.'/files/'.$this->mode.$filepath; + return $url; + } + public function set_mode($mode) { $this->mode = $mode; } diff --git a/repository/filepicker.js b/repository/filepicker.js index 540fd6383ef..3a82f7b55ee 100644 --- a/repository/filepicker.js +++ b/repository/filepicker.js @@ -46,6 +46,19 @@ M.core_filepicker = M.core_filepicker || {}; M.core_filepicker.instances = M.core_filepicker.instances || {}; M.core_filepicker.active_filepicker = null; +/** + * Set selected file info + * + * @parma object file info + */ +M.core_filepicker.select_file = function(file) { + var fileinfo = {}; + fileinfo['title'] = file.title; + fileinfo['source'] = file.reference; + fileinfo['thumbnail'] = file.thumbnail; + M.core_filepicker.active_filepicker.select_file(fileinfo); +} + /** * Init and show file picker */ @@ -375,13 +388,18 @@ M.core_filepicker.init = function(Y, options) { // it is not working well with search result this.view_as_icons(); } else { - this.viewbar.set('disabled', false); - if (this.viewmode == 1) { - this.view_as_icons(); - } else if (this.viewmode == 2) { - this.view_as_list(p); + if (this.objecttag) { + // handle cancle action for repo using iframe + this.create_object_container(this.objecttag); } else { - this.view_as_icons(); + this.viewbar.set('disabled', false); + if (this.viewmode == 1) { + this.view_as_icons(); + } else if (this.viewmode == 2) { + this.view_as_list(p); + } else { + this.view_as_icons(); + } } } }, @@ -594,6 +612,7 @@ M.core_filepicker.init = function(Y, options) { path.setStyle('display', 'none'); } var panel = Y.one('#panel-'+client_id); + panel.set('innerHTML', ''); var form_id = 'fp-rename-form-'+client_id; var html = '
                            '; html += '

                            '; @@ -603,16 +622,28 @@ M.core_filepicker.init = function(Y, options) { var le_checked = ''; var le_style = ''; - if (this.options.repositories[this.active_repo.id].return_types == 1) { - // support external links only - le_checked = 'checked'; - le_style = ' style="display:none;"'; - } else if(this.options.repositories[this.active_repo.id].return_types == 2) { - // support internal files only - le_style = ' style="display:none;"'; - } - if ((this.options.externallink && this.options.env == 'editor' && this.options.return_types != 1)) { - html += '
                            '; + var returntypes = this.options.repositories[this.active_repo.id].return_types; + + if (returntypes == 1) { + // support link only + html += ''; + } else if (returntypes == 4) { + html += ''; + } else { + if (((returntypes & 1) == 1) && ((this.options.return_types & 1) == 1)) { + // support external links + html += ''; + } + // form element support file reference and repository support it too + if (((returntypes & 4) == 4) && ((this.options.return_types & 4) == 4)) { + // file reference + html += ''; + } + + if (((returntypes & 4) != 4) && ((returntypes & 1) != 1)) { + html += ''; + html += ''; + } } if (!args.hasauthor) { @@ -673,7 +704,7 @@ M.core_filepicker.init = function(Y, options) { // in editor, images are stored in '/' only params.savepath = '/'; // when image or media button is clicked - if ( this.options.return_types != 1 ) { + if (this.options.return_types != 1) { var linkexternal = Y.one('#linkexternal-'+client_id); if (linkexternal && linkexternal.get('checked')) { params['linkexternal'] = 'yes'; @@ -688,6 +719,15 @@ M.core_filepicker.init = function(Y, options) { params['linkexternal'] = 'yes'; } + if (this.options.return_types != 4) { + var usefilereference = Y.one('#filereference-'+client_id); + if (usefilereference && usefilereference.get('checked')) { + params['usefilereference'] = 'yes'; + } + } else { + params['usefilereference'] = 'yes'; + } + this.wait('download', title); this.request({ action:'download', @@ -846,6 +886,7 @@ M.core_filepicker.init = function(Y, options) { parse_repository_options: function(data) { this.filelist = data.list?data.list:null; this.filepath = data.path?data.path:null; + this.objecttag = data.object?data.object:null; this.active_repo = {}; this.active_repo.issearchresult = Boolean(data.issearchresult); this.active_repo.dynload = data.dynload?data.dynload:false; @@ -1132,7 +1173,11 @@ M.core_filepicker.init = function(Y, options) { scope.parse_repository_options(obj); scope.create_upload_form(obj); - } else if (obj.iframe) { + } else if (obj.object) { + M.core_filepicker.active_filepicker = scope; + scope.viewbar.set('disabled', true); + scope.parse_repository_options(obj); + scope.create_object_container(obj.object); } else if (obj.list) { obj.issearchresult = false; @@ -1143,6 +1188,16 @@ M.core_filepicker.init = function(Y, options) { } }, true); }, + create_object_container: function(data) { + var client_id = this.options.client_id; + Y.one('#panel-'+client_id).set('innerHTML', ''); + var types = this.options.accepted_types; + var panel = Y.one('#panel-'+client_id); + var str = ''; + str += ''; + var container = Y.Node.create(str); + Y.one('#panel-'+client_id).appendChild(container); + }, create_upload_form: function(data) { var client_id = this.options.client_id; Y.one('#panel-'+client_id).set('innerHTML', ''); diff --git a/repository/filesystem/lib.php b/repository/filesystem/lib.php index 6133434411b..955b2785c0e 100644 --- a/repository/filesystem/lib.php +++ b/repository/filesystem/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access files on server file system + * + * @since 2.0 + * @package repository_filesystem + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once($CFG->libdir . '/filelib.php'); + /** * repository_filesystem class + * * Create a repository from your local filesystem * *NOTE* for security issue, we use a fixed repository path * which is %moodledata%/repository * - * @since 2.0 * @package repository - * @subpackage filesystem - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_filesystem extends repository { + + /** + * Constructor + * + * @param int $repositoryid repository ID + * @param int $context context ID + * @param array $options + */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { global $CFG; parent::__construct($repositoryid, $context, $options); @@ -114,6 +130,7 @@ class repository_filesystem extends repository { public function global_search() { return false; } + /** * Return file path * @return array @@ -176,10 +193,6 @@ class repository_filesystem extends repository { } } - public function supported_returntypes() { - return FILE_INTERNAL; - } - public static function create($type, $userid, $context, $params, $readonly=0) { global $PAGE; if (has_capability('moodle/site:config', get_system_context())) { @@ -195,4 +208,52 @@ class repository_filesystem extends repository { } return $errors; } + + /** + * User cannot use the external link to dropbox + * + * @return int + */ + public function supported_returntypes() { + return FILE_INTERNAL | FILE_REFERENCE; + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param stdClass $reference file reference db record + * @return stdClass|null|false + */ + public function get_file_by_reference($reference) { + $ref = $reference->reference; + if ($ref{0} == '/') { + $filepath = $this->root_path.substr($ref, 1, strlen($ref)-1); + } else { + $filepath = $this->root_path.$ref; + } + $fileinfo = new stdClass; + $fileinfo->filepath = $filepath; + return $fileinfo; + } + + /** + * Repository method to serve file + * + * @param stored_file $storedfile + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + $reference = $storedfile->get_reference(); + if ($reference{0} == '/') { + $file = $this->root_path.substr($reference, 1, strlen($reference)-1); + } else { + $file = $this->root_path.$reference; + } + send_file($file, $storedfile->get_filename(), 'default' , $filter, false, $forcedownload); + } } diff --git a/repository/flickr/lib.php b/repository/flickr/lib.php index 7d5b6fdcd5c..b54ad931f27 100644 --- a/repository/flickr/lib.php +++ b/repository/flickr/lib.php @@ -1,5 +1,4 @@ . /** - * repository_flickr class - * This plugin is used to access user's private flickr repository + * This plugin is used to access flickr pictures * * @since 2.0 - * @package repository - * @subpackage flickr - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_flickr + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - +require_once($CFG->dirroot . '/repository/lib.php'); require_once($CFG->libdir.'/flickrlib.php'); /** + * This plugin is used to access user's private flickr repository * + * @since 2.0 + * @package repository_flickr + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_flickr extends repository { private $flickr; diff --git a/repository/flickr_public/lib.php b/repository/flickr_public/lib.php index 2c91090247c..3b34b980b94 100644 --- a/repository/flickr_public/lib.php +++ b/repository/flickr_public/lib.php @@ -14,6 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * This plugin is used to access flickr pictures + * + * @since 2.0 + * @package repository_flickr_public + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once($CFG->libdir.'/flickrlib.php'); +require_once(dirname(__FILE__) . '/image.php'); + /** * repository_flickr_public class * This one is used to create public repository @@ -21,16 +33,10 @@ * flickr photos from this plugin * * @since 2.0 - * @package repository - * @subpackage flickr_public - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_flickr_public + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once($CFG->libdir.'/flickrlib.php'); -require_once(dirname(__FILE__) . '/image.php'); - class repository_flickr_public extends repository { private $flickr; public $photos; diff --git a/repository/googledocs/lib.php b/repository/googledocs/lib.php index acb991dd003..833eee953b5 100644 --- a/repository/googledocs/lib.php +++ b/repository/googledocs/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access google docs + * + * @since 2.0 + * @package repository_googledocs + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once($CFG->libdir.'/googleapi.php'); + /** * Google Docs Plugin * * @since 2.0 - * @package repository - * @subpackage googledocs + * @package repository_googledocs * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once($CFG->libdir.'/googleapi.php'); - class repository_googledocs extends repository { private $subauthtoken = ''; diff --git a/repository/lib.php b/repository/lib.php index 7ddb8989f19..274e7c1a6cd 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1,5 +1,4 @@ . - /** * This file contains classes used to manage the repository plugins in Moodle * and was introduced as part of the changes occuring in Moodle 2.0 * * @since 2.0 - * @package core - * @subpackage repository - * @copyright 2009 Dongsheng Cai - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package repository + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(dirname(dirname(__FILE__)) . '/config.php'); require_once($CFG->libdir . '/filelib.php'); require_once($CFG->libdir . '/formslib.php'); -define('FILE_EXTERNAL', 1); -define('FILE_INTERNAL', 2); +define('FILE_EXTERNAL', 1); +define('FILE_INTERNAL', 2); +define('FILE_REFERENCE', 4); define('RENAME_SUFFIX', '_2'); /** @@ -51,8 +49,7 @@ define('RENAME_SUFFIX', '_2'); * - When you create a type for a plugin that can't have multiple instances, a * instance is automatically created. * - * @package moodlecore - * @subpackage repository + * @package repository * @copyright 2009 Jerome Mouneyrac * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -92,12 +89,13 @@ class repository_type { */ private $_sortorder; - /** + /** * Return if the instance is visible in a context - * TODO: check if the context visibility has been overwritten by the plugin creator + * + * @todo check if the context visibility has been overwritten by the plugin creator * (need to create special functions to be overvwritten in repository class) - * @param objet $context - context - * @return boolean + * @param stdClass $context context + * @return bool */ public function get_contextvisibility($context) { global $USER; @@ -118,11 +116,11 @@ class repository_type { /** * repository_type constructor - * @global object $CFG - * @param integer $typename + * + * @param int $typename * @param array $typeoptions - * @param boolean $visible - * @param integer $sortorder (don't really need set, it will be during create() call) + * @param bool $visible + * @param int $sortorder (don't really need set, it will be during create() call) */ public function __construct($typename = '', $typeoptions = array(), $visible = true, $sortorder = 0) { global $CFG; @@ -163,7 +161,8 @@ class repository_type { /** * Get the type name (no whitespace) * For a human readable name, use get_readablename() - * @return String the type name + * + * @return string the type name */ public function get_typename() { return $this->_typename; @@ -171,6 +170,7 @@ class repository_type { /** * Return a human readable and user-friendly type name + * * @return string user-friendly type name */ public function get_readablename() { @@ -179,6 +179,7 @@ class repository_type { /** * Return general options + * * @return array the general options */ public function get_options() { @@ -187,7 +188,8 @@ class repository_type { /** * Return visibility - * @return boolean + * + * @return bool */ public function get_visible() { return $this->_visible; @@ -195,7 +197,8 @@ class repository_type { /** * Return order / position of display in the file picker - * @return integer + * + * @return int */ public function get_sortorder() { return $this->_sortorder; @@ -203,10 +206,8 @@ class repository_type { /** * Create a repository type (the type name must not already exist) - * @param boolean throw exception? + * @param bool $silent throw exception? * @return mixed return int if create successfully, return false if - * any errors - * @global object $DB */ public function create($silent = false) { global $DB; @@ -279,8 +280,9 @@ class repository_type { /** * Update plugin options into the config_plugin table + * * @param array $options - * @return boolean + * @return bool */ public function update_options($options = null) { global $DB; @@ -314,9 +316,9 @@ class repository_type { * or with the visible value of this object * This function is private. * For public access, have a look to switch_and_update_visibility() - * @global object $DB - * @param boolean $visible - * @return boolean + * + * @param bool $visible + * @return bool */ private function update_visible($visible = null) { global $DB; @@ -336,9 +338,9 @@ class repository_type { * or with the sortorder value of this object * This function is private. * For public access, have a look to move_order() - * @global object $DB - * @param integer $sortorder - * @return boolean + * + * @param int $sortorder + * @return bool */ private function update_sortorder($sortorder = null) { global $DB; @@ -362,7 +364,7 @@ class repository_type { * 1. retrieve all types in an array. This array is sorted by sortorder, * and the array keys start from 0 to X (incremented by 1) * 2. switch sortorder values of this type and its adjacent type - * @global object $DB + * * @param string $move "up" or "down" */ public function move_order($move) { @@ -370,7 +372,7 @@ class repository_type { $types = repository::get_types(); // retrieve all types - /// retrieve this type into the returned array + // retrieve this type into the returned array $i = 0; while (!isset($indice) && $iget_typename() == $this->_typename) { @@ -379,7 +381,7 @@ class repository_type { $i++; } - /// retrieve adjacent indice + // retrieve adjacent indice switch ($move) { case "up": $adjacentindice = $indice - 1; @@ -403,9 +405,10 @@ class repository_type { /** * 1. Change visibility to the value chosen - * * 2. Update the type - * @return boolean + * + * @param bool $visible + * @return bool */ public function update_visibility($visible = null) { if (is_bool($visible)) { @@ -420,10 +423,11 @@ class repository_type { /** * Delete a repository_type (general options are removed from config_plugin * table, and all instances are deleted) - * @global object $DB - * @return boolean + * + * @param bool $downloadcontents download external contents if exist + * @return bool */ - public function delete() { + public function delete($downloadcontents = false) { global $DB; //delete all instances of this type @@ -433,7 +437,7 @@ class repository_type { $params['type'] = $this->_typename; $instances = repository::get_instances($params); foreach ($instances as $instance) { - $instance->delete(); + $instance->delete($downloadcontents); } //delete all general options @@ -441,53 +445,50 @@ class repository_type { set_config($name, null, $this->_typename); } - return $DB->delete_records('repository', array('type' => $this->_typename)); + try { + $DB->delete_records('repository', array('type' => $this->_typename)); + } catch (dml_exception $ex) { + return false; + } + return true; } } /** - * This is the base class of the repository class + * This is the base class of the repository class. * - * To use repository plugin, see: - * http://docs.moodle.org/dev/Repository_How_to_Create_Plugin - * class repository is an abstract class, some functions must be implemented in subclass. - * See an example: repository/boxnet/lib.php + * To create repository plugin, see: {@link http://docs.moodle.org/dev/Repository_plugins} + * See an example: {@link repository_boxnet} * - * A few notes: - * // for ajax file picker, this will print a json string to tell file picker - * // how to build a login form - * $repo->print_login(); - * // for ajax file picker, this will return a files list. - * $repo->get_listing(); - * // this function will be used for non-javascript version. - * $repo->print_listing(); - * // print a search box - * $repo->print_search(); - * - * @package moodlecore - * @subpackage repository - * @copyright 2009 Dongsheng Cai + * @package repository + * @category repository + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class repository { // $disabled can be set to true to disable a plugin by force // example: self::$disabled = true + /** @var bool force disable repository instance */ public $disabled = false; + /** @var int repository instance id */ public $id; - /** @var object current context */ + /** @var stdClass current context */ public $context; + /** @var array repository options */ public $options; + /** @var bool Whether or not the repository instance is editable */ public $readonly; + /** @var int return types */ public $returntypes; - /** @var object repository instance database record */ + /** @var stdClass repository instance database record */ public $instance; /** - * 1. Initialize context and options - * 2. Accept necessary parameters + * Constructor * - * @param integer $repositoryid repository instance id - * @param integer|object a context id or context object + * @param int $repositoryid repository instance id + * @param int|stdClass $context a context id or context object * @param array $options repository options + * @param int $readonly indicate this repo is readonly or not */ public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array(), $readonly = 0) { global $DB; @@ -502,6 +503,7 @@ abstract class repository { $this->options = array(); if (is_array($options)) { + // The get_option() method will get stored options in database. $options = array_merge($this->get_option(), $options); } else { $options = $this->get_option(); @@ -514,9 +516,41 @@ abstract class repository { $this->super_called = true; } + /** + * Get repository instance using repository id + * + * @param int $repositoryid repository ID + * @param stdClass|int $context context instance or context ID + * @return repository + */ + public static function get_repository_by_id($repositoryid, $context) { + global $CFG, $DB; + + $sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i WHERE i.id=? AND i.typeid=r.id'; + + if (!$record = $DB->get_record_sql($sql, array($repositoryid))) { + throw new repository_exception('invalidrepositoryid', 'repository'); + } else { + $type = $record->type; + if (file_exists($CFG->dirroot . "/repository/$type/lib.php")) { + require_once($CFG->dirroot . "/repository/$type/lib.php"); + $classname = 'repository_' . $type; + $contextid = $context; + if (is_object($context)) { + $contextid = $context->id; + } + $repository = new $classname($repositoryid, $contextid, array('type'=>$type)); + return $repository; + } else { + throw new moodle_exception('error'); + } + } + } + /** * Get a repository type object by a given type name. - * @global object $DB + * + * @static * @param string $typename the repository type name * @return repository_type|bool */ @@ -532,7 +566,8 @@ abstract class repository { /** * Get the repository type by a given repository type id. - * @global object $DB + * + * @static * @param int $id the type id * @return object */ @@ -549,9 +584,9 @@ abstract class repository { /** * Return all repository types ordered by sortorder field * first repository type in returnedarray[0], second repository type in returnedarray[1], ... - * @global object $DB - * @global object $CFG - * @param boolean $visible can return types by visiblity, return all types if null + * + * @static + * @param bool $visible can return types by visiblity, return all types if null * @return array Repository types */ public static function get_types($visible=null) { @@ -575,9 +610,11 @@ abstract class repository { /** * To check if the context id is valid - * @global object $USER + * + * @static * @param int $contextid - * @return boolean + * @param stdClass $instance + * @return bool */ public static function check_capability($contextid, $instance) { $context = get_context_instance_by_id($contextid); @@ -590,10 +627,11 @@ abstract class repository { /** * Check if file already exists in draft area * + * @static * @param int $itemid * @param string $filepath * @param string $filename - * @return boolean + * @return bool */ public static function draftfile_exists($itemid, $filepath, $filename) { global $USER; @@ -606,33 +644,25 @@ abstract class repository { } } - /** - * Does this repository used to browse moodle files? - * - * @return boolean - */ - public function has_moodle_files() { - return false; - } /** * This function is used to copy a moodle file to draft area * - * @global object $USER - * @global object $DB * @param string $encoded The metainfo of file, it is base64 encoded php serialized data - * @param string $draftitemid itemid - * @param string $new_filename The intended name of file + * @param int $draftitemid itemid * @param string $new_filepath the new path in draft area + * @param string $new_filename The intended name of file * @return array The information of file */ public function copy_to_area($encoded, $draftitemid, $new_filepath, $new_filename) { global $USER, $DB; + $fs = get_file_storage(); + $browser = get_file_browser(); if ($this->has_moodle_files() == false) { - throw new coding_exception('Only repository used to browse moodle files can use copy_to_area'); + throw new coding_exception('Only repository used to browse moodle files can use repository::copy_to_area()'); } - $browser = get_file_browser(); + $params = unserialize(base64_decode($encoded)); $user_context = get_context_instance(CONTEXT_USER, $USER->id); @@ -677,6 +707,7 @@ abstract class repository { /** * Get unused filename by appending suffix * + * @static * @param int $itemid * @param string $filepath * @param string $filename @@ -694,6 +725,7 @@ abstract class repository { /** * Append a suffix to filename * + * @static * @param string $filename * @return string */ @@ -709,7 +741,9 @@ abstract class repository { /** * Return all types that you a user can create/edit and which are also visible * Note: Mostly used in order to know if at least one editable type can be set - * @param object $context the context for which we want the editable types + * + * @static + * @param stdClass $context the context for which we want the editable types * @return array types */ public static function get_editable_types($context = null) { @@ -733,10 +767,8 @@ abstract class repository { /** * Return repository instances - * @global object $DB - * @global object $CFG - * @global object $USER * + * @static * @param array $args Array containing the following keys: * currentcontext * context @@ -890,8 +922,8 @@ abstract class repository { /** * Get single repository instance - * @global object $DB - * @global object $CFG + * + * @static * @param integer $id repository id * @return object repository instance */ @@ -919,9 +951,10 @@ abstract class repository { /** * Call a static function. Any additional arguments than plugin and function will be passed through. - * @global object $CFG - * @param string $plugin - * @param string $function + * + * @static + * @param string $plugin repository plugin name + * @param string $function funciton name * @return mixed */ public static function static_function($plugin, $function) { @@ -964,7 +997,6 @@ abstract class repository { * @param string $thefile * @param string $filename name of the file * @param bool $deleteinfected - * @return void */ public static function antivir_scan_file($thefile, $filename, $deleteinfected) { global $CFG; @@ -1024,14 +1056,82 @@ abstract class repository { } } + /** + * Repository method to serve file + * + * @param stored_file $storedfile + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + } + + /** + * Return reference file life time + * + * @param string $ref + * @return int + */ + public function get_reference_file_lifetime($ref) { + // One day + return 60 * 60 * 24; + } + + /** + * Decide whether or not the file should be synced + * + * @param stored_file $storedfile + * @return bool + */ + public function sync_individual_file(stored_file $storedfile) { + return true; + } + + /** + * Return human readable reference information + * {@link stored_file::get_reference()} + * + * @param string $reference + * @return string|null + */ + public function get_reference_details($reference) { + return null; + } + + /** + * Cache file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * Invoked at MOODLE/repository/repository_ajax.php + * + * @param string $reference this reference is generated by + * repository::get_file_reference() + * @param stored_file $storedfile created file reference + */ + public function cache_file_by_reference($reference, $storedfile = null) { + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param stdClass $reference file reference db record + * @return stdClass|null|false + */ + public function get_file_by_reference($reference) { + return null; + } + /** * Move file from download folder to file pool using FILE API - * @global object $DB - * @global object $CFG - * @global object $USER - * @global object $OUTPUT + * + * @todo MDL-28637 + * @static * @param string $thefile file path in download folder - * @param object $record + * @param stdClass $record * @return array containing the following keys: * icon * file @@ -1044,29 +1144,13 @@ abstract class repository { // scan for viruses if possible, throws exception if problem found self::antivir_scan_file($thefile, $record->filename, empty($CFG->repository_no_delete)); //TODO: MDL-28637 this repository_no_delete is a bloody hack! - if ($record->filepath !== '/') { - $record->filepath = trim($record->filepath, '/'); - $record->filepath = '/'.$record->filepath.'/'; - } - $context = get_context_instance(CONTEXT_USER, $USER->id); - $now = time(); - - $record->contextid = $context->id; - $record->component = 'user'; - $record->filearea = 'draft'; - $record->timecreated = $now; - $record->timemodified = $now; - $record->userid = $USER->id; - $record->mimetype = mimeinfo('type', $thefile); - if(!is_numeric($record->itemid)) { - $record->itemid = 0; - } $fs = get_file_storage(); - if ($existingfile = $fs->get_file($context->id, $record->component, $record->filearea, $record->itemid, $record->filepath, $record->filename)) { + // If file name being used. + if (repository::draftfile_exists($record->itemid, $record->filepath, $record->filename)) { $draftitemid = $record->itemid; $new_filename = repository::get_unused_filename($draftitemid, $record->filepath, $record->filename); $old_filename = $record->filename; - // create a tmp file + // Create a tmp file. $record->filename = $new_filename; $newfile = $fs->create_file_from_pathname($record, $thefile); $event = array(); @@ -1099,16 +1183,16 @@ abstract class repository { } /** - * Builds a tree of files This function is - * then called recursively. + * Builds a tree of files This function is then called recursively. * - * @param $fileinfo an object returned by file_browser::get_file_info() - * @param $search searched string - * @param $dynamicmode bool no recursive call is done when in dynamic mode - * @param $list - the array containing the files under the passed $fileinfo + * @static + * @todo take $search into account, and respect a threshold for dynamic loading + * @param file_info $fileinfo an object returned by file_browser::get_file_info() + * @param string $search searched string + * @param bool $dynamicmode no recursive call is done when in dynamic mode + * @param array $list the array containing the files under the passed $fileinfo * @returns int the number of files found * - * todo: take $search into account, and respect a threshold for dynamic loading */ public static function build_tree($fileinfo, $search, $dynamicmode, &$list) { global $CFG, $OUTPUT; @@ -1184,13 +1268,11 @@ abstract class repository { return $filecount; } - /** * Display a repository instance list (with edit/delete/create links) - * @global object $CFG - * @global object $USER - * @global object $OUTPUT - * @param object $context the context for which we display the instance + * + * @static + * @param stdClass $context the context for which we display the instance * @param string $typename if set, we display only one type of instance */ public static function display_instances_list($context, $typename = null) { @@ -1205,7 +1287,6 @@ abstract class repository { } else { $baseurl = new moodle_url('/repository/manage_instances.php', array('contextid'=>$context->id, 'sesskey'=>sesskey())); } - $url = $baseurl; $namestr = get_string('name'); $pluginstr = get_string('plugin', 'repository'); @@ -1240,15 +1321,15 @@ abstract class repository { if ($type->get_contextvisibility($context)) { if (!$i->readonly) { - $url->param('type', $i->options['type']); - $url->param('edit', $i->id); - $settings .= html_writer::link($url, $settingsstr); + $settingurl = new moodle_url($baseurl); + $settingurl->param('type', $i->options['type']); + $settingurl->param('edit', $i->id); + $settings .= html_writer::link($settingurl, $settingsstr); - $url->remove_params('edit'); - $url->param('delete', $i->id); - $delete .= html_writer::link($url, $deletestr); - - $url->remove_params('type'); + $deleteurl = new moodle_url($baseurl); + $deleteurl->param('delete', $i->id); + $deleteurl->param('type', $i->options['type']); + $delete .= html_writer::link($deleteurl, $deletestr); } } @@ -1294,9 +1375,7 @@ abstract class repository { if (!empty($instanceoptionnames)) { //create a unique type of instance $addable = 1; $baseurl->param('new', $typename); - $instancehtml .= "
                            -

                            - "; + $output .= $OUTPUT->single_button($baseurl, get_string('createinstance', 'repository'), 'get'); $baseurl->remove_params('new'); } } @@ -1312,9 +1391,20 @@ abstract class repository { print($output); } + /** + * Prepare file reference information + * + * @param string $source + * @return string file referece + */ + public function get_file_reference($source) { + return $source; + } /** * Decide where to save the file, can be overwriten by subclass - * @param string filename + * + * @param string $filename file name + * @return file path */ public function prepare_file($filename) { global $CFG; @@ -1333,6 +1423,15 @@ abstract class repository { return $dir.$filename; } + /** + * Does this repository used to browse moodle files? + * + * @return bool + */ + public function has_moodle_files() { + return false; + } + /** * Return file URL, for most plugins, the parameter is the original * url, but some plugins use a file id, so we need this function to @@ -1346,14 +1445,11 @@ abstract class repository { } /** - * Download a file, this function can be overridden by - * subclass. + * Download a file, this function can be overridden by subclass. {@link curl} * - * @global object $CFG * @param string $url the url of file * @param string $filename save location * @return string the location of the file - * @see curl package */ public function get_file($url, $filename = '') { global $CFG; @@ -1361,6 +1457,8 @@ abstract class repository { $fp = fopen($path, 'w'); $c = new curl; $c->download(array(array('url'=>$url, 'file'=>$fp))); + // Close file handler. + fclose($fp); return array('path'=>$path, 'url'=>$url); } @@ -1368,7 +1466,7 @@ abstract class repository { * Return size of a file in bytes. * * @param string $source encoded and serialized data of file - * @return integer file size in bytes + * @return int file size in bytes */ public function get_file_size($source) { $browser = get_file_browser(); @@ -1392,7 +1490,8 @@ abstract class repository { /** * Return is the instance is visible * (is the type visible ? is the context enable ?) - * @return boolean + * + * @return bool */ public function is_visible() { $type = repository::get_type_by_id($this->options['typeid']); @@ -1410,7 +1509,7 @@ abstract class repository { /** * Return the name of this instance, can be overridden. - * @global object $DB + * * @return string */ public function get_name() { @@ -1423,7 +1522,8 @@ abstract class repository { } /** - * what kind of files will be in this repository? + * What kind of files will be in this repository? + * * @return array return '*' means this repository support any files, otherwise * return mimetypes of files, it can be an array */ @@ -1433,17 +1533,18 @@ abstract class repository { } /** - * does it return a file url or a item_id + * Does it return a file url or a item_id + * * @return string */ public function supported_returntypes() { - return (FILE_INTERNAL | FILE_EXTERNAL); + return (FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE); } /** * Provide repository instance information for Ajax - * @global object $CFG - * @return object + * + * @return stdClass */ final public function get_meta() { global $CFG, $OUTPUT; @@ -1461,13 +1562,13 @@ abstract class repository { /** * Create an instance for this plug-in - * @global object $CFG - * @global object $DB + * + * @static * @param string $type the type of the repository - * @param integer $userid the user id - * @param object $context the context + * @param int $userid the user id + * @param stdClass $context the context * @param array $params the options for this instance - * @param integer $readonly whether to create it readonly or not (defaults to not) + * @param int $readonly whether to create it readonly or not (defaults to not) * @return mixed */ public static function create($type, $userid, $context, $params, $readonly=0) { @@ -1512,21 +1613,29 @@ abstract class repository { /** * delete a repository instance - * @global object $DB - * @return mixed + * + * @param bool $downloadcontents + * @return bool */ - final public function delete() { + final public function delete($downloadcontents = false) { global $DB; - $DB->delete_records('repository_instances', array('id'=>$this->id)); - $DB->delete_records('repository_instance_config', array('instanceid'=>$this->id)); + if ($downloadcontents) { + $this->convert_references_to_local(); + } + try { + $DB->delete_records('repository_instances', array('id'=>$this->id)); + $DB->delete_records('repository_instance_config', array('instanceid'=>$this->id)); + } catch (dml_exception $ex) { + return false; + } return true; } /** * Hide/Show a repository - * @global object $DB + * * @param string $hide - * @return boolean + * @return bool */ final public function hide($hide = 'toggle') { global $DB; @@ -1552,9 +1661,9 @@ abstract class repository { /** * Save settings for repository instance * $repo->set_option(array('api_key'=>'f2188bde132', 'name'=>'dongsheng')); - * @global object $DB + * * @param array $options settings - * @return int Id of the record + * @return bool */ public function set_option($options = array()) { global $DB; @@ -1582,7 +1691,7 @@ abstract class repository { /** * Get settings for repository instance - * @global object $DB + * * @param string $config * @return array Settings */ @@ -1607,6 +1716,12 @@ abstract class repository { } } + /** + * Filter file listing to display specific types + * + * @param array $value + * @return bool + */ public function filter(&$value) { $pass = false; $accepted_types = optional_param_array('accepted_types', '', PARAM_RAW); @@ -1642,11 +1757,10 @@ abstract class repository { /** * Given a path, and perhaps a search, get a list of files. * - * See details on http://docs.moodle.org/dev/Repository_plugins + * See details on {@link http://docs.moodle.org/dev/Repository_plugins} * - * @param string $path, this parameter can - * a folder name, or a identification of folder - * @param string $page, the page number of file list + * @param string $path this parameter can a folder name, or a identification of folder + * @param string $page the page number of file list * @return array the list of files, including meta infomation, containing the following keys * manage, url to manage url * client_id @@ -1666,11 +1780,11 @@ abstract class repository { } /** - * Search files in repository - * When doing global search, $search_text will be used as - * keyword. + * Search files in repository. * - * @return mixed, see get_listing() + * @param string $search_text search key word + * @param int $page page + * @return mixed {@see repository::get_listing} */ public function search($search_text, $page = 0) { $list = array(); @@ -1691,7 +1805,7 @@ abstract class repository { /** * To check whether the user is logged in. * - * @return boolean + * @return bool */ public function check_login(){ return true; @@ -1700,6 +1814,8 @@ abstract class repository { /** * Show the login screen, if required + * + * @return string */ public function print_login(){ return $this->get_listing(); @@ -1707,7 +1823,8 @@ abstract class repository { /** * Show the search screen, if required - * @return null + * + * @return string */ public function print_search() { $str = ''; @@ -1727,7 +1844,8 @@ abstract class repository { /** * is it possible to do glboal search? - * @return boolean + * + * @return bool */ public function global_search() { return false; @@ -1735,7 +1853,8 @@ abstract class repository { /** * Defines operations that happen occasionally on cron - * @return boolean + * + * @return bool */ public function cron() { return true; @@ -1743,7 +1862,8 @@ abstract class repository { /** * function which is run when the type is created (moodle administrator add the plugin) - * @return boolean success or fail? + * + * @return bool success or fail? */ public static function plugin_init() { return true; @@ -1751,7 +1871,8 @@ abstract class repository { /** * Edit/Create Admin Settings Moodle form - * @param object $mform Moodle form (passed by reference) + * + * @param moodleform $mform Moodle form (passed by reference) * @param string $classname repository class name */ public static function type_config_form($mform, $classname = 'repository') { @@ -1767,9 +1888,11 @@ abstract class repository { /** * Validate Admin Settings Moodle form - * @param object $mform Moodle form (passed by reference) - * @param array array of ("fieldname"=>value) of submitted data - * @param array array of ("fieldname"=>errormessage) of errors + * + * @static + * @param moodleform $mform Moodle form (passed by reference) + * @param array $data array of ("fieldname"=>value) of submitted data + * @param array $errors array of ("fieldname"=>errormessage) of errors * @return array array of errors */ public static function type_form_validation($mform, $data, $errors) { @@ -1779,14 +1902,16 @@ abstract class repository { /** * Edit/Create Instance Settings Moodle form - * @param object $mform Moodle form (passed by reference) + * + * @param moodleform $mform Moodle form (passed by reference) */ public function instance_config_form($mform) { } /** - * Return names of the general options + * Return names of the general options. * By default: no general option name + * * @return array */ public static function get_type_option_names() { @@ -1794,18 +1919,34 @@ abstract class repository { } /** - * Return names of the instance options + * Return names of the instance options. * By default: no instance option name + * * @return array */ public static function get_instance_option_names() { return array(); } + /** + * Validate repository plugin instance form + * + * @param moodleform $mform moodle form + * @param array $data form data + * @param array $errors errors + * @return array errors + */ public static function instance_form_validation($mform, $data, $errors) { return $errors; } + /** + * Create a shorten filename + * + * @param string $str filename + * @param int $maxlength max file name length + * @return string short filename + */ public function get_short_filename($str, $maxlength) { if (textlib::strlen($str) >= $maxlength) { return trim(textlib::substr($str, 0, $maxlength)).'...'; @@ -1822,7 +1963,7 @@ abstract class repository { * @param string $filename * @param string $newfilepath * @param string $newfilename - * @return boolean + * @return bool */ public static function overwrite_existing_draftfile($itemid, $filepath, $filename, $newfilepath, $newfilename) { global $USER; @@ -1848,7 +1989,7 @@ abstract class repository { * @param int $draftitemid * @param string $filepath * @param string $filename - * @return boolean + * @return bool */ public static function delete_tempfile_from_draft($draftitemid, $filepath, $filename) { global $USER; @@ -1861,15 +2002,106 @@ abstract class repository { return false; } } + + /** + * Find all external files in this repo and import them + */ + public function convert_references_to_local() { + $fs = get_file_storage(); + $files = $fs->get_external_files($this->id); + foreach ($files as $storedfile) { + $fs->import_external_file($storedfile); + } + } + + + + /** + * Call to request proxy file sync with repository source. + * + * @param stored_file $file + * @return bool success + */ + public static function sync_external_file(stored_file $file) { + global $DB; + + $fs = get_file_storage(); + + if (!$reference = $DB->get_record('files_reference', array('id'=>$file->get_referencefileid()))) { + return false; + } + + if (!empty($reference->lastsync) and ($reference->lastsync + $reference->lifetime > time())) { + return false; + } + + if (!$repository = self::get_repository_by_id($reference->repositoryid, SYSCONTEXTID)) { + return false; + } + + if (!$repository->sync_individual_file($file)) { + return false; + } + + $fileinfo = $repository->get_file_by_reference($reference); + if ($fileinfo === null) { + // does not exist any more - set status to missing + $sql = "UPDATE {files} SET status = :missing WHERE referencefileid = :referencefileid"; + $params = array('referencefileid'=>$reference->id, 'missing'=>666); + $DB->execute($sql, $params); + //TODO: purge content from pool if we set some other content hash and it is no used any more + return true; + } else if ($fileinfo === false) { + // error + return false; + } + + $contenthash = null; + $filesize = null; + if (!empty($fileinfo->contenthash)) { + // contenthash returned, file already in moodle + $contenthash = $fileinfo->contenthash; + $filesize = $fileinfo->filesize; + } else if (!empty($fileinfo->filepath)) { + // File path returned + list($contenthash, $filesize, $newfile) = $fs->add_file_to_pool($fileinfo->filepath); + } else if (!empty($fileinfo->handle) && is_resource($fileinfo->handle)) { + // File handle returned + $contents = ''; + while (!feof($fileinfo->handle)) { + $contents .= fread($handle, 8192); + } + fclose($fileinfo->handle); + list($contenthash, $filesize, $newfile) = $fs->add_string_to_pool($content); + } else if (isset($fileinfo->content)) { + // File content returned + list($contenthash, $filesize, $newfile) = $fs->add_string_to_pool($fileinfo->content); + } + + if (!isset($contenthash) or !isset($filesize)) { + return false; + } + + $now = time(); + // update files table + $sql = "UPDATE {files} SET contenthash = :contenthash, filesize = :filesize, referencelastsync = :now, referencelifetime = :lifetime, timemodified = :now2 WHERE referencefileid = :referencefileid AND contenthash <> :contenthash2"; + $params = array('contenthash'=>$contenthash, 'filesize'=>$filesize, 'now'=>$now, 'lifetime'=>$reference->lifetime, + 'now2'=>$now, 'referencefileid'=>$reference->id, 'contenthash2'=>$contenthash); + $DB->execute($sql, $params); + + $DB->set_field('files_reference', 'lastsync', $now, array('id'=>$reference->id)); + + return true; + } } /** * Exception class for repository api * * @since 2.0 - * @package moodlecore - * @subpackage repository - * @copyright 2009 Dongsheng Cai + * @package repository + * @category repository + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_exception extends moodle_exception { @@ -1879,14 +2111,20 @@ class repository_exception extends moodle_exception { * This is a class used to define a repository instance form * * @since 2.0 - * @package moodlecore - * @subpackage repository - * @copyright 2009 Dongsheng Cai + * @package repository + * @category repository + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class repository_instance_form extends moodleform { + /** @var stdClass repository instance */ protected $instance; + /** @var string repository plugin type */ protected $plugin; + + /** + * Added defaults to moodle form + */ protected function add_defaults() { $mform =& $this->_form; $strrequired = get_string('required'); @@ -1906,6 +2144,9 @@ final class repository_instance_form extends moodleform { $mform->addRule('name', $strrequired, 'required', null, 'client'); } + /** + * Define moodle form elements + */ public function definition() { global $CFG; // type of plugin, string @@ -1952,6 +2193,13 @@ final class repository_instance_form extends moodleform { } } + /** + * Validate moodle form data + * + * @param array $data form data + * @param array $files files in form + * @return array errors + */ public function validation($data, $files) { global $DB; $errors = array(); @@ -1980,19 +2228,21 @@ final class repository_instance_form extends moodleform { * This is a class used to define a repository type setting form * * @since 2.0 - * @package moodlecore - * @subpackage repository - * @copyright 2009 Dongsheng Cai + * @package repository + * @category repository + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ final class repository_type_form extends moodleform { + /** @var stdClass repository instance */ protected $instance; + /** @var string repository plugin name */ protected $plugin; + /** @var string action */ protected $action; /** * Definition of the moodleform - * @global object $CFG */ public function definition() { global $CFG; @@ -2062,6 +2312,13 @@ final class repository_type_form extends moodleform { $this->add_action_buttons(true, get_string('save','repository')); } + /** + * Validate moodle form data + * + * @param array $data moodle form data + * @param array $files + * @return array errors + */ public function validation($data, $files) { $errors = array(); $plugin = $this->_customdata['plugin']; @@ -2081,7 +2338,7 @@ final class repository_type_form extends moodleform { /** * Generate all options needed by filepicker * - * @param array $args, including following keys + * @param array $args including following keys * context * accepted_types * return_types @@ -2163,6 +2420,7 @@ function initialise_filepicker($args) { } /** * Small function to walk an array to attach repository ID + * * @param array $value * @param string $key * @param int $id diff --git a/repository/local/lib.php b/repository/local/lib.php index 3f154382f53..f31317e184f 100644 --- a/repository/local/lib.php +++ b/repository/local/lib.php @@ -1,5 +1,4 @@ . /** - * repository_local class is used to browse moodle files + * This plugin is used to access local files * - * @since 2.0 + * @since 2.0 * @package repository_local - * @copyright 2009 Dongsheng Cai + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +require_once($CFG->dirroot . '/repository/lib.php'); +/** + * repository_local class is used to browse moodle files + * + * @since 2.0 + * @package repository_local + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class repository_local extends repository { /** * local plugin doesn't require login, so list all files diff --git a/repository/merlot/lib.php b/repository/merlot/lib.php index 91f2da7e57c..7f876431029 100644 --- a/repository/merlot/lib.php +++ b/repository/merlot/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access merlot files + * + * @since 2.0 + * @package repository_merlot + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); + /** * repository_merlot is used to search merlot.org in moodle * * @since 2.0 - * @package repository - * @subpackage merlot - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_merlot + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_merlot extends repository { diff --git a/repository/picasa/lib.php b/repository/picasa/lib.php index bd43d848242..c1cbc3ef8cb 100644 --- a/repository/picasa/lib.php +++ b/repository/picasa/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access picasa pictures + * + * @since 2.0 + * @package repository_picasa + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once($CFG->libdir.'/googleapi.php'); + /** * Picasa Repository Plugin * @@ -25,9 +35,6 @@ * @author Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once($CFG->libdir.'/googleapi.php'); - class repository_picasa extends repository { private $subauthtoken = ''; diff --git a/repository/recent/lib.php b/repository/recent/lib.php index 1f4299a531b..05f739b1189 100644 --- a/repository/recent/lib.php +++ b/repository/recent/lib.php @@ -15,16 +15,24 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * This plugin is used to access recent used files + * + * @since 2.0 + * @package repository_recent + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); + /** * repository_recent class is used to browse recent used files * * @since 2.0 - * @package repository - * @subpackage recent - * @copyright 2010 Dongsheng Cai + * @package repository_recent + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - define('DEFAULT_RECENT_FILES_NUM', 50); class repository_recent extends repository { diff --git a/repository/repository_ajax.php b/repository/repository_ajax.php index b7793c8b9b0..35a985cd319 100644 --- a/repository/repository_ajax.php +++ b/repository/repository_ajax.php @@ -1,5 +1,4 @@ + * @package repository + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -34,7 +32,7 @@ require_once(dirname(__FILE__).'/lib.php'); $err = new stdClass(); -/// Parameters +// Parameters $action = optional_param('action', '', PARAM_ALPHA); $repo_id = optional_param('repo_id', 0, PARAM_INT); // Repository ID $contextid = optional_param('ctx_id', SYSCONTEXTID, PARAM_INT); // Context ID @@ -51,6 +49,7 @@ $saveas_filename = optional_param('title', '', PARAM_FILE); // save as file $saveas_path = optional_param('savepath', '/', PARAM_PATH); // save as file path $search_text = optional_param('s', '', PARAM_CLEANHTML); $linkexternal = optional_param('linkexternal', '', PARAM_ALPHA); +$usefilereference = optional_param('usefilereference', '', PARAM_ALPHA); list($context, $course, $cm) = get_context_info_array($contextid); require_login($course, false, $cm); @@ -59,7 +58,7 @@ $PAGE->set_context($context); echo $OUTPUT->header(); // send headers @header('Content-type: text/html; charset=utf-8'); -// if uploaded file is larger than post_max_size (php.ini) setting, $_POST content will lost +// If uploaded file is larger than post_max_size (php.ini) setting, $_POST content will be empty. if (empty($_POST) && !empty($action)) { $err->error = get_string('errorpostmaxsize', 'repository'); die(json_encode($err)); @@ -70,7 +69,7 @@ if (!confirm_sesskey()) { die(json_encode($err)); } -/// Get repository instance information +// Get repository instance information $sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i WHERE i.id=? AND i.typeid=r.id'; if (!$repository = $DB->get_record_sql($sql, array($repo_id))) { @@ -80,7 +79,7 @@ if (!$repository = $DB->get_record_sql($sql, array($repo_id))) { $type = $repository->type; } -/// Check permissions +// Check permissions repository::check_capability($contextid, $repository); $moodle_maxbytes = get_max_upload_file_size(); @@ -89,7 +88,7 @@ if ($maxbytes == 0 || $maxbytes>=$moodle_maxbytes) { $maxbytes = $moodle_maxbytes; } -/// Wait as long as it takes for this script to finish +// Wait as long as it takes for this script to finish set_time_limit(0); // Early actions which need to be done before repository instances initialised @@ -125,13 +124,19 @@ switch ($action) { if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) { require_once($CFG->dirroot.'/repository/'.$type.'/lib.php'); $classname = 'repository_' . $type; - $repo = new $classname($repo_id, $contextid, array('ajax'=>true, 'name'=>$repository->name, 'type'=>$type)); + $repooptions = array( + 'ajax' => true, + 'name' => $repository->name, + 'type' => $type, + 'mimetypes' => $accepted_types + ); + $repo = new $classname($repo_id, $contextid, $repooptions); } else { $err->error = get_string('invalidplugin', 'repository', $type); die(json_encode($err)); } -/// These actions all occur on the currently active repository instance +// These actions all occur on the currently active repository instance switch ($action) { case 'sign': case 'signin': @@ -201,45 +206,43 @@ switch ($action) { echo json_encode($info); die; } else { - // some repository plugins deal with moodle internal files, so we cannot use get_file + $fs = get_file_storage(); + // Some repository plugins are hosting moodle internal files, we cannot use get_file // method, so we use copy_to_area method // (local, user, coursefiles, recent) - if ($repo->has_moodle_files()) { + if ($repo->has_moodle_files() && ($usefilereference != 'yes')) { // check filesize against max allowed size $filesize = $repo->get_file_size($source); if (empty($filesize)) { - $err->error = get_string('filesizenull', 'repository'); - die(json_encode($err)); + $filesize = 0; } if (($maxbytes !== -1) && ($filesize > $maxbytes)) { throw new file_exception('maxbytes'); } + // If the moodle file is an alias to a file in external repository + // we copy this alias instead of create alias to alias + // {@link repository::copy_to_area()}. $fileinfo = $repo->copy_to_area($source, $itemid, $saveas_path, $saveas_filename); + if (!isset($fileinfo['event'])) { $fileinfo['file'] = $fileinfo['title']; } + echo json_encode($fileinfo); die; } - // Download file to moodle - $file = $repo->get_file($source, $saveas_filename); - if ($file['path'] === false) { - $err->error = get_string('cannotdownload', 'repository'); - die(json_encode($err)); - } - - // check if exceed maxbytes - if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) { - throw new file_exception('maxbytes'); - } + // Prepare file record. $record = new stdClass(); $record->filepath = $saveas_path; $record->filename = $saveas_filename; $record->component = 'user'; $record->filearea = 'draft'; - $record->itemid = $itemid; - + if (!is_numeric($itemid)) { + $record->itemid = 0; + } else { + $record->itemid = $itemid; + } if (!empty($file['license'])) { $record->license = $file['license']; } else { @@ -250,11 +253,78 @@ switch ($action) { } else { $record->author = $author; } - $record->source = !empty($file['url']) ? $file['url'] : ''; - $info = repository::move_to_filepool($file['path'], $record); - if (empty($info)) { - $info['e'] = get_string('error', 'moodle'); + if ($record->filepath !== '/') { + $record->filepath = trim($record->filepath, '/'); + $record->filepath = '/'.$record->filepath.'/'; + } + $usercontext = get_context_instance(CONTEXT_USER, $USER->id); + $now = time(); + $record->contextid = $usercontext->id; + $record->timecreated = $now; + $record->timemodified = $now; + $record->userid = $USER->id; + $record->mimetype = mimeinfo('type', $record->filename); + + + if ($usefilereference == 'yes') { + $reference = $repo->get_file_reference($source); + // get reference life time from repo + $record->referencelifetime = $repo->get_reference_file_lifetime($reference); + // Check if file exists. + if (repository::draftfile_exists($itemid, $saveas_path, $saveas_filename)) { + // File name being used, rename it. + $unused_filename = repository::get_unused_filename($itemid, $saveas_path, $saveas_filename); + $record->filename = $unused_filename; + // Create a file copy using unused filename. + $storedfile = $fs->create_file_from_reference($record, $repo_id, $reference); + + $event = array(); + $event['event'] = 'fileexists'; + $event['newfile'] = new stdClass; + $event['newfile']->filepath = $saveas_path; + $event['newfile']->filename = $unused_filename; + $event['newfile']->url = moodle_url::make_draftfile_url($itemid, $saveas_path, $unused_filename)->out(); + + $event['existingfile'] = new stdClass; + $event['existingfile']->filepath = $saveas_path; + $event['existingfile']->filename = $saveas_filename; + $event['existingfile']->url = moodle_url::make_draftfile_url($itemid, $saveas_path, $saveas_filename)->out();; + echo json_encode($event); + die; + } + $storedfile = $fs->create_file_from_reference($record, $repo_id, $reference); + // Repository plugin callback + // You can cache reository file in this callback + // or complete other tasks. + $repo->cache_file_by_reference($reference, $storedfile); + $info = array( + 'url'=>moodle_url::make_draftfile_url($storedfile->get_itemid(), $storedfile->get_filepath(), $storedfile->get_filename())->out(), + 'id'=>$storedfile->get_itemid(), + 'file'=>$storedfile->get_filename(), + 'icon' => $OUTPUT->pix_url(file_extension_icon($storedfile->get_filename(), 32))->out(), + ); + echo json_encode($info); + die; + } else { + // Download file to moodle. + $downloadedfile = $repo->get_file($source, $saveas_filename); + if ($downloadedfile['path'] === false) { + $err->error = get_string('cannotdownload', 'repository'); + die(json_encode($err)); + } + + // Check if exceed maxbytes. + if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) { + throw new file_exception('maxbytes'); + } + + $record->source = !empty($downloadedfile['url']) ? $downloadedfile['url'] : ''; + + $info = repository::move_to_filepool($downloadedfile['path'], $record); + if (empty($info)) { + $info['e'] = get_string('error', 'moodle'); + } } echo json_encode($info); die; diff --git a/repository/s3/lib.php b/repository/s3/lib.php index e0a8f328f7f..b74a87dbdfc 100644 --- a/repository/s3/lib.php +++ b/repository/s3/lib.php @@ -15,20 +15,25 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * This plugin is used to access s3 files + * + * @since 2.0 + * @package repository_s3 + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once('S3.php'); /** * This is a repository class used to browse Amazon S3 content. * * @since 2.0 - * @package repository - * @subpackage s3 - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_s3 + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once('S3.php'); - class repository_s3 extends repository { /** diff --git a/repository/tests/repository_test.php b/repository/tests/repository_test.php new file mode 100644 index 00000000000..46eaf449264 --- /dev/null +++ b/repository/tests/repository_test.php @@ -0,0 +1,61 @@ +. + +/** + * Repository API unit tests + * + * @package repository + * @category phpunit + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once("$CFG->dirroot/repository/lib.php"); + +class repositorylib_testcase extends advanced_testcase { + + /** + * Installing repository tests + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + */ + public function test_install_repository() { + global $CFG, $DB; + + $this->resetAfterTest(true); + + $syscontext = context_system::instance(); + $repositorypluginname = 'boxnet'; + // override repository permission + $capability = 'repository/' . $repositorypluginname . ':view'; + $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id'); + assign_capability($capability, CAP_ALLOW, $allroles['guest'], $syscontext->id, true); + + $plugintype = new repository_type($repositorypluginname); + $pluginid = $plugintype->create(false); + $this->assertInternalType('int', $pluginid); + $args = array(); + $args['type'] = $repositorypluginname; + $repos = repository::get_instances($args); + $repository = reset($repos); + $this->assertInstanceOf('repository', $repository); + $info = $repository->get_meta(); + $this->assertEquals($repositorypluginname, $info->type); + } +} diff --git a/repository/upload/lib.php b/repository/upload/lib.php index 1b2bb9d85f7..cd5ac10f47b 100644 --- a/repository/upload/lib.php +++ b/repository/upload/lib.php @@ -15,14 +15,22 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * This plugin is used to upload files + * + * @since 2.0 + * @package repository_upload + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); + /** * A repository plugin to allow user uploading files * * @since 2.0 - * @package repository - * @subpackage upload - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_upload + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/repository/url/lib.php b/repository/url/lib.php index bc31e9531f7..16f2eb07ae5 100644 --- a/repository/url/lib.php +++ b/repository/url/lib.php @@ -15,20 +15,26 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * This plugin is used to access files by providing an url + * + * @since 2.0 + * @package repository_url + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once(dirname(__FILE__).'/locallib.php'); + /** * repository_url class * A subclass of repository, which is used to download a file from a specific url * * @since 2.0 - * @package repository - * @subpackage url - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_url + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once(dirname(__FILE__).'/locallib.php'); - class repository_url extends repository { var $processedfiles = array(); diff --git a/repository/user/lib.php b/repository/user/lib.php index c86eb3cb02b..1f06ddd28ea 100644 --- a/repository/user/lib.php +++ b/repository/user/lib.php @@ -16,19 +16,28 @@ // along with Moodle. If not, see . /** - * repository_user class is used to browse user private files + * This plugin is used to access user's private files * * @since 2.0 - * @package repository - * @subpackage user - * @copyright 2010 Dongsheng Cai + * @package repository_user + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +require_once($CFG->dirroot . '/repository/lib.php'); +/** + * repository_user class is used to browse user private files + * + * @since 2.0 + * @package repository_user + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class repository_user extends repository { /** * user plugin doesn't require login + * * @return mixed */ public function print_login() { @@ -115,15 +124,6 @@ class repository_user extends repository { return $ret; } - /** - * User file don't support to link to external links - * - * @return int - */ - public function supported_returntypes() { - return FILE_INTERNAL; - } - /** * Does this repository used to browse moodle files? * @@ -132,4 +132,111 @@ class repository_user extends repository { public function has_moodle_files() { return true; } + + /** + * User cannot use the external link to dropbox + * + * @return int + */ + public function supported_returntypes() { + return FILE_INTERNAL | FILE_REFERENCE; + } + + + /** + * Prepare file reference information + * + * @param string $source + * @return string file referece + */ + public function get_file_reference($source) { + global $USER; + $params = unserialize(base64_decode($source)); + if (is_array($params)) { + $filepath = clean_param($params['filepath'], PARAM_PATH);; + $filename = clean_param($params['filename'], PARAM_FILE); + $contextid = clean_param($params['contextid'], PARAM_INT); + } + // We store all file parameters, so file api could + // find the refernces later. + $reference = array(); + $reference['contextid'] = $contextid; + $reference['component'] = 'user'; + $reference['filearea'] = 'private'; + $reference['itemid'] = 0; + $reference['filepath'] = $filepath; + $reference['filename'] = $filename; + + return file_storage::pack_reference($reference); + } + + /** + * Get file from external repository by reference + * {@link repository::get_file_reference()} + * {@link repository::get_file()} + * + * @param stdClass $reference file reference db record + * @return stdClass|null|false + */ + public function get_file_by_reference($reference) { + $fs = get_file_storage(); + $ref = $reference->reference; + $params = unserialize(base64_decode($ref)); + if (!is_array($params)) { + throw new repository_exception('invalidparams', 'repository'); + } + $filename = is_null($params['filename']) ? null : clean_param($params['filename'], PARAM_FILE); + $filepath = is_null($params['filepath']) ? null : clean_param($params['filepath'], PARAM_PATH);; + $contextid = is_null($params['contextid']) ? null : clean_param($params['contextid'], PARAM_INT); + + // hard coded component, filearea and item for security + $component = 'user'; + $filearea = 'private'; + $itemid = 0; + + $storedfile = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename); + + $fileinfo = new stdClass; + $fileinfo->contenthash = $storedfile->get_contenthash(); + $fileinfo->filesize = $storedfile->get_filesize(); + return $fileinfo; + } + + /** + * Return human readable reference information + * {@link stored_file::get_reference()} + * + * @param string $reference + * @return string|null + */ + public function get_reference_details($reference) { + $params = file_storage::unpack_reference($reference); + // Indicate this is from user private area + return $this->get_name() . ': ' . $params['filepath'] . $params['filename']; + } + + /** + * Repository method to serve file + * + * @param stored_file $storedfile + * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) + * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only + * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin + * @param array $options additional options affecting the file serving + */ + public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + $reference = $storedfile->get_reference(); + $params = file_storage::unpack_reference($reference); + $filepath = clean_param($params['filepath'], PARAM_PATH);; + $filename = clean_param($params['filename'], PARAM_FILE); + $contextid = clean_param($params['contextid'], PARAM_INT); + $filearea = 'private'; + $component = 'user'; + $itemid = 0; + + $fs = get_file_storage(); + $storedfile = $fs->get_file($contextid, $component, $filearea, $itemid, $filepath, $filename); + + send_stored_file($storedfile, $lifetime, $filter, $forcedownload, $options); + } } diff --git a/repository/webdav/lib.php b/repository/webdav/lib.php index ea4444d2fc5..bccb7f07063 100644 --- a/repository/webdav/lib.php +++ b/repository/webdav/lib.php @@ -15,19 +15,25 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +/** + * This plugin is used to access webdav files + * + * @since 2.0 + * @package repository_webdav + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once($CFG->libdir.'/webdavlib.php'); + /** * repository_webdav class * * @since 2.0 - * @package repository - * @subpackage webdav - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_webdav + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -require_once($CFG->libdir.'/webdavlib.php'); - class repository_webdav extends repository { public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { parent::__construct($repositoryid, $context, $options); diff --git a/repository/wikimedia/lib.php b/repository/wikimedia/lib.php index 8583bbab9c6..50d85562873 100644 --- a/repository/wikimedia/lib.php +++ b/repository/wikimedia/lib.php @@ -15,17 +15,24 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -require_once('wikimedia.php'); +/** + * This plugin is used to access wikimedia files + * + * @since 2.0 + * @package repository_wikimedia + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); +require_once(dirname(__FILE__) . '/wikimedia.php'); /** * repository_wikimedia class * This is a class used to browse images from wikimedia * * @since 2.0 - * @package repository - * @subpackage wikimedia - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_wikimedia + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/repository/youtube/lib.php b/repository/youtube/lib.php index 41151f9a3b4..7a7c695ed5b 100644 --- a/repository/youtube/lib.php +++ b/repository/youtube/lib.php @@ -1,5 +1,4 @@ . +/** + * This plugin is used to access youtube videos + * + * @since 2.0 + * @package repository_youtube + * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +require_once($CFG->dirroot . '/repository/lib.php'); + /** * repository_youtube class * * @since 2.0 - * @package repository - * @subpackage youtube - * @copyright 2009 Dongsheng Cai - * @author Dongsheng Cai + * @package repository_youtube + * @copyright 2009 Dongsheng Cai {@link http://dongsheng.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/user/filesedit.php b/user/filesedit.php index 716456e569b..86eb52ee7ed 100644 --- a/user/filesedit.php +++ b/user/filesedit.php @@ -57,7 +57,7 @@ $PAGE->set_pagetype('user-files'); $data = new stdClass(); $data->returnurl = $returnurl; -$options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL); +$options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*'); file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0); $mform = new user_filesedit_form(null, array('data'=>$data, 'options'=>$options)); diff --git a/version.php b/version.php index 4dad272d864..2732db6eb73 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012051900.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052100.00; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From 4adecd7beb1ef29691e61d4f568b4f0f6fec7dbd Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 26 Mar 2012 11:19:36 +0800 Subject: [PATCH 232/455] MDL-31901: brushing the filepicker code - use the same function for displaying request result for list/search/login/logout commands since sometimes we can not predict what kind of result is going to be returned - prevent default behaviour for links, so ### does not appear in URL - use flag issearchresult as received in the response from repository because we can't guess it right sometimes - do not make excessive AJAX request when user switches to list view --- repository/filepicker.js | 341 +++++++++++++-------------------------- 1 file changed, 110 insertions(+), 231 deletions(-) diff --git a/repository/filepicker.js b/repository/filepicker.js index 3a82f7b55ee..285735a0646 100644 --- a/repository/filepicker.js +++ b/repository/filepicker.js @@ -46,19 +46,6 @@ M.core_filepicker = M.core_filepicker || {}; M.core_filepicker.instances = M.core_filepicker.instances || {}; M.core_filepicker.active_filepicker = null; -/** - * Set selected file info - * - * @parma object file info - */ -M.core_filepicker.select_file = function(file) { - var fileinfo = {}; - fileinfo['title'] = file.title; - fileinfo['source'] = file.reference; - fileinfo['thumbnail'] = file.thumbnail; - M.core_filepicker.active_filepicker.select_file(fileinfo); -} - /** * Init and show file picker */ @@ -381,25 +368,19 @@ M.core_filepicker.init = function(Y, options) { tmpNode.isLeaf = true; } }, - view_files: function(page) { - var p= page?page:null; + view_files: function() { if (this.active_repo.issearchresult) { // list view is desiged to display treeview // it is not working well with search result this.view_as_icons(); } else { - if (this.objecttag) { - // handle cancle action for repo using iframe - this.create_object_container(this.objecttag); + this.viewbar.set('disabled', false); + if (this.viewmode == 1) { + this.view_as_icons(); + } else if (this.viewmode == 2) { + this.view_as_list(); } else { - this.viewbar.set('disabled', false); - if (this.viewmode == 1) { - this.view_as_icons(); - } else if (this.viewmode == 2) { - this.view_as_list(p); - } else { - this.view_as_icons(); - } + this.view_as_icons(); } } }, @@ -414,7 +395,6 @@ M.core_filepicker.init = function(Y, options) { path:node.path?node.path:'', page:node.page?args.page:'', callback: function(id, obj, args) { - obj.issearchresult = false; var list = obj.list; scope.viewbar.set('disabled', false); scope.parse_repository_options(obj); @@ -425,70 +405,46 @@ M.core_filepicker.init = function(Y, options) { } }, false); }, - view_as_list: function(p) { + view_as_list: function() { var scope = this; - var page = null; - if (!p) { - if (scope.active_repo.page) { - page = scope.active_repo.page; - } - } else { - page = p; + var client_id = scope.options.client_id; + var dynload = scope.active_repo.dynload; + var list = this.filelist; + var panel_id = '#panel-'+client_id; + scope.viewmode = 2; + Y.one(panel_id).set('innerHTML', ''); + scope.print_header(); + + var html = '
                            '; + if (list && list.length==0) { + html += '
                            ' +M.str.repository.nofilesavailable+'
                            '; } - scope.request({ - action:'list', - client_id: scope.options.client_id, - repository_id: scope.active_repo.id, - path:'', - page:page, - callback: function(id, obj, args) { - scope.parse_repository_options(obj); - if (obj.login) { - scope.viewbar.set('disabled', true); - scope.print_login(obj); - return; - } - var client_id = scope.options.client_id; - var dynload = scope.active_repo.dynload; - var list = obj.list; - var panel_id = '#panel-'+client_id; - scope.viewmode = 2; - Y.one(panel_id).set('innerHTML', ''); + html += '
                            '; - scope.print_header(); + var tree = Y.Node.create(html); + Y.one(panel_id).appendChild(tree); + if (!list || list.length==0) { + return; + } - var html = '
                            '; - if (list && list.length==0) { - html += '
                            ' +M.str.repository.nofilesavailable+'
                            '; - } - html += '
                            '; + scope.treeview = new YAHOO.widget.TreeView('treeview-'+client_id); + if (dynload) { + scope.treeview.setDynamicLoad(scope.treeview_dynload, 1); + } - var tree = Y.Node.create(html); - Y.one(panel_id).appendChild(tree); - if (!list || list.length==0) { - return; - } - - scope.treeview = new YAHOO.widget.TreeView('treeview-'+client_id); - if (dynload) { - scope.treeview.setDynamicLoad(scope.treeview_dynload, 1); - } - - for(k in list) { - scope.build_tree(list[k], scope.treeview.getRoot()); - } - scope.treeview.subscribe('clickEvent', function(e){ - if(e.node.isLeaf){ - var fileinfo = {}; - fileinfo['title'] = e.node.data.filename; - fileinfo['source'] = e.node.data.source; - fileinfo['thumbnail'] = e.node.data.thumbnail; - scope.select_file(fileinfo); - } - }); - scope.treeview.draw(); + for(k in list) { + scope.build_tree(list[k], scope.treeview.getRoot()); + } + scope.treeview.subscribe('clickEvent', function(e){ + if(e.node.isLeaf){ + var fileinfo = {}; + fileinfo['title'] = e.node.data.filename; + fileinfo['source'] = e.node.data.source; + fileinfo['thumbnail'] = e.node.data.thumbnail; + scope.select_file(fileinfo); } - }, true); + }); + scope.treeview.draw(); }, view_as_icons: function() { var scope = this; @@ -564,6 +520,7 @@ M.core_filepicker.init = function(Y, options) { var dynload = this.active_repo.dynload; if(node.children) { y_file.on('click', function(e, p) { + e.preventDefault(); if(dynload) { var params = {'path':p.path}; scope.list(params); @@ -573,6 +530,7 @@ M.core_filepicker.init = function(Y, options) { } }, this, node); y_title.on('click', function(e, p, id){ + e.preventDefault(); var icon = Y.one(id); icon.simulate('click'); }, this, node, '#'+link.id); @@ -584,9 +542,11 @@ M.core_filepicker.init = function(Y, options) { fileinfo['haslicense'] = list[k].haslicense?true:false; fileinfo['hasauthor'] = list[k].hasauthor?true:false; y_title.on('click', function(e, args) { + e.preventDefault(); this.select_file(args); }, this, fileinfo); y_file.on('click', function(e, args) { + e.preventDefault(); this.select_file(args); }, this, fileinfo); } @@ -612,7 +572,6 @@ M.core_filepicker.init = function(Y, options) { path.setStyle('display', 'none'); } var panel = Y.one('#panel-'+client_id); - panel.set('innerHTML', ''); var form_id = 'fp-rename-form-'+client_id; var html = '
                            '; html += '

                            '; @@ -622,28 +581,16 @@ M.core_filepicker.init = function(Y, options) { var le_checked = ''; var le_style = ''; - var returntypes = this.options.repositories[this.active_repo.id].return_types; - - if (returntypes == 1) { - // support link only - html += ''; - } else if (returntypes == 4) { - html += ''; - } else { - if (((returntypes & 1) == 1) && ((this.options.return_types & 1) == 1)) { - // support external links - html += '
                            '; - } - // form element support file reference and repository support it too - if (((returntypes & 4) == 4) && ((this.options.return_types & 4) == 4)) { - // file reference - html += ''; - } - - if (((returntypes & 4) != 4) && ((returntypes & 1) != 1)) { - html += ''; - html += ''; - } + if (this.options.repositories[this.active_repo.id].return_types == 1) { + // support external links only + le_checked = 'checked'; + le_style = ' style="display:none;"'; + } else if(this.options.repositories[this.active_repo.id].return_types == 2) { + // support internal files only + le_style = ' style="display:none;"'; + } + if ((this.options.externallink && this.options.env == 'editor' && this.options.return_types != 1)) { + html += ''; } if (!args.hasauthor) { @@ -704,7 +651,7 @@ M.core_filepicker.init = function(Y, options) { // in editor, images are stored in '/' only params.savepath = '/'; // when image or media button is clicked - if (this.options.return_types != 1) { + if ( this.options.return_types != 1 ) { var linkexternal = Y.one('#linkexternal-'+client_id); if (linkexternal && linkexternal.get('checked')) { params['linkexternal'] = 'yes'; @@ -719,15 +666,6 @@ M.core_filepicker.init = function(Y, options) { params['linkexternal'] = 'yes'; } - if (this.options.return_types != 4) { - var usefilereference = Y.one('#filereference-'+client_id); - if (usefilereference && usefilereference.get('checked')) { - params['usefilereference'] = 'yes'; - } - } else { - params['usefilereference'] = 'yes'; - } - this.wait('download', title); this.request({ action:'download', @@ -832,15 +770,19 @@ M.core_filepicker.init = function(Y, options) { // adding buttons var view_icons = {label: M.str.repository.iconview, value: 't', 'checked': true, onclick: { - fn: function(){ - scope.view_as_icons(); + fn: function(e){ + e.preventDefault(); + scope.viewmode = 1; + scope.view_files(); } } }; var view_listing = {label: M.str.repository.listview, value: 'l', onclick: { - fn: function(){ - scope.view_as_list(); + fn: function(e){ + e.preventDefault(); + scope.viewmode = 2; + scope.view_files(); } } }; @@ -868,6 +810,7 @@ M.core_filepicker.init = function(Y, options) { list.append('
                          • '+repository.name+'
                          • '); Y.one('#'+link_id).prepend(' '); Y.one('#'+link_id).on('click', function(e, scope, repository_id) { + e.preventDefault(); YAHOO.util.Cookie.set('recentrepository', repository_id); scope.repository_id = repository_id; this.list({'repo_id':repository_id}); @@ -886,9 +829,8 @@ M.core_filepicker.init = function(Y, options) { parse_repository_options: function(data) { this.filelist = data.list?data.list:null; this.filepath = data.path?data.path:null; - this.objecttag = data.object?data.object:null; this.active_repo = {}; - this.active_repo.issearchresult = Boolean(data.issearchresult); + this.active_repo.issearchresult = data.issearchresult?true:false; this.active_repo.dynload = data.dynload?data.dynload:false; this.active_repo.pages = Number(data.pages?data.pages:null); this.active_repo.page = Number(data.page?data.page:null); @@ -1035,10 +977,7 @@ M.core_filepicker.init = function(Y, options) { 'path': '', 'client_id': client_id, 'repository_id': repository_id, - 'callback': function(id, o, args) { - scope.parse_repository_options(o); - scope.view_files(); - } + 'callback': this.display_response }, true); }, this); } @@ -1072,11 +1011,7 @@ M.core_filepicker.init = function(Y, options) { client_id: client_id, repository_id: repository_id, form: {id: 'fp-form-'+scope.options.client_id,upload:false,useDisabled:true}, - callback: function(id, o, args) { - o.issearchresult = true; - scope.parse_repository_options(o); - scope.view_files(); - } + callback: scope.display_response }, true); }, this); } @@ -1110,94 +1045,47 @@ M.core_filepicker.init = function(Y, options) { }, this); }, - search: function(args) { - var data = this.logindata; - var params = {}; + display_response: function(id, obj, args) { + var scope = args.scope + // highlight the current repository in repositories list + Y.all('#fp-list-'+scope.options.client_id+' li a').setStyle('backgroundColor', 'transparent'); + var el = Y.one('#repository-'+scope.options.client_id+'-'+obj.repo_id+'-link'); + if (el) { + el.setStyle('backgroundColor', '#AACCEE'); + } + // display response + if (obj.login) { + scope.viewbar.set('disabled', true); + scope.print_login(obj); + } else if (obj.upload) { + scope.viewbar.set('disabled', true); + scope.parse_repository_options(obj); + scope.create_upload_form(obj); + } else if (obj.iframe) { - for (var k in data) { - if(data[k].type!='popup') { - var el = document.getElementsByName(data[k].name)[0]; - params[data[k].name] = ''; - if(el.type == 'checkbox') { - params[data[k].name] = el.checked; - } else if(el.type == 'radio') { - var tmp = document.getElementsByName(data[k].name); - for(var i in tmp) { - if (tmp[i].checked) { - params[data[k].name] = tmp[i].value; - } - } - } else { - params[data[k].name] = el.value; - } - } + } else if (obj.list) { + scope.viewbar.set('disabled', false); + scope.parse_repository_options(obj); + scope.view_files(); } - this.request({ - scope: scope, - action:'search', - client_id: client_id, - repository_id: repository_id, - form: {id: 'fp-form-'+scope.options.client_id,upload:false,useDisabled:true}, - callback: function(id, o, args) { - o.issearchresult = true; - scope.parse_repository_options(o); - scope.view_files(); - } - }, true); }, list: function(args) { - var scope = this; if (!args) { args = {}; } if (!args.repo_id) { - args.repo_id = scope.active_repo.id; + args.repo_id = this.active_repo.id; } - scope.request({ - action:'list', - client_id: scope.options.client_id, + this.request({ + action: 'list', + client_id: this.options.client_id, repository_id: args.repo_id, - path:args.path?args.path:'', - page:args.page?args.page:'', - callback: function(id, obj, args) { - Y.all('#fp-list-'+scope.options.client_id+' li a').setStyle('backgroundColor', 'transparent'); - var el = Y.one('#repository-'+scope.options.client_id+'-'+obj.repo_id+'-link'); - if (el) { - el.setStyle('backgroundColor', '#AACCEE'); - } - if (obj.login) { - scope.viewbar.set('disabled', true); - scope.print_login(obj); - } else if (obj.upload) { - scope.viewbar.set('disabled', true); - scope.parse_repository_options(obj); - scope.create_upload_form(obj); - - } else if (obj.object) { - M.core_filepicker.active_filepicker = scope; - scope.viewbar.set('disabled', true); - scope.parse_repository_options(obj); - scope.create_object_container(obj.object); - - } else if (obj.list) { - obj.issearchresult = false; - scope.viewbar.set('disabled', false); - scope.parse_repository_options(obj); - scope.view_files(); - } - } + path: args.path, + page: args.page, + scope: this, + callback: this.display_response }, true); }, - create_object_container: function(data) { - var client_id = this.options.client_id; - Y.one('#panel-'+client_id).set('innerHTML', ''); - var types = this.options.accepted_types; - var panel = Y.one('#panel-'+client_id); - var str = ''; - str += ''; - var container = Y.Node.create(str); - Y.one('#panel-'+client_id).appendChild(container); - }, create_upload_form: function(data) { var client_id = this.options.client_id; Y.one('#panel-'+client_id).set('innerHTML', ''); @@ -1303,7 +1191,8 @@ M.core_filepicker.init = function(Y, options) { if(!r.nosearch) { var html = ' '+M.str.repository.search+''; var search = Y.Node.create(html); - search.on('click', function() { + search.on('click', function(e) { + e.preventDefault(); scope.request({ scope: scope, action:'searchform', @@ -1345,10 +1234,7 @@ M.core_filepicker.init = function(Y, options) { client_id: client_id, repository_id: repository_id, form: {id: 'fp-search-form',upload:false,useDisabled:true}, - callback: function(id, o, args) { - scope.parse_repository_options(o); - scope.view_files(); - } + callback: scope.display_response }, true); search_dialog.cancel(); } @@ -1391,7 +1277,8 @@ M.core_filepicker.init = function(Y, options) { if(!r.norefresh) { var html = ' '+M.str.repository.refresh+''; var refresh = Y.Node.create(html); - refresh.on('click', function() { + refresh.on('click', function(e) { + e.preventDefault(); this.list(); }, this); toolbar.appendChild(refresh); @@ -1400,16 +1287,14 @@ M.core_filepicker.init = function(Y, options) { var label = r.logouttext?r.logouttext:M.str.repository.logout; var html = ' '+label+''; var logout = Y.Node.create(html); - logout.on('click', function() { + logout.on('click', function(e) { + e.preventDefault(); this.request({ action:'logout', client_id: client_id, repository_id: repository_id, path:'', - callback: function(id, obj, args) { - scope.viewbar.set('disabled', true); - scope.print_login(obj); - } + callback: this.display_response }, true); }, this); toolbar.appendChild(logout); @@ -1503,6 +1388,7 @@ M.core_filepicker.init = function(Y, options) { Y.all('#fp-header-'+client_id+' .fp-paging a').each( function(node, id) { node.on('click', function(e) { + e.preventDefault(); var id = node.get('id'); var re = new RegExp("repo-page-(\\d+)", "i"); var result = id.match(re); @@ -1515,19 +1401,11 @@ M.core_filepicker.init = function(Y, options) { client_id: client_id, repository_id: r.id, params: {'page':result[1]}, - callback: function(id, o, args) { - o.issearchresult = true; - scope.parse_repository_options(o); - scope.view_files(result[1]); - } + callback: scope.display_response }, true); } else { - if (scope.viewmode == 2) { - scope.view_as_list(result[1]); - } else { - scope.list(args); - } + scope.list(args); } }); }); @@ -1549,7 +1427,8 @@ M.core_filepicker.init = function(Y, options) { var sep = Y.Node.create('/'); path.appendChild(link); path.appendChild(sep); - Y.one('#'+link.id).on('click', function(Y, path){ + Y.one('#'+link.id).on('click', function(e, path){ + e.preventDefault(); this.list({'path':path}); }, this, link_path) } From b5e7b6385e22d09668397765b08008cf411e1862 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Fri, 30 Mar 2012 10:11:43 +0800 Subject: [PATCH 233/455] MDL-31901: Introducing renderers for filepicker: - create repository renderer, implement functions for returning HTML templates used in filepicker - let filepicker use HTML from templates - move CSS for filemanager and filepicker to the separate css file in base theme - use only YUI3 in filepicker (get rid of YUI2) - add button for 'View details' in filepicker (though this view mode is still not ready) --- lang/en/repository.php | 3 +- lib/outputrequirementslib.php | 9 +- repository/filepicker.js | 1073 ++++++++++++++---------------- repository/lib.php | 11 +- repository/renderer.php | 309 +++++++++ repository/repository_ajax.php | 2 + theme/base/config.php | 3 +- theme/base/style/core.css | 102 --- theme/base/style/filemanager.css | 106 +++ 9 files changed, 944 insertions(+), 674 deletions(-) create mode 100644 repository/renderer.php create mode 100644 theme/base/style/filemanager.css diff --git a/lang/en/repository.php b/lang/en/repository.php index b288e85f0f0..2af26a974ea 100644 --- a/lang/en/repository.php +++ b/lang/en/repository.php @@ -76,6 +76,7 @@ $string['createxxinstance'] = 'Create "{$a}" instance'; $string['date'] = 'Date'; $string['deleted'] = 'Repository deleted'; $string['deleterepository'] = 'Delete this repository'; +$string['detailview'] = 'View details'; $string['disabled'] = 'Disabled'; $string['download'] = 'Download'; $string['downloadfolder'] = 'Download all'; @@ -156,7 +157,7 @@ $string['readonlyinstance'] = 'You cannot edit/delete a read-only instance'; $string['refresh'] = 'Refresh'; $string['refreshnonjsfilepicker'] = 'Please close this window and refresh non-javascript file picker'; $string['removed'] = 'Repository removed'; -$string['renameto'] = 'Rename to'; +$string['renameto'] = 'Rename to "{$a}"'; $string['repositories'] = 'Repositories'; $string['repository'] = 'Repository'; $string['repositorycourse'] = 'Course repositories'; diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 25711c7ae46..f8f0167cff7 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -428,7 +428,7 @@ class page_requirements_manager { * @return array description of module or null if not found */ protected function find_module($component) { - global $CFG; + global $CFG, $PAGE; $module = null; @@ -439,12 +439,13 @@ class page_requirements_manager { case 'core_filepicker': $module = array('name' => 'core_filepicker', 'fullpath' => '/repository/filepicker.js', - 'requires' => array('base', 'node', 'node-event-simulate', 'json', 'async-queue', 'io-base', 'io-upload-iframe', 'io-form', 'yui2-button', 'yui2-container', 'yui2-layout', 'yui2-menu', 'yui2-treeview', 'yui2-dragdrop', 'yui2-cookie'), + 'requires' => array('base', 'node', 'node-event-simulate', 'json', 'async-queue', 'io-base', 'io-upload-iframe', 'io-form', 'yui2-menu', 'yui2-treeview', 'yui2-dragdrop', 'panel', 'cookie'), + // TODO check if those all are really required 'strings' => array(array('add', 'repository'), array('back', 'repository'), array('cancel', 'moodle'), array('close', 'repository'), array('cleancache', 'repository'), array('copying', 'repository'), array('date', 'repository'), array('downloadsucc', 'repository'), array('emptylist', 'repository'), array('error', 'repository'), array('federatedsearch', 'repository'), array('filenotnull', 'repository'), array('getfile', 'repository'), array('help', 'moodle'), array('iconview', 'repository'), - array('invalidjson', 'repository'), array('linkexternal', 'repository'), array('listview', 'repository'), + array('invalidjson', 'repository'), array('linkexternal', 'repository'), array('listview', 'repository'), array('detailview', 'repository'), array('loading', 'repository'), array('login', 'repository'), array('logout', 'repository'), array('noenter', 'repository'), array('noresult', 'repository'), array('manageurl', 'repository'), array('popup', 'repository'), array('preview', 'repository'), array('refresh', 'repository'), array('save', 'repository'), array('saveas', 'repository'), array('saved', 'repository'), @@ -453,7 +454,7 @@ class page_requirements_manager { array('uploading', 'repository'), array('xhtmlerror', 'repository'), array('cancel'), array('chooselicense', 'repository'), array('author', 'repository'),array('next', 'moodle'), array('ok', 'moodle'), array('error', 'moodle'), array('info', 'moodle'), array('norepositoriesavailable', 'repository'), array('norepositoriesexternalavailable', 'repository'), - array('nofilesattached', 'repository'), array('filepicker', 'repository'), + array('attachment', 'repository'), array('nofilesattached', 'repository'), array('filepicker', 'repository'), array('nofilesavailable', 'repository'), array('overwrite', 'repository'), array('renameto', 'repository'), array('fileexists', 'repository'), array('fileexistsdialogheader', 'repository'), array('fileexistsdialog_editor', 'repository'), diff --git a/repository/filepicker.js b/repository/filepicker.js index 285735a0646..a6c2c86d24f 100644 --- a/repository/filepicker.js +++ b/repository/filepicker.js @@ -5,12 +5,16 @@ * * File Picker UI * ===== - * this.rendered, it tracks if YUI Panel rendered + * this.fpnode, contains reference to filepicker Node, non-empty if and only if rendered * this.api, stores the URL to make ajax request * this.mainui, YUI Panel + * this.selectui, YUI Panel for selecting particular file + * this.msg_dlg, YUI Panel for error or info message + * this.process_dlg, YUI Panel for processing existing filename * this.treeview, YUI Treeview - * this.viewbar, a button group to switch view mode * this.viewmode, store current view mode + * this.pathbar, reference to the Node with path bar + * this.pathnode, a Node element representing one folder in a path bar (not attached anywhere, just used for template) * * Filepicker options: * ===== @@ -46,6 +50,11 @@ M.core_filepicker = M.core_filepicker || {}; M.core_filepicker.instances = M.core_filepicker.instances || {}; M.core_filepicker.active_filepicker = null; +/** + * HTML Templates to use in FilePicker + */ +M.core_filepicker.templates = M.core_filepicker.templates || {}; + /** * Init and show file picker */ @@ -60,6 +69,11 @@ M.core_filepicker.show = function(Y, options) { * Add new file picker to current instances */ M.core_filepicker.init = function(Y, options) { + if (options.templates); + for (var templid in options.templates) { + this.templates[templid] = options.templates[templid]; + } + var FilePickerHelper = function(options) { FilePickerHelper.superclass.constructor.apply(this, arguments); }; @@ -134,8 +148,8 @@ M.core_filepicker.init = function(Y, options) { method: 'POST', on: { complete: function(id,o,p) { - var panel_id = '#panel-'+client_id; if (!o) { + // TODO alert('IO FATAL'); return; } @@ -144,7 +158,7 @@ M.core_filepicker.init = function(Y, options) { data = Y.JSON.parse(o.responseText); } catch(e) { scope.print_msg(M.str.repository.invalidjson, 'error'); - Y.one(panel_id).set('innerHTML', 'ERROR: '+M.str.repository.invalidjson+'
                            '+stripHTML(o.responseText)+'
                            '); + scope.display_error(M.str.repository.invalidjson+'
                            '+stripHTML(o.responseText)+'
                            ', 'invalidjson') return; } // error checking @@ -196,31 +210,31 @@ M.core_filepicker.init = function(Y, options) { } else { Y.io(api, cfg); if (redraw) { - this.wait('load'); + this.wait(); } } }, + /** displays the dialog and processes rename/overwrite if there is a file with the same name in the same filearea*/ process_existing_file: function(data) { var scope = this; - var repository_id = scope.active_repo.id; - var client_id = scope.options.client_id; - var handleOverwrite = function() { + var handleOverwrite = function(e) { // overwrite - var dialog = this; + e.preventDefault(); + var data = this.process_dlg.dialogdata; var params = {} params['existingfilename'] = data.existingfile.filename; params['existingfilepath'] = data.existingfile.filepath; params['newfilename'] = data.newfile.filename; params['newfilepath'] = data.newfile.filepath; - scope.request({ + this.hide_header(); + this.request({ 'params': params, - 'scope': scope, + 'scope': this, 'action':'overwrite', 'path': '', - 'client_id': client_id, - 'repository_id': repository_id, + 'client_id': this.options.client_id, + 'repository_id': this.active_repo.id, 'callback': function(id, o, args) { - dialog.cancel(); scope.hide(); // editor needs to update url // filemanager do nothing @@ -228,7 +242,7 @@ M.core_filepicker.init = function(Y, options) { scope.options.editor_target.value = data.existingfile.url; scope.options.editor_target.onchange(); } else if (scope.options.env === 'filepicker') { - var fileinfo = {'client_id':client_id, + var fileinfo = {'client_id':scope.options.client_id, 'url':data.existingfile.url, 'file':data.existingfile.filename}; scope.options.formcallback.apply(scope, [fileinfo]); @@ -236,12 +250,15 @@ M.core_filepicker.init = function(Y, options) { } }, true); } - var handleRename = function() { + var handleRename = function(e) { + // inserts file with the new name + e.preventDefault(); + var scope = this; + var data = this.process_dlg.dialogdata; if (scope.options.editor_target && scope.options.env == 'editor') { scope.options.editor_target.value = data.newfile.url; scope.options.editor_target.onchange(); } - this.cancel(); scope.hide(); var formcallback_scope = null; if (scope.options.magicscope) { @@ -249,85 +266,92 @@ M.core_filepicker.init = function(Y, options) { } else { formcallback_scope = scope; } - var fileinfo = {'client_id':client_id, + var fileinfo = {'client_id':scope.options.client_id, 'url':data.newfile.url, 'file':data.newfile.filename}; scope.options.formcallback.apply(formcallback_scope, [fileinfo]); } - var handleCancel = function() { + var handleCancel = function(e) { // Delete tmp file - var dialog = this; + e.preventDefault(); var params = {}; - params['newfilename'] = data.newfile.filename; - params['newfilepath'] = data.newfile.filepath; - scope.request({ + params['newfilename'] = this.process_dlg.dialogdata.newfile.filename; + params['newfilepath'] = this.process_dlg.dialogdata.newfile.filepath; + this.request({ 'params': params, - 'scope': scope, + 'scope': this, 'action':'deletetmpfile', 'path': '', - 'client_id': client_id, - 'repository_id': repository_id, + 'client_id': this.options.client_id, + 'repository_id': this.active_repo.id, 'callback': function(id, o, args) { - scope.hide(); - dialog.cancel(); + // let it be in background, from user point of view nothing is happenning } - }, true); + }, false); + this.process_dlg.hide(); + this.selectui.hide(); } - var dialog = new YAHOO.widget.SimpleDialog("dlg", { - width: "50em", - fixedcenter: true, - close: false, - icon: YAHOO.widget.SimpleDialog.ICON_HELP, - visible: true, - zIndex: 9999993, - draggable: true, - buttons: [{ text: M.str.repository.overwrite, handler: handleOverwrite }, - { text: M.str.repository.renameto + ' "' + data.newfile.filename + '"', handler: handleRename }, - { text: M.str.moodle.cancel, handler: handleCancel, isDefault: true}] - }); - dialog.setHeader(M.str.repository.fileexistsdialogheader); - if (scope.options.env == 'editor') { - dialog.setBody(M.str.repository.fileexistsdialog_editor); - } else { - dialog.setBody(M.str.repository.fileexistsdialog_filemanager); + if (!this.process_dlg) { + var node = Y.Node.create(M.core_filepicker.templates.processexistingfile); + this.fpnode.appendChild(node); + this.process_dlg = new Y.Panel({ + srcNode : node, + headerContent: M.str.repository.fileexistsdialogheader, + zIndex : 800000, + centered : true, + modal : true, + visible : false, + render : true, + buttons : {} + }); + node.one('.fp-dlg-butoverwrite').on('click', handleOverwrite, this); + node.one('.fp-dlg-butrename').on('click', handleRename, this); + node.one('.fp-dlg-butcancel').on('click', handleCancel, this); + if (this.options.env == 'editor') { + node.one('.fp-dlg-text').setContent(M.str.repository.fileexistsdialog_editor); + } else { + node.one('.fp-dlg-text').setContent(M.str.repository.fileexistsdialog_filemanager); + } } - - dialog.render(document.body); - dialog.show(); + this.process_dlg.dialogdata = data; + this.fpnode.one('.fp-dlg .fp-dlg-butrename').setContent(M.util.get_string('renameto', 'repository', data.newfile.filename)); + this.process_dlg.show(); }, + /** displays error instead of filepicker contents */ + display_error: function(errortext, errorcode) { + this.fpnode.one('.fp-content').setContent(M.core_filepicker.templates.error); + this.fpnode.one('.fp-content .fp-error'). + addClass(errorcode). + setContent(errortext); + }, + /** displays message in a popup */ print_msg: function(msg, type) { - var client_id = this.options.client_id; - var dlg_id = 'fp-msg-dlg-'+client_id; - function handleYes() { - this.hide(); - } - var icon = YAHOO.widget.SimpleDialog.ICON_INFO; - if (type=='error') { - icon = YAHOO.widget.SimpleDialog.ICON_ALARM; + var header = M.str.moodle.error; + if (type != 'error') { + type = 'info'; // one of only two types excepted + header = M.str.moodle.info; } if (!this.msg_dlg) { - this.msg_dlg = new YAHOO.widget.SimpleDialog(dlg_id, - { width: "300px", - fixedcenter: true, - visible: true, - draggable: true, - close: true, - text: msg, - modal: false, - icon: icon, - zindex: 9999992, - constraintoviewport: true, - buttons: [{ text:M.str.moodle.ok, handler:handleYes, isDefault:true }] - }); - this.msg_dlg.render(document.body); - } else { - this.msg_dlg.setBody(msg); + var node = Y.Node.create(M.core_filepicker.templates.message); + this.fpnode.appendChild(node); + + this.msg_dlg = new Y.Panel({ + srcNode : node, + zIndex : 800000, + centered : true, + modal : true, + visible : false, + render : true + }); + node.one('.fp-msg-butok').on('click', function(e) { + e.preventDefault(); + this.msg_dlg.hide(); + }, this); } - var header = M.str.moodle.info; - if (type=='error') { - header = M.str.moodle.error; - } - this.msg_dlg.setHeader(header); + + this.msg_dlg.set('headerContent', header); + this.fpnode.one('.fp-msg').removeClass('fp-msg-info').removeClass('fp-msg-error').addClass('fp-msg-'+type) + this.fpnode.one('.fp-msg .fp-msg-text').setContent(msg); this.msg_dlg.show(); }, build_tree: function(node, level) { @@ -335,7 +359,6 @@ M.core_filepicker.init = function(Y, options) { var dynload = this.active_repo.dynload; var info = { label:node.title, - //title:fp_lang.date+' '+node.date+fp_lang.size+' '+node.size, filename:node.title, source:node.source?node.source:'', thumbnail:node.thumbnail, @@ -374,7 +397,7 @@ M.core_filepicker.init = function(Y, options) { // it is not working well with search result this.view_as_icons(); } else { - this.viewbar.set('disabled', false); + this.viewbar_set_enabled(true); if (this.viewmode == 1) { this.view_as_icons(); } else if (this.viewmode == 2) { @@ -396,7 +419,7 @@ M.core_filepicker.init = function(Y, options) { page:node.page?args.page:'', callback: function(id, obj, args) { var list = obj.list; - scope.viewbar.set('disabled', false); + scope.viewbar_set_enabled(true); scope.parse_repository_options(obj); for(k in list) { scope.build_tree(list[k], node); @@ -406,27 +429,20 @@ M.core_filepicker.init = function(Y, options) { }, false); }, view_as_list: function() { + // TODO !!!!!!!!!! var scope = this; var client_id = scope.options.client_id; var dynload = scope.active_repo.dynload; var list = this.filelist; - var panel_id = '#panel-'+client_id; scope.viewmode = 2; - Y.one(panel_id).set('innerHTML', ''); - scope.print_header(); - - var html = '
                            '; if (list && list.length==0) { - html += '
                            ' +M.str.repository.nofilesavailable+'
                            '; - } - html += '
                            '; - - var tree = Y.Node.create(html); - Y.one(panel_id).appendChild(tree); - if (!list || list.length==0) { + this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable'); return; } + var html = '
                            '; + this.fpnode.one('.fp-content').setContent(html); + scope.treeview = new YAHOO.widget.TreeView('treeview-'+client_id); if (dynload) { scope.treeview.setDynamicLoad(scope.treeview_dynload, 1); @@ -450,76 +466,64 @@ M.core_filepicker.init = function(Y, options) { var scope = this; var client_id = this.options.client_id; var list = this.filelist; - var panel_id = '#panel-'+client_id; this.viewmode = 1; - Y.one(panel_id).set('innerHTML', ''); - this.print_header(); - - var html = '
                            '; if (list && list.length==0) { - html += '
                            ' +M.str.repository.nofilesavailable+'
                            '; + this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable'); + return; } - html += '
                            '; + this.fpnode.one('.fp-content').setContent(M.core_filepicker.templates.iconview); - var gridpanel = Y.Node.create(html); - Y.one('#panel-'+client_id).appendChild(gridpanel); + var element_template = this.fpnode.one('.fp-content').one('.fp-file'); + var container = element_template.get('parentNode'); + container.removeChild(element_template); var count = 0; for(var k in list) { var node = list[k]; - var grid = document.createElement('DIV'); - grid.className='fp-grid'; - // the file name - var title = document.createElement('DIV'); - title.id = 'grid-title-'+client_id+'-'+String(count); - title.className = 'label'; - var filename = node.title; - if (node.shorttitle) { - filename = node.shorttitle; + var element = element_template.cloneNode(true); + container.appendChild(element); + /*html = M.core_filepicker.templates.gridelementtemplate. + replace(/\{GRIDELEMENTID\}/g, 'fp-grid-'+client_id+'-'+count). + replace(/\{IMGID\}/g, 'fp-img-'+client_id+'-'+count). + replace(/\{FILENAMEID\}/g, 'fp-filename-'+client_id+'-'+count);*/ + var filename = node.shorttitle ? node.shorttitle : node.title; + var filenamediv = element.one('.fp-filename'); + filenamediv.setContent(filename); + var imgdiv = element.one('.fp-thumbnail'); + var set_width = function(node, width) { + var widthmatches = node.getStyle('minWidth').match(/^(\d+)px$/) + if (widthmatches && parseInt(widthmatches[1])>width) { + width = parseInt(widthmatches[1]); + } + node.setStyle('width', '' + width + 'px') } - var filename_id = 'filname-link-'+client_id+'-'+String(count); - title.innerHTML += ''+filename+""; - - - if(node.thumbnail_width){ - grid.style.width = node.thumbnail_width+'px'; - title.style.width = (node.thumbnail_width-10)+'px'; - } else { - grid.style.width = title.style.width = '90px'; + var set_height = function(node, height) { + var heightmatches = node.getStyle('minHeight').match(/^(\d+)px$/) + if (heightmatches && parseInt(heightmatches[1])>height) { + height = parseInt(heightmatches[1]); + } + node.setStyle('height', '' + height + 'px') } - var frame = document.createElement('DIV'); - frame.style.textAlign='center'; - if(node.thumbnail_height){ - frame.style.height = node.thumbnail_height+'px'; - } - var img = document.createElement('img'); - img.src = node.thumbnail; - img.title = node.title; + var width = node.thumbnail_width ? node.thumbnail_width : 90; + var height = node.thumbnail_height ? node.thumbnail_height : 90; + set_width(filenamediv, width) + set_width(imgdiv, width) + set_height(imgdiv, height); + var img = Y.Node.create(''). + set('src', node.thumbnail). + set('title', node.title); if(node.thumbnail_alt) { - img.alt = node.thumbnail_alt; + img.set('alt', node.thumbnail_alt); } if(node.thumbnail_title) { - img.title = node.thumbnail_title; + img.set('title', node.thumbnail_title); } + img.setStyle('maxWidth', ''+width+'px').setStyle('maxHeight', ''+height+'px'); + imgdiv.appendChild(img) - var link = document.createElement('A'); - link.href='###'; - link.id = 'img-id-'+client_id+'-'+String(count); - if(node.url) { - // hide - //grid.innerHTML += '

                            '+M.str.repository.preview+'

                            '; - } - link.appendChild(img); - frame.appendChild(link); - grid.appendChild(frame); - grid.appendChild(title); - gridpanel.appendChild(grid); - - var y_title = Y.one('#'+title.id); - var y_file = Y.one('#'+link.id); var dynload = this.active_repo.dynload; if(node.children) { - y_file.on('click', function(e, p) { + element.on('click', function(e, p) { e.preventDefault(); if(dynload) { var params = {'path':p.path}; @@ -529,11 +533,6 @@ M.core_filepicker.init = function(Y, options) { this.view_files(); } }, this, node); - y_title.on('click', function(e, p, id){ - e.preventDefault(); - var icon = Y.one(id); - icon.simulate('click'); - }, this, node, '#'+link.id); } else { var fileinfo = {}; fileinfo['title'] = list[k].title; @@ -541,11 +540,7 @@ M.core_filepicker.init = function(Y, options) { fileinfo['thumbnail'] = list[k].thumbnail; fileinfo['haslicense'] = list[k].haslicense?true:false; fileinfo['hasauthor'] = list[k].hasauthor?true:false; - y_title.on('click', function(e, args) { - e.preventDefault(); - this.select_file(args); - }, this, fileinfo); - y_file.on('click', function(e, args) { + element.on('click', function(e, args) { e.preventDefault(); this.select_file(args); }, this, fileinfo); @@ -554,95 +549,67 @@ M.core_filepicker.init = function(Y, options) { } }, select_file: function(args) { + this.selectui.show(); var client_id = this.options.client_id; - var thumbnail = Y.one('#fp-grid-panel-'+client_id); - if(thumbnail){ - thumbnail.setStyle('display', 'none'); - } - var header = Y.one('#fp-header-'+client_id); - if (header) { - header.setStyle('display', 'none'); - } - var footer = Y.one('#fp-footer-'+client_id); - if (footer) { - footer.setStyle('display', 'none'); - } - var path = Y.one('#path-'+client_id); - if(path){ - path.setStyle('display', 'none'); - } - var panel = Y.one('#panel-'+client_id); - var form_id = 'fp-rename-form-'+client_id; - var html = '
                            '; - html += '

                            '; - html += '
                            '+M.str.repository.linkexternal+'
                            '+M.str.repository.linkexternal+'
                            '+M.str.repository.uselatestfile+'
                            '+M.str.repository.linkexternal+'
                            '+M.str.repository.uselatestfile+'
                            '+M.str.repository.linkexternal+'
                            '; - html += ''; - html += ''; + var selectnode = this.fpnode.one('.fp-select'); + selectnode.one('#newname-'+client_id).set('value', args.title); + selectnode.one('#text-author-'+client_id).set('value', this.options.author); - var le_checked = ''; - var le_style = ''; - if (this.options.repositories[this.active_repo.id].return_types == 1) { - // support external links only - le_checked = 'checked'; - le_style = ' style="display:none;"'; - } else if(this.options.repositories[this.active_repo.id].return_types == 2) { - // support internal files only - le_style = ' style="display:none;"'; - } + var imgnode = Y.Node.create('').set('src', args.thumbnail) + selectnode.one('#img-'+client_id).setContent('').appendChild(imgnode); + + selectnode.one('#linkexternal-'+client_id).set('checked', ''); // default to unchecked if ((this.options.externallink && this.options.env == 'editor' && this.options.return_types != 1)) { - html += ''; + // enable checkbox 'Link external' + selectnode.one('#linkexternal-'+client_id).set('disabled', ''); + selectnode.all('#linkexternal-'+client_id+',#wrap-linkexternal-'+client_id).removeClass('uneditable') + } else { + // disable checkbox 'Link external' + selectnode.one('#linkexternal-'+client_id).set('disabled', 'disabled'); + selectnode.all('#linkexternal-'+client_id+',#wrap-linkexternal-'+client_id).addClass('uneditable') + if (this.options.return_types == 1) { + // support external links only + selectnode.one('#linkexternal-'+client_id).set('checked', 'checked'); + } } - if (!args.hasauthor) { - // the author of the file - html += ''; - html += ''; - html += ''; + if (args.hasauthor) { + selectnode.one('#text-author-'+client_id).set('disabled', 'disabled'); + selectnode.all('#text-author-'+client_id+',#wrap-text-author-'+client_id).addClass('uneditable') + } else { + selectnode.one('#text-author-'+client_id).set('disabled', ''); + selectnode.all('#text-author-'+client_id+',#wrap-text-author-'+client_id).removeClass('uneditable') } if (!args.haslicense) { // the license of the file - var licenses = this.options.licenses; - html += ''; - html += ''; + this.populate_licenses_select(selectnode.one('#select-license-'+client_id)); + selectnode.one('#wrap-select-license-'+client_id).set('disabled', ''); + selectnode.all('#select-license-'+client_id+'#wrap-select-license-'+client_id).removeClass('uneditable'); + } else { + selectnode.one('#wrap-select-license-'+client_id).set('disabled', 'disabled'); + selectnode.all('#select-license-'+client_id+'#wrap-select-license-'+client_id).addClass('uneditable'); } - html += '
                            '+M.str.repository.linkexternal+'
                            '; - - html += '

                            '; - html += ''; - html += '

                            '; - html += '
                          '; - - var getfile_form = Y.Node.create(html); - panel.appendChild(getfile_form); - - var getfile = Y.one('#fp-confirm-'+client_id); + selectnode.one('form #filesource-'+client_id).set('value', args.source); + }, + setup_select_file: function() { + var client_id = this.options.client_id; + var selectnode = this.fpnode.one('.fp-select'); + var getfile = selectnode.one('#fp-confirm-'+client_id); getfile.on('click', function(e) { + e.preventDefault(); var client_id = this.options.client_id; var scope = this; var repository_id = this.active_repo.id; - var title = Y.one('#newname-'+client_id).get('value'); - var filesource = Y.one('#filesource-'+client_id).get('value'); + var title = selectnode.one('#newname-'+client_id).get('value'); + var filesource = selectnode.one('form #filesource-'+client_id).get('value'); var params = {'title':title, 'source':filesource, 'savepath': this.options.savepath}; - var license = Y.one('#select-license-'+client_id); + var license = selectnode.one('#select-license-'+client_id); if (license) { params['license'] = license.get('value'); - YAHOO.util.Cookie.set('recentlicense', license.get('value')); + Y.Cookie.set('recentlicense', license.get('value')); } - var author = Y.one('#text-author-'+client_id); + var author = selectnode.one('#text-author-'+client_id); if (author){ params['author'] = author.get('value'); } @@ -652,7 +619,7 @@ M.core_filepicker.init = function(Y, options) { params.savepath = '/'; // when image or media button is clicked if ( this.options.return_types != 1 ) { - var linkexternal = Y.one('#linkexternal-'+client_id); + var linkexternal = selectnode.one('#linkexternal-'+client_id); if (linkexternal && linkexternal.get('checked')) { params['linkexternal'] = 'yes'; } @@ -666,14 +633,14 @@ M.core_filepicker.init = function(Y, options) { params['linkexternal'] = 'yes'; } - this.wait('download', title); + // TODO show some waiting process here this.request({ action:'download', client_id: client_id, repository_id: repository_id, 'params': params, onerror: function(id, obj, args) { - scope.view_files(); + scope.selectui.hide(); }, callback: function(id, obj, args) { if (scope.options.editor_target && scope.options.env=='editor') { @@ -690,141 +657,152 @@ M.core_filepicker.init = function(Y, options) { } scope.options.formcallback.apply(formcallback_scope, [obj]); } - }, true); + }, false); }, this); - var elform = Y.one('#'+form_id); + var elform = selectnode.one('form'); + elform.appendChild(Y.Node.create('').set('id', 'filesource-'+client_id)); elform.on('keydown', function(e) { if (e.keyCode == 13) { getfile.simulate('click'); e.preventDefault(); } }, this); - var cancel = Y.one('#fp-cancel-'+client_id); + var cancel = selectnode.one('#fp-cancel-'+client_id); cancel.on('click', function(e) { - this.view_files(); + e.preventDefault(); + this.selectui.hide(); }, this); - var treeview = Y.one('#treeview-'+client_id); - if (treeview){ - treeview.setStyle('display', 'none'); - } }, - wait: function(type) { - var panel = Y.one('#panel-'+this.options.client_id); - panel.set('innerHTML', ''); - var name = ''; - var str = '
                          '; - if(type=='load') { - str += ''; - str += '

                          '+M.str.repository.loading+'

                          '; - }else{ - str += ''; - str += '

                          '+M.str.repository.copying+' '+name+'

                          '; + wait: function() { + this.fpnode.one('.fp-content').setContent(M.core_filepicker.templates.loading); + }, + viewbar_set_enabled: function(mode) { + var viewbar = this.fpnode.one('.fp-viewbar') + if (viewbar) { + if (mode) { + viewbar.addClass('enabled').removeClass('disabled') + } else { + viewbar.removeClass('enabled').addClass('disabled') + } } - str += '
                          '; - try { - panel.set('innerHTML', str); - } catch(e) { - alert(e.toString()); + this.fpnode.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').removeClass('checked') + var modes = {1:'icons', 2:'tree', 3:'details'}; + this.fpnode.all('.fp-vb-'+modes[this.viewmode]).addClass('checked'); + }, + viewbar_clicked: function(e) { + e.preventDefault(); + var viewbar = this.fpnode.one('.fp-viewbar') + if (!viewbar || !viewbar.hasClass('disabled')) { + if (e.currentTarget.hasClass('fp-vb-tree')) { + this.viewmode = 2; + } else if (e.currentTarget.hasClass('fp-vb-details')) { + this.viewmode = 3; + } else { + this.viewmode = 1; + } + this.viewbar_set_enabled(true) + this.view_files(); + Y.Cookie.set('recentviewmode', this.viewmode); } }, render: function() { var client_id = this.options.client_id; - var scope = this; - var filepicker_id = 'filepicker-'+client_id; - var fpnode = Y.Node.create('
                          '); - Y.one(document.body).appendChild(fpnode); - // render file picker panel - this.mainui = new YAHOO.widget.Panel(filepicker_id, { - draggable: true, - close: true, - underlay: 'none', - zindex: 9999990, - monitorresize: false, - xy: [50, YAHOO.util.Dom.getDocumentScrollTop()+20] + var nodecontent = M.core_filepicker.templates.generallayout. + replace(/\{TOOLBARID}/g, 'fp-tb-'+client_id). + replace(/\{TOOLBACKID}/g, 'fp-tb-back-'+client_id). + replace(/\{TOOLSEARCHID}/g, 'fp-tb-search-'+client_id). + replace(/\{TOOLREFRESHID}/g, 'fp-tb-refresh-'+client_id). + replace(/\{TOOLLOGOUTID}/g, 'fp-tb-logout-'+client_id). + replace(/\{TOOLMANAGEID}/g, 'fp-tb-manage-'+client_id). + replace(/\{TOOLHELPID}/g, 'fp-tb-help-'+client_id); + this.fpnode = Y.Node.create(nodecontent); + this.fpnode.set('id', 'filepicker-'+client_id); + var fpselectnode = Y.Node.create(M.core_filepicker.templates.selectlayout. + replace(/\{IMGID}/g, 'img-'+client_id). + replace(/\{NEWNAMEID}/g, 'newname-'+client_id). + replace(/\{LINKEXTID}/g, 'linkexternal-'+client_id). + replace(/\{AUTHORID}/g, 'text-author-'+client_id). + replace(/\{LICENSEID}/g, 'select-license-'+client_id). + replace(/\{BUTCONFIRMID}/g, 'fp-confirm-'+client_id). + replace(/\{BUTCANCELID}/g, 'fp-cancel-'+client_id) + ); + Y.one(document.body).appendChild(this.fpnode); + this.fpnode.appendChild(fpselectnode); + this.mainui = new Y.Panel({ + srcNode : this.fpnode, + headerContent: M.str.repository.filepicker, + zIndex : 500000, + centered : true, + modal : true, + visible : false, + render : true, + plugins : [Y.Plugin.Drag] }); - var layout = null; - this.mainui.beforeRenderEvent.subscribe(function() { - YAHOO.util.Event.onAvailable('layout-'+client_id, function() { - layout = new YAHOO.widget.Layout('layout-'+client_id, { - height: 480, width: 700, - units: [ - {position: 'top', height: 32, resize: false, - body:'
                          ', gutter: '2'}, - {position: 'left', width: 200, resize: true, scroll:true, - body:'
                            ', gutter: '0 5 0 2', minWidth: 150, maxWidth: 300 }, - {position: 'center', body: '
                            ', - scroll: true, gutter: '0 2 0 0' } - ] - }); - layout.render(); - scope.show_recent_repository(); - }); + this.mainui.show(); + this.selectui = new Y.Panel({ + srcNode : fpselectnode, + zIndex : 600000, + centered : true, + modal : true, + close : true, + render : true }); + this.selectui.hide(); + // save template for one path element and location of path bar + if (this.fpnode.one('.fp-path-folder')) { + this.pathnode = this.fpnode.one('.fp-path-folder'); + this.pathbar = this.pathnode.get('parentNode'); + this.pathbar.removeChild(this.pathnode); + } + // assign callbacks for view mode switch buttons + this.fpnode.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details'). + on('click', this.viewbar_clicked, this); + // assign callbacks for toolbar links + this.setup_toolbar(); + this.setup_select_file(); - this.mainui.setHeader(M.str.repository.filepicker); - this.mainui.setBody('
                            '); - this.mainui.render(); - this.rendered = true; - - var scope = this; - // adding buttons - var view_icons = {label: M.str.repository.iconview, value: 't', 'checked': true, - onclick: { - fn: function(e){ - e.preventDefault(); - scope.viewmode = 1; - scope.view_files(); - } - } - }; - var view_listing = {label: M.str.repository.listview, value: 'l', - onclick: { - fn: function(e){ - e.preventDefault(); - scope.viewmode = 2; - scope.view_files(); - } - } - }; - this.viewbar = new YAHOO.widget.ButtonGroup({ - id: 'btngroup-'+client_id, - name: 'buttons', - disabled: true, - container: 'fp-viewbar-'+client_id - }); - this.viewbar.addButtons([view_icons, view_listing]); // processing repository listing - var r = this.options.repositories; - Y.on('contentready', function(el) { - var list = Y.one(el); - var count = 0; - // Resort the repositories by sortorder - var sorted_repositories = new Array(); - for (var i in r) { - sorted_repositories[r[i].sortorder - 1] = r[i]; + // Resort the repositories by sortorder + var sorted_repositories = [] + for (var i in this.options.repositories) { + sorted_repositories[i] = this.options.repositories[i] + } + sorted_repositories.sort(function(a,b){return a.sortorder-b.sortorder}) + // extract one repository template and repeat it for all repositories available, + // set name and icon and assign callbacks + var reponode = this.fpnode.one('.fp-repo'); + if (reponode) { + var list = reponode.get('parentNode'); + list.removeChild(reponode); + for (i in sorted_repositories) { + var repository = sorted_repositories[i] + var node = reponode.cloneNode(true); + list.appendChild(node); + node. + set('id', 'fp-repo-'+client_id+'-'+repository.id). + on('click', function(e, repository_id) { + e.preventDefault(); + Y.Cookie.set('recentrepository', repository_id); + this.hide_header(); + this.list({'repo_id':repository_id}); + }, this /*handler running scope*/, repository.id/*second argument of handler*/); + node.one('.fp-repo-name').setContent(repository.name) + node.one('.fp-repo-icon').set('src', repository.icon) + if (i==0) {node.addClass('first');} + if (i==sorted_repositories.length-1) {node.addClass('last');} + if (i%2) {node.addClass('even');} else {node.addClass('odd');} } - for (var i in sorted_repositories){ - repository = sorted_repositories[i]; - var id = 'repository-'+client_id+'-'+repository.id; - var link_id = id + '-link'; - list.append('
                          • '+repository.name+'
                          • '); - Y.one('#'+link_id).prepend(' '); - Y.one('#'+link_id).on('click', function(e, scope, repository_id) { - e.preventDefault(); - YAHOO.util.Cookie.set('recentrepository', repository_id); - scope.repository_id = repository_id; - this.list({'repo_id':repository_id}); - }, this /*handler running scope*/, this/*second argument*/, repository.id/*third argument of handler*/); - count++; + } + // display error if no repositories found + if (sorted_repositories.length==0) { + if (this.options.externallink) { + list.set('innerHTML', M.str.repository.norepositoriesexternalavailable); // TODO as error + } else { + list.set('innerHTML', M.str.repository.norepositoriesavailable); // TODO as error } - if (count==0) { - if (this.options.externallink) { - list.set('innerHTML', M.str.repository.norepositoriesexternalavailable); - } else { - list.set('innerHTML', M.str.repository.norepositoriesavailable); - } - } - }, '#fp-list-'+client_id, this /* handler running scope */, '#fp-list-'+client_id /*first argument of handler*/); + } + // display repository that was used last time + this.show_recent_repository(); }, parse_repository_options: function(data) { this.filelist = data.list?data.list:null; @@ -835,20 +813,22 @@ M.core_filepicker.init = function(Y, options) { this.active_repo.pages = Number(data.pages?data.pages:null); this.active_repo.page = Number(data.page?data.page:null); this.active_repo.id = data.repo_id?data.repo_id:null; - this.active_repo.nosearch = data.nosearch?true:false; - this.active_repo.norefresh = data.norefresh?true:false; - this.active_repo.nologin = data.nologin?true:false; + this.active_repo.nosearch = (data.login || data.nosearch); // this is either login form or 'nosearch' attribute set + this.active_repo.norefresh = (data.login || data.norefresh); // this is either login form or 'norefresh' attribute set + this.active_repo.nologin = (data.login || data.nologin); // this is either login form or 'nologin' attribute is set this.active_repo.logouttext = data.logouttext?data.logouttext:null; this.active_repo.help = data.help?data.help:null; this.active_repo.manage = data.manage?data.manage:null; + this.print_header(); }, print_login: function(data) { + // TODO !!!! this.parse_repository_options(data); var client_id = this.options.client_id; var repository_id = data.repo_id; var l = this.logindata = data.login; var loginurl = ''; - var panel = Y.one('#panel-'+client_id); + var panel = this.fpnode.one('.fp-content'); var action = 'login'; if (data['login_btn_action']) { action=data['login_btn_action']; @@ -970,6 +950,7 @@ M.core_filepicker.init = function(Y, options) { } } // start ajax request + this.hide_header(); this.request({ 'params': params, 'scope': scope, @@ -1005,6 +986,7 @@ M.core_filepicker.init = function(Y, options) { } } } + this.hide_header(); this.request({ scope: scope, action:'search', @@ -1048,23 +1030,20 @@ M.core_filepicker.init = function(Y, options) { display_response: function(id, obj, args) { var scope = args.scope // highlight the current repository in repositories list - Y.all('#fp-list-'+scope.options.client_id+' li a').setStyle('backgroundColor', 'transparent'); - var el = Y.one('#repository-'+scope.options.client_id+'-'+obj.repo_id+'-link'); - if (el) { - el.setStyle('backgroundColor', '#AACCEE'); - } + scope.fpnode.all('.fp-repo.active').removeClass('active'); + scope.fpnode.all('#fp-repo-'+scope.options.client_id+'-'+obj.repo_id).addClass('active') // display response if (obj.login) { - scope.viewbar.set('disabled', true); + scope.viewbar_set_enabled(false); scope.print_login(obj); } else if (obj.upload) { - scope.viewbar.set('disabled', true); + scope.viewbar_set_enabled(false); scope.parse_repository_options(obj); scope.create_upload_form(obj); } else if (obj.iframe) { } else if (obj.list) { - scope.viewbar.set('disabled', false); + scope.viewbar_set_enabled(true); scope.parse_repository_options(obj); scope.view_files(); } @@ -1086,63 +1065,58 @@ M.core_filepicker.init = function(Y, options) { callback: this.display_response }, true); }, - create_upload_form: function(data) { - var client_id = this.options.client_id; - Y.one('#panel-'+client_id).set('innerHTML', ''); - var types = this.options.accepted_types; - - this.print_header(); - var id = data.upload.id+'_'+client_id; - var str = '
                            '; - str += '
                            '; - str += ''; - str += ''; - str += ''; - str += ''; - str += ''; - for (var i in types) { - str += ''; + populate_licenses_select: function(node) { + if (!node) { + return; } - str += ''; - str += ''; - str += ''; - str += ''; - str += ''; - str += ''; - str += ''; - str += '
                            '; - str += ''; - str += '
                            '+M.str.repository.chooselicense+': '; + node.setContent(''); var licenses = this.options.licenses; - str += ''; - str += '
                            '; - str += '
                            '; - str += '
                            '; - str += '
                            '; - var upload_form = Y.Node.create(str); - Y.one('#panel-'+client_id).appendChild(upload_form); + }, + create_upload_form: function(data) { + var client_id = this.options.client_id; + var id = data.upload.id+'_'+client_id; + var str = M.core_filepicker.templates.uploadform. + replace(/\{UPLOADFORMID}/g, id). + replace(/\{INPUTFILEID}/g, id+'_file'). + replace(/\{NEWNAMEID}/g, 'newname-'+client_id). + replace(/\{AUTHORID}/g, 'author-'+client_id). + replace(/\{LICENSEID}/g, 'license-'+client_id). + replace(/\{BUTUPLOADID}/g, id+'_action'); + this.fpnode.one('.fp-content').setContent(str); + + Y.all('#'+id+'_file').set('name', 'repo_upload_file'); + Y.all('#'+'newname-'+client_id).set('name', 'title'); + Y.all('#'+'author-'+client_id).set('name', 'author'); + Y.all('#'+'author-'+client_id).set('value', this.options.author); + Y.all('#'+'license-'+client_id).set('name', 'license'); + this.populate_licenses_select(Y.one('#'+'license-'+client_id)) + Y.one('#'+id).append(''); // TODO nicer! + var types = this.options.accepted_types; + for (var i in types) { + Y.one('#'+id).append(''); // TODO nicer! + } + var scope = this; Y.one('#'+id+'_action').on('click', function(e) { e.preventDefault(); - var license = Y.one('#select-license-'+client_id).get('value'); - YAHOO.util.Cookie.set('recentlicense', license); + var license = Y.one('#license-'+client_id); + Y.Cookie.set('recentlicense', license.get('value')); if (!Y.one('#'+id+'_file').get('value')) { scope.print_msg(M.str.repository.nofilesattached, 'error'); return false; } + this.hide_header(); scope.request({ scope: scope, action:'upload', @@ -1171,149 +1145,123 @@ M.core_filepicker.init = function(Y, options) { }, true); }, this); }, + /** setting handlers and labels for elements in toolbar. Called once during the initial render of filepicker */ + setup_toolbar: function() { + var client_id = this.options.client_id; + Y.one('#fp-tb-logout-'+client_id).on('click', function(e) { + e.preventDefault(); + if (!this.active_repo.nologin) { + this.hide_header(); + this.request({ + action:'logout', + client_id: this.options.client_id, + repository_id: this.active_repo.id, + path:'', + callback: this.display_response + }, true); + } + }, this); + Y.one('#fp-tb-refresh-'+client_id).on('click', function(e) { + e.preventDefault(); + if (!this.active_repo.norefresh) { + this.list(); + } + }, this); + Y.one('#fp-tb-search-'+client_id). + set('method', 'POST'). + on('submit', function(e) { + e.preventDefault(); + if (!this.active_repo.nosearch) { + this.request({ + scope: this, + action:'search', + client_id: this.options.client_id, + repository_id: this.active_repo.id, + form: {id: 'fp-tb-search-'+client_id, upload:false, useDisabled:true}, + callback: this.display_response + }, true); + } + }, this); + + // it does not matter what kind of element is {TOOLMANAGEID}, we create a dummy + // element and use it to open url on click event + var managelnk = Y.Node.create(''); + managelnk.set('id', 'fp-tb-manage-'+client_id+'-link').set('target', '_blank').setStyle('display', 'none'); + Y.one('#fp-tb-'+client_id).append(managelnk); + Y.one('#fp-tb-manage-'+client_id).on('click', function(e) { + e.preventDefault(); + managelnk.simulate('click') + }); + + // same with {TOOLHELPID} + var helplnk = Y.Node.create(''); + helplnk.set('id', 'fp-tb-help-'+client_id+'-link').set('target', '_blank').setStyle('display', 'none'); + Y.one('#fp-tb-'+client_id).append(helplnk); + Y.one('#fp-tb-help-'+client_id).on('click', function(e) { + e.preventDefault(); + helplnk.simulate('click') + }); + }, + hide_header: function() { + var client_id = this.options.client_id; + if (Y.one('#fp-tb-'+client_id)) { + Y.one('#fp-tb-'+client_id).addClass('empty'); + } + }, print_header: function() { var r = this.active_repo; var scope = this; var client_id = this.options.client_id; - var repository_id = this.active_repo.id; - var panel = Y.one('#panel-'+client_id); - var str = '
                            '; - str += '
                            '; - str += '
                            '; - var head = Y.Node.create(str); - panel.appendChild(head); - //if(this.active_repo.pages < 8){ - this.print_paging('header'); - //} + this.print_paging(); - var toolbar = Y.one('#repo-tb-'+client_id); + this.hide_header(); + var enable_tb_control = function(elementid, enabled) { + if (!enabled) { + Y.all('#'+elementid+',#wrap-'+elementid).addClass('disabled').removeClass('enabled') + } else { + Y.all('#'+elementid+',#wrap-'+elementid).removeClass('disabled').addClass('enabled') + Y.one('#fp-tb-'+client_id).removeClass('empty'); + } + } + // TODO 'back' permanently disabled for now. Note, flickr_public uses 'Logout' for it! + enable_tb_control('fp-tb-back-'+client_id, false); + + // search form + enable_tb_control('fp-tb-search-'+client_id, !r.nosearch); if(!r.nosearch) { - var html = '
                            '+M.str.repository.search+''; - var search = Y.Node.create(html); - search.on('click', function(e) { - e.preventDefault(); - scope.request({ - scope: scope, - action:'searchform', - repository_id: repository_id, - callback: function(id, obj, args) { - var scope = args.scope; - var client_id = scope.options.client_id; - var repository_id = scope.active_repo.id; - var container = document.getElementById('fp-search-dlg'); - if(container) { - container.innerHTML = ''; - container.parentNode.removeChild(container); - } - var container = document.createElement('DIV'); - container.id = 'fp-search-dlg'; - - var dlg_title = document.createElement('DIV'); - dlg_title.className = 'hd'; - dlg_title.innerHTML = M.str.repository.search; - - var dlg_body = document.createElement('DIV'); - dlg_body.className = 'bd'; - - var sform = document.createElement('FORM'); - sform.method = 'POST'; - sform.id = "fp-search-form"; - sform.innerHTML = obj.form; - - dlg_body.appendChild(sform); - container.appendChild(dlg_title); - container.appendChild(dlg_body); - Y.one(document.body).appendChild(container); - var search_dialog= null; - function dialog_handler() { - scope.viewbar.set('disabled', false); - scope.request({ - scope: scope, - action:'search', - client_id: client_id, - repository_id: repository_id, - form: {id: 'fp-search-form',upload:false,useDisabled:true}, - callback: scope.display_response - }, true); - search_dialog.cancel(); - } - Y.one('#fp-search-form').on('keydown', function(e){ - if (e.keyCode == 13) { - dialog_handler(); - e.preventDefault(); - } - }, this); - - search_dialog = new YAHOO.widget.Dialog("fp-search-dlg", { - postmethod: 'async', - draggable: true, - width : "30em", - modal: true, - fixedcenter : true, - zindex: 9999991, - visible : false, - constraintoviewport : true, - buttons: [ - { - text:M.str.repository.submit, - handler:dialog_handler, - isDefault:true - }, { - text:M.str.moodle.cancel, - handler:function(){ - this.destroy() - } - }] - }); - search_dialog.render(); - search_dialog.show(); + Y.all('#fp-tb-search-'+client_id).setContent(''); + this.request({ + scope: this, + action:'searchform', + repository_id: this.active_repo.id, + callback: function(id, obj, args) { + if (obj.repo_id == scope.active_repo.id && obj.form) { + // if we did not jump to another repository meanwhile + Y.all('#fp-tb-search-'+scope.options.client_id).setContent(obj.form); } - }); - },this); - toolbar.appendChild(search); + } + }, false); } + + // refresh button // weather we use cache for this instance, this button will reload listing anyway - if(!r.norefresh) { - var html = ' '+M.str.repository.refresh+''; - var refresh = Y.Node.create(html); - refresh.on('click', function(e) { - e.preventDefault(); - this.list(); - }, this); - toolbar.appendChild(refresh); - } + enable_tb_control('fp-tb-refresh-'+client_id, !r.norefresh); + + // login button + enable_tb_control('fp-tb-logout-'+client_id, !r.nologin); if(!r.nologin) { var label = r.logouttext?r.logouttext:M.str.repository.logout; - var html = ' '+label+''; - var logout = Y.Node.create(html); - logout.on('click', function(e) { - e.preventDefault(); - this.request({ - action:'logout', - client_id: client_id, - repository_id: repository_id, - path:'', - callback: this.display_response - }, true); - }, this); - toolbar.appendChild(logout); + Y.one('#fp-tb-logout-'+client_id).setContent(label) } - if(r.manage) { - var mgr = document.createElement('A'); - mgr.href = r.manage; - mgr.target = "_blank"; - mgr.innerHTML = ' '+M.str.repository.manageurl; - toolbar.appendChild(mgr); - } - if(r.help) { - var help = document.createElement('A'); - help.href = r.help; - help.target = "_blank"; - help.innerHTML = ' '+M.str.repository.help; - toolbar.appendChild(help); - } + // manage url + enable_tb_control('fp-tb-manage-'+client_id, r.manage); + Y.one('#fp-tb-manage-'+client_id+'-link').set('href', r.manage); + + // help url + enable_tb_control('fp-tb-help-'+client_id, r.help); + Y.one('#fp-tb-help-'+client_id+'-link').set('href', r.help); this.print_path(); }, @@ -1327,6 +1275,7 @@ M.core_filepicker.init = function(Y, options) { return str; }, print_paging: function(html_id) { + // TODO !!! var client_id = this.options.client_id; var scope = this; var r = this.active_repo; @@ -1339,7 +1288,6 @@ M.core_filepicker.init = function(Y, options) { lastpagetext = M.str.moodle.next; } if (lastpage > 1) { - str += '
                            '; str += this.get_page_button(1)+'1 '; var span = 5; @@ -1379,17 +1327,11 @@ M.core_filepicker.init = function(Y, options) { str += this.get_page_button(max)+max+''; str += ' ... '+this.get_page_button(lastpage)+lastpagetext+''; } - str += '
                            '; } - if (str) { - var a = Y.Node.create(str); - Y.one('#fp-header-'+client_id).appendChild(a); - - Y.all('#fp-header-'+client_id+' .fp-paging a').each( - function(node, id) { - node.on('click', function(e) { + this.fpnode.one('.fp-paging').setContent(str); + this.fpnode.all('.fp-paging a').on('click', function(e) { e.preventDefault(); - var id = node.get('id'); + var id = e.currentTarget.get('id'); var re = new RegExp("repo-page-(\\d+)", "i"); var result = id.match(re); var args = {}; @@ -1408,39 +1350,44 @@ M.core_filepicker.init = function(Y, options) { scope.list(args); } }); - }); - } }, print_path: function() { - var client_id = this.options.client_id; - var panel = Y.one('#panel-'+client_id); + if (!this.pathbar) { return; } + this.pathbar.setContent(''); var p = this.filepath; if (p && p.length!=0) { - var path = Y.Node.create('
                            '); - panel.appendChild(path); for(var i = 0; i < p.length; i++) { - var link_path = p[i].path; - var link = document.createElement('A'); - link.href = "###"; - link.innerHTML = p[i].name; - link.id = 'path-node-'+client_id+'-'+i; - var sep = Y.Node.create('/'); - path.appendChild(link); - path.appendChild(sep); - Y.one('#'+link.id).on('click', function(e, path){ - e.preventDefault(); - this.list({'path':path}); - }, this, link_path) + var el = this.pathnode.cloneNode(true); + this.pathbar.appendChild(el); + if (i == 0) {el.addClass('first');} + if (i == p.length-1) {el.addClass('last');} + if (i%2) {el.addClass('even');} else {el.addClass('odd');} + el.all('.fp-path-folder-name').setContent(p[i].name); + el.on('click', + function(e, path) { + e.preventDefault(); + this.list({'path':path}); + }, + this, p[i].path); } + this.pathbar.removeClass('empty'); + } else { + this.pathbar.addClass('empty'); } }, hide: function() { + this.selectui.hide(); + if (this.process_dlg) { + this.process_dlg.hide(); + } + if (this.msg_dlg) { + this.msg_dlg.hide(); + } this.mainui.hide(); }, show: function() { - if (this.rendered) { - var panel = Y.one('#panel-'+this.options.client_id); - panel.set('innerHTML', ''); + if (this.fpnode) { + this.hide(); this.mainui.show(); this.show_recent_repository(); } else { @@ -1451,7 +1398,13 @@ M.core_filepicker.init = function(Y, options) { this.render(); }, show_recent_repository: function() { - var repository_id = YAHOO.util.Cookie.get('recentrepository'); + this.hide_header(); + this.viewbar_set_enabled(false); + var repository_id = Y.Cookie.get('recentrepository'); + this.viewmode = Y.Cookie.get('recentviewmode', Number); + if (this.viewmode != 1 && this.viewmode != 2 && this.viewmode != 3) { + this.viewmode = 1; + } if (this.options.repositories[repository_id]) { this.list({'repo_id':repository_id}); } diff --git a/repository/lib.php b/repository/lib.php index 274e7c1a6cd..85cfb10153f 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1827,12 +1827,9 @@ abstract class repository { * @return string */ public function print_search() { - $str = ''; - $str .= ''; - $str .= ''; - $str .= ''; - $str .= '

                            '; - return $str; + global $PAGE; + $renderer = $PAGE->get_renderer('core', 'repository'); + return $renderer->repository_default_searchform(); } /** @@ -2416,6 +2413,8 @@ function initialise_filepicker($args) { // JavaScript a lot, the key NEEDS to be the repository id. $return->repositories[$repository->id] = $meta; } + $fprenderer = $PAGE->get_renderer('core', 'repository'); + $return->templates = $fprenderer->filepicker_templates(); return $return; } /** diff --git a/repository/renderer.php b/repository/renderer.php new file mode 100644 index 00000000000..ab23689422e --- /dev/null +++ b/repository/renderer.php @@ -0,0 +1,309 @@ +. + +/** + * Renderer for filepicker and base repositories output. + * + * @package core_repository + * @copyright 2012 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +/** + * The core repository renderer + * + * Can be retrieved with the following: + * $renderer = $PAGE->get_renderer('core', 'repository'); + */ +class core_repository_renderer extends plugin_renderer_base { + + /** + * Template for FilePicker with general layout (not QuickUpload). + * + * Must have one top element containing everything else (recommended
                            ), + * CSS for this element must define width and height of the filepicker window; + * + * Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode + * can be changed or not; + * Inside element with class 'fp-viewbar' there are expected elements with classes + * 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch + * between the view modes, the last clicked element will have the class 'checked'; + * + * Element with class 'fp-repo' is a template for displaying one repository. Other repositories + * will be attached as siblings (classes first/last/even/odd will be added respectfully). + * The currently selected repostory will have class 'active'. Contents of element with class + * 'fp-repo-name' will be replaced with repository name, source of image with class + * 'fp-repo-icon' will be replaced with repository icon; + * + * Element with class 'fp-content' is obligatory and will hold the current contents; + * + * Element with class 'fp-paging' will contain page navigation (will be deprecated soon); + * + * Element with class 'fp-path-folder' will contain template for one folder in path toolbar. + * It will hold mouse click event and will be assigned classes first/last/even/odd respectfully. + * The content of element with class 'fp-path-folder-name' will be substituted with folder name; + * + * Element with id {TOOLBARID} will have class 'empty' if all 'Search', 'Login', 'Refresh' and + * 'Logout' are unavailable for this repo; + * Element with id {TOOLBACKID} will hold the click event for going back to Login form; + * Element (
                            !) with id {TOOLSEARCHID} is responsible for search inside the repo (if + * repository provides this functionality), it must have one input-text field; + * Element with id {TOOLREFRESHID} will hold the click event for refreshing current view; + * Element with id {TOOLLOGOUTID} will hold the click event for logout (the content of the + * element will be substituted with logout string provided by repository or default + * M.str.repository.logout if not specified); + * Element with id {TOOLMANAGEID} will hold the click event for opening new window to manage + * repository files; + * Element with id {TOOLHELPID} will hold the click event for opening new window for help; + * Elements with ids {TOOLBACKID}, {TOOLSEARCHID}, {TOOLREFRESHID}, {TOOLLOGOUTID}, + * {TOOLMANAGEID}, {TOOLHELPID} and also optional elements width ids wrap-{TOOLBACKID}, + * wrap-{TOOLSEARCHID}, wrap-{TOOLREFRESHID}, wrap-{TOOLLOGOUTID}, wrap-{TOOLMANAGEID} and + * wrap-{TOOLHELPID} will have class 'enabled' or 'disabled' when applicable or not for + * the current repository view; + */ + public function js_template_generallayout() { + $rv = ' +
                            +
                            +
                            + + + +
                            +
                            + +
                            '; + return preg_replace('/\{\!\}/', '', $rv); + } + + /** + * Template for displaying list of files in 'icon view' mode. + * + * Element with class 'fp-file' is a template for displaying one file and indicates a place + * where files shall be output. It also will hold mouse events (click, over, out, etc.); + * + * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size + * (both width and height, unless min-width and/or min-height is set in CSS) and the content of + * an element will be replaced with an appropriate img; + * + * the width of element with class 'fp-filename' will be set to the repository thumbnail width + * (unless min-width is set in css) and the content of an element will be replaced with filename + * supplied by repository; + */ + public function js_template_iconview() { + $rv = '
                            +
                            +
                            +
                            +
                            +
                            '; + return preg_replace('/\{\!\}/', '', $rv); + } + + /** + * Template for window appearing to select a file. + * + * All content must be enclosed in an element with class 'fp-select', CSS for this class + * must define width and height of the window; + * + * Image will be added as content to the element with id {IMGID}; + * + * Inside the window
                            element must be present and contain followng input fields: + * {NEWNAMEID} (input-text) + * {LINKEXTID} (input-checkbox) + * {AUTHORID} (input-text) + * {LICENSEID} (select, will be populated with available options) + * {BUTCONFIRMID} (will hold onclick event) + * {BUTCANCELID} (will hold onclick event) + * + * Elements with ids 'wrap-{LINKEXTID}', 'wrap-{AUTHORID}' and 'wrap-{LICENSEID}' may be + * assigned with class 'uneditable' if not applicable for particular repository; + */ + public function js_template_selectlayout() { + $rv = '
                            +

                            + + + + + + + + + +
                            :
                            :
                            :
                            +

                            +

                            +
                            '; + return preg_replace('/\{\!\}/', '', $rv); + } + + /** + * Content to display when user chooses 'Upload file' repository (will be nested inside + * element with class 'fp-content'). + * + * Must contain form (enctype="multipart/form-data" method="POST") with id {UPLOADFORMID} + * The elements with the following ids are obligatory: + * {INPUTFILEID} (input-file) + * {NEWNAMEID} (input-text) + * {AUTHORID} (input-text) + * {LICENSEID} (select, will be populated with available options) + * {BUTUPLOADID} (any element type, will hold onclick event) + * + * Please note that some fields may be hidden using CSS if this is part of quickupload form + */ + public function js_template_uploadform() { + return '
                            +
                            + + + + + + + + + + + + + + + + + +
                            :
                            :
                            :
                            :
                            +
                            +
                            +
                            '; + } + + /** + * Content to display during loading process in filepicker (inside element with class 'fp-content'). + */ + public function js_template_loading() { + return '
                            + +

                            '.get_string('loading', 'repository').'

                            +
                            '; + } + + /** + * Template for error displayed in filepicker (inside element with class 'fp-content'). + * + * must have element with class 'fp-error', its content will be replaced with error text + * and the error code will be assigned as additional class to this element + * used errors: invalidjson, nofilesavailable + */ + public function js_template_error() { + $rv = '
                            '; + return preg_replace('/\{\!\}/', '', $rv); + } + + /** + * Template for error/info message displayed as a separate popup window. + * + * Must be wrapped in an element with class 'fp-msg', CSS for this element must define + * width and height of the window. It will be assigned with an additional class 'fp-msg-error' + * or 'fp-msg-info' depending on message type; + * + * content of element with class 'fp-msg-text' will be replaced with error/info text; + * + * element with class 'fp-msg-butok' will hold onclick event + */ + public function js_template_message() { + $rv = '
                            +
                            +
                            +
                            '; + return preg_replace('/\{\!\}/', '', $rv); + } + + /** + * Template for popup dialogue window asking for action when file with the same name already exists. + * + * Must be wrapped in an element with class 'fp-dlg', CSS for this element must define width + * and height of the window; + * + * content of element with class 'fp-dlg-text' will be replaced with dialog text; + * elements with classes 'fp-dlg-butoverwrite', 'fp-dlg-butrename' and 'fp-dlg-butcancel' will + * hold onclick events; + * + * content of element with class 'fp-dlg-butrename' will be substituted with appropriate string + * (Note that it may have long text) + */ + public function js_template_processexistingfile() { + $rv = '
                            +
                            +
                            +
                            +
                            '; + return preg_replace('/\{\!\}/', '', $rv); + } + + /** + * Returns all Javascript templates as an array. + * + * @return array + */ + public function filepicker_templates() { + $class_methods = get_class_methods($this); + $templates = array(); + foreach ($class_methods as $method_name) { + if (preg_match('/^js_template_(.*)$/', $method_name, $matches)) + $templates[$matches[1]] = $this->$method_name(); + } + return $templates; + } + + /** + * Outputs HTML for default repository searchform. + * + * This will be used as contents for search form defined in generallayout template + * (form with id {TOOLSEARCHID}). + * Default contents is one text input field with name="s" + */ + public function repository_default_searchform() { + $str = '

                            '; + return $str; + } +} diff --git a/repository/repository_ajax.php b/repository/repository_ajax.php index 35a985cd319..f581a13ab5f 100644 --- a/repository/repository_ajax.php +++ b/repository/repository_ajax.php @@ -160,7 +160,9 @@ switch ($action) { echo json_encode($logout); break; case 'searchform': + $search_form['repo_id'] = $repo_id; $search_form['form'] = $repo->print_search(); + $search_form['allowcaching'] = true; echo json_encode($search_form); break; case 'search': diff --git a/theme/base/config.php b/theme/base/config.php index 561fb1ddbaf..978396c955b 100644 --- a/theme/base/config.php +++ b/theme/base/config.php @@ -48,7 +48,8 @@ $THEME->sheets = array( 'grade', 'message', 'question', - 'user' + 'user', + 'filemanager' ); $THEME->editor_sheets = array('editor'); diff --git a/theme/base/style/core.css b/theme/base/style/core.css index ceb387d10c2..8e7c3a7a7e6 100644 --- a/theme/base/style/core.css +++ b/theme/base/style/core.css @@ -444,108 +444,6 @@ body.tag .managelink {padding: 5px;} .tag_cloud .s1 {font-size: 0.9em;} .tag_cloud .s0 {font-size: 0.8em;} -/** - * File picker - * Copyright (c) 2006 Yahoo! Inc. All rights reserved. - * copy from yui/examples/treeview/assets/css/folders/tree.css - * first or middle sibling, no children - */ -/* first or middle sibling, no children */ -.file-picker .ygtvtn {background: url([[pix:moodle|y/tn]]) 0 0 no-repeat;width:17px;height:22px;} -/* first or middle sibling, collapsable */ -.file-picker .ygtvtm {background: url([[pix:moodle|y/tm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* first or middle sibling, collapsable, hover */ -.file-picker .ygtvtmh {background: url([[pix:moodle|y/tmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* first or middle sibling, expandable */ -.file-picker .ygtvtp {background: url([[pix:moodle|y/tp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* first or middle sibling, expandable, hover */ -.file-picker .ygtvtph {background: url([[pix:moodle|y/tph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* last sibling, no children */ -.file-picker .ygtvln {background: url([[pix:moodle|y/ln]]) 0 0 no-repeat;width:17px;height:22px;} -/* Last sibling, collapsable */ -.file-picker .ygtvlm {background: url([[pix:moodle|y/lm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Last sibling, collapsable, hover */ -.file-picker .ygtvlmh {background: url([[pix:moodle|y/lmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Last sibling, expandable */ -.file-picker .ygtvlp {background: url([[pix:moodle|y/lp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Last sibling, expandable, hover */ -.file-picker .ygtvlph {background: url([[pix:moodle|y/lph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Loading icon */ -.file-picker .ygtvloading {background: url([[pix:moodle|y/loading]]) 0 0 no-repeat;width:16px;height:22px;} -/* the style for the empty cells that are used for rendering the depth* of the node */ -.file-picker .ygtvdepthcell {background: url([[pix:moodle|y/vline]]) 0 0 no-repeat;width:17px;height:22px;} -.file-picker .ygtvblankdepthcell {width:17px;height:22px;} -/* the style of the div around each node */ -.file-picker .ygtvitem table{margin-bottom:0;} -.file-picker .ygtvitem td {border:none;padding:0;} -/* the style of the div around each node's collection of children */ -* html .file-picker .ygtvchildren {height:1%;} -/* the style of the text label in ygTextNode */ -.file-picker .ygtvlabel, -.file-picker .ygtvlabel:link, -.file-picker .ygtvlabel:visited, -.file-picker .ygtvlabel:hover {margin-left:2px;text-decoration: none;} -.file-picker {font-size:12px;} -.file-picker strong {background:#FFFFCC;} -.file-picker .fp-panel {padding:0;margin:0;text-align:left;} -.file-picker .fp-login-form {text-align:center;} -.file-picker .fp-searchbar {float:right;} -.file-picker .fp-viewbar {width:300px;float:left;} -.file-picker .fp-toolbar {padding: .8em;background: #FFFFCC;text-align:center;margin: 3px;} -.file-picker .fp-toolbar a {padding: 0 .5em;} -.file-picker .fp-list {list-style-type:none;padding:0;float:left;width:100%;margin:0;} -.dir-rtl .file-picker .fp-list {text-align:right;} -.file-picker .fp-list li {border-bottom:1px dotted gray;margin-bottom: 1em;} -.file-picker .fp-repo-name {display:block;padding: .5em;margin-bottom: .5em;} -.file-picker .fp-pathbar {margin: .4em;border-bottom: 1px dotted gray;} -.file-picker .fp-pathbar a {padding: .4em;} -.file-picker .fp-rename-form {text-align:center;} -.file-picker .fp-rename-form p {margin: 1em;} -.file-picker .fp-upload-form {margin: 2em 0;text-align:center;} -.file-picker .fp-upload-btn {clear:both;margin-top: 2em;} -.file-picker .fp-paging {margin:1em .5em;clear:both;text-align:center;line-height: 2.5em;} -.file-picker .fp-paging a {padding: .5em;border: 1px solid #CCC;} -.file-picker .fp-paging a.cur_page {border: 1px solid blue;} -.file-picker .fp-popup {text-align:center;} -.file-picker .fp-grid-panel{} -.file-picker .fp-grid {float:left;text-align:center;} -.file-picker .fp-grid div {overflow: hidden;} -.file-picker .fp-grid p {margin:0;padding:0;background: #FFFFCC;} -.file-picker .fp-grid .label {height:48px;text-align:center;} -.file-picker .fp-grid span {color:gray;} -.file-picker .fp-error {padding: 2em 0;margin: 3em 5px;text-align:center;background: #FFBBBB;} -.file-picker .fp-emptylist, .file-picker .fp-msg {text-align:center;} -.filepicker-filelist {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid} -/* file picker search dialog */ -.file-picker div.bd {text-align:left;} - -/** - * File Manager - */ -.filemanager-toolbar {margin: 5px 0;} -.filemanager-toolbar a {border: 1px solid #AACCEE;background: #F4FAFF;color: black;padding: 3px;} -.filemanager-toolbar a:hover {background: #FFFFFF;} -.filemanager-toolbar .helplink a {border: 0px; background: transparent;} -.fm-breadcrumb {margin:0;} -.filemanager-container {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid} -.filemanager-container ul{margin:0;padding:0;} -.filemanager-container ul li{white-space:nowrap;list-style-type:none;} -.filemanager-container ul li a{padding:0} -.filemanager-loading{display:none} -.jsenabled .filemanager-loading{display:block} -.fm-menuicon{cursor: pointer;} -#fm-move-div {margin: 6px;} -#fm-move-div strong{color:red;} -.fm-file-entry{border: 1px solid red;} -.fm-operation {font-weight: bold;} - -.filemanager-container, -.filepicker-filelist {overflow:hidden;} -.filemanager-container .dndupload-target, -.filepicker-filelist .dndupload-target {background:#f7f998;position:absolute;height:100%;width:100%;top:0;left:0;text-align:center;padding:5px;z-index:1000} -.filemanager-container.dndupload-over .dndupload-target, -.filepicker-filelist.dndupload-over .dndupload-target {background:#8EF947;font-weight:bold} - /* * Backup and Restore CSS */ diff --git a/theme/base/style/filemanager.css b/theme/base/style/filemanager.css new file mode 100644 index 00000000000..cb174c32ad1 --- /dev/null +++ b/theme/base/style/filemanager.css @@ -0,0 +1,106 @@ +/** + * File picker + */ +/* first or middle sibling, no children */ +.file-picker .ygtvtn {background: url([[pix:moodle|y/tn]]) 0 0 no-repeat;width:17px;height:22px;} +/* first or middle sibling, collapsable */ +.file-picker .ygtvtm {background: url([[pix:moodle|y/tm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* first or middle sibling, collapsable, hover */ +.file-picker .ygtvtmh {background: url([[pix:moodle|y/tmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* first or middle sibling, expandable */ +.file-picker .ygtvtp {background: url([[pix:moodle|y/tp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* first or middle sibling, expandable, hover */ +.file-picker .ygtvtph {background: url([[pix:moodle|y/tph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* last sibling, no children */ +.file-picker .ygtvln {background: url([[pix:moodle|y/ln]]) 0 0 no-repeat;width:17px;height:22px;} +/* Last sibling, collapsable */ +.file-picker .ygtvlm {background: url([[pix:moodle|y/lm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* Last sibling, collapsable, hover */ +.file-picker .ygtvlmh {background: url([[pix:moodle|y/lmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* Last sibling, expandable */ +.file-picker .ygtvlp {background: url([[pix:moodle|y/lp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* Last sibling, expandable, hover */ +.file-picker .ygtvlph {background: url([[pix:moodle|y/lph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} +/* Loading icon */ +.file-picker .ygtvloading {background: url([[pix:moodle|y/loading]]) 0 0 no-repeat;width:16px;height:22px;} +/* the style for the empty cells that are used for rendering the depth* of the node */ +.file-picker .ygtvdepthcell {background: url([[pix:moodle|y/vline]]) 0 0 no-repeat;width:17px;height:22px;} +.file-picker .ygtvblankdepthcell {width:17px;height:22px;} +/* the style of the div around each node */ +.file-picker .ygtvitem table{margin-bottom:0;} +.file-picker .ygtvitem td {border:none;padding:0;} +/* the style of the div around each node's collection of children */ +* html .file-picker .ygtvchildren {height:1%;} +/* the style of the text label in ygTextNode */ +.file-picker .ygtvlabel, +.file-picker .ygtvlabel:link, +.file-picker .ygtvlabel:visited, +.file-picker .ygtvlabel:hover {margin-left:2px;text-decoration: none;} +.file-picker {font-size:12px;} +.file-picker.fp-generallayout {width:700px;height:480px;} +.file-picker strong {background:#FFFFCC;} +.file-picker .fp-content {padding:0;margin:0;text-align:left;max-height:350px;overflow:auto;border:1px solid black;} +.file-picker .fp-login-form {text-align:center;} +.file-picker .fp-searchbar {float:right;} +.file-picker .fp-viewbar {width:300px;float:left;} +.file-picker .fp-viewbar.disabled {display:none;} +.file-picker .fp-viewbar .checked {font-weight:bold;} +.file-picker .fp-toolbar {padding: .8em;background: #FFFFCC;text-align:center;margin: 3px;} +.file-picker .fp-toolbar.empty {display:none;} +.file-picker .fp-toolbar div {display: inline-block;} +.file-picker .fp-toolbar .disabled {display:none;} +.file-picker .fp-toolbar a {padding: 0 .5em;} +.file-picker .fp-list {list-style-type:none;padding:0;float:left;width:100%;margin:0;} +.dir-rtl .file-picker .fp-list {text-align:right;} +.file-picker .fp-list .fp-repo {display:block;border-bottom:1px dotted gray;padding: .5em;} +.file-picker .fp-list .fp-repo.active {background:#AACCEE;} +.file-picker .fp-pathbar {margin: .4em;border-bottom: 1px dotted gray;} +.file-picker .fp-pathbar a {padding: .4em;} +.file-picker .fp-select {width:550px;height:430px;text-align:center;overflow:auto;} +.file-picker .fp-select .uneditable {display:none;} +.file-picker .fp-select p {margin: 1em;} +.file-picker .fp-upload-form {margin: 2em 0;text-align:center;} +.file-picker .fp-upload-btn {clear:both;margin-top: 2em;} +.file-picker .fp-paging {margin:1em .5em;clear:both;text-align:center;line-height: 2.5em;} +.file-picker .fp-paging a {padding: .5em;border: 1px solid #CCC;} +.file-picker .fp-paging a.cur_page {border: 1px solid blue;} +.file-picker .fp-popup {text-align:center;} +.file-picker .fp-iconview .fp-file {float:left;text-align:center;} +.file-picker .fp-iconview .fp-file div {overflow: hidden;} +.file-picker .fp-iconview .fp-file .fp-filename {height:48px;text-align:center;min-width:50px;} +.file-picker .fp-error {padding: 2em 0;margin: 3em 5px;text-align:center;background: #FFBBBB;} +.file-picker .fp-msg {} +.file-picker .fp-msg .fp-msg-text {min-width:300px;min-height:150px;max-width:500px;max-height:300px;overflow:auto;} +.file-picker .fp-msg.fp-msg-error .fp-msg-text {color:red;} +.file-picker .fp-msg .fp-msg-butok {text-align:center;} +.filepicker-filelist {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid} +/* file picker search dialog */ +.file-picker div.bd {text-align:left;} + +/** + * File Manager + */ +.filemanager-toolbar {margin: 5px 0;} +.filemanager-toolbar a {border: 1px solid #AACCEE;background: #F4FAFF;color: black;padding: 3px;} +.filemanager-toolbar a:hover {background: #FFFFFF;} +.filemanager-toolbar .helplink a {border: 0px; background: transparent;} +.fm-breadcrumb {margin:0;} +.filemanager-container {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid} +.filemanager-container ul{margin:0;padding:0;} +.filemanager-container ul li{white-space:nowrap;list-style-type:none;} +.filemanager-container ul li a{padding:0} +.filemanager-loading{display:none} +.jsenabled .filemanager-loading{display:block} +.fm-menuicon{cursor: pointer;} +#fm-move-div {margin: 6px;} +#fm-move-div strong{color:red;} +.fm-file-entry{border: 1px solid red;} +.fm-operation {font-weight: bold;} + +.filemanager-container, +.filepicker-filelist {overflow:hidden;} +.filemanager-container .dndupload-target, +.filepicker-filelist .dndupload-target {background:#f7f998;position:absolute;height:100%;width:100%;top:0;left:0;text-align:center;padding:5px;z-index:1000} +.filemanager-container.dndupload-over .dndupload-target, +.filepicker-filelist.dndupload-over .dndupload-target {background:#8EF947;font-weight:bold} + From 5ce13292b5c10f2c7554b41ea371808ec644acf0 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Fri, 30 Mar 2012 14:38:45 +0800 Subject: [PATCH 234/455] MDL-31901: Filepicker: Moved HTML for loginform into renderer --- repository/filepicker.js | 104 +++++++++++++++++++++++++++++++-------- repository/renderer.php | 63 ++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 21 deletions(-) diff --git a/repository/filepicker.js b/repository/filepicker.js index a6c2c86d24f..0d345dbc445 100644 --- a/repository/filepicker.js +++ b/repository/filepicker.js @@ -839,7 +839,68 @@ M.core_filepicker.init = function(Y, options) { var login_button_id = 'fp-form-login-button-'+client_id; var popup_button_id = 'fp-form-popup-button-'+client_id; - var str = '
                          -
                          -
                          - - - -
                          -
                          - - -
                          -
                          - - +
                          +
                          @@ -522,9 +545,10 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_iconfilename() { - $rv = ' + $rv = ' +
                          -
                          +

                          '; return preg_replace('/\{\!\}/', '', $rv); } @@ -564,12 +588,13 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_nextpage() { - $rv = '
                          - -
                          - -

                          '.get_string('loading', 'repository').'

                          -
                          + $rv = ' +
                          + +
                          + +

                          '.get_string('loading', 'repository').'

                          +
                          '; return preg_replace('/\{\!\}/', '', $rv); } @@ -603,39 +628,49 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_selectlayout() { - $rv = '
                          -
                          - -

                          '.get_string('loading', 'repository').'

                          -
                          - -

                          '.get_string('getfile', 'repository').' -'.get_string('cancel').'

                          -

                           

                          - - - - - - - - - - - - - -
                          :
                          :
                          :
                          - -

                          -
                          -
                          '.get_string('lastmodified', 'moodle').':
                          -
                          '.get_string('datecreated', 'repository').':
                          -
                          '.get_string('size', 'repository').':
                          -
                          '.get_string('license', 'moodle').':
                          -
                          '.get_string('author', 'repository').':
                          -
                          '.get_string('dimensions', 'repository').':
                          -
                          + $rv = ' +
                          +
                          + +

                          '.get_string('loading', 'repository').'

                          +
                          +
                          + +
                          + + + + + + + + + + + + + + + + + + + + +
                          :
                          :
                          :
                          +
                          +

                          +
                          +
                          '.get_string('lastmodified', 'moodle').':
                          +
                          '.get_string('datecreated', 'repository').':
                          +
                          '.get_string('size', 'repository').':
                          +
                          '.get_string('license', 'moodle').':
                          +
                          '.get_string('author', 'repository').':
                          +
                          '.get_string('dimensions', 'repository').':
                          +
                          '; return preg_replace('/\{\!\}/', '', $rv); } @@ -659,30 +694,27 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_uploadform() { - $rv = '
                          -
                          -
                          - - - - - - - - - - - - - - - - - -
                          :
                          :
                          :
                          :
                          -
                          -
                          -
                          + $rv = ' +
                          +
                          +
                          + + + + + + + + + + + + + +
                          :
                          :
                          :
                          :
                          +
                          +
                          +
                          '; return preg_replace('/\{\!\}/', '', $rv); } @@ -693,9 +725,10 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_loading() { - return '
                          - -

                          '.get_string('loading', 'repository').'

                          + return ' +
                          + +

                          '.get_string('loading', 'repository').'

                          '; } @@ -709,7 +742,8 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_error() { - $rv = '
                          '; + $rv = ' +
                          '; return preg_replace('/\{\!\}/', '', $rv); } @@ -727,10 +761,11 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_message() { - $rv = '
                          -
                          -
                          -
                          '; + $rv = ' +'; return preg_replace('/\{\!\}/', '', $rv); } @@ -749,14 +784,16 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_processexistingfile() { - $rv = '
                          -
                          -
                          -
                          + $rv = ' +'; return preg_replace('/\{\!\}/', '', $rv); } - + /** * FilePicker JS template for repository login form including templates for each element type * @@ -782,36 +819,28 @@ class core_files_renderer extends plugin_renderer_base { private function fp_js_template_loginform() { $rv = ' '; return preg_replace('/\{\!\}/', '', $rv); } diff --git a/pix/a/add_file.png b/pix/a/add_file.png new file mode 100644 index 0000000000000000000000000000000000000000..57d559ed49963f3949df555aa722eeab20173481 GIT binary patch literal 1365 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{l@EB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=wnUkTVshOLlfuXsfp{t>#i=mT+nW>S1 zlaqm)lc^(2uSMv>2~2MaT(7wSPQ9SSkXrz>*(J3ovn(~mttdZN0qkk3Ox$j9 z!D${;ZwgMgn7QKAs}FRHJ}7FDq8cUyOg|tdJmCU4@T8xb2Tbopz=U0MV$nwi2FBx_ zE{-7;x28-!opmTcpiN!PMK#hyqe+89=_`|%{6X`A>*go+dF!u!*ZqUd&Z+$F?vLAq zSXj4*I_?q*{5We~{TspT9B+0t^>n{yvu}4kvf%Ta>9_n`+3u(1H~No1HuqhA`Te68 zfiK!GurFLM6?-CU>!J*ks(Z{z%slPRufA4==}o_Uv`qI4!|vxo1r{AJ#8A`2Wxmun43?!DEOmXTy+N5(jX~r3jz`u3&s}m(m1n8I@0Szxmejt7>s7}$TMAf|NW=!?6db+60~?`oPQpoBewG}!-9W7E026% z5Vf}G*Y%>xgC;%hR}N`5_XN5r3Hk|6nD1r5{9#3imJH`s<^a9vKbvpnxYctS1sw5j z(X)QR{Ne^b8?#gM?z`_YV-}gDWX@9aSCZkIzbVs1>W;v}7boO7l@Cd7I`RDT{mdKI;Vst0HgiqR{#J2 literal 0 HcmV?d00001 diff --git a/pix/a/create_folder.png b/pix/a/create_folder.png new file mode 100644 index 0000000000000000000000000000000000000000..643bc98efb3079f1ff73f2a8dd93d6ad28bd6a91 GIT binary patch literal 1464 zcmeAS@N?(olHy`uVBq!ia0vp^f8U}fi7AzZCsS=07?@QuLn2Bde0{8v^K*7iAWdWaj57fJ{tG z$}cUkRRX#c;)UD-xUqS~&|m@vn0`fKfxe-h0mw@*g}%P{mFDKcRTq~8r6Sym)!^cg z%7Rq=pw#00(xPNw#HA^NtSYc_E=o--$uA1Y&(DE{Vn9ZINq%ugeu08>u&JJ*f^TAS zW*$fcti#vW$}_LHBrz{J)zigR32261W@d_&vze2jrK!2GrGcTjp`ojxrHi4Hg_)_5 zfs>Pgo0F*{Os`9Ra%paAUI|QZ3PP_5PQ9SSkXrz>*(J3ovn(~mttdZN0qkk3Ox$iU z#AzN>ZwhX=7~#~b4|I$^C~A?S8YToxKOiPN;Q~4Eq@S7xOz%a&gq^_5EyKXTq~+=2 z7*cVoC-`iikfX$!d6Ei|0m(@xq$Z_)+`#^bd4g|GXa581f=@n7HcW99tp3$k#6LX9 zVv6gj{*bU}9*4Kt4n1onW1sI^uHJvZl~pkN4FBD)SHnXuuU)e>LjHXG{F{|aHu?np z>EIEm_m_LGnIn1c*Zjwmi>>!YJi2#R_Rafu3-;AB$ES1l#m&2wt0FBsPp)<&d$sDF zol~1Hidk)y@K-*wFZ&6T{Jbqs_H68UB=Y&jgD1fq33F2pw*KBasX>R6XZ_vVm5Rah z9?2wR*e^P})Ni81gSYM7zLQS39(-A;qZM_^0OSt7cesG~}Vm|DZ{mqBgpzN2+z5S!vqD zJx{iNN`-t#(Y6SkBrDtGaQ=L|=`OBb0`iNT-ptU6F|X0`TP#>86&Kn+jCchIt>D ze3GTTy*>JTZ_OjO#fl3a7GxYY5HWrHF`_GbtJFHBQ?j=w0|{mD+McO66hyifIV h2VOV)Gq2+^U?_j)S-i?MUlLT7db;|#taD0e0su*@C58Y1 literal 0 HcmV?d00001 diff --git a/pix/a/download_all.png b/pix/a/download_all.png new file mode 100644 index 0000000000000000000000000000000000000000..7520b39ff64714e60da5d05bbd9232926d44bc28 GIT binary patch literal 1208 zcmaJ>U2NM_6m}MrPVHI^3B;N`)N_IH7u(m%Pi>M_Nt`Z0q=YmQ5vWoe`zA51e`en< zX&J0#qSBy)F-_VA4---aJQaAJpsiX&VJ}ELASPg%Cd3P9;b&}PDdD~$eK2)+d?fut?>$Y?}QnOTuVVC z5o%pjKAj=sh6Tw0&H7|E2*{wH27Z?J^G}c*3s?ql3>)$RRtSUy7LXecg{xUgNyv%= z8@2E$LRAnl1%|0st911MZCGUn@I2439K&%woZ+*_btKh%y4~Ai5TPwws)Gc1nYT9PDjk55r-Ytpk+_(vuEVPX= zOU8pM^*W_YA#Onl8CK3PMq9U-sTjzxD~3tNhXOPp(~_*}PGk*{P75jBMv^YWlo+8f z2d%1#z=whZAQ1pO%f$dl0A2*KzF>f3V=;Ch7Kpa6q9KoIP)9ASau>^Oi*?MPnYgkD zE%gXg1}sA(*P0g8Ewmiq6JneLm=E-Atz{jnY_EmgRttm0FwSWIGwN0d`^VXC8W$fn ztq*nVcMBW)zJ1>zf^a>S5~I1=~}vjd15NI5KBg{{W8+LJ)Yl_&!6jlW%Zv+ z_1`XCICN5d{&#V2{l*tPo~|RM>1MMD8jTxgukJnd%-0<=Gc#smwJr0_&Hlp4E5{o0 zt-n`8uZN=#9Cf`|g0NUc&EEjLxzSFbx!AJAY4!_~^ zzTDAuamNqecKzf%zWUYjO8q*M@%1h-)6HFHr~K|ygNt6z3lCrZ)$`PkQ>tg`Saac> z=wxT|`0`t$=PNI{szO0Yww(@LJ$f#_k3QJ74EsJM+J|@7AMG0@X5Vyy{ipwYk_>*& zE&g@y;+dT}%xcB|@AI|Q|g*%cy_nixGzvo`L63zN!u1CV3xes?vSKGp& b9rx@ZsCM-E&3EU3^Djvy2F1Bp;njZuYYd=c literal 0 HcmV?d00001 diff --git a/pix/y/lm.gif b/pix/y/lm.gif deleted file mode 100644 index b5623002a654745049da926cd3c0f8f1cded2a43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 666 zcmdUs&1(}u0L90+Npyp<*4FQ|(*)B>s*aFDr9G?=@`0B<8U@)>u!$CZK>4{;Dd1Yu45FZ>;TyyJVkcrw;|av%Wq zfG+?z4H#w2V2nDOlx z;NPf*{|h>QbM96U2R+TU%};>$7mkmlRc$n*YmwV`#_z_#MDG41(8u(AF?UY`K}z>d zJxE8Mmr7btaJjZ{p|&YCQhb;WZGFvge0TUm7(IG6r-j@Gx83(?ZE@nwvfAx_4#>auF!nVb-p1_?dcQL-&j)(e^W~9mo}iy!^R*{xVj!d4ocu98Xw}8^Pz$=k zXfSr<)GTW|`&o{9+`9q^icY9}$Dw2G$&WLZZ$~{E`zbtDd4K=YYX`W>Vy0C*S0TlYsHo&F(Z=n|-)DHQORu zMTFu(@gNpN@FaqWH&G8F7PJWBL523{$&+5h7ebv)lUAhEf!&$;`M&@E{>RK`$B%Zk z?`~%prYk)v=lq?1o!f%+|M*dKnQq-ARU~<9lGGFjGsBuy!XRxZWt_u`HgkFj4=_yN zfL|UVLluVQAEg{F^S@ZOt+`$LB_7?=r++U6ZjsLk~K}@ELFOef?;Pe>yAyg zQ7Bq6-cxKIaga9*Kd(C4B{{qyV^g$Sn6WXR!>%>$sI(uGJxwyL-PVD8AXOvDmO5=< zlceQ1OD&wHYmy)&Vq#Pj`(;E|3MEiqA_a#NvM?-)A`+V1wCNJXRB@B5Z*YYzxl+=> z3bCAmWmTKq%T_F6xfRO>$-KZJkWp0K^eujI8(OiWpTXLQV;P`c9ZCO3fv+C+^+SZB z5f}|au^*v+IgyA(gd`MYQB3v8Y=f(9lKFqRJQc(Ht^KRjO%t6T|F}N5^s+ws*rfCB z(7_(){<()fic4vExZtgney^?$2JX$xU+5gV(Yte(`r-b`TSLb>uC8?Gx_c$uyFlKD)8!I>)CTs>*DLTi@)Z6Y`-&iDDaWbe#-;%VDHzV_PayN z!f0^f^1kqdrd8WUo^aP5-~8mYo?;e0@95e)mRw4YFfBpm-3#{p^!Jx#|COdwxs6;fB3g&~9pLX!Z?#N%XSx-#onl$*-={{EYn;!?ZF9iqq*9Y$)O zL^O2v!n4m`zwv*pfBDbZ{abJW5C{7=JU5yEAII@TGL_C`^=$p^{GGc=d9*NgU(V|9rG+*(e{gU0+I6d|Gx1!`9TJ*==jShv&v)>c{bf0^;&mA-U=kdF zlDu{*bz%^V`S*5R1NB$@hb0x?ing7c`V(qWJW|H9xdqi;ttGsT9i74MGp}Jf{G)g1 zqSlr1Zt8q-V_z?Nm#>qrztQ1c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=$rIDqJnX8+Hvze2jp{t>zlbMBuxsj=v znTx5ZqoE;8uSMv>2~2MaT(6q}PQ9SSkXrz>*(J3ovn(~mttdZN0qkk3Ox$j9 z!D${;ZwgMgxVqxhs}FRHJ}7FDq8cUyOg|tdJmCU4@T8xb2Tbopz=Yj)m(!PlfpLSU zi(^Q|tv6H7dmVNVIJW=p61i1M9SbTnjyAIk)`-U+p8kQchX3mm?ia59RoWFIHf%@# zapvAq`F(!o-6)stP7i)3bCyG!?wcF$pSh;sT%w?Nl4EwJP4ve-XIJkIpZ-*8={5;} z9u`~mztw%ewUfb{%R#vIhxl9!2YkwQ6U-CtYYtQDLOt~DLQwrL? zudzSALWFgHy-bL)-*GO_^(}@Ag~X!y4&BjEcU-?TVe%cN)0z_b9a3kty~HF>-DuRD zdg{;x^Vh1D#iBWLL`&Q(O_Cz>wbt-H70t}Gm&HE2N937h68gWi_LH9O=9!9SyeCh`SF`6qH#R&pVU8=B>gcs!t^=s zUjDJJ19A2$#`Eq~p89oQ276#A;7`m!-0gEGiQEyv0*|-fq{m?^~?J| z>~JV3NKgVJ6fewKQ9S#346#RcN;lm1p|3K9N0UsVr*w7&G;Y7jz4;vmVFt{*5 zV8en54|W7NSQs=^6#RcMK|w*_!v=>BI|2$40{-7<*wCPGV1~l~7YjaINZ7Dq!UdoM zfD!=?2?+rYHW)0J(D30vz=sbT{@(x^xL`qr!nco4KAcGSaG~JA3Im|q9xPC}dgy&i(lS!fIo{IEaOaL=_X9`6^9K}JOtdUitn5@zIG(!S`qsa)!YWd0 zRwy&DOLJ-PdVNrCXP2;QSm03jh=om>*=2>u6b6@OaXmW?frkrL1hQLC)`~r~W##4N K0fMYd4AuY$xzKt5 diff --git a/pix/y/lp.png b/pix/y/lp.png new file mode 100644 index 0000000000000000000000000000000000000000..2bad8e5ac7baa5e05cb002c1dd50f42f4f7eb6ff GIT binary patch literal 1028 zcmaJ=O=#0l9FNW~#>RFS0~PU+i3hRy=$dv3ty|l)Tg8mo7OW?iCa-JQl9wfKYc@nS zVYn$GUetpif*^v7p$8ov6#M`$9%Kh~2akFX$L`8}>DtbN^+EF9`}6z#{-1AYWO%T> z^-wECQSF%_IqUD_Ydf%y{8yhvK9lVrP8Dztm2gFMAQjh95rT}Vj=?Nc^_j`{FiKG^ z$BcXd7nC!ShD=8FF^p&0giTS=e$Q65afm??ju}>r-gxnn28JG^&j|{r*hyG6hGrd@ zn;p(;v*Vhm)BUGF)RTyS39$-1bHZ{ZFGg2&C35!7EDfp6ywk4LWR4PoR zmqE@L%ZsAOazQp23=l-Xow2a$1uVCxt{_8Ka||0B$O68iT0~PgMw3XlQ!wp@tmW3q zL<+`ws?G8Y=ciN$D$4(%rrAKdI16{;{im>-pRpmEg)W+MG}5?IkMGKsk`7cca`FgG z)T=mBMi{weWP@Z*V0fUYnqm2tDnn7EjOAk0(qKl8(L{qW3|$h0gcy#5#XgxQE5#@H z-b9LvCuAWW4u^T6&XtiiWkL(rx%v(_-jwSPgJ~1bGIWe-sHYudf@;!|(L9z&Q@t8j zZyrluQ!Yz_Vg1(r)#|#5%#VL;3@*7eMju*a-W@X7uM6uUc@)zbIiB~v6n|}P^|w5l zTbgehxOKc+|M2+y)8PEtX>jSvG8YK6KUB^RT{gVZnq26B_=1*q|UF@c+Ys4J#)6f6(yZM8f|U3;w?VvM2n% zQSjkFKtn^rhYJM{Rv3KP5%2*>e%SEgLc)dyfe$Y>I9M1MXej)@P@tdyG-1Jm8443R z3N|z-eAwX7P>^t7hQfy(4ht$2J{(ARu)yH;%f}5B1s4`5Bm@Lpzr6p!0)@R(1TIVv zn9$KMbLPws4;FlQFyY(BCkY7w1qBHK4h|1C7(Cb!Frh%VVPuHSjez`*eT|9>Dk6oKMT7DfgJCk7pm<3Vx4!2Y7asj0c8wXMCQowu{6 zx37OfQ}@Iv{f4YFW~ffIpF3|}E2}6IlaK*}<^+3(HESL0TNyTO-o&_VyJh?8HI8dH zv@oz7Vp+n$$z?5Jr!2o~?cO!}oAr(?l{(HQABQLewYZ?6v7JLpU-pHOgN z5t7!3xbXF5@Io!W%; zlC?_@VeQ5~>tomYT9kDdw%lEN+|?d~PSbg*$r#hUt3Ts@f5GoJKUPGTe*kwc0Gcne z00@F`97km^ZsZ^^gqtAz6#@VNEaKrt9zM=S5g4C3kD+uNL#D(4reR_jikVvf*clfhnErG!nT%wDCIg}$)zax8#A8F591}vvFoefp z_i9EBC{L$>$3`b`1G`+1Tmu(_WHJnKJ{5gR_+LQVv>*Tg3pn`M_VW|K3Wr#E`2t}< zp{NijD!qLtpHNm_QAsE*5#6gPzgtK!Ll8enl@Mr=$%JNKIXKu6ZTCwGfST%j+dw6e zNTON{TUbk*)k51{DACn?dggIiw_ZTqHQ?fcI5~}2?6#h@T3jTQtgtM$6L*+du3?rW zl5gnjJx$)Kj~SCRV=mYap&?;#PUU(N^=Ug)e8I+@nP}pMdj|JlJ6zFVpul1qWk2Za zJ1Vq0=3^K6L`AmR`A=xrC7AZa(w_E^e?Y()zH7yd>Owj7M3EgO-St$s^(_bIfNWi+ zuQ{v8@kp`LJgMm0rsGBZH(dieF5Kx$_dB^WJiq+tBigoC&nPDqN87S_ zug8^>s_3Is{+nlN)(UZ8J}qT>=&+SK@OtXiaXr-|zJK@CcOx^FEc?KZDg2@5&idy5 z+T;%dFW(jD8G~1{v@1c^)+&#^&;GFXrQVM*l=d<7jpIxGQ10d20i3YY6lvZZjewit z3^31D+r!B#J!%96im1eT0cB4(_j~F{75A3&L`HpqTVBipL`&VE6?+h?8?Jf(yRq<- z?*~7(>t5QJ#hZQ;_Zv$YFP^*I2%4juyAd+SO2Eqk_XNb3-|+TqD*DFe?{nAL>u2_r zpBcR0lzUpGS*rMAhw^zCys_1j$MS{k~(z9@O9IVqPk^>bGx&AO`xq%DtcU6jhk%jDA5srpr^+|Y5L zR`JX5#o9;4r}ElH;harf`@-AEI^{BwewzZPHUI=R9|a% zZNgS-Pkkywu5QZ9k!xDZ`{ccC4O?<;hl-)->mJEbbVN_|DFy}>wiJWI>x@T3PhNPU z)$dbDn98yu3%zOUW#kD+icOx-F->;x?5M+JY)9c2YrP#J7lrXHLK}@ablYRmKefSg zOS9hS?YNoR?&}pmmmcAP|K U-ZKv*d~KX^p5GT`Wd<<*0~01CaR2}S diff --git a/pix/y/tm.png b/pix/y/tm.png new file mode 100644 index 0000000000000000000000000000000000000000..0b112ab7b2e3d5b01cf7ee4bb4c703790b0578b4 GIT binary patch literal 1042 zcmah|OK1~87~VECNFRC=tD?hJiwCnilV&%~(%3fH)JB>TlYsHo&F(Z=n|-)DHQORu zMTFu(@gNpN@FaqWH&G8F7PJWBL523{$&+5h7ebv)lUAhEf!&$;`M&@E{>RK`$B%Zk z?`~%prYk)v=lq?1o!f%+|M*dKnQq-ARU~<9lGGFjGsBuy!XRxZWt_u`HgkFj4=_yN zfL|UVLluVQAEg{F^S@ZOt+`$LB_7?=r++U6ZjsLk~K}@ELFOef?;Pe>yAyg zQ7Bq6-cxKIaga9*Kd(C4B{{qyV^g$Sn6WXR!>%>$sI(uGJxwyL-PVD8AXOvDmO5=< zlceQ1OD&wHYmy)&Vq#Pj`(;E|3MEiqA_a#NvM?-)A`+V1wCNJXRB@B5Z*YYzxl+=> z3bCAmWmTKq%T_F6xfRO>$-KZJkWp0K^eujI8(OiWpTXLQV;P`c9ZCO3fv+C+^+SZB z5f}|au^*v+IgyA(gd`MYQB3v8Y=f(9lKFqRJQc(Ht^KRjO%t6T|F}N5^s+ws*rfCB z(7_(){<()fic4vExZtgney^?$2JX$xU+5gV(Yte(`r-b`TSLb>uC8?Gx_c$uyFlKD)8!I>)CTs>*DLTi@)Z6Y`-&iDDaWbe#-;%VDHzV_PayN z!f0^f^1kqdrd8WUo^aP5-~8mYo?;e0@95e)mRw4YFfBpm-3#{p^!Jx#|COdwnOB7NkAIc21m~j<41Z*~FG&=t^9gUEYvo zS5gsZbyHJTazQ&2vvQ<`<;YSK`I5euyH$t z*&qi(gUUD%pN-qtG!X3X>$d6H>@+4)2Eq`BLZPT61@F4vCH&79;aTDZ04yNxz32N+ z03RG;iNq4AOsC^6M)# z8}r;X?ex)}272zi{APjmH%-N!za$SfBnD`|$X*aWWt1|sl`$Uu3*9I~ef&7Cbi}NL zyaJOOgfeo2T2vR&fQXe_(#YZtR)bC&lA9L63oeRP%RBce)UrrX)@o&JY1Y(d5@&Yo~oz+sqlX=!2EAGu`)e5@RGve~z z@tE@C+o`eV#M(@!M5!`6!PDI2nOgbcxU)$8s($v6&UPPqkU*dTjOo3daj~>V|QWYz1&bk%cGJU zL+hAGYtTPdO&ET9(in3CZ{+(kqz9!IT)tM&G=7-+nXi%{%_#v9SGo zZvZ4cg8&3UbV`)Kw*mnG0Hja|+(2N6PK^?aN@5WuFqD{r@drHIz`>0$re@+>Uew`z z930o-MxG9#5Jni+K_IxrDiN56N?=R|>JSj`gP40j2Zs5T@j!_08mtYv? zVSOB83c-|2ObJf@^3Wim)YjJCt)lQa98`iBQ3?lwR+j$2AHX=KG%7(%$K>%iIEI=g zhEW*gaG;H~d4eFeYX5&ldue3>01)8!cEa0F05X9<0^v1Lkys)IuHPvArVJI7lvkA< zw2{d|%7ME2dXbHTrKJz>R`MK$x*u7u=n$-pr3>a3*k!b8E%5%Mnngqg#R_NWf|)YQfwuZ-YsoPE&i zv5+{(&R888wj)!+KY-VUMmK#%2L>->^^eaSOJ^s1mEF~qIx=)d%8p-!JB9Y_H>r7T z3%xCyjG>4>U&PJY=cFs%iqF0*!^*rBLmTivrz|0*@Ui*qdo5Ue0 z(l3(P@+q&xgFaF7$rS6>IRce>^t*{2e0=GmkE2?>Z=8&Jb}l96a9(q1{D~eqgFhGB zav^D5+LE4XX=;Jf9jK~|EYCPqW^Pc8D(muLlj>qY6jhxqJZqv~7wctvN=w$K)M#0N ztFN?D5Z_uR%Bfk(RTSm=me*BKHF-^qahiNp$7XV6>wVMm6>ZAP<*V(*`&SBjt;3pY z20UNUTe{`0e)17byq{uJU+een*rUgOb>q{n{`C{f@%}eWuWJ33=55pd4Kr@980y)S z(*df5`~v~nrQ+#;)>XM%pys(of9KWRFS0~PU+i3hRy=$dv3ty|l)Tg8mo7OW?iCa-JQl9wfKYc@nS zVYn$GUetpif*^v7p$8ov6#M`$9%Kh~2akFX$L`8}>DtbN^+EF9`}6z#{-1AYWO%T> z^-wECQSF%_IqUD_Ydf%y{8yhvK9lVrP8Dztm2gFMAQjh95rT}Vj=?Nc^_j`{FiKG^ z$BcXd7nC!ShD=8FF^p&0giTS=e$Q65afm??ju}>r-gxnn28JG^&j|{r*hyG6hGrd@ zn;p(;v*Vhm)BUGF)RTyS39$-1bHZ{ZFGg2&C35!7EDfp6ywk4LWR4PoR zmqE@L%ZsAOazQp23=l-Xow2a$1uVCxt{_8Ka||0B$O68iT0~PgMw3XlQ!wp@tmW3q zL<+`ws?G8Y=ciN$D$4(%rrAKdI16{;{im>-pRpmEg)W+MG}5?IkMGKsk`7cca`FgG z)T=mBMi{weWP@Z*V0fUYnqm2tDnn7EjOAk0(qKl8(L{qW3|$h0gcy#5#XgxQE5#@H z-b9LvCuAWW4u^T6&XtiiWkL(rx%v(_-jwSPgJ~1bGIWe-sHYudf@;!|(L9z&Q@t8j zZyrluQ!Yz_Vg1(r)#|#5%#VL;3@*7eMju*a-W@X7uM6uUc@)zbIiB~v6n|}P^|w5l zTbgehxOKc+|M2+y)8PEtX>jSvG8YK6KUB^RToZ#k0L8C}7*aOORERAXp(@d;M@y64rfH{IcG_rnP;5nYc8JnjcG0T#E+QU5 zs*iZ2#G_3_kWz#owBBWKhJWhppTDHXvOs!~Zs003ZUKS&~}ed}3sHF?YR>HR z7{ukEh}00l=3&S%D)quJ%z*uWl+!3yo)oEzQ3mZ?m!XWd7XK$6wn{ zCI0pY`la=WzvW~gB7kjN@IJdA#F?7!c0<6`pbDvxt*|}T_7I*AQruwO`?b?GWLwIG z3#%bn1Y5@g-#S06F~#o)psL(MoR8$0IdX(?zH2%Hg>`-ccp8Jxl5wmiB;#`T*~W0< znaT0nzdmc`x@1}eckrIK6%W^bmr&dk$>w3NON(e^`pfR9b^VYcttCtww}oq_rmMmq zr&tL*m1S{@%|b_)0{U~((m1p?x>wnixKb|h6AUxEljFx^j;*9pB6C?#lY>gXQER~sqEX35bbegB4}YF^IdrZK;M znl`#LDXZ=|8q)iiRsK;<(pLKZud5_)mN!+nha$ zWNrBQ-{wyo4|n3P$E-?ncO=hO33T~thkU_L{i%-0sZ zd2{S+4(o(`QOHbPsXKG{Rrp&hHBccwUlM$Fj+$|jVz-oXx;xDEX4pQl>($7h=S#`a z<7BrxvDZS~G7lxC-xtTHb}WM_`nm7(E|%KK;xbB~$>Oiq+Q@m?t)cP+!J|9!3x(6q z1~avUd~h#e#S9o_7?V7N4yM rAJu+hrOyL~{R^MggEV{Jw!@4_--m(0mA>u4kuQ8ZP9_jTL4ffes3;L^ diff --git a/theme/base/pix/fp/dnd_arrow.png b/theme/base/pix/fp/dnd_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..771f95a6a95c2aee08c403be60b5439e8df1e6da GIT binary patch literal 3158 zcmaJ@c{r47A08Dc;be#-)ijpLHVej>(PSH>jAYAF7&8-N%wlHjzGLW=M6#T;SR%5N zH6b}en=KQ{Qlcm#TbArbzR{_^?~kwVy{`9tp67Sn_x)S1>v>~rZ7e0XD{cn>0FqXR zadyJhK={JM#f0BV$8A{Q@;k@enPbm5%?To~$N&=(!;1{Eq7l5wc4Pu6#J`z*5CGV$ zLUC~BIODA`L`kF#!BaJLU=W3b1)o6T;drJQ z*@tpClts1=wQ(SZQi*61*ys@GU@%4~KqGSqpkSIGos9{`g1_lvg!>IM3=H}P;ZU*Q ze}Zzx+k(s(EHVfQg=-Vx`UsG|9u%PmN9&=rKss;)9EQ+=!BN@>I0lKrz!9MD4_N4p zMLLbK!&!XyB|KrlJ{%4c1A_$x1wn&!p$wKc41q?YVQ?Loj*hkvq0J7Va|prObhh#j z1ss`8WKozL3WE;XP$YOU0ytQ(Fw%cgpfP{S(%Ik3BrF&#n81V~pzw{9egN_K{|}|n zexlhNJMw?x{hz{YhY%(iW=Cc-0$4<0<4!AYxME_=SY!f+!E#_Q{C-r?)`!7iuzeUz zkeNLaiU8pWL<)Vw@{NJVW31?G4uMW2Tj8)^p$3#fAz_e6lnw$8H$cOYx(I|h0*ynM z8t5Z+;HIW<3sa=Y4=#>D44{$eoF81$f4JyhayN#7#uR$Sky(^LGRcC)pn<+6jiLNH z7X4r9edm&X9SiE0T$nHz*hXvrtJObD!ui?Q{v2H4;pga+>B4zu2?v`iPYD13#G9;e zCJw=GI$ddTj+Vb?ET)Am-t9dV*n;w+T+gjQ9`H$Zwm;#!mK7sN$o&fcqrF=p|F`#- zw$%y9cEHqJ{TD`fsvFRJ`(GMVio@+Tlt1!{4wgg7t+Z@ z*M9TH&Peao^`52&x)(Re0;eV>M}u|Jr1dt1m?DgDvBm)~%+qm)H3eQJGigfQ-O1eG zLumMIfxLfLzYQ03qQ*A_;>NoftECwCw4)Vi`KJoK^Rdax=e7G%HOiGCmcHi;L%1xE z@enr+vA5maQ_IOVvv6eWTFqgvrv+=a1-8B^E!26Ny(Ziju{n?0wt?E!Aj5rec@Rl$ z@e0)f@Ao(FfhWJNU@J~7$Fq@9Tb?1(Q^YPn6if2zEs&p-r4OPN^M-+&V^r{M`6@ST z74PSsj}KvaDJ-1SN;66W${IUKlX68SLkP)dW__ZZ6B02l6T~5&liPKQ={?ilw3urw zYkwa9rU_`|JYZ%1l=Gn4n3a^+OI)Jr@}CWCi-_}^O}w6^`HJ}g$?Ag-#-+~69O{UQ z4sFdPK(f&aTl!|14M_>ii_l#~%LPu^muC{H#6N|bHKMwW4{R#f$tot8`r2-nN}RSy z^#OYpm`Bf*itg~ANapQeBxmaJuBz&dhRbfv+L>^%(WD~N_zbw%4I>7kOTFk)D>u8q zS&swmj~tD5HKN4PDnerpmq71L0v+tQB`Zf9|S(JWlUiida&!Zh)qe`l9Xl0m94X0YLYCf>9cZ zoA@Q+WVykkIIEj0jrsb6FS)*Ft|Nl$-76=kcRu+qmFZ+er6lkt>#z9!ptb zoSMN-0AvvG{@PAwrR*KSt-Av<*-V|sXBxV;AhMiuefl2IZXfB#c;=A~sPT=p#A$MB zVI9}_;r_PKbX=phflU-i|2^1DxBk8$64!hbNChj5CK4H<{$sEBgy$86)dBsPA%tE0 znIjjl{t>;W?#M$I4%P&+qe?E@znOA44=7C&n}4{=Bc?Y;Jyo{7`l!8V;_Dlil|u(8 zqoY&tG2?r-W=!6&Y7rYa+Pgj{37CQ$U17aFB_RkdyB61|Q#;bh(yG{mY86$|K0}O` zayu1?j_Qn#tN$p2+E#0zww+vkdFD&cc_z2?Cq!);>zJO8Ny*9KcUB%(rGJpimx<}iUXz5hsVd)J*81|K zcui)b0W5tSfpPaD0y`ijlIxSyDM9E+>AjP3L>~zgK+oWGvrFh}em$_JEnuNgsfp9S zz*Qi)Kt~!uaMdyYNy5BX5^xW?;hd*p!RP7+-HV4St%myT&PE$jmtV~A8pUeYmwK{c zAMJfBm!|Ldv_n8^>+T9^O4Z?l3iEwm=S)e}6-khnB$L!aea&JS2F*sJOsdM|gSWov zQ0|SSILd=dp@+1W0=12H4_QLj1{T{QmJ1%g{uuH8GikNgW|xMRk&6=VQ20=9#M_ExfJja% z_2xEimjOkjZtmT~5I{sG^#yj(e>x?AvxLYi9CD2u^kF3UUzw$4(K-7xU(DxXld&X;avc~^z zCskCLRiH_?rE{vw%N?_ml)_dmu+kb$xw!D%EhCF{yu})~k_@cg827e=NHlco9a+n+ zjs=!~l!rkrwUkl+phK&Q#2c`Mrp`O6i=MOLPn3NEJB=heP)}DuU%DUPGAkgdH+j@8 zb?$QypR+7KyIXY=ZnI_{V5qZa3HcDMgBO*!a;(nZUTQVfV1!^Hq~a2Z#qL;ja5gKjlT-PXp(e3`46U2YD1z22^EEY ps^(u=S?d=mM9H^~*=du0Fs literal 0 HcmV?d00001 diff --git a/theme/base/style/filemanager.css b/theme/base/style/filemanager.css index 559f39aa044..1d1c1eac5eb 100644 --- a/theme/base/style/filemanager.css +++ b/theme/base/style/filemanager.css @@ -1,78 +1,36 @@ /** - * File picker + * File Picker and File Manager */ -/* first or middle sibling, no children */ -.file-picker .ygtvtn, .filemanager .ygtvtn {background: url([[pix:moodle|y/tn]]) 0 0 no-repeat;width:17px;height:22px;} -/* first or middle sibling, collapsable */ -.file-picker .ygtvtm, .filemanager .ygtvtm {background: url([[pix:moodle|y/tm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* first or middle sibling, collapsable, hover */ -.file-picker .ygtvtmh, .filemanager .ygtvtmh {background: url([[pix:moodle|y/tmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* first or middle sibling, expandable */ -.file-picker .ygtvtp, .filemanager .ygtvtp {background: url([[pix:moodle|y/tp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* first or middle sibling, expandable, hover */ -.file-picker .ygtvtph, .filemanager .ygtvtph {background: url([[pix:moodle|y/tph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* last sibling, no children */ -.file-picker .ygtvln, .filemanager .ygtvln {background: url([[pix:moodle|y/ln]]) 0 0 no-repeat;width:17px;height:22px;} -/* Last sibling, collapsable */ -.file-picker .ygtvlm, .filemanager .ygtvlm {background: url([[pix:moodle|y/lm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Last sibling, collapsable, hover */ -.file-picker .ygtvlmh, .filemanager .ygtvlmh {background: url([[pix:moodle|y/lmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Last sibling, expandable */ -.file-picker .ygtvlp, .filemanager .ygtvlp {background: url([[pix:moodle|y/lp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Last sibling, expandable, hover */ -.file-picker .ygtvlph, .filemanager .ygtvlph {background: url([[pix:moodle|y/lph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;} -/* Loading icon */ -.file-picker .ygtvloading, .filemanager .ygtvloading {background: url([[pix:moodle|y/loading]]) 0 0 no-repeat;width:16px;height:22px;} -/* the style for the empty cells that are used for rendering the depth* of the node */ -.file-picker .ygtvdepthcell, .filemanager .ygtvdepthcell {background: url([[pix:moodle|y/vline]]) 0 0 no-repeat;width:17px;height:22px;} -.file-picker .ygtvblankdepthcell, .filemanager .ygtvblankdepthcell {width:17px;height:22px;} -/* the style of the div around each node */ -.file-picker .ygtvitem table, .filemanager .ygtvitem table{margin-bottom:0;} -.file-picker .ygtvitem td, .filemanager .ygtvitem td {border:none;padding:0;} -/* the style of the div around each node's collection of children */ -* html .file-picker .ygtvchildren, * html .filemanager .ygtvchildren {height:1%;} -/* the style of the text label in ygTextNode */ -.file-picker .ygtvlabel, -.file-picker .ygtvlabel:link, -.file-picker .ygtvlabel:visited, -.file-picker .ygtvlabel:hover, -.filemanager .ygtvlabel, -.filemanager .ygtvlabel:link, -.filemanager .ygtvlabel:visited, -.filemanager .ygtvlabel:hover {margin-left:2px;text-decoration: none;} -.file-picker .fp-treeview .fp-folder .fp-icon, -.filemanager .fp-treeview .fp-folder .fp-icon {display:none;} - -.file-picker {font-size:12px;} -.file-picker.fp-generallayout {width:700px;height:480px;} - - -.file-picker {font-size:11px;color: #555;letter-spacing: .2px;} -.file-picker a {color:#555;} -.file-picker a:hover {color:#555;text-decoration: none;} -.file-picker select, input, button, textarea {/*font: 99% arial,helvetica,clean,sans-serif;*/color:#555;letter-spacing: .2px;} -.file-picker input {border: 1px solid #BBB;width: 265px;height: 18px;padding: 1px 6px;} -.file-picker select {height: 22px;padding: 2px 1px;} -.file-picker strong {background:#FFFFCC;} -.file-picker .fp-content-center {height: 100%;width: 100%;display:table-cell;vertical-align: middle;} + +.filemanager, .file-picker {font-size:11px;color: #555;letter-spacing: .2px;} +.filemanager a, .file-picker a {color:#555;} +.filemanager a:hover, .file-picker a:hover {color:#555;text-decoration: none;} +.filemanager select, input, button, textarea, +.file-picker select, input, button, textarea {color:#555;letter-spacing: .2px;} +.filemanager input, .file-picker input {border: 1px solid #BBB;width: 265px;height: 18px;padding: 1px 6px;} +.filemanager select, .file-picker select {height: 22px;padding: 2px 1px;} +.fp-content-center {height: 100%;width: 100%;display:table-cell;vertical-align: middle;} /* - * Layout + * Dialogue (File Picker and File Manager) */ -.file-picker.fp-generallayout {/*width: 724px;*/min-width: 724px;max-width: 980px;border: none;border:1px solid #CCC;border-radius:10px;position: relative;} -.file-picker .fp-wrapper {width:724px;} -.file-picker .yui3-widget-hd {border-radius: 10px 10px 0px 0px;border-bottom: 1px solid #BBB;padding:5px 5px 5px 5px!important;text-align: center;font-size:12px;letter-spacing: 1px;color:#333!important; text-shadow: 1px 1px 1px #FFF;filter: dropshadow(color=#FFF, offx=1, offy=1); +.yui3-panel-content {padding-bottom: 20px!important;background: #F2F2F2!important;border-radius: 8px;border: 1px solid #FFF!important;display: inline-block;-webkit-box-shadow: 5px 5px 20px 0px #666!important;-moz-box-shadow: 5px 5px 20px 0px #666!important;box-shadow: 5px 5px 20px 0px #666!important;} +.yui3-widget-hd {border-radius: 10px 10px 0px 0px;border-bottom: 1px solid #BBB;padding:5px 5px 5px 5px!important;text-align: center;font-size:12px;letter-spacing: 1px;color:#333!important; text-shadow: 1px 1px 1px #FFF;filter: dropshadow(color=#FFF, offx=1, offy=1); background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF', endColorstr='#CCC')!important;background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#CCC))!important;background: -moz-linear-gradient(top, #FFF, #CCC)!important;} +.fp-panel-button {background: #FFF;padding: 3px 20px 2px 20px; text-align: center;margin:10px; border-radius: 10px;display: inline-block;-webkit-box-shadow: 2px 2px 3px .1px #999;-moz-box-shadow: 2px 2px 3px .1px #999;box-shadow: 2px 2px 3px .1px #999;} + +/* + * File Picker layout + */ +.file-picker.fp-generallayout {width: 724px;background: #FFF!important;border-radius:10px;border: 1px solid #CCC!important;position: relative;} .file-picker .fp-repo-area {width:180px;overflow:auto;display:inline-block;border-right:1px solid #BBB;position:absolute;top:26px;bottom:1px;} -.file-picker .fp-right {background: yellow;height: auto;} .file-picker .fp-repo-items {vertical-align:top;display: inline-block;margin-left: 181px;} -.file-picker .fp-navbar {background: #F2F2F2;min-height:27px;border-bottom: 1px solid #BBB;padding: 5px 8px;/*position: absolute;left:182px;right:0px;*/width:527px;} -.file-picker .fp-content {background: #FFF;clear: both;overflow:auto;/*resize:both;*/width: 543px;min-width: 543px;max-width: 780px;height: 349px;min-height: 349px;max-height: 700px;/*border-bottom-right-radius: 10px;*//*top:100px;position: relative;*/margin-bottom: 6px;} -.file-picker .fp-repo-items p{width: auto;} +.file-picker .fp-navbar {background: #F2F2F2;min-height:22px;border-bottom: 1px solid #BBB;padding: 5px 8px;} +.file-picker .fp-content {background: #FFF;clear: both;overflow:auto;width: 543px;height: 349px;margin-bottom:-14px;} .file-picker .fp-content .fp-object-container {width:98%;height:98%;} /* - * Repositories + * Repositories on fp-repo-area (File Picker only) */ .file-picker .fp-list {list-style-type:none;padding:0;float:left;width:100%;margin:0;} .dir-rtl .file-picker .fp-list {text-align:right;} @@ -81,174 +39,235 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st .file-picker .fp-repo-icon {padding: 0px 7px 0px 5px;} /* - * Repository tools, path & view + * Tools, Path & View on fp-navbar (File Picker and File Manager) */ -.file-picker .fp-viewbar {float:right;width:69px;height:22px;/*margin-top:3px;*/margin-right:8px;} -.file-picker .fp-viewbar.disabled {/*display:none;*/} -.file-picker .fp-vb-icons {background:url('[[pix:theme|fp/view_icon_active]]') no-repeat 0 0;width:22px;height:22px;display: inline-block;} -.file-picker .fp-vb-icons.checked {background:url('[[pix:theme|fp/view_icon_selected]]');} -.file-picker .fp-viewbar.disabled .fp-vb-icons {background:url('[[pix:theme|fp/view_icon_inactive]]');} -.file-picker .fp-vb-details {background:url('[[pix:theme|fp/view_list_active]]') no-repeat 0px 0px;width:23px;height:22px;display: inline-block;/*margin-left: -4px;*/margin-left: -3px;} -.file-picker .fp-vb-details.checked {background:url('[[pix:theme|fp/view_list_selected]]');} -.file-picker .fp-viewbar.disabled .fp-vb-details {background:url('[[pix:theme|fp/view_list_inactive]]');} -.file-picker .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_active]]') no-repeat 0px 0px;width:23px;height:22px;display: inline-block;/*margin-left: -4px;*/margin-left: -4px;} -.file-picker .fp-vb-tree.checked {background:url('[[pix:theme|fp/view_tree_selected]]');} -.file-picker .fp-viewbar.disabled .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_inactive]]');} - -.file-picker .fp-toolbar {/*padding:7px 0px 0px 0px;*/display: table-row;} -.file-picker .fp-toolbar.empty {display:none;} -.file-picker .fp-toolbar .disabled {display:none;} -.file-picker .fp-toolbar div {display: inline-block;padding: 0px 2px 2px;} -.file-picker .fp-toolbar img {vertical-align: -20%;margin-right: 5px;} -.file-picker .fp-toolbar a {} -.file-picker .fp-toolbar .fp-search {} -.file-picker .fp-searchbar {} -.file-picker .search-entry {background:#FFF url('[[pix:a/search]]') no-repeat 3px 3px;height:18px;width:230px;border: 1px solid #BBB;padding-left:20px;/*margin-left: 7px;*/} +.fp-toolbar {display: table-row;line-height: 22px;} +.fp-toolbar.empty {display:none;} +.fp-toolbar .disabled {display:none;} +.fp-toolbar div {display: inline-block;padding: 0px 2px;} +.fp-toolbar img {vertical-align: -15%; margin-right: 5px;} +.file-picker .search-entry {background:#FFF url('[[pix:a/search]]') no-repeat 3px 3px;height:18px;width:230px;border: 1px solid #BBB;padding-left:20px;} .file-picker .fp-pathbar {display: table-row;} -.file-picker .fp-pathbar .fp-path-folder {background:url('[[pix:theme|fp/path_folder]]') no-repeat 0 0;width:27px;height:12px;margin-left: 4px;} -.file-picker .fp-pathbar .fp-path-folder-name {margin-left: 32px;line-height: 20px;} +.fp-pathbar .fp-path-folder {background:url('[[pix:theme|fp/path_folder]]') no-repeat 0 0;width:27px;height:12px;margin-left: 4px;} +.fp-pathbar .fp-path-folder-name {margin-left: 32px;line-height: 20px;} + +.fp-viewbar {float:right;width:69px;height:22px;margin-right:8px;} +.fp-vb-icons {background:url('[[pix:theme|fp/view_icon_active]]') no-repeat 0 0;width:22px;height:22px;display: inline-block;} +.fp-vb-icons.checked {background:url('[[pix:theme|fp/view_icon_selected]]');} +.fp-viewbar.disabled .fp-vb-icons {background:url('[[pix:theme|fp/view_icon_inactive]]');} +.fp-vb-details {background:url('[[pix:theme|fp/view_list_active]]') no-repeat 0px 0px;width:23px;height:22px;display: inline-block;margin-left: -4px;} +.fp-vb-details.checked {background:url('[[pix:theme|fp/view_list_selected]]');} +.fp-viewbar.disabled .fp-vb-details {background:url('[[pix:theme|fp/view_list_inactive]]');} +.fp-vb-tree {background:url('[[pix:theme|fp/view_tree_active]]') no-repeat 0px 0px;width:23px;height:22px;display: inline-block;margin-left: -4px;} +.fp-vb-tree.checked {background:url('[[pix:theme|fp/view_tree_selected]]');} +.fp-viewbar.disabled .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_inactive]]');} /* - * Icon view + * Icon view (File Picker and File Manager) */ -.file-picker .fp-iconview .fp-file {float:left;display: block;text-align:center;padding: 5px 5px;} -.file-picker .fp-iconview .fp-thumbnail {/*overflow: hidden;*/display: table-cell;vertical-align: middle;} -.file-picker .fp-iconview .fp-thumbnail img {border: 1px solid #CCC;padding: 3px;-webkit-box-shadow: 1px 1px 2px 0px #CCC;-moz-box-shadow: 1px 1px 2px 0px #CCC;box-shadow: 1px 1px 2px 0px #CCC;} -/*.file-picker .fp-iconview .fp-file .fp-thumbnail.over {border:1px solid red;}*/ -.file-picker .fp-iconview .fp-filename {height:28px;min-width:50px;word-wrap:break-word;padding-top: 5px;overflow: hidden;} +.fp-iconview .fp-file {float:left;display: block;text-align:center;padding: 5px 5px;margin-bottom: 33px;position: relative;} +.fp-iconview .fp-thumbnail {display: table-cell;vertical-align: middle;} +.fp-iconview .fp-thumbnail img {border: 1px solid #CCC;padding: 3px;-webkit-box-shadow: 1px 1px 2px 0px #CCC;-moz-box-shadow: 1px 1px 2px 0px #CCC;box-shadow: 1px 1px 2px 0px #CCC;} +.fp-iconview .fp-file .fp-thumbnail:hover {background: #FFF;-webkit-box-shadow: inset 0px 0px 10px 0px #BBB;-moz-box-shadow: inset 0px 0px 10px 0px #BBB;box-shadow: inset 0px 0px 10px 0px #BBB;} +.fp-iconview .fp-filename {height:28px;min-width:50px;word-wrap:break-word;padding-top: 5px;overflow: hidden;position: absolute;} +.fp-iconview .fp-filename:hover {overflow: visible;z-index: 1000;background-color: #FFF;position:absolute;display: table;padding-bottom: 12px;} /* - * Table view + * Table view (File Picker only) */ .file-picker .yui3-datatable table {border: 0px solid #BBB;width:100%;} .file-picker .yui3-datatable-header {background: #FFF;border-bottom: 1px solid #CCC;border-left: 0 solid #FFF;color: #555;} .file-picker .yui3-datatable-columns .yui3-datatable-sorted, .file-picker .yui3-datatable-sortable-column:hover {background-color: #FFF;} -.file-picker .yui3-datatable-odd .yui3-datatable-cell {background-color: #F2F2F2;border-left: 0px solid #F2F2F2;} -.file-picker .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted {background-color: #F2F2F2;} +.file-picker .yui3-datatable-odd .yui3-datatable-cell {background-color: #F6F6F6;border-left: 0px solid #F6F6F6;} +.file-picker .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted {background-color: #F6F6F6;} .file-picker .yui3-datatable-even .yui3-datatable-cell {background-color: #FFF;border-left: 0px solid #FFF;} .file-picker .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted {background-color: #FFF;} .file-picker .fp-icon img {max-height:16px;max-width:16px;} /* - * Login + * Tree view (File Picker and File Manager) + */ +/*.file-picker .fp-treeview .fp-folder .fp-icon, .filemanager .fp-treeview .fp-folder .fp-icon {}*/ +/* first or middle sibling, no children */ +/*.file-picker .ygtvtn, .filemanager*/ .ygtvtn {background: url('[[pix:moodle|y/tn]]') 0 0 no-repeat;width:17px;height:22px;} +/* first or middle sibling, collapsable */ +/*.file-picker .ygtvtm, .filemanager*/ .ygtvtm {background: url('[[pix:moodle|y/tm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* first or middle sibling, collapsable, hover */ +/*.file-picker .ygtvtmh, .filemanager*/ .ygtvtmh {background: url('[[pix:moodle|y/tm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* first or middle sibling, expandable */ +/*.file-picker .ygtvtp, .filemanager*/ .ygtvtp {background: url('[[pix:moodle|y/tp]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* first or middle sibling, expandable, hover */ +/*.file-picker .ygtvtph, .filemanager*/ .ygtvtph {background: url('[[pix:moodle|y/tp]]') 0 0 no-repeat;width:13px;height:22px;cursor:pointer;} +/* last sibling, no children */ +/*.file-picker .ygtvln, .filemanager*/ .ygtvln {background: url('[[pix:moodle|y/ln]]') 0 0 no-repeat;width:17px;height:22px;} +/* Last sibling, collapsable */ +/*.file-picker .ygtvlm, .filemanager*/ .ygtvlm {background: url('[[pix:moodle|y/lm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* Last sibling, collapsable, hover */ +/*.file-picker .ygtvlmh, .filemanager*/ .ygtvlmh {background: url('[[pix:moodle|y/lm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* Last sibling, expandable */ +/*.file-picker .ygtvlp, .filemanager*/ .ygtvlp {background: url('[[pix:moodle|y/lp]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* Last sibling, expandable, hover */ +/*.file-picker .ygtvlph, .filemanager*/ .ygtvlph {background: url('[[pix:moodle|y/lp]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +/* Loading icon */ +/*.file-picker .ygtvloading, .filemanager*/ .ygtvloading {background: url('[[pix:moodle|y/loading]]') 0 0 no-repeat;width:16px;height:22px;} +/* the style for the empty cells that are used for rendering the depth* of the node */ +/*.file-picker .ygtvdepthcell, .filemanager*/ .ygtvdepthcell {background: url('[[pix:moodle|y/vline]]') 0 0 no-repeat;width:17px;height:22px;} +/*.file-picker .ygtvblankdepthcell, .filemanager*/ .ygtvblankdepthcell {width:17px;height:22px;} +/* the style of the div around each node */ +/*.file-picker .ygtvitem table, .filemanager .ygtvitem table{margin-bottom:0;}*/ +/*.file-picker .ygtvitem td, .filemanager .ygtvitem td {border:none;padding:0;}*/ +/* the style of the div around each node's collection of children */ +/** html .file-picker .ygtvchildren, * html .filemanager .ygtvchildren {height:1%;}*/ +/* the style of the text label in ygTextNode */ +/*.file-picker .ygtvlabel,.file-picker .ygtvlabel:link,.file-picker .ygtvlabel:visited,.file-picker .ygtvlabel:hover, +.filemanager .ygtvlabel,.filemanager .ygtvlabel:link,.filemanager .ygtvlabel:visited,.filemanager .ygtvlabel:hover {margin-left:2px;text-decoration: none;}*/ +a.ygtvspacer:hover {color: transparent;text-decoration: none;} +.ygtvlabel, .ygtvlabel:link, .ygtvlabel:visited, .ygtvlabel:hover {background-color: transparent;cursor: pointer;margin-left: 2px;text-decoration: none;} +/*.file-picker*/ .ygtvfocus {background-color: /*#FFF*/ transparent;} + +/* + * Repositories Login on fp-content (File Picker only) */ .file-picker .fp-login-form {height: 100%;width: 100%;display: table;} .file-picker .fp-login-form table {margin: 0 auto;} .file-picker .fp-login-form p {text-align: center;margin-top: 3em;} -.file-picker .fp-login-form .fp-login-input .label {text-align: right;vertical-align: middle;/*width: 30%;*/} +.file-picker .fp-login-form .fp-login-input .label {text-align: right;vertical-align: middle;} .file-picker .fp-login-form .fp-login-input .input {text-align: left;} .file-picker .fp-login-form input[type="checkbox"]{width: 15px;height:15px;} /* - * Select - */ -.file-picker .fp-select {width:420px;min-height:auto;text-align:left;background: #F2F2F2;border-radius: 8px;border: 1px solid #FFF; --webkit-box-shadow: 5px 5px 20px 0px #666666;-moz-box-shadow: 5px 5px 20px 0px #666666;box-shadow: 5px 5px 20px 0px #666666;text-align: center;} -.file-picker.fp-select .uneditable {display:none;} -.file-picker.fp-select p {} -.file-picker.fp-select .fp-select-loading {display:none;} -.file-picker.fp-select.loading .fp-select-loading {display:block;} -.file-picker.fp-select.loading form {display:none;} -.file-picker .fp-select-confirm {background: #FFF;padding: 3px 20px 2px 20px; margin: 5px 0px 10px 20px; border-radius: 10px;float:left;-webkit-box-shadow: 2px 2px 1px .1px #999;-moz-box-shadow: 2px 2px 1px .1px #999;box-shadow: 2px 2px 3px .1px #999;} -.file-picker .fp-select-cancel {background: #FFF;padding: 3px 20px 2px 20px; margin: 5px 0px 10px 20px; border-radius: 10px;float:left;-webkit-box-shadow: 2px 2px 1px .1px #999;-moz-box-shadow: 2px 2px 1px .1px #999;box-shadow: 2px 2px 3px .1px #999;} -.file-picker.fp-select .fp-hr {clear: both;height: 1px; background-color: #FFF;border-bottom: 1px solid #BBB;width: auto; margin: 20px;} -.file-picker.fp-select table {margin: 10px 10px;} -.file-picker.fp-select .fp-thumbnail {float:left;width:110px;height:110px;line-height: 110px;text-align: center;margin: 10px 0px 10px 20px;background: #FFF;-webkit-box-shadow: inset 0px 0px 10px 0px #BBB;-moz-box-shadow: inset 0px 0px 10px 0px #BBB;box-shadow: inset 0px 0px 10px 0px #BBB;} -.file-picker.fp-select .fp-thumbnail img {border: 1px solid #CCC;padding:3px;vertical-align: middle;} -.file-picker.fp-select .fp-fileinfo {display: inline-block;/*margin-left: 10px; */margin: 4px 0px 20px 0px;width:240px;text-align: left;} -.file-picker.fp-select .fp-fileinfo div {/*paddign-top:5px;padding-bottom:5px;*/padding: 4px 0px;} - -/* - * Upload + * Upload on fp-content (File Picker only) */ .file-picker .fp-upload-form {height: 100%;width: 100%;display: table;} .file-picker .fp-upload-form table {margin: 0 auto;} -.file-picker .fp-upload-btn {/*clear:both;*/margin: 2em;} +.file-picker .fp-upload-btn {margin: 2em;} /* - * Error + * File exists dialogue on Upload (File Picker only) + */ +.file-picker.fp-dlg {text-align: center;} +.file-picker.fp-dlg .fp-dlg-text {padding: 40px 20px 10px 20px;} + +/* + * Error dialogue on Upload (File Picker only) + */ +.file-picker.fp-msg {text-align: center;} +.file-picker.fp-msg .fp-msg-text {padding: 40px 20px 10px 20px;min-width:200px;max-width:500px;max-height:300px;overflow:auto;} +.file-picker.fp-msg.fp-msg-error .fp-msg-text {padding: 40px 20px 10px 20px;} + +/* + * Error on fp-content (File Picker only) */ .file-picker .fp-content-error {height: 100%;width: 100%;display: table;text-align: center;} -.file-picker .fp-content-error .fp-error {height: 100%;width: 100%;display:table-cell;vertical-align: middle;} - -.file-picker .fp-msg {border: none;border:1px solid #CCCCCC;border-radius:10px;text-align: center;padding-bottom: 30px;} -.file-picker .fp-msg .fp-msg-text {min-width:200px;/*min-height:50px;*/max-width:500px;max-height:300px;overflow:auto;} -.file-picker .fp-msg.fp-msg-error .fp-msg-text {padding: 30px 40px 20px 40px;margin-bottom: 10px;} -.file-picker .fp-msg .fp-msg-butok {} - - +.file-picker .fp-content-error .fp-error {height: 100%;width: 100%;display:table-cell;vertical-align: middle;padding: 40px 20px 10px 20px;} +/* + * Lazy loading on fp-content (File Picker only) + */ .file-picker .fp-nextpage {clear:both;align:center;} .file-picker .fp-nextpage .fp-nextpage-link {align:center;} .file-picker .fp-nextpage .fp-nextpage-loading {display:none;} .file-picker .fp-nextpage.loading .fp-nextpage-link {display:none;} .file-picker .fp-nextpage.loading .fp-nextpage-loading {display:block;} -.file-picker .fp-popup {text-align:center;} + +/* + * Select Dialogue (File Picker and File Manager) + */ +.file-picker.fp-select {width:420px;} +.fp-select .fp-hr {clear: both;height: 1px; background-color: #FFF;border-bottom: 1px solid #BBB;width: auto; margin: 5px 20px;} +.fp-select table {margin: 10px 20px;} -.filepicker-filelist {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid} +/*.file-select table input[type="radio"]{text-align: left;}*/ -/* file picker search dialog */ -.file-picker div.bd {text-align:left;} +.fp-select-update {float:right;width: auto;margin-right: 20px;} +.fp-select .fp-thumbnail {float:left;min-width:110px;min-height:110px;line-height: 110px;text-align: center;margin: 10px 20px 0px 20px;background: #FFF;-webkit-box-shadow: inset 0px 0px 10px 0px #BBB;-moz-box-shadow: inset 0px 0px 10px 0px #BBB;box-shadow: inset 0px 0px 10px 0px #BBB;} +.fp-select .fp-thumbnail img {border: 1px solid #CCC;padding:3px;vertical-align: middle;margin: 10px;} +.fp-select .fp-fileinfo {display: inline-block;margin-top: 4px;margin-right: 20px;} +.file-picker.fp-select .fp-fileinfo {/*width:240px;*/} +.fp-select .fp-fileinfo div {padding: 4px 0px;} -/** +.file-picker.fp-select .uneditable {display:none;} +.file-picker.fp-select .fp-select-loading {display:none;} +.file-picker .fp-select.loading .fp-select-loading {display:block;} +.file-picker .fp-select.loading form {display:none;} + + /* * File Manager */ -.filemanager-toolbar {margin: 5px 0;} -.filemanager-toolbar a {border: 1px solid #AACCEE;background: #F4FAFF;color: black;padding: 3px;} -.filemanager-toolbar a:hover {background: #FFFFFF;} -.filemanager-toolbar .helplink a {border: 0px; background: transparent;} -.fp-pathbar {margin:0;} -.filemanager .fp-pathbar.empty {display:none;} -.filemanager-container {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid;position: relative;} -.filemanager-container ul{margin:0;padding:0;} -.filemanager-container ul li{white-space:nowrap;list-style-type:none;} -.filemanager-container ul li a{padding:0} .filemanager-loading{display:none} .jsenabled .filemanager-loading{display:block} -.fm-menuicon{cursor: pointer;} -#fm-move-div {margin: 6px;} -#fm-move-div strong{color:red;} -.fm-file-entry{border: 1px solid red;} -.fm-operation {font-weight: bold;} - -.filemanager-container, -.filepicker-filelist {overflow:hidden;} - -.filemanager.fm-loading .fp-pathbar, .filemanager.fm-loading .filemanager-toolbar, +.filemanager.fm-loading .fp-pathbar, .filemanager.fm-loading .filemanager-container {display:none;} - .filemanager.fm-loaded .filemanager-loading {display:none;} - -.filemanager.fm-nofiles .fp-btn-download {display:none;} - -.filemanager.fm-nomkdir .fp-btn-mkdir {display:none;} - .filemanager.fm-maxfiles .fp-btn-add {display:none;} .filemanager.fm-maxfiles .dndupload-message {display:none;} - +.filemanager.fm-nofiles .fp-btn-download {display:none;} .filemanager .fm-empty-container {display:none;} -.filemanager.fm-noitems .fm-empty-container {display:block;} .filemanager.fm-noitems .filemanager-container .fp-content {display:none;} - .filemanager .filemanager-updating {display:none;text-align:center;} .filemanager.fm-updating .filemanager-updating {display:block;} .filemanager.fm-updating .fm-content-wrapper {display:none;} -.filemanager .fp-iconview .fp-file {float:left;text-align:center;} -.filemanager .fp-iconview .fp-file div {overflow: hidden;} -.filemanager .fp-iconview .fp-file .fp-filename {height:48px;text-align:center;min-width:50px;} -.filemanager .fp-mainfile .fp-filename {font-weight:bold;} +.filemanager.fm-nomkdir .fp-btn-mkdir {display:none;} + /* + * File Manager layout + */ +.fp-restrictions{text-align: right;} +.filemanager .fp-navbar {background: #F2F2F2;border-top: 1px solid #BBB;border-left: 1px solid #BBB;border-right: 1px solid #BBB;} +.filemanager-toolbar{padding: 5px 8px;min-height:22px;} +.fp-pathbar {border-top: 1px solid #BBB;padding: 5px 8px 1px;min-height: 20px;} +.filemanager .fp-pathbar.empty {display:none;} +.filemanager-container {background: #FFF;clear: both;overflow:auto;border: 1px solid #BBB;min-height: 140px;position: relative;} +/*.filemanager-container ul{margin:0;padding:0;} +.filemanager-container ul li{white-space:nowrap;list-style-type:none;} +.filemanager-container ul li a{padding:0}*/ +.filemanager .fp-content{overflow: auto;max-height: 400px;} +.filepicker-filelist {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid} +.filemanager-container, .filepicker-filelist {overflow:hidden;} + +/* + * Table view (File Manager only) + */ +.filemanager .yui3-datatable table {border: 0px solid #BBB;width:100%;} +.filemanager .yui3-datatable-header {background: #FFF;border-bottom: 1px solid #CCC;border-left: 0 solid #FFF;color: #555;} +.filemanager .yui3-datatable-columns .yui3-datatable-sorted, .filemanager .yui3-datatable-sortable-column:hover {background-color: #FFF;} +.filemanager .yui3-datatable-odd .yui3-datatable-cell {background-color: #F6F6F6;border-left: 0px solid #F6F6F6;} +.filemanager .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted {background-color: #F6F6F6;} +.filemanager .yui3-datatable-even .yui3-datatable-cell {background-color: #FFF;border-left: 0px solid #FFF;} +.filemanager .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted {background-color: #FFF;} + +/* + * Drag and drop support (File Manager only) + */ +.filemanager.fm-noitems .fm-empty-container {display:block;position: absolute; top: 10px;bottom: 10px;left:10px;right: 10px;border: 2px dashed #BBB;padding-top: 85px;} +.filemanager-container .dndupload-target, +.filepicker-filelist .dndupload-target {background:#FFF;position:absolute;top:10px;left:10px;bottom:10px;right:10px;text-align:center;z-index:1000;border: 2px dashed #BBB;padding-top: 85px;-webkit-box-shadow: 0px 0px 0px 10px #FFF;-moz-box-shadow: 0px 0px 0px 10px #FFF;box-shadow: 0px 0px 0px 10px #FFF;} +.filemanager-container.dndupload-over .dndupload-target, +.filepicker-filelist.dndupload-over .dndupload-target {background:#FFF;position:absolute;top:10px;left:10px;bottom:10px;right:10px;border: 2px dashed #4c70c3;padding-top: 85px;} +.dndupload-message {display:none;} +.dndsupported .dndupload-message {display:inline;} +.dndupload-target {display:none;} +.dndsupported .dndupload-ready .dndupload-target {display:block;} +.dndupload-uploadinprogress {display:none;text-align:center;} +.dndupload-uploading .dndupload-uploadinprogress {display:block;} +.dndupload-arrow {background:url('[[pix:theme|fp/dnd_arrow]]') 0 0 no-repeat;width:56px;height:47px;position:absolute;left: 45%;animation:mymove 5s infinite;-moz-animation:mymove 5s infinite;-webkit-animation:mymove 5s infinite;}@keyframes mymove {0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}}@-moz-keyframes mymove{0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}}@-webkit-keyframes mymove {0%{top:10px;} 12%{top:40px;} 30%{top:20px} 65%{top:35px;} 100%{top:9px;}} + +/* + * Folder Context Menu (File Manager only) + */ .filemanager .fp-contextmenu {display:none;} -.filemanager .fp-iconview .fp-folder.fp-hascontextmenu .fp-contextmenu {display:block;position:absolute;right:0px;top:0px;} +.filemanager .fp-iconview .fp-folder.fp-hascontextmenu .fp-contextmenu {display:block;position:absolute;right:7px;bottom:5px;} .filemanager .fp-treeview .fp-folder.fp-hascontextmenu .fp-contextmenu, .filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu {display:inline;} +/* + * Select Dialogue (File Manager only) + */ .filemanager.fp-select .fp-select-loading {display:none;} .filemanager.fp-select.loading .fp-select-loading {display:block;} .filemanager.fp-select.loading form {display:none;} - /* disable unavailable actions: */ /*.filemanager.fp-select.fp-zip .fp-license,*/ .filemanager.fp-select.fp-folder .fp-license, @@ -260,26 +279,35 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st .filemanager.fp-select.fp-zip .fp-file-zip {display:none;} .filemanager.fp-select .fp-file-setmain {display:none;} .filemanager.fp-select.fp-cansetmain .fp-file-setmain {display:inline-block;} +.filemanager .fp-mainfile .fp-filename {font-weight:bold;} .filemanager.fp-select.fp-folder .fp-file-download {display:none;} /* to be implemented */ +.fm-operation {font-weight: bold;} .filemanager .fp-iconview .fp-reficons {position:absolute;height:100%;width:100%;top:0;left:0;z-index:1000;} -.filemanager .fp-iconview .fp-file.fp-hasreferences .fp-reficons {background: url([[pix:moodle|t/lock]]) no-repeat;background-position:bottom left;} -.filemanager .fp-iconview .fp-file.fp-isreference .fp-reficons {background: url([[pix:moodle|t/right]]) no-repeat;background-position:bottom right;} +.filemanager .fp-iconview .fp-file.fp-hasreferences .fp-reficons {background: url('[[pix:moodle|t/lock]]') no-repeat;background-position:bottom left;} +.filemanager .fp-iconview .fp-file.fp-isreference .fp-reficons {background: url('[[pix:moodle|t/right]]') no-repeat;background-position:bottom right;} .filemanager.fp-select .fp-original.fp-unknown {display:none;} .filemanager.fp-select .fp-original .fp-originloading {display:none;} .filemanager.fp-select .fp-original.fp-loading .fp-originloading {display:inline;} /* - * Drag and drop support + * Create folder dialogue (File Manager only) */ -.filemanager-container .dndupload-target, -.filepicker-filelist .dndupload-target {background:#f7f998;position:absolute;height:100%;width:100%;top:0;left:0;text-align:center;padding:5px;z-index:1000} -.filemanager-container.dndupload-over .dndupload-target, -.filepicker-filelist.dndupload-over .dndupload-target {background:#8EF947;font-weight:bold} -.dndupload-message {display:none;} -.dndsupported .dndupload-message {display:inline;} -.dndupload-target {display:none;} -.dndsupported .dndupload-ready .dndupload-target {display:block;} -.dndupload-uploadinprogress {display:none;text-align:center;} -.dndupload-uploading .dndupload-uploadinprogress {display:block;} +.filemanager .fp-mkdir-dlg input {margin-top: 20px;margin-left: 20px;float:left;} +.filemanager .fp-dlg-butcreate {margin-top: 20px;margin-right: 20px;} + + +/* + * Confirm dialogue for delete (File Manager only) + */ +.filemanager.fp-dlg {text-align: center;} +.filemanager.fp-dlg .fp-dlg-text {padding: 0px 10px;min-width:200px;max-width:340px;max-height:300px;overflow:auto;line-height: 22px;margin: 40px 20px 20px 20px;} + + + + +/* + *file picker search dialog + */ +.file-picker div.bd {text-align:left;} From 9dbdf31f8c1569af0bead5bf47a58d74acd2fb64 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 15 May 2012 10:51:00 +0800 Subject: [PATCH 268/455] MDL-32867 Display a list of references pointing to the file in filemanager --- files/renderer.php | 13 ++++++++++--- lang/en/repository.php | 3 +++ lib/filebrowser/file_info.php | 14 ++++++++++++++ lib/form/filemanager.js | 32 ++++++++++++++++++++++++++++++-- lib/outputrequirementslib.php | 3 ++- repository/draftfiles_ajax.php | 28 ++++++++++++++++++++++++++++ theme/base/style/filemanager.css | 5 +++++ 7 files changed, 92 insertions(+), 6 deletions(-) diff --git a/files/renderer.php b/files/renderer.php index 5746a464998..64f5fa15ee0 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -322,13 +322,18 @@ class core_files_renderer extends plugin_renderer_base { * disabled if they are not applicable for the particular file; * * There may be present elements with classes 'fp-original', 'fp-datemodified', 'fp-datecreated', - * 'fp-size', 'fp-dimensions'. They will receive additional class 'fp-unknown' if information - * is unavailable. If there is information available, the content of embedded element - * with class 'fp-value' will be substituted with the value; + * 'fp-size', 'fp-dimensions', 'fp-reflist'. They will receive additional class 'fp-unknown' if + * information is unavailable. If there is information available, the content of embedded + * element with class 'fp-value' will be substituted with the value; * * The value of Original ('fp-original') is loaded in separate request. When it is applicable * but not yet loaded the 'fp-original' element receives additional class 'fp-loading'; * + * The value of 'Aliases/Shortcuts' ('fp-reflist') is also loaded in separate request. When it + * is applicable but not yet loaded the 'fp-original' element receives additional class + * 'fp-loading'. The string explaining that XX references exist will replace content of element + * 'fp-refcount'. Inside '.fp-reflist .fp-value' each reference will be enclosed in
                        • ; + * * Elements with classes 'fp-file-update', 'fp-file-download', 'fp-file-delete', 'fp-file-zip', * 'fp-file-unzip', 'fp-file-setmain' and 'fp-file-cancel' will hold corresponding onclick * events (there may be several elements with class 'fp-file-cancel'); @@ -371,6 +376,8 @@ class core_files_renderer extends plugin_renderer_base { : '.$icon_progress.' '.$strloading.' + : +

                          '.$icon_progress.' '.$strloading.'

                        • - +
                          -
                          '.$icon_progress.'
                          +
                          '.$icon_progress.'
                          -
                          '.$strnofilesattached.' - '.$strdndenabledinbox.'
                          +
                          '.$strnofilesattached.' + '.$strdndenabledinbox.'
                          -
                          '.$strdroptoupload.'
                          +
                          '.$strdroptoupload.'
                          '.$icon_progress.'
                          '.$icon_progress.'
                          @@ -243,10 +243,14 @@ class core_files_renderer extends plugin_renderer_base { '; return preg_replace('/\{\!\}/', '', $rv); @@ -268,8 +272,10 @@ class core_files_renderer extends plugin_renderer_base { private function fm_js_template_listfilename() { $rv = ' + + '.$this->pix_icon('i/menu', '▶').' '; return preg_replace('/\{\!\}/', '', $rv); @@ -383,8 +389,8 @@ class core_files_renderer extends plugin_renderer_base {

                          - - + '.get_string('update', 'moodle').' + '.get_string('cancel').'

                          @@ -508,12 +514,12 @@ class core_files_renderer extends plugin_renderer_base {
                          -
                          +
                          - +
                          @@ -525,8 +531,8 @@ class core_files_renderer extends plugin_renderer_base {
                          - -
                          + +
                          @@ -555,7 +561,9 @@ class core_files_renderer extends plugin_renderer_base { $rv = '
                          -

                          +
                          +

                          +
                          '; return preg_replace('/\{\!\}/', '', $rv); } @@ -648,16 +656,15 @@ class core_files_renderer extends plugin_renderer_base {
                          - - + - + - + @@ -703,7 +710,7 @@ class core_files_renderer extends plugin_renderer_base { private function fp_js_template_uploadform() { $rv = '
                          -
                          +
                          :
                          @@ -733,9 +740,11 @@ class core_files_renderer extends plugin_renderer_base { */ private function fp_js_template_loading() { return ' -
                          - -

                          '.get_string('loading', 'repository').'

                          +
                          +
                          + +

                          '.get_string('loading', 'repository').'

                          +
                          '; } @@ -794,13 +803,13 @@ class core_files_renderer extends plugin_renderer_base { $rv = ' '; return preg_replace('/\{\!\}/', '', $rv); } - + /** * FilePicker JS template for repository login form including templates for each element type * diff --git a/theme/base/pix/fp/check.png b/theme/base/pix/fp/check.png new file mode 100644 index 0000000000000000000000000000000000000000..1fd55ffbcc2f9bd81dc2e6bfdf3126d3dcd57b5c GIT binary patch literal 1299 zcmeAS@N?(olHy`uVBq!ia0vp^f8U}fi7AzZCsS=07?@QuLn2Bde0{8v^K*7iAWdWaj57fJ{tG z$}cUkRRX#c;)UD-xUqS~&|m@vn0`fKfxe-h0mw@*g}%P{mFDKcRTq~8r6Sym)!^cg z%7Rq=pw#00(xPNw#HA^NtSYc_E=o--$uA1Y&(DE{Vn9ZINq%ugeu08>u&JJ*f^TAS zW*$fcti#vW$}_LHBrz{J)zigR32261W@d_&rMaQAk*lkzrMbDOp`ojxql>wjlewFj zv$>0zo0GXEOs`9Ra%paAUI|QZ3PP_LPQ9SSkXrz>*(J3ovn(~mttdZN0qkk3Ox$iU z#%Uf@ZwhX=nBdf_4|I$^C~A?S8YToxKOiPN;Q~4Eq@S7xOz%a&gk8n5d=Uc!W2>i& zV@SoVnkoCW+X6+7zpu2JdG8auhGb9M_8hgDK5ETA_a-GR+%6I*)*NJXA|cUGBQ?=f zQ*e{#%s<>dUe}-ht9kdda(?i0%kT4k+ukpJZ~44->1UfoMS>x#(>iC^eb$`PQ5>~e zt7(TnbMp&EyX*|21*5nX-Mh+xiQ|UrtV#&bgb}Su0|0#OxDu*D}9Z^!SB) zhjy}>Y@V{=a@7vYFM>NN!-Ut|Pv!}_wcTyQIUgnV2h$F$-BkBs$;S;Vblo(z-OgF0 z{ovgVnSaM4g`yw2+swbQ^Oc&FNa6A8**8m+UQb#d`jFeSZF#HhLF*TV&M#)F?^bxQ zv}$!oZu^M|GU{*sR*3(tRt(Xd9-I5Lc=B`xp`Ax}PW-WqW5z+hUw=)1O%pSk9razN zdPn!XUrpOMZmdKI;Vst0FC_F!2kdN literal 0 HcmV?d00001 diff --git a/theme/base/pix/fp/cross.png b/theme/base/pix/fp/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..7899d43f9ebfaacd7e8cea9c5564595ea837be86 GIT binary patch literal 1286 zcmeAS@N?(olHy`uVBq!ia0vp^f8U}fi7AzZCsS=07?@QuLn2Bde0{8v^K*7iAWdWaj57fJ{tG z$}cUkRRX#c;)UD-xUqS~&|m@vn0`fKfxe-h0mw@*g}%P{mFDKcRTq~8r6Sym)!^cg z%7Rq=pw#00(xPNw#HA^NtSYc_E=o--$uA1Y&(DE{Vn9ZINq%ugeu08>u&JJ*f^TAS zW*$fcti#vW$}_LHBrz{J)zigR32261W@d_&rMaQAk*lkvrMbDOp`ojxql>wjlewFj zv$>0zo0GXEOs`9Ra%paAUI|QZ3PP_VPQ9SSkXrz>*(J3ovn(~mttdZN0qkk3Ox$iU z$7vo^ZwhX=Sm4yF4|I$^C~A?S8YToxKOiPN;Q~4Eq@S7xOz%a&gl)3Ibr%BzV}+-S zV@SoVHIomzA8`~p{yewy1%F3J$E8HqD6e)~w~4>lg<=;)Tj|cdtXqA{Py40NTrclk zOPxzrcxWcw3@(Y9cH&FrXX*WOZ{afy zdxmur#4I!RI_~dsFssuRveDYQ?Tvmy$aHx|HijQB Date: Thu, 17 May 2012 14:18:13 +0800 Subject: [PATCH 277/455] MDL-28666, Fixed source field when download a file using filepicker --- repository/repository_ajax.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/repository/repository_ajax.php b/repository/repository_ajax.php index 56a482a2964..55c65ebe6e9 100644 --- a/repository/repository_ajax.php +++ b/repository/repository_ajax.php @@ -317,11 +317,18 @@ switch ($action) { } // Check if exceed maxbytes. - if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) { + if (($maxbytes!==-1) && (filesize($downloadedfile['path']) > $maxbytes)) { throw new file_exception('maxbytes'); } - $record->source = !empty($downloadedfile['url']) ? $downloadedfile['url'] : ''; + // {@link file_restore_source_field_from_draft_file()} + $sourcefield = ''; + if (!empty($downloadedfile['url'])) { + $source = new stdClass; + $source->source = $downloadedfile['url']; + $sourcefield = serialize($source); + } + $record->source = $sourcefield; $info = repository::move_to_filepool($downloadedfile['path'], $record); if (empty($info)) { From 61506a0af97bbc2ee7e14dfb04aeeb3095515779 Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Thu, 17 May 2012 13:55:03 +0800 Subject: [PATCH 278/455] MDL-33032 Fixed issues for file integration 1. Added tracker issue number in comment 2. Fixed stored_file::delete_reference() 3. repository::send_file() will throw exception if not implemented by subclass 4. Fixed renaming unit test, added one unit test for deleting original file 5. Fixed copyright statement for googledoc and picasa repository plugin 6. Implemented stored_file::set_filesize() --- lang/en/error.php | 1 + lib/filelib.php | 17 +++-- lib/filestorage/stored_file.php | 29 +++++++- lib/filestorage/tests/file_storage_test.php | 10 +-- lib/tests/filelib_test.php | 74 +++++++++++++++++++++ repository/coursefiles/lib.php | 11 +++ repository/googledocs/lib.php | 2 +- repository/lib.php | 1 + repository/picasa/lib.php | 2 +- repository/user/lib.php | 11 +++ 10 files changed, 145 insertions(+), 13 deletions(-) diff --git a/lang/en/error.php b/lang/en/error.php index 371cf469fd3..b40859b4e18 100644 --- a/lang/en/error.php +++ b/lang/en/error.php @@ -324,6 +324,7 @@ $string['invalidsection'] = 'Course module record contains invalid section'; $string['invalidsesskey'] = 'Incorrect sesskey submitted, form not accepted!'; $string['invalidshortname'] = 'That\'s an invalid short course name'; $string['invalidstatedetected'] = 'Something has gone wrong: {$a}. This should never normally happen.'; +$string['invalidsourcefield'] = 'Draft file\'s source field is invalid'; $string['invalidurl'] = 'Invalid URL'; $string['invaliduser'] = 'Invalid user'; $string['invaliduserid'] = 'Invalid user id'; diff --git a/lib/filelib.php b/lib/filelib.php index 11cba0fac86..8d8faf4db96 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -375,7 +375,7 @@ function file_prepare_draft_area(&$draftitemid, $contextid, $component, $fileare continue; } $draftfile = $fs->create_file_from_storedfile($file_record, $file); - // XXX: This is a hack for file manager + // XXX: This is a hack for file manager (MDL-28666) // File manager needs to know the original file information before copying // to draft area, so we append these information in mdl_files.source field // {@link file_storage::search_references()} @@ -679,9 +679,13 @@ function file_get_submitted_draft_itemid($elname) { */ function file_restore_source_field_from_draft_file($storedfile) { $source = unserialize($storedfile->get_source()); - if (!empty($source) && is_object($source)) { - $restoredsource = $source->source; - $storedfile->set_source($restoredsource); + if (!empty($source)) { + if (is_object($source)) { + $restoredsource = $source->source; + $storedfile->set_source($restoredsource); + } else { + throw new moodle_exception('invalidsourcefield', 'error'); + } } return $storedfile; } @@ -813,6 +817,11 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea $oldfile->set_sortorder($newfile->get_sortorder()); } + // Update file size + if ($oldfile->get_filesize() != $newfile->get_filesize()) { + $oldfile->set_filesize($newfile->get_filesize()); + } + // unchanged file or directory - we keep it as is unset($newhashes[$oldhash]); if (!$oldfile->is_directory()) { diff --git a/lib/filestorage/stored_file.php b/lib/filestorage/stored_file.php index f20a528700b..5141c61caa2 100644 --- a/lib/filestorage/stored_file.php +++ b/lib/filestorage/stored_file.php @@ -191,15 +191,27 @@ class stored_file { */ public function delete_reference() { global $DB; + // Remove repository info. $this->repository = null; + + // Remove reference info from DB. + $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid)); + + // Must refresh $this->file_record form DB + $filerecord = $DB->get_record('files', array('id'=>$this->get_id())); + // Update DB + $filerecord->referencelastsync = null; + $filerecord->referencelifetime = null; + $filerecord->referencefileid = null; + $this->update($filerecord); + + // unset object variable unset($this->file_record->repositoryid); unset($this->file_record->reference); unset($this->file_record->referencelastsync); unset($this->file_record->referencelifetime); - - // Remove reference info from DB. - $DB->delete_records('files_reference', array('id'=>$this->file_record->referencefileid)); + unset($this->file_record->referencefileid); } /** @@ -560,6 +572,17 @@ class stored_file { return $this->file_record->filesize; } + /** + * Returns the size of file in bytes. + * + * @param int $filesize bytes + */ + public function set_filesize($filesize) { + $filerecord = new stdClass; + $filerecord->filesize = $filesize; + $this->update($filerecord); + } + /** * Returns mime type of file. * diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index 9685e3f401a..5f70959c17d 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -109,15 +109,17 @@ class filestoragelib_testcase extends advanced_testcase { $contenthash = $originalfile->get_contenthash(); $newpath = '/test/'; $newname = 'newtest.txt'; - // try break it - $this->setExpectedException('file_exception'); - // this shall throw exception - $originalfile->rename($filepath, $filename); + // this should work $originalfile->rename($newpath, $newname); $file = $fs->get_file($syscontext->id, $component, $filearea, $itemid, $newpath, $newname); $this->assertInstanceOf('stored_file', $file); $this->assertEquals($contenthash, $file->get_contenthash()); + + // try break it + $this->setExpectedException('file_exception'); + // this shall throw exception + $originalfile->rename($newpath, $newname); } /** diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 9a419de243a..ee743e8055e 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -195,4 +195,78 @@ class filelib_testcase extends advanced_testcase { $this->assertEquals($license, $file->get_license()); $this->assertEquals($newsourcefield, $file->get_source()); } + + /** + * Testing deleting original files + * + * @copyright 2012 Dongsheng Cai {@link http://dongsheng.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + public function test_delete_original_file_from_draft() { + global $USER, $DB; + + $this->resetAfterTest(true); + + $generator = $this->getDataGenerator(); + $user = $generator->create_user(); + $usercontext = context_user::instance($user->id); + $USER = $DB->get_record('user', array('id'=>$user->id)); + + $repositorypluginname = 'user'; + + $args = array(); + $args['type'] = $repositorypluginname; + $repos = repository::get_instances($args); + $userrepository = reset($repos); + $this->assertInstanceOf('repository', $userrepository); + + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $filecontent = 'User file content'; + + // create a user private file + $userfilerecord = new stdClass; + $userfilerecord->contextid = $usercontext->id; + $userfilerecord->component = 'user'; + $userfilerecord->filearea = 'private'; + $userfilerecord->itemid = 0; + $userfilerecord->filepath = '/'; + $userfilerecord->filename = 'userfile.txt'; + $userfilerecord->source = 'test'; + $userfile = $fs->create_file_from_string($userfilerecord, $filecontent); + $userfileref = $fs->pack_reference($userfilerecord); + $contenthash = $userfile->get_contenthash(); + + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => 'core', + 'filearea' => 'phpunit', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => 'test.txt', + ); + // create a file reference + $fileref = $fs->create_file_from_reference($filerecord, $userrepository->id, $userfileref); + $this->assertInstanceOf('stored_file', $fileref); + $this->assertEquals($userrepository->id, $fileref->repository->id); + $this->assertEquals($userfile->get_contenthash(), $fileref->get_contenthash()); + $this->assertEquals($userfile->get_filesize(), $fileref->get_filesize()); + $this->assertRegExp('#' . $userfile->get_filename(). '$#', $fileref->get_reference_details()); + + $draftitemid = 0; + file_prepare_draft_area($draftitemid, $usercontext->id, 'user', 'private', 0); + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftitemid); + $this->assertEquals(2, count($draftfiles)); + $draftfile = $fs->get_file($usercontext->id, 'user', 'draft', $draftitemid, $userfilerecord->filepath, $userfilerecord->filename); + $draftfile->delete(); + // Save changed file + file_save_draft_area_files($draftitemid, $usercontext->id, 'user', 'private', 0); + + // The file reference should be a regular moodle file now + $fileref = $fs->get_file($syscontext->id, 'core', 'phpunit', 0, '/', 'test.txt'); + $this->assertEquals(false, $fileref->is_external_file()); + $this->assertEquals($contenthash, $fileref->get_contenthash()); + $this->assertEquals($filecontent, $fileref->get_content()); + } } diff --git a/repository/coursefiles/lib.php b/repository/coursefiles/lib.php index 06d75f689da..64fb1a0c60a 100644 --- a/repository/coursefiles/lib.php +++ b/repository/coursefiles/lib.php @@ -279,6 +279,17 @@ class repository_coursefiles extends repository { return $coursename . ': ' . $params['filepath'] . $params['filename']; } + /** + * Return reference file life time + * + * @param string $ref + * @return int + */ + public function get_reference_file_lifetime($ref) { + // this should be realtime + return 0; + } + /** * Repository method to serve file * diff --git a/repository/googledocs/lib.php b/repository/googledocs/lib.php index 833eee953b5..36648bdb81e 100644 --- a/repository/googledocs/lib.php +++ b/repository/googledocs/lib.php @@ -19,7 +19,7 @@ * * @since 2.0 * @package repository_googledocs - * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/repository/lib.php'); diff --git a/repository/lib.php b/repository/lib.php index 9cea0f8eb39..20849b0eef5 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1066,6 +1066,7 @@ abstract class repository { * @param array $options additional options affecting the file serving */ public function send_file($storedfile, $lifetime=86400 , $filter=0, $forcedownload=false, array $options = null) { + throw new coding_exception("Repository plugin must implement send_file() method."); } /** diff --git a/repository/picasa/lib.php b/repository/picasa/lib.php index c1cbc3ef8cb..6a83ca08238 100644 --- a/repository/picasa/lib.php +++ b/repository/picasa/lib.php @@ -19,7 +19,7 @@ * * @since 2.0 * @package repository_picasa - * @copyright 2010 Dongsheng Cai {@link http://dongsheng.org} + * @copyright 2009 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/repository/lib.php'); diff --git a/repository/user/lib.php b/repository/user/lib.php index 80dc94b6667..9d0537a8a27 100644 --- a/repository/user/lib.php +++ b/repository/user/lib.php @@ -225,6 +225,17 @@ class repository_user extends repository { return $this->get_name() . ': ' . $params['filepath'] . $params['filename']; } + /** + * Return reference file life time + * + * @param string $ref + * @return int + */ + public function get_reference_file_lifetime($ref) { + // this should be realtime + return 0; + } + /** * Repository method to serve file * From b53fad1e8b1b5c77454587fa85046b10903233c9 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 18 May 2012 15:42:30 +0200 Subject: [PATCH 279/455] MDL-33098 filemanager now stores the new author field correctly --- repository/draftfiles_ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repository/draftfiles_ajax.php b/repository/draftfiles_ajax.php index 246f66c559e..3857a0da965 100644 --- a/repository/draftfiles_ajax.php +++ b/repository/draftfiles_ajax.php @@ -154,7 +154,7 @@ switch ($action) { $file->set_license($updatedata['license']); } if (array_key_exists('author', $updatedata)) { - $file->set_license($updatedata['author']); + $file->set_author($updatedata['author']); } $changes = array_diff(array_keys($updatedata), array('filepath')); if (!empty($changes)) { From 3333e7e20c817c94273c216f6bb3b41641c693dc Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 18 May 2012 22:17:41 +0200 Subject: [PATCH 280/455] MDL-33093 invalidate the thumbnail in the local browser's cache on update This adds &oid= parameter to the URL of file preview images. The parameter is supposed to be ignored by draftfile.php and pluginfile.php. It just holds some unique identification of the original file's revision. Currently, we use the timestamp of the most recent modification of the original file. --- lib/filelib.php | 4 ++-- repository/coursefiles/lib.php | 4 ++-- repository/local/lib.php | 4 ++-- repository/recent/lib.php | 4 ++-- repository/user/lib.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/filelib.php b/lib/filelib.php index 8d8faf4db96..09d26b046b3 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -625,8 +625,8 @@ function file_get_drafarea_files($draftitemid, $filepath = '/') { $item->url = $itemurl->out(); $item->thumbnail = $OUTPUT->pix_url(file_extension_icon($item->filename, 32))->out(false); if ($imageinfo = $file->get_imageinfo()) { - $item->realthumbnail = $itemurl->out(false, array('preview' => 'thumb')); - $item->realicon = $itemurl->out(false, array('preview' => 'tinyicon')); + $item->realthumbnail = $itemurl->out(false, array('preview' => 'thumb', 'oid' => $file->get_timemodified())); + $item->realicon = $itemurl->out(false, array('preview' => 'tinyicon', 'oid' => $file->get_timemodified())); $item->image_width = $imageinfo['width']; $item->image_height = $imageinfo['height']; } diff --git a/repository/coursefiles/lib.php b/repository/coursefiles/lib.php index 64fb1a0c60a..10457314aa6 100644 --- a/repository/coursefiles/lib.php +++ b/repository/coursefiles/lib.php @@ -126,8 +126,8 @@ class repository_coursefiles extends repository { ); if ($imageinfo = $child->get_imageinfo()) { $fileurl = new moodle_url($child->get_url()); - $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb')); - $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon')); + $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $child->get_timemodified())); + $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $child->get_timemodified())); $node['image_width'] = $imageinfo['width']; $node['image_height'] = $imageinfo['height']; } diff --git a/repository/local/lib.php b/repository/local/lib.php index 93bc5e8251e..9c204a9cfe9 100644 --- a/repository/local/lib.php +++ b/repository/local/lib.php @@ -224,8 +224,8 @@ class repository_local_file { if ($imageinfo = $this->fileinfo->get_imageinfo()) { // what a beautiful picture, isn't it $fileurl = new moodle_url($this->fileinfo->get_url()); - $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb')); - $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon')); + $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $this->fileinfo->get_timemodified())); + $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $this->fileinfo->get_timemodified())); $node['image_width'] = $imageinfo['width']; $node['image_height'] = $imageinfo['height']; } diff --git a/repository/recent/lib.php b/repository/recent/lib.php index 25abf00d013..f7d91d4c14e 100644 --- a/repository/recent/lib.php +++ b/repository/recent/lib.php @@ -139,8 +139,8 @@ class repository_recent extends repository { ); if ($imageinfo = $fileinfo->get_imageinfo()) { $fileurl = new moodle_url($fileinfo->get_url()); - $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb')); - $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon')); + $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $fileinfo->get_timemodified())); + $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $fileinfo->get_timemodified())); $node['image_width'] = $imageinfo['width']; $node['image_height'] = $imageinfo['height']; } diff --git a/repository/user/lib.php b/repository/user/lib.php index 9d0537a8a27..d15f572f167 100644 --- a/repository/user/lib.php +++ b/repository/user/lib.php @@ -117,8 +117,8 @@ class repository_user extends repository { ); if ($imageinfo = $child->get_imageinfo()) { $fileurl = new moodle_url($child->get_url()); - $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb')); - $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon')); + $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $child->get_timemodified())); + $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $child->get_timemodified())); $node['image_width'] = $imageinfo['width']; $node['image_height'] = $imageinfo['height']; } From f653c9d8307b49ac27582c9f5ed469f282cab25a Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 18 May 2012 22:58:50 +0200 Subject: [PATCH 281/455] MDL-33096 update the file's timemodified if it was changed in the draft area Previously up to 2.2, new file records were created for all files that were modified in the draft area - see file_save_draft_area_files(). The commit aba1e17dd7ffa5e42d309fb2efe7945aeb3b3d39 introduced a new way of re-using the previous file's record. We need to transfer the timemodified of the file in the draft area into the file in the real area when saving the draft area to achieve the same behaviour now in 2.3. Note this may eventually lead to kinda weird situation when the file was created say on a certain timecreated but then was replaced with another file that has timemodified set to a lower value (in other words, the file will look as if it was firstly modified and then created). This case should be handled by the filepicker if it is seen as the issue. --- lib/filelib.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/filelib.php b/lib/filelib.php index 09d26b046b3..a38cba1f7e6 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -822,6 +822,11 @@ function file_save_draft_area_files($draftitemid, $contextid, $component, $filea $oldfile->set_filesize($newfile->get_filesize()); } + // Update file timemodified + if ($oldfile->get_timemodified() != $newfile->get_timemodified()) { + $oldfile->set_timemodified($newfile->get_timemodified()); + } + // unchanged file or directory - we keep it as is unset($newhashes[$oldhash]); if (!$oldfile->is_directory()) { From 78de00448302acd950c3052f8170dd74efe167f2 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 21 May 2012 12:12:44 +0800 Subject: [PATCH 282/455] MDL-33051 - topics format: remove section number from section column We don't think its necessary anymore --- course/format/topics/renderer.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/course/format/topics/renderer.php b/course/format/topics/renderer.php index 7050488c5b1..5ef126f5987 100644 --- a/course/format/topics/renderer.php +++ b/course/format/topics/renderer.php @@ -102,23 +102,4 @@ class format_topics_renderer extends format_section_renderer_base { return array_merge($controls, parent::section_edit_controls($course, $section, $onsectionpage)); } - - /** - * Generate the content to displayed on the left part of a section - * - * before course modules are included - * @param stdClass $section The course_section entry from DB - * @param stdClass $course The course entry from DB - * @param bool $onsectionpage true if being printed on a section page - * @return string HTML to output. - */ - protected function section_left_content($section, $course, $onsectionpage) { - $o = parent::section_left_content($section, $course, $onsectionpage); - - if ($section->section > 0) { - $o.= $section->section; - } - - return $o; - } } From 55e25598e767a50b58d8e44fb202cda78117fc2c Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Mon, 21 May 2012 13:32:02 +0800 Subject: [PATCH 283/455] MDL-33122 repositories: Enable youtube,url and wikimedia repositories by default --- repository/url/db/install.php | 40 +++++++++++++++++++++++++++++ repository/wikimedia/db/install.php | 40 +++++++++++++++++++++++++++++ repository/youtube/db/install.php | 40 +++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 repository/url/db/install.php create mode 100644 repository/wikimedia/db/install.php create mode 100644 repository/youtube/db/install.php diff --git a/repository/url/db/install.php b/repository/url/db/install.php new file mode 100644 index 00000000000..4a431f68621 --- /dev/null +++ b/repository/url/db/install.php @@ -0,0 +1,40 @@ +. + +/** + * + * @package repository_url + * @category repository + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +/** + * Create a instance of url repository + * + * @return bool A status indicating success or failure + */ +function xmldb_repository_url_install() { + global $CFG; + $result = true; + require_once($CFG->dirroot.'/repository/lib.php'); + $url_plugin = new repository_type('url', array(), true); + if(!$id = $url_plugin->create(true)) { + $result = false; + } + return $result; +} diff --git a/repository/wikimedia/db/install.php b/repository/wikimedia/db/install.php new file mode 100644 index 00000000000..e1bc22ce422 --- /dev/null +++ b/repository/wikimedia/db/install.php @@ -0,0 +1,40 @@ +. + +/** + * + * @package repository_wikimedia + * @category repository + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +/** + * Create a instance of wikimedia repository + * + * @return bool A status indicating success or failure + */ +function xmldb_repository_wikimedia_install() { + global $CFG; + $result = true; + require_once($CFG->dirroot.'/repository/lib.php'); + $wikimedia_plugin = new repository_type('wikimedia', array(), true); + if(!$id = $wikimedia_plugin->create(true)) { + $result = false; + } + return $result; +} diff --git a/repository/youtube/db/install.php b/repository/youtube/db/install.php new file mode 100644 index 00000000000..47741a0d27f --- /dev/null +++ b/repository/youtube/db/install.php @@ -0,0 +1,40 @@ +. + +/** + * + * @package repository_youtube + * @category repository + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +/** + * Create a instance of youtube repository + * + * @return bool A status indicating success or failure + */ +function xmldb_repository_youtube_install() { + global $CFG; + $result = true; + require_once($CFG->dirroot.'/repository/lib.php'); + $youtube_plugin = new repository_type('youtube', array(), true); + if(!$id = $youtube_plugin->create(true)) { + $result = false; + } + return $result; +} From b456271028f432f8ba25311d28dad92d884b29a3 Mon Sep 17 00:00:00 2001 From: Barbara Ramiro Date: Mon, 21 May 2012 14:47:14 +0800 Subject: [PATCH 284/455] MDL-31901 filemanager and filepicker styling - Swaped tool buttons and view buttons sequence for keyboard access both on filemanager and filepicker - Added "new folder name" label and "cancel" button on create a folder dialogue - Added href="#" and resized fonts on confirmation and message dialogue --- files/renderer.php | 36 +++++++++++++++---------------- theme/base/pix/fp/alias.png | Bin 0 -> 1249 bytes theme/base/pix/fp/link.png | Bin 0 -> 1442 bytes theme/base/style/filemanager.css | 28 +++++++++++++----------- 4 files changed, 33 insertions(+), 31 deletions(-) create mode 100644 theme/base/pix/fp/alias.png create mode 100644 theme/base/pix/fp/link.png diff --git a/files/renderer.php b/files/renderer.php index bd5303f042a..e9479f7670b 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -195,16 +195,16 @@ class core_files_renderer extends plugin_renderer_base {
                          @@ -297,8 +297,10 @@ class core_files_renderer extends plugin_renderer_base { private function fm_js_template_mkdir() { $rv = ' '; return preg_replace('/\{\!\}/', '', $rv); } @@ -418,10 +420,8 @@ class core_files_renderer extends plugin_renderer_base { $rv = ' '; return preg_replace('/\{\!\}/', '', $rv); } @@ -510,17 +510,12 @@ class core_files_renderer extends plugin_renderer_base {
                            -
                          •  
                          • +
                          •  
                          -
                          - - - -
                          @@ -529,6 +524,11 @@ class core_files_renderer extends plugin_renderer_base {
                          +
                          + + + +
                          @@ -780,7 +780,7 @@ class core_files_renderer extends plugin_renderer_base { $rv = ' '; return preg_replace('/\{\!\}/', '', $rv); } diff --git a/theme/base/pix/fp/alias.png b/theme/base/pix/fp/alias.png new file mode 100644 index 0000000000000000000000000000000000000000..e1695923796a5494ef3191c0dafa681cfeeba31b GIT binary patch literal 1249 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{l@EB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=mp@E~Zvx|$Rg|oS#p{t>#se!45g@vKH ztEr`tfr$}JuSMv>2~2MaLa!@My`aR9TL84#CABECEH%ZgC_h&L>}jh^+-`Bg zX&zK>3U0SJ}I&lg`<%Y9~xG!et&Dj27{_Ue}CWqeZQWq`Tl-MJ?7SO zh1HIR3TvP0sEex?bC|1l%d4|*7B*+!ETF7xeE58Pz2v@{|7Sn^`|Qu-J!699=B%Fm z^?yFi{(N|P{Jr`6{s{g0^p^kdasB-g_iBHg{qX87f7^BWx`*ZrEYGgbKKJX-Q~!7E z`t=fVd;cH&@Z>6g+i(B<1~zpcdml<)a42aIWNTD)zd2)ug!lgce@=f8fAR5t{Xa() z3CWFZ!flN8|NikO{`eg~x6$K3i>r=U>vwq{J+?>7k4PmjTxBV>a=!emZnlMjH-E== zp)X7V1xg$B8486v7)_qYPFSUKjJ15i4O55SdQaYFQ=XoJ|MKd#0{@MDSkyjc2mG&B zyxDM8IABy@nSdg*gk$6+AqIg22BEy=z5*Arw}T2D MPgg&ebxsLQ0OJ9-wg3PC literal 0 HcmV?d00001 diff --git a/theme/base/pix/fp/link.png b/theme/base/pix/fp/link.png new file mode 100644 index 0000000000000000000000000000000000000000..c456eced04a08cce06fed82725cd1fb2c97ed3ba GIT binary patch literal 1442 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{l@EB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=Gxuc<*n}Ly~g`0t)p{t>#se!45g@vKH ztEr`tfr$}JuSMv>2~2MaLa#ASy`aR9TL84#CABECEH%ZgC_h&L>}jh^+-@3U0R;;?%1Tbc{YIYLTKECIn1BASOKF0y*%cpPC0u??u3b{b{|j3j+g_h^LEV zNX4z5VDF4zN0Gh8nvoo=Z{uQqI>wX+D}{=O3i!rK6ePB8VHH2-dQs@8zj&9@REJeU zADKBf>gg;Bkk1Q=`N6DN#}&A{KzT=@Vo=7c@6Yz`yl$)-X>w}`^YgQ{#rJnU-)C&> z<+9?g#O~0S-Q`F6vV5hLw72`7;MYsv_ET^9EzuKkvwgMK<{uF$ounkBW;9Wj-)Ucn z#nrtRE_T%z*;|XaZR601I320@ll81jv}LYN{bBW|qTD^t?A0&k85#twWxaUtWVh}4 zyH#4h^)~1PAJ{mJ_0h)&g=2D;y!JKx*}5@L>0S(f{f_oLwRyTBzs`$jU7q$*kvp{| zyd&MSfm!X;`8Z?#rPR<1nop>^h61<}6^|8;%^X1(%yB)YlAJ&*UwF$bIe zYpW~dKYZHzH0^wd*6(YVqf{?CzPfnzZND_9#5TdpdJOLE%N+mx-GBFzMd0tO#<|%_ z-xI5t-muPF>r!@jZu9jFW5!Dj!A#$n&u#E~V0FSidTv;_LVNuegZu2y5`Itnb&Rh$ zCae77v~7Z~JWC9loUAuK`}Rxignovo^V(-t+okGRB^YLTh^?$GQ;q?Znx3wHF6*2U FngHS(4k-Wt literal 0 HcmV?d00001 diff --git a/theme/base/style/filemanager.css b/theme/base/style/filemanager.css index 8f7e5046e77..09f898379fa 100644 --- a/theme/base/style/filemanager.css +++ b/theme/base/style/filemanager.css @@ -36,14 +36,14 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st */ .file-picker .fp-list {list-style-type:none;padding:0;float:left;width:100%;margin:0;} .dir-rtl .file-picker .fp-list {text-align:right;} -.file-picker .fp-list .fp-repo {display:block;padding:.5em .7em;} +.file-picker .fp-list .fp-repo a{display:block;padding:.5em .7em;} .file-picker .fp-list .fp-repo.active {background:#F2F2F2;} .file-picker .fp-repo-icon {padding: 0px 7px 0px 5px;} /* * Tools, Path & View on fp-navbar (File Picker and File Manager) */ -.fp-toolbar {display: table-row;line-height: 22px;} +.fp-toolbar {display: table-row;line-height: 22px;float:left;} .fp-toolbar.empty {display:none;} .fp-toolbar .disabled {display:none;} .fp-toolbar div {display: inline-block;padding: 0px 2px;} @@ -150,20 +150,20 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} * File exists dialogue on Upload (File Picker only) */ .file-picker.fp-dlg {text-align: center;} -.file-picker.fp-dlg .fp-dlg-text {padding: 40px 20px 10px 20px;} +.file-picker.fp-dlg .fp-dlg-text {padding: 40px 20px 10px 20px;font-size: 12px;} /* * Error dialogue on Upload (File Picker only) */ .file-picker.fp-msg {text-align: center;} -.file-picker.fp-msg .fp-msg-text {padding: 40px 20px 10px 20px;min-width:200px;max-width:500px;max-height:300px;overflow:auto;} -.file-picker.fp-msg.fp-msg-error .fp-msg-text {padding: 40px 20px 10px 20px;} +.file-picker.fp-msg .fp-msg-text {padding: 40px 20px 10px 20px;min-width:200px;max-width:500px;max-height:300px;overflow:auto;font-size: 12px;} +.file-picker.fp-msg.fp-msg-error .fp-msg-text {padding: 40px 20px 10px 20px;font-size: 12px;} /* * Error on fp-content (File Picker only) */ .file-picker .fp-content-error {height: 100%;width: 100%;display: table;text-align: center;} -.file-picker .fp-content-error .fp-error {height: 100%;width: 100%;display:table-cell;vertical-align: middle;padding: 40px 20px 10px 20px;} +.file-picker .fp-content-error .fp-error {height: 100%;width: 100%;display:table-cell;vertical-align: middle;padding: 40px 20px 10px 20px;font-size: 12px;} /* * Lazy loading on fp-content (File Picker only) @@ -236,8 +236,8 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} */ .filemanager .fp-iconview .fp-reficons1 {position:absolute;height:100%;width:100%;top:0;left:0;z-index:1000;} .filemanager .fp-iconview .fp-reficons2 {position:absolute;height:100%;width:100%;top:0;left:0;z-index:1001;} -.filemanager .fp-iconview .fp-file.fp-hasreferences .fp-reficons1 {background: url('[[pix:moodle|t/lock]]') no-repeat;background-position:bottom left;} -.filemanager .fp-iconview .fp-file.fp-isreference .fp-reficons2 {background: url('[[pix:moodle|t/right]]') no-repeat;background-position:bottom right;} +.filemanager .fp-iconview .fp-file.fp-hasreferences .fp-reficons1 {background: url('[[pix:theme|fp/link]]') no-repeat;background-position:bottom right;} +.filemanager .fp-iconview .fp-file.fp-isreference .fp-reficons2 {background: url('[[pix:theme|fp/alias]]') no-repeat;background-position:bottom left;} /* * Table view (File Manager only) @@ -261,7 +261,6 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} /* * Drag and drop support (File Manager only) */ -/*.filepicker-filelist div:not(.dndupload-target),*/ .filemanager.fm-noitems .fm-empty-container {display:block;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #BBB;padding-top:85px;text-align:center;z-index: 3000;} .filepicker-filelist .dndupload-target, .filemanager-container .dndupload-target {background:#FFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #fb7979;padding-top:85px;text-align:center;z-index:3000;-webkit-box-shadow: 0px 0px 0px 10px #FFF;-moz-box-shadow: 0px 0px 0px 10px #FFF;box-shadow: 0px 0px 0px 10px #FFF;z-index: 3000;} @@ -303,20 +302,23 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} .filemanager.fp-select .fp-reflist.fp-unknown {display:none;} .filemanager.fp-select .fp-reflist .fp-reflistloading {display:none;} +.filemanager.fp-select .fp-refcount {max-width: 265px;} .filemanager.fp-select .fp-reflist.fp-loading .fp-reflistloading {display:inline;} -.filemanager.fp-select .fp-reflist .fp-value {max-width:400px;max-height:50px;overflow:auto;} +.filemanager.fp-select .fp-reflist .fp-value {background: #FFF;border: 1px solid #BBB;padding: 8px 7px;margin: 0px;max-width: 265px;max-height: 75px;overflow:auto;} +.filemanager.fp-select .fp-reflist .fp-value li {padding-bottom: 7px;} /* * Create folder dialogue (File Manager only) */ -.filemanager .fp-mkdir-dlg input {margin-top: 20px;margin-left: 20px;float:left;} -.filemanager .fp-dlg-butcreate {margin-top: 20px;margin-right: 20px;} +.filemanager .fp-mkdir-dlg {text-align: center;} +.filemanager .fp-mkdir-dlg p {text-align: left;margin: 40px 20px 0px;} +.filemanager .fp-mkdir-dlg input {margin: 0px 20px 20px;} /* * Confirm dialogue for delete (File Manager only) */ .filemanager.fp-dlg {text-align: center;} -.filemanager.fp-dlg .fp-dlg-text {padding: 0px 10px;min-width:200px;max-width:340px;max-height:300px;overflow:auto;line-height: 22px;margin: 40px 20px 20px 20px;} +.filemanager.fp-dlg .fp-dlg-text {padding: 0px 10px;min-width:200px;max-width:340px;max-height:300px;overflow:auto;line-height: 22px;margin: 40px 20px 20px;font-size: 12px;} /* *file picker search dialog From 8177b7b9f05878cfac92740869d3ea076320e0db Mon Sep 17 00:00:00 2001 From: Dongsheng Cai Date: Mon, 21 May 2012 13:30:41 +0800 Subject: [PATCH 285/455] MDL-33082 Detecting mimetype based on content bytes --- lib/filestorage/file_storage.php | 28 ++++++++++++++++++++++++---- lib/filestorage/stored_file.php | 11 +++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index fd3fb1011aa..3672fd54331 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -1028,7 +1028,7 @@ class file_storage { $newrecord->timecreated = $filerecord->timecreated; $newrecord->timemodified = $filerecord->timemodified; - $newrecord->mimetype = empty($filerecord->mimetype) ? mimeinfo('type', $filerecord->filename) : $filerecord->mimetype; + $newrecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($pathname) : $filerecord->mimetype; $newrecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; $newrecord->source = empty($filerecord->source) ? null : $filerecord->source; $newrecord->author = empty($filerecord->author) ? null : $filerecord->author; @@ -1145,7 +1145,6 @@ class file_storage { $newrecord->timecreated = $filerecord->timecreated; $newrecord->timemodified = $filerecord->timemodified; - $newrecord->mimetype = empty($filerecord->mimetype) ? mimeinfo('type', $filerecord->filename) : $filerecord->mimetype; $newrecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; $newrecord->source = empty($filerecord->source) ? null : $filerecord->source; $newrecord->author = empty($filerecord->author) ? null : $filerecord->author; @@ -1153,6 +1152,9 @@ class file_storage { $newrecord->sortorder = $filerecord->sortorder; list($newrecord->contenthash, $newrecord->filesize, $newfile) = $this->add_string_to_pool($content); + $filepathname = $this->path_from_hash($newrecord->contenthash) . '/' . $newrecord->contenthash; + // get mimetype by magic bytes + $newrecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($filepathname) : $filerecord->mimetype; $newrecord->pathnamehash = $this->get_pathname_hash($newrecord->contextid, $newrecord->component, $newrecord->filearea, $newrecord->itemid, $newrecord->filepath, $newrecord->filename); @@ -1216,7 +1218,7 @@ class file_storage { $filerecord->referencefileid = empty($filerecord->referencefileid) ? 0 : $filerecord->referencefileid; $filerecord->referencelastsync = empty($filerecord->referencelastsync) ? 0 : $filerecord->referencelastsync; $filerecord->referencelifetime = empty($filerecord->referencelifetime) ? 0 : $filerecord->referencelifetime; - $filerecord->mimetype = empty($filerecord->mimetype) ? mimeinfo('type', $filerecord->filename) : $filerecord->mimetype; + $filerecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($filerecord->filename) : $filerecord->mimetype; $filerecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; $filerecord->source = empty($filerecord->source) ? null : $filerecord->source; $filerecord->author = empty($filerecord->author) ? null : $filerecord->author; @@ -1333,7 +1335,7 @@ class file_storage { } if (!isset($filerecord['mimetype'])) { - $filerecord['mimetype'] = mimeinfo('type', $filerecord['filename']); + $filerecord['mimetype'] = $imageinfo['mimetype']; } $width = $imageinfo['width']; @@ -1789,6 +1791,24 @@ class file_storage { return $storedfile; } + /** + * Return mimetype by given file pathname + * + * This method uses fileinfo module to get mimetype using magic bytes if file exists. + * If not, it will get mimetype based on filename + * + * @param string $pathname + * @return string + */ + public static function mimetype($pathname) { + if (file_exists($pathname)) { + $finfo = new finfo(FILEINFO_MIME_TYPE); + return $finfo->file($pathname); + } else { + return mimeinfo('type', $pathname); + } + } + /** * Cron cleanup job. */ diff --git a/lib/filestorage/stored_file.php b/lib/filestorage/stored_file.php index 5141c61caa2..e9b2e3f5c67 100644 --- a/lib/filestorage/stored_file.php +++ b/lib/filestorage/stored_file.php @@ -154,6 +154,17 @@ class stored_file { throw new coding_exception("Invalid field name, $field doesn't exist in file record"); } } + // Validate mimetype field + $pathname = $this->get_content_file_location(); + // try to recover the content from trash + if (!is_readable($pathname)) { + if (!$this->fs->try_content_recovery($this) or !is_readable($pathname)) { + throw new file_exception('storedfilecannotread', '', $pathname); + } + } + $mimetype = $this->fs->mimetype($pathname); + $this->file_record->mimetype = $mimetype; + $DB->update_record('files', $this->file_record); } From 5ac3b1c0ba616fbe7a807a88d7524a8a858d9732 Mon Sep 17 00:00:00 2001 From: Kordan Date: Mon, 21 May 2012 09:26:52 +0200 Subject: [PATCH 286/455] MDL-33055 theme_formal_white: changed "general" to "standard" in $theme->layouts array index --- theme/formal_white/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/formal_white/config.php b/theme/formal_white/config.php index 6c0ba87c9b1..37888abf11a 100644 --- a/theme/formal_white/config.php +++ b/theme/formal_white/config.php @@ -93,7 +93,7 @@ $THEME->layouts = array( 'regions' => array('side-pre', 'side-post'), 'defaultregion' => 'side-post', ), - 'general' => array( + 'standard' => array( 'file' => 'general.php', 'regions' => array('side-pre', 'side-post'), 'defaultregion' => 'side-post', From f684250bda8bfc36969d35c3e0a63b361fca47af Mon Sep 17 00:00:00 2001 From: Davo Smith Date: Mon, 21 May 2012 08:34:50 +0100 Subject: [PATCH 287/455] MDL-22504 Course drag and drop upload - removed browser specific content hacks, made 'text and link' dragging an experimental feature --- admin/settings/development.php | 4 ++++ course/dndupload.js | 41 ---------------------------------- course/dndupload.php | 4 ---- course/dnduploadlib.php | 16 +++++++++---- lang/en/admin.php | 4 ++++ lang/en/moodle.php | 1 + 6 files changed, 21 insertions(+), 49 deletions(-) diff --git a/admin/settings/development.php b/admin/settings/development.php index 9d7b5a09981..dcddf32a903 100644 --- a/admin/settings/development.php +++ b/admin/settings/development.php @@ -13,6 +13,10 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page $temp->add(new admin_setting_configcheckbox('enablesafebrowserintegration', new lang_string('enablesafebrowserintegration', 'admin'), new lang_string('configenablesafebrowserintegration', 'admin'), 0)); $temp->add(new admin_setting_configcheckbox('enablegroupmembersonly', new lang_string('enablegroupmembersonly', 'admin'), new lang_string('configenablegroupmembersonly', 'admin'), 0)); + $dndopts = array(0 => new lang_string('dnduploadfiles', 'admin'), + 1 => new lang_string('dnduploadfilestextlink', 'admin')); + $temp->add(new admin_setting_configselect('dndallowtextandlinks', new lang_string('dndallowtextandlinks', 'admin'), new lang_string('configdndallowtextandlinks', 'admin'), 0, $dndopts)); + $ADMIN->add('experimental', $temp); // "debugging" settingpage diff --git a/course/dndupload.js b/course/dndupload.js index bdfe18a99d9..9b7c4e4a6fe 100644 --- a/course/dndupload.js +++ b/course/dndupload.js @@ -903,34 +903,6 @@ M.course_dndupload = { } }; - if (type == 'text/html') { - // If this was html content dragged from Chrome => Firefox, we will - // need to fix the byte order of the content. - if (this.Y.UA.gecko > 0) { - if (contents.indexOf('<') == -1) { - // There are no html tags in this content => it probably needs fixing. - var codes = new Array(); - for (i=0; i it is probably correct. - contents = fixedcontents; - } - } - } - } - // Prepare the data to send var formData = new FormData(); formData.append('contents', contents); @@ -941,19 +913,6 @@ M.course_dndupload = { formData.append('type', type); formData.append('module', module); - if (type == 'text/html') { - // This html content might have been dragged from Firefox to Chrome (in Linux). - // Need to provide an extra fixed version of the contents, in case the original does not upload. - if (this.Y.UA.webkit > 0 && this.Y.UA.os == 'linux') { - var fixedcontents = ''; - for (i=0; iprocess($displayname, $contents); diff --git a/course/dnduploadlib.php b/course/dnduploadlib.php index 402c91f66ba..d82da3544e2 100644 --- a/course/dnduploadlib.php +++ b/course/dnduploadlib.php @@ -304,17 +304,21 @@ class dndupload_handler { * @return object Data to pass on to Javascript code */ public function get_js_data() { + global $CFG; + $ret = new stdClass; // Sort the types by priority. uasort($this->types, array($this, 'type_compare')); $ret->types = array(); - foreach ($this->types as $type) { - if (empty($type->handlers)) { - continue; // Skip any types without registered handlers. + if ($CFG->dndallowtextandlinks) { + foreach ($this->types as $type) { + if (empty($type->handlers)) { + continue; // Skip any types without registered handlers. + } + $ret->types[] = $type; } - $ret->types[] = $type; } $ret->filehandlers = $this->filehandlers; @@ -436,6 +440,10 @@ class dndupload_ajax_processor { if ($content != null) { throw new moodle_exception('fileuploadwithcontent', 'moodle'); } + } else { + if (empty($content)) { + throw new moodle_exception('dnduploadwithoutcontent', 'moodle'); + } } require_sesskey(); diff --git a/lang/en/admin.php b/lang/en/admin.php index 5cee004eef8..9ae4445a51a 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -183,6 +183,7 @@ $string['configdenyemailaddresses'] = 'To deny email addresses from particular d $string['configenabledevicedetection'] = 'Enables detection of mobiles, smartphones, tablets or default devices (desktop PCs, laptops, etc) for the application of themes and other features.'; $string['configdisableuserimages'] = 'Disable the ability for users to change user profile images.'; $string['configdisplayloginfailures'] = 'This will display information to selected users about previous failed logins.'; +$string['configdndallowtextandlinks'] = 'Enable or disable the dragging and dropping of text and links onto a course page, alongside the dragging and dropping of files. Note that the dragging of text into Firefox or between different browsers is unreliable and may result in no data being uploaded, or corrupted text being uploaded.'; $string['configdocroot'] = 'Defines the path to the Moodle Docs. You can change this if you wish to have your own custom online documentation. However, if you do that make sure that the paths in your documentation follow the same format as http://docs.moodle.org.'; $string['configdoctonewwindow'] = 'If you enable this, then links to Moodle Docs will be shown in a new window.'; $string['configeditordictionary'] = 'This value will be used if aspell doesn\'t have dictionary for users own language.'; @@ -431,6 +432,9 @@ $string['devicetype'] = 'Device type'; $string['disableuserimages'] = 'Disable user profile images'; $string['displayerrorswarning'] = 'Enabling the PHP setting display_errors is not recommended on production sites because some error messages may reveal sensitive information about your server.'; $string['displayloginfailures'] = 'Display login failures to'; +$string['dndallowtextandlinks'] = 'Drag and drop upload allows'; +$string['dnduploadfiles'] = 'files only'; +$string['dnduploadfilestextlink'] = 'files, text and links'; $string['docroot'] = 'Moodle Docs document root'; $string['doctonewwindow'] = 'Open in new window'; $string['download'] = 'Download'; diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 8950c320020..859e874dd25 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -466,6 +466,7 @@ $string['dndenabled'] = 'Drag and drop available'; $string['dndenabled_help'] = 'You can drag one or more files from your desktop and drop them onto the box below to upload them.
                          Note: this may not work with other web browsers'; $string['dndenabled_insentence'] = 'drag and drop available'; $string['dndenabled_inbox'] = 'drag and drop files here to upload them'; +$string['dnduploadwithoutcontent'] = 'This upload does not have any content'; $string['dndworkingfiletextlink'] = 'Drag and drop files, text or links onto course sections to upload them'; $string['dndworkingfilelink'] = 'Drag and drop files or links onto course sections to upload them'; $string['dndworkingfiletext'] = 'Drag and drop files or text onto course sections to upload them'; From 559276b153640310d6c7fa3695f8d71ad0396f39 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 21 May 2012 15:17:53 +0800 Subject: [PATCH 288/455] MDL-32247,MDL-32831,MDL-32900 Use correct url building of file type icons - function get_mimetypes_array() now contains also information about filetype groups and language strings - use 'smart' human-readable mimetype description - never determine filetype group based on filetype icon image! remove function mimeinfo_from_icon() - get rid of class filetype_parser and file lib/filestorage/file_types.mm, replaced with functions file_get_typegroup(), file_extension_in_typegroup() and file_mimetype_in_typegroup() - support multiple icon sizes, not only 16 and 32 - retrieve filetype icon only using proper functions file_..._icon() from lib/filelib.php throughout the code - increase size of repository thumbnails to 90 and icons to 24 (will take effect when new icons exist) --- admin/tool/unittest/coveragefile.php | 5 +- .../block_activity_modules.php | 5 +- blocks/private_files/renderer.php | 5 +- blog/locallib.php | 7 +- course/lib.php | 7 - files/filebrowser_ajax.php | 4 +- files/renderer.php | 39 +- grade/lib.php | 3 +- lang/en/mimetypes.php | 35 +- lib/filelib.php | 652 ++++++++++-------- lib/filestorage/file_types.mm | 112 --- lib/filestorage/stored_file.php | 3 +- lib/portfolio/formats.php | 22 +- mod/assign/renderer.php | 5 +- mod/assignment/lib.php | 2 +- mod/assignment/renderer.php | 5 +- .../type/online/assignment.class.php | 4 +- .../type/upload/assignment.class.php | 2 +- .../type/uploadsingle/assignment.class.php | 4 +- mod/data/field/file/field.class.php | 4 +- mod/data/field/picture/field.class.php | 2 +- mod/forum/lib.php | 2 +- mod/glossary/lib.php | 2 +- mod/resource/lib.php | 2 +- mod/resource/locallib.php | 11 +- mod/url/locallib.php | 9 +- mod/wiki/edit_form.php | 3 +- mod/wiki/editors/wikifiletable.php | 10 +- mod/wiki/renderer.php | 5 +- mod/workshop/renderer.php | 5 +- question/type/essay/renderer.php | 3 +- repository/alfresco/lib.php | 4 +- repository/boxnet/lib.php | 2 +- repository/coursefiles/lib.php | 4 +- repository/draftfiles_manager.php | 8 +- repository/dropbox/lib.php | 4 +- repository/filesystem/lib.php | 5 +- repository/lib.php | 61 +- repository/local/lib.php | 5 +- repository/merlot/lib.php | 2 +- repository/recent/lib.php | 5 +- repository/repository_ajax.php | 5 +- repository/s3/lib.php | 4 +- repository/upload/lib.php | 6 +- repository/user/lib.php | 5 +- repository/webdav/lib.php | 4 +- repository/wikimedia/wikimedia.php | 4 +- user/renderer.php | 5 +- 48 files changed, 524 insertions(+), 588 deletions(-) delete mode 100644 lib/filestorage/file_types.mm diff --git a/admin/tool/unittest/coveragefile.php b/admin/tool/unittest/coveragefile.php index 8c17b60e3eb..d3c8737a4e8 100644 --- a/admin/tool/unittest/coveragefile.php +++ b/admin/tool/unittest/coveragefile.php @@ -60,9 +60,8 @@ if (!isset($args[0]) || !in_array($args[0], $alloweddirs)) { print_error('invalidarguments'); } -// only serve some controlled extensions -$allowedextensions = array('text/html', 'text/css', 'image/gif', 'application/x-javascript'); -if (!in_array(mimeinfo('type', $filepath), $allowedextensions)) { +// only serve some controlled extensions/mimetypes +if (!file_extension_in_typegroup($filepath, array('web_file', 'web_image'), true)) { print_error('invalidarguments'); } diff --git a/blocks/activity_modules/block_activity_modules.php b/blocks/activity_modules/block_activity_modules.php index c290b2444f4..2aa257865c9 100644 --- a/blocks/activity_modules/block_activity_modules.php +++ b/blocks/activity_modules/block_activity_modules.php @@ -1,5 +1,8 @@ libdir . '/filelib.php'); + class block_activity_modules extends block_list { function init() { $this->title = get_string('pluginname', 'block_activity_modules'); @@ -50,7 +53,7 @@ class block_activity_modules extends block_list { foreach ($modfullnames as $modname => $modfullname) { if ($modname === 'resources') { - $icon = ' '; + $icon = $OUTPUT->pix_icon(file_extension_icon('.htm'), '', 'moodle', array('class' => 'icon')). ' '; $this->content->items[] = ''.$icon.$modfullname.''; } else { $icon = ' '; diff --git a/blocks/private_files/renderer.php b/blocks/private_files/renderer.php index 5c27971e55a..eb109faa1b8 100644 --- a/blocks/private_files/renderer.php +++ b/blocks/private_files/renderer.php @@ -65,14 +65,13 @@ class block_private_files_renderer extends plugin_renderer_base { } $result = '
                            '; foreach ($dir['subdirs'] as $subdir) { - $image = $this->output->pix_icon("f/folder", $subdir['dirname'], 'moodle', array('class'=>'icon')); + $image = $this->output->pix_icon(file_folder_icon(), $subdir['dirname'], 'moodle', array('class'=>'icon')); $result .= '
                          • '.$image.' '.s($subdir['dirname']).'
                            '.$this->htmllize_tree($tree, $subdir).'
                          • '; } foreach ($dir['files'] as $file) { $url = file_encode_url("$CFG->wwwroot/pluginfile.php", '/'.$tree->context->id.'/user/private'.$file->get_filepath().$file->get_filename(), true); $filename = $file->get_filename(); - $icon = mimeinfo("icon", $filename); - $image = $this->output->pix_icon("f/$icon", $filename, 'moodle', array('class'=>'icon')); + $image = $this->output->pix_icon(file_file_icon($file), $filename, 'moodle', array('class'=>'icon')); $result .= '
                          • '.html_writer::link($url, $image.' '.$filename).'
                          • '; } $result .= '
                          '; diff --git a/blog/locallib.php b/blog/locallib.php index 9eb1e8fe621..6ac89440782 100644 --- a/blog/locallib.php +++ b/blog/locallib.php @@ -513,10 +513,7 @@ class blog_entry { $ffurl = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.SYSCONTEXTID.'/blog/attachment/'.$this->id.'/'.$filename); $mimetype = $file->get_mimetype(); - $icon = mimeinfo_from_type("icon", $mimetype); - $type = mimeinfo_from_type("type", $mimetype); - - $image = $OUTPUT->pix_icon("f/$icon", $filename, 'moodle', array('class'=>'icon')); + $image = $OUTPUT->pix_icon(file_file_icon($file), $filename, 'moodle', array('class'=>'icon')); if ($return == "html") { $output .= html_writer::link($ffurl, $image); @@ -526,7 +523,7 @@ class blog_entry { $output .= "$strattachment $filename:\n$ffurl\n"; } else { - if (in_array($type, array('image/gif', 'image/jpeg', 'image/png'))) { // Image attachments don't get printed as links + if (file_mimetype_in_typegroup($file->get_mimetype(), 'web_image')) { // Image attachments don't get printed as links $imagereturn .= '
                          '; } else { $imagereturn .= html_writer::link($ffurl, $image); diff --git a/course/lib.php b/course/lib.php index 9a64052c153..8e073737607 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1518,13 +1518,6 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false, //Accessibility: for files get description via icon, this is very ugly hack! $altname = ''; $altname = $mod->modfullname; - if (!empty($customicon)) { - $archetype = plugin_supports('mod', $mod->modname, FEATURE_MOD_ARCHETYPE, MOD_ARCHETYPE_OTHER); - if ($archetype == MOD_ARCHETYPE_RESOURCE) { - $mimetype = mimeinfo_from_icon('type', $customicon); - $altname = get_mimetype_description($mimetype); - } - } // Avoid unnecessary duplication: if e.g. a forum name already // includes the word forum (or Forum, etc) then it is unhelpful // to include that in the accessible description that is added. diff --git a/files/filebrowser_ajax.php b/files/filebrowser_ajax.php index 2d651e95765..a8b638b5c54 100644 --- a/files/filebrowser_ajax.php +++ b/files/filebrowser_ajax.php @@ -70,10 +70,10 @@ switch ($action) { if ($child->is_directory()) { $fileitem['isdir'] = true; $fileitem['url'] = $url->out(false); - $fileitem['icon'] = $OUTPUT->pix_icon('f/folder', get_string('icon')); + $fileitem['icon'] = $OUTPUT->pix_icon(file_folder_icon(), get_string('icon')); } else { $fileitem['url'] = $child->get_url(); - $fileitem['icon'] = $OUTPUT->pix_icon('f/'.mimeinfo('icon', $child->get_visible_name()), get_string('icon')); + $fileitem['icon'] = $OUTPUT->pix_icon(file_file_icon($child), get_string('icon')); } $tree[] = $fileitem; } diff --git a/files/renderer.php b/files/renderer.php index e9479f7670b..e6f0a225cd6 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -56,25 +56,31 @@ class core_files_renderer extends plugin_renderer_base { $html .= $this->output->box_start(); $table = new html_table(); - $table->head = array(get_string('filename', 'backup'), get_string('size'), get_string('modified')); - $table->align = array('left', 'right', 'right'); + $table->head = array(get_string('name'), get_string('lastmodified'), get_string('size', 'repository'), get_string('type', 'repository')); + $table->align = array('left', 'left', 'left', 'left'); $table->width = '100%'; $table->data = array(); foreach ($tree->tree as $file) { - if (!empty($file['isdir'])) { - $table->data[] = array( - html_writer::link($file['url'], $this->output->pix_icon('f/folder', 'icon') . ' ' . $file['filename']), - '', - $file['filedate'], - ); - } else { - $table->data[] = array( - html_writer::link($file['url'], $this->output->pix_icon('f/'.mimeinfo('icon', $file['filename']), get_string('icon')) . ' ' . $file['filename']), - $file['filesize'], - $file['filedate'], - ); + $filedate = $filesize = $filetype = ''; + if ($file['filedate']) { + $filedate = userdate($file['filedate'], get_string('strftimedatetimeshort', 'langconfig')); } + if (empty($file['isdir'])) { + if ($file['filesize']) { + $filesize = display_size($file['filesize']); + } + $fileicon = file_file_icon($file, 24); + $filetype = get_mimetype_description($file); + } else { + $fileicon = file_folder_icon(24); + } + $table->data[] = array( + html_writer::link($file['url'], $this->output->pix_icon($fileicon, get_string('icon')) . ' ' . $file['filename']), + $filedate, + $filesize, + $filetype + ); } $html .= html_writer::table($table); @@ -952,8 +958,9 @@ class files_tree_viewer implements renderable { $fileitem = array( 'params' => $params, 'filename' => $child->get_visible_name(), - 'filedate' => $filedate ? userdate($filedate) : '', - 'filesize' => $filesize ? display_size($filesize) : '' + 'mimetype' => $child->get_mimetype(), + 'filedate' => $filedate ? $filedate : '', + 'filesize' => $filesize ? $filesize : '' ); $url = new moodle_url('/files/index.php', $params); if ($child->is_directory()) { diff --git a/grade/lib.php b/grade/lib.php index 185fed52039..e1937be2ce7 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -1049,6 +1049,7 @@ class grade_structure { */ public function get_element_icon(&$element, $spacerifnone=false) { global $CFG, $OUTPUT; + require_once $CFG->libdir.'/filelib.php'; switch ($element['type']) { case 'item': @@ -1114,7 +1115,7 @@ class grade_structure { case 'category': $strcat = get_string('category', 'grades'); - return ''.s($strcat).''; } diff --git a/lang/en/mimetypes.php b/lang/en/mimetypes.php index 17d224e7c4d..9cb966dd3cb 100644 --- a/lang/en/mimetypes.php +++ b/lang/en/mimetypes.php @@ -18,6 +18,19 @@ /** * Strings for component 'mimetypes', language 'en', branch 'MOODLE_20_STABLE' * + * Strings are used to display human-readable name of mimetype. Some mimetypes share the same + * string. The following attributes are passed in the parameter when processing the string: + * $a->ext - filename extension in lower case + * $a->EXT - filename extension, capitalized + * $a->Ext - filename extension with first capital letter + * $a->mimetype - file mimetype + * $a->mimetype1 - first chunk of mimetype (before /) + * $a->mimetype2 - second chunk of mimetype (after /) + * $a->Mimetype, $a->MIMETYPE, $a->Mimetype1, $a->Mimetype2, $a->MIMETYPE1, $a->MIMETYPE2 + * - the same with capitalized first/all letters + * + * @see get_mimetypes_array() + * @see get_mimetype_description() * @package mimetypes * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -25,15 +38,19 @@ $string['application/msword'] = 'Word document'; $string['application/pdf'] = 'PDF document'; +$string['application/vnd.moodle.backup'] = 'Moodle backup'; $string['application/vnd.ms-excel'] = 'Excel spreadsheet'; $string['application/vnd.ms-powerpoint'] = 'Powerpoint presentation'; -$string['application/zip'] = 'zip archive'; -$string['audio/mp3'] = 'MP3 audio file'; -$string['audio/wav'] = 'sound file'; -$string['document/unknown'] = 'file'; -$string['image/bmp'] = 'uncompressed BMP image'; -$string['image/gif'] = 'GIF image'; -$string['image/jpeg'] = 'JPEG image'; -$string['image/png'] = 'PNG image'; -$string['text/plain'] = 'text file'; +$string['application/vnd.openxmlformats-officedocument.presentationml.presentation'] = 'Powerpoint presentation'; +$string['application/vnd.openxmlformats-officedocument.presentationml.slideshow'] = 'Powerpoint slideshow'; +$string['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] = 'Excel spreadsheet'; +$string['application/vnd.openxmlformats-officedocument.spreadsheetml.template'] = 'Excel template'; +$string['application/vnd.openxmlformats-officedocument.wordprocessingml.document'] = 'Word document'; +$string['archive'] = 'Archive ({$a->EXT})'; +$string['audio'] = 'Audio file ({$a->EXT})'; +$string['default'] = '{$a->mimetype}'; +$string['document/unknown'] = 'File'; +$string['image'] = 'Image ({$a->MIMETYPE2})'; +$string['text/html'] = 'HTML document'; +$string['text/plain'] = 'Text file'; $string['text/rtf'] = 'RTF document'; diff --git a/lib/filelib.php b/lib/filelib.php index a38cba1f7e6..972a8d10638 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -590,8 +590,6 @@ function file_get_drafarea_files($draftitemid, $filepath = '/') { $item->size = $filesize ? $filesize : null; $item->filesize = $filesize ? display_size($filesize) : ''; - $icon = mimeinfo_from_type('icon', $file->get_mimetype()); - $item->icon = $OUTPUT->pix_url('f/' . $icon)->out(); $item->sortorder = $file->get_sortorder(); $item->author = $file->get_author(); $item->license = $file->get_license(); @@ -605,25 +603,25 @@ function file_get_drafarea_files($draftitemid, $filepath = '/') { $item->refcount = $fs->search_references_count($source->original); } - // TODO MDL-32900 this is not the correct way to check that it is archive, use filetype_parser instead - if ($icon == 'zip') { - $item->type = 'zip'; - } else { - $item->type = 'file'; - } - if ($file->is_directory()) { $item->filesize = 0; - $item->icon = $OUTPUT->pix_url('f/folder')->out(); + $item->icon = $OUTPUT->pix_url(file_folder_icon(24))->out(false); $item->type = 'folder'; $foldername = explode('/', trim($item->filepath, '/')); $item->fullname = trim(array_pop($foldername), '/'); - $item->thumbnail = $OUTPUT->pix_url('f/folder-32')->out(false); + $item->thumbnail = $OUTPUT->pix_url(file_folder_icon(90))->out(false); } else { // do NOT use file browser here! + $item->mimetype = get_mimetype_description($file); + if (file_mimetype_in_typegroup($item->mimetype, 'archive')) { + $item->type = 'zip'; + } else { + $item->type = 'file'; + } $itemurl = moodle_url::make_draftfile_url($draftitemid, $item->filepath, $item->filename); $item->url = $itemurl->out(); - $item->thumbnail = $OUTPUT->pix_url(file_extension_icon($item->filename, 32))->out(false); + $item->icon = $OUTPUT->pix_url(file_file_icon($file, 24))->out(false); + $item->thumbnail = $OUTPUT->pix_url(file_file_icon($file, 90))->out(false); if ($imageinfo = $file->get_imageinfo()) { $item->realthumbnail = $itemurl->out(false, array('preview' => 'thumb', 'oid' => $file->get_timemodified())); $item->realicon = $itemurl->out(false, array('preview' => 'tinyicon', 'oid' => $file->get_timemodified())); @@ -1323,7 +1321,32 @@ function download_file_content_write_handler($received, $ch, $data) { } /** - * Returns a list of information about file t ypes based on extensions + * Returns a list of information about file types based on extensions. + * + * The following elements expected in value array for each extension: + * 'type' - mimetype + * 'icon' - location of the icon file. If value is FILENAME, then either pix/f/FILENAME.gif + * or pix/f/FILENAME.png must be present in moodle and contain 16x16 filetype icon; + * also files with bigger sizes under names + * FILENAME-24, FILENAME-32, FILENAME-64, FILENAME-128, FILENAME-256 are recommended. + * 'groups' (optional) - array of filetype groups this filetype extension is part of; + * commonly used in moodle the following groups: + * - web_image - image that can be included as in HTML + * - image - image that we can parse using GD to find it's dimensions, also used for portfolio format + * - video - file that can be imported as video in text editor + * - audio - file that can be imported as audio in text editor + * - archive - we can extract files from this archive + * - spreadsheet - used for portfolio format + * - document - used for portfolio format + * - presentation - used for portfolio format + * 'string' (optional) - the name of the string from lang/en/mimetypes.php that displays + * human-readable description for this filetype; + * Function {@link get_mimetype_description()} first looks at the presence of string for + * particular mimetype (value of 'type'), if not found looks for string specified in 'string' + * attribute, if not found returns the value of 'type'; + * 'defaulticon' (boolean, optional) - used by function {@link file_mimetype_icon()} to find + * an icon for mimetype. If an entry with 'defaulticon' is not found for a particular mimetype, + * this function will return first found icon; Especially usefull for types such as 'text/plain' * * @category files * @return array List of information about file types based on extensions. @@ -1331,57 +1354,57 @@ function download_file_content_write_handler($received, $ch, $data) { * from 'element name' to data. Current element names are 'type' and 'icon'. * Unknown types should use the 'xxx' entry which includes defaults. */ -function get_mimetypes_array() { +function &get_mimetypes_array() { static $mimearray = array ( 'xxx' => array ('type'=>'document/unknown', 'icon'=>'unknown'), - '3gp' => array ('type'=>'video/quicktime', 'icon'=>'video'), - 'aac' => array ('type'=>'audio/aac', 'icon'=>'audio'), - 'ai' => array ('type'=>'application/postscript', 'icon'=>'image'), - 'aif' => array ('type'=>'audio/x-aiff', 'icon'=>'audio'), - 'aiff' => array ('type'=>'audio/x-aiff', 'icon'=>'audio'), - 'aifc' => array ('type'=>'audio/x-aiff', 'icon'=>'audio'), + '3gp' => array ('type'=>'video/quicktime', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'aac' => array ('type'=>'audio/aac', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'ai' => array ('type'=>'application/postscript', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), + 'aif' => array ('type'=>'audio/x-aiff', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'aiff' => array ('type'=>'audio/x-aiff', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'aifc' => array ('type'=>'audio/x-aiff', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), 'applescript' => array ('type'=>'text/plain', 'icon'=>'text'), 'asc' => array ('type'=>'text/plain', 'icon'=>'text'), 'asm' => array ('type'=>'text/plain', 'icon'=>'text'), - 'au' => array ('type'=>'audio/au', 'icon'=>'audio'), - 'avi' => array ('type'=>'video/x-ms-wm', 'icon'=>'avi'), - 'bmp' => array ('type'=>'image/bmp', 'icon'=>'image'), + 'au' => array ('type'=>'audio/au', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'avi' => array ('type'=>'video/x-ms-wm', 'icon'=>'avi', 'groups'=>array('video'), 'string'=>'video'), + 'bmp' => array ('type'=>'image/bmp', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), 'c' => array ('type'=>'text/plain', 'icon'=>'text'), 'cct' => array ('type'=>'shockwave/director', 'icon'=>'flash'), 'cpp' => array ('type'=>'text/plain', 'icon'=>'text'), 'cs' => array ('type'=>'application/x-csh', 'icon'=>'text'), - 'css' => array ('type'=>'text/css', 'icon'=>'text'), - 'csv' => array ('type'=>'text/csv', 'icon'=>'excel'), - 'dv' => array ('type'=>'video/x-dv', 'icon'=>'video'), + 'css' => array ('type'=>'text/css', 'icon'=>'text', 'groups'=>array('web_file')), + 'csv' => array ('type'=>'text/csv', 'icon'=>'excel', 'groups'=>array('spreadsheet')), + 'dv' => array ('type'=>'video/x-dv', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), 'dmg' => array ('type'=>'application/octet-stream', 'icon'=>'dmg'), - 'doc' => array ('type'=>'application/msword', 'icon'=>'word'), - 'docx' => array ('type'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'icon'=>'docx'), + 'doc' => array ('type'=>'application/msword', 'icon'=>'word', 'groups'=>array('document')), + 'docx' => array ('type'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'icon'=>'docx', 'groups'=>array('document')), 'docm' => array ('type'=>'application/vnd.ms-word.document.macroEnabled.12', 'icon'=>'docm'), 'dotx' => array ('type'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'icon'=>'dotx'), 'dotm' => array ('type'=>'application/vnd.ms-word.template.macroEnabled.12', 'icon'=>'dotm'), 'dcr' => array ('type'=>'application/x-director', 'icon'=>'flash'), - 'dif' => array ('type'=>'video/x-dv', 'icon'=>'video'), + 'dif' => array ('type'=>'video/x-dv', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), 'dir' => array ('type'=>'application/x-director', 'icon'=>'flash'), 'dxr' => array ('type'=>'application/x-director', 'icon'=>'flash'), 'eps' => array ('type'=>'application/postscript', 'icon'=>'pdf'), 'fdf' => array ('type'=>'application/pdf', 'icon'=>'pdf'), - 'flv' => array ('type'=>'video/x-flv', 'icon'=>'video'), - 'f4v' => array ('type'=>'video/mp4', 'icon'=>'video'), - 'gif' => array ('type'=>'image/gif', 'icon'=>'image'), - 'gtar' => array ('type'=>'application/x-gtar', 'icon'=>'zip'), - 'tgz' => array ('type'=>'application/g-zip', 'icon'=>'zip'), - 'gz' => array ('type'=>'application/g-zip', 'icon'=>'zip'), - 'gzip' => array ('type'=>'application/g-zip', 'icon'=>'zip'), + 'flv' => array ('type'=>'video/x-flv', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'f4v' => array ('type'=>'video/mp4', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'gif' => array ('type'=>'image/gif', 'icon'=>'image', 'groups'=>array('image', 'web_image'), 'string'=>'image'), + 'gtar' => array ('type'=>'application/x-gtar', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), + 'tgz' => array ('type'=>'application/g-zip', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), + 'gz' => array ('type'=>'application/g-zip', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), + 'gzip' => array ('type'=>'application/g-zip', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), 'h' => array ('type'=>'text/plain', 'icon'=>'text'), 'hpp' => array ('type'=>'text/plain', 'icon'=>'text'), - 'hqx' => array ('type'=>'application/mac-binhex40', 'icon'=>'zip'), + 'hqx' => array ('type'=>'application/mac-binhex40', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), 'htc' => array ('type'=>'text/x-component', 'icon'=>'text'), - 'html' => array ('type'=>'text/html', 'icon'=>'html'), + 'html' => array ('type'=>'text/html', 'icon'=>'html', 'groups'=>array('web_file')), 'xhtml'=> array ('type'=>'application/xhtml+xml', 'icon'=>'html'), - 'htm' => array ('type'=>'text/html', 'icon'=>'html'), - 'ico' => array ('type'=>'image/vnd.microsoft.icon', 'icon'=>'image'), + 'htm' => array ('type'=>'text/html', 'icon'=>'html', 'groups'=>array('web_file')), + 'ico' => array ('type'=>'image/vnd.microsoft.icon', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), 'ics' => array ('type'=>'text/calendar', 'icon'=>'text'), 'isf' => array ('type'=>'application/inspiration', 'icon'=>'isf'), 'ist' => array ('type'=>'application/inspiration.template', 'icon'=>'isf'), @@ -1391,52 +1414,52 @@ function get_mimetypes_array() { 'jcw' => array ('type'=>'text/xml', 'icon'=>'jcw'), 'jmt' => array ('type'=>'text/xml', 'icon'=>'jmt'), 'jmx' => array ('type'=>'text/xml', 'icon'=>'jmx'), - 'jpe' => array ('type'=>'image/jpeg', 'icon'=>'image'), - 'jpeg' => array ('type'=>'image/jpeg', 'icon'=>'image'), - 'jpg' => array ('type'=>'image/jpeg', 'icon'=>'image'), + 'jpe' => array ('type'=>'image/jpeg', 'icon'=>'image', 'groups'=>array('image', 'web_image'), 'string'=>'image'), + 'jpeg' => array ('type'=>'image/jpeg', 'icon'=>'image', 'groups'=>array('image', 'web_image'), 'string'=>'image'), + 'jpg' => array ('type'=>'image/jpeg', 'icon'=>'image', 'groups'=>array('image', 'web_image'), 'string'=>'image'), 'jqz' => array ('type'=>'text/xml', 'icon'=>'jqz'), - 'js' => array ('type'=>'application/x-javascript', 'icon'=>'text'), + 'js' => array ('type'=>'application/x-javascript', 'icon'=>'text', 'groups'=>array('web_file')), 'latex'=> array ('type'=>'application/x-latex', 'icon'=>'text'), 'm' => array ('type'=>'text/plain', 'icon'=>'text'), 'mbz' => array ('type'=>'application/vnd.moodle.backup', 'icon'=>'moodle'), - 'mov' => array ('type'=>'video/quicktime', 'icon'=>'video'), - 'movie'=> array ('type'=>'video/x-sgi-movie', 'icon'=>'video'), - 'm3u' => array ('type'=>'audio/x-mpegurl', 'icon'=>'audio'), - 'mp3' => array ('type'=>'audio/mp3', 'icon'=>'audio'), - 'mp4' => array ('type'=>'video/mp4', 'icon'=>'video'), - 'm4v' => array ('type'=>'video/mp4', 'icon'=>'video'), - 'm4a' => array ('type'=>'audio/mp4', 'icon'=>'audio'), - 'mpeg' => array ('type'=>'video/mpeg', 'icon'=>'video'), - 'mpe' => array ('type'=>'video/mpeg', 'icon'=>'video'), - 'mpg' => array ('type'=>'video/mpeg', 'icon'=>'video'), + 'mov' => array ('type'=>'video/quicktime', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'movie'=> array ('type'=>'video/x-sgi-movie', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'm3u' => array ('type'=>'audio/x-mpegurl', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'mp3' => array ('type'=>'audio/mp3', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'mp4' => array ('type'=>'video/mp4', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'm4v' => array ('type'=>'video/mp4', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'm4a' => array ('type'=>'audio/mp4', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'mpeg' => array ('type'=>'video/mpeg', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'mpe' => array ('type'=>'video/mpeg', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'mpg' => array ('type'=>'video/mpeg', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), - 'odt' => array ('type'=>'application/vnd.oasis.opendocument.text', 'icon'=>'odt'), - 'ott' => array ('type'=>'application/vnd.oasis.opendocument.text-template', 'icon'=>'odt'), - 'oth' => array ('type'=>'application/vnd.oasis.opendocument.text-web', 'icon'=>'odt'), + 'odt' => array ('type'=>'application/vnd.oasis.opendocument.text', 'icon'=>'odt', 'groups'=>array('document')), + 'ott' => array ('type'=>'application/vnd.oasis.opendocument.text-template', 'icon'=>'odt', 'groups'=>array('document')), + 'oth' => array ('type'=>'application/vnd.oasis.opendocument.text-web', 'icon'=>'odt', 'groups'=>array('document')), 'odm' => array ('type'=>'application/vnd.oasis.opendocument.text-master', 'icon'=>'odm'), 'odg' => array ('type'=>'application/vnd.oasis.opendocument.graphics', 'icon'=>'odg'), 'otg' => array ('type'=>'application/vnd.oasis.opendocument.graphics-template', 'icon'=>'odg'), 'odp' => array ('type'=>'application/vnd.oasis.opendocument.presentation', 'icon'=>'odp'), 'otp' => array ('type'=>'application/vnd.oasis.opendocument.presentation-template', 'icon'=>'odp'), - 'ods' => array ('type'=>'application/vnd.oasis.opendocument.spreadsheet', 'icon'=>'ods'), - 'ots' => array ('type'=>'application/vnd.oasis.opendocument.spreadsheet-template', 'icon'=>'ods'), + 'ods' => array ('type'=>'application/vnd.oasis.opendocument.spreadsheet', 'icon'=>'ods', 'groups'=>array('spreadsheet')), + 'ots' => array ('type'=>'application/vnd.oasis.opendocument.spreadsheet-template', 'icon'=>'ods', 'groups'=>array('spreadsheet')), 'odc' => array ('type'=>'application/vnd.oasis.opendocument.chart', 'icon'=>'odc'), 'odf' => array ('type'=>'application/vnd.oasis.opendocument.formula', 'icon'=>'odf'), 'odb' => array ('type'=>'application/vnd.oasis.opendocument.database', 'icon'=>'odb'), 'odi' => array ('type'=>'application/vnd.oasis.opendocument.image', 'icon'=>'odi'), - 'oga' => array ('type'=>'audio/ogg', 'icon'=>'audio'), - 'ogg' => array ('type'=>'audio/ogg', 'icon'=>'audio'), - 'ogv' => array ('type'=>'video/ogg', 'icon'=>'video'), + 'oga' => array ('type'=>'audio/ogg', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'ogg' => array ('type'=>'audio/ogg', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'ogv' => array ('type'=>'video/ogg', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), - 'pct' => array ('type'=>'image/pict', 'icon'=>'image'), + 'pct' => array ('type'=>'image/pict', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), 'pdf' => array ('type'=>'application/pdf', 'icon'=>'pdf'), 'php' => array ('type'=>'text/plain', 'icon'=>'text'), - 'pic' => array ('type'=>'image/pict', 'icon'=>'image'), - 'pict' => array ('type'=>'image/pict', 'icon'=>'image'), - 'png' => array ('type'=>'image/png', 'icon'=>'image'), + 'pic' => array ('type'=>'image/pict', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), + 'pict' => array ('type'=>'image/pict', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), + 'png' => array ('type'=>'image/png', 'icon'=>'image', 'groups'=>array('image', 'web_image'), 'string'=>'image'), - 'pps' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'powerpoint'), - 'ppt' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'powerpoint'), + 'pps' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'powerpoint', 'groups'=>array('presentation')), + 'ppt' => array ('type'=>'application/vnd.ms-powerpoint', 'icon'=>'powerpoint', 'groups'=>array('presentation')), 'pptx' => array ('type'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'icon'=>'pptx'), 'pptm' => array ('type'=>'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'icon'=>'pptm'), 'potx' => array ('type'=>'application/vnd.openxmlformats-officedocument.presentationml.template', 'icon'=>'potx'), @@ -1446,22 +1469,22 @@ function get_mimetypes_array() { 'ppsm' => array ('type'=>'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'icon'=>'ppsm'), 'ps' => array ('type'=>'application/postscript', 'icon'=>'pdf'), - 'qt' => array ('type'=>'video/quicktime', 'icon'=>'video'), - 'ra' => array ('type'=>'audio/x-realaudio-plugin', 'icon'=>'audio'), - 'ram' => array ('type'=>'audio/x-pn-realaudio-plugin', 'icon'=>'audio'), + 'qt' => array ('type'=>'video/quicktime', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'ra' => array ('type'=>'audio/x-realaudio-plugin', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'ram' => array ('type'=>'audio/x-pn-realaudio-plugin', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), 'rhb' => array ('type'=>'text/xml', 'icon'=>'xml'), - 'rm' => array ('type'=>'audio/x-pn-realaudio-plugin', 'icon'=>'audio'), - 'rmvb' => array ('type'=>'application/vnd.rn-realmedia-vbr', 'icon'=>'video'), - 'rtf' => array ('type'=>'text/rtf', 'icon'=>'text'), + 'rm' => array ('type'=>'audio/x-pn-realaudio-plugin', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'rmvb' => array ('type'=>'application/vnd.rn-realmedia-vbr', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'rtf' => array ('type'=>'text/rtf', 'icon'=>'text', 'groups'=>array('document')), 'rtx' => array ('type'=>'text/richtext', 'icon'=>'text'), - 'rv' => array ('type'=>'audio/x-pn-realaudio-plugin', 'icon'=>'video'), + 'rv' => array ('type'=>'audio/x-pn-realaudio-plugin', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), 'sh' => array ('type'=>'application/x-sh', 'icon'=>'text'), - 'sit' => array ('type'=>'application/x-stuffit', 'icon'=>'zip'), + 'sit' => array ('type'=>'application/x-stuffit', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), 'smi' => array ('type'=>'application/smil', 'icon'=>'text'), 'smil' => array ('type'=>'application/smil', 'icon'=>'text'), 'sqt' => array ('type'=>'text/xml', 'icon'=>'xml'), - 'svg' => array ('type'=>'image/svg+xml', 'icon'=>'image'), - 'svgz' => array ('type'=>'image/svg+xml', 'icon'=>'image'), + 'svg' => array ('type'=>'image/svg+xml', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), + 'svgz' => array ('type'=>'image/svg+xml', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), 'swa' => array ('type'=>'application/x-director', 'icon'=>'flash'), 'swf' => array ('type'=>'application/x-shockwave-flash', 'icon'=>'flash'), 'swfl' => array ('type'=>'application/x-shockwave-flash', 'icon'=>'flash'), @@ -1477,25 +1500,25 @@ function get_mimetypes_array() { 'sxg' => array ('type'=>'application/vnd.sun.xml.writer.global', 'icon'=>'odt'), 'sxm' => array ('type'=>'application/vnd.sun.xml.math', 'icon'=>'odt'), - 'tar' => array ('type'=>'application/x-tar', 'icon'=>'zip'), - 'tif' => array ('type'=>'image/tiff', 'icon'=>'image'), - 'tiff' => array ('type'=>'image/tiff', 'icon'=>'image'), + 'tar' => array ('type'=>'application/x-tar', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive'), + 'tif' => array ('type'=>'image/tiff', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), + 'tiff' => array ('type'=>'image/tiff', 'icon'=>'image', 'groups'=>array('image'), 'string'=>'image'), 'tex' => array ('type'=>'application/x-tex', 'icon'=>'text'), 'texi' => array ('type'=>'application/x-texinfo', 'icon'=>'text'), 'texinfo' => array ('type'=>'application/x-texinfo', 'icon'=>'text'), 'tsv' => array ('type'=>'text/tab-separated-values', 'icon'=>'text'), - 'txt' => array ('type'=>'text/plain', 'icon'=>'text'), - 'wav' => array ('type'=>'audio/wav', 'icon'=>'audio'), - 'webm' => array ('type'=>'video/webm', 'icon'=>'video'), - 'wmv' => array ('type'=>'video/x-ms-wmv', 'icon'=>'avi'), - 'asf' => array ('type'=>'video/x-ms-asf', 'icon'=>'avi'), + 'txt' => array ('type'=>'text/plain', 'icon'=>'text', 'defaulticon'=>true), + 'wav' => array ('type'=>'audio/wav', 'icon'=>'audio', 'groups'=>array('audio'), 'string'=>'audio'), + 'webm' => array ('type'=>'video/webm', 'icon'=>'video', 'groups'=>array('video'), 'string'=>'video'), + 'wmv' => array ('type'=>'video/x-ms-wmv', 'icon'=>'avi', 'groups'=>array('video'), 'string'=>'video'), + 'asf' => array ('type'=>'video/x-ms-asf', 'icon'=>'avi', 'groups'=>array('video'), 'string'=>'video'), 'xdp' => array ('type'=>'application/pdf', 'icon'=>'pdf'), 'xfd' => array ('type'=>'application/pdf', 'icon'=>'pdf'), 'xfdf' => array ('type'=>'application/pdf', 'icon'=>'pdf'), - 'xls' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'excel'), + 'xls' => array ('type'=>'application/vnd.ms-excel', 'icon'=>'excel', 'groups'=>array('spreadsheet')), 'xlsx' => array ('type'=>'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'icon'=>'xlsx'), - 'xlsm' => array ('type'=>'application/vnd.ms-excel.sheet.macroEnabled.12', 'icon'=>'xlsm'), + 'xlsm' => array ('type'=>'application/vnd.ms-excel.sheet.macroEnabled.12', 'icon'=>'xlsm', 'groups'=>array('spreadsheet')), 'xltx' => array ('type'=>'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'icon'=>'xltx'), 'xltm' => array ('type'=>'application/vnd.ms-excel.template.macroEnabled.12', 'icon'=>'xltm'), 'xlsb' => array ('type'=>'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'icon'=>'xlsb'), @@ -1503,7 +1526,7 @@ function get_mimetypes_array() { 'xml' => array ('type'=>'application/xml', 'icon'=>'xml'), 'xsl' => array ('type'=>'text/xml', 'icon'=>'xml'), - 'zip' => array ('type'=>'application/zip', 'icon'=>'zip') + 'zip' => array ('type'=>'application/zip', 'icon'=>'zip', 'groups'=>array('archive'), 'string'=>'archive') ); return $mimearray; } @@ -1515,39 +1538,41 @@ function get_mimetypes_array() { * * @category files * @param string $element Desired information (usually 'icon' - * for icon filename or 'type' for MIME type) + * for icon filename or 'type' for MIME type. Can also be + * 'icon24', ...32, 48, 64, 72, 80, 96, 128, 256) * @param string $filename Filename we're looking up * @return string Requested piece of information from array */ function mimeinfo($element, $filename) { global $CFG; - $mimeinfo = get_mimetypes_array(); + $mimeinfo = & get_mimetypes_array(); + static $iconpostfixes = array(256=>'-256', 128=>'-128', 96=>'-96', 80=>'-80', 72=>'-72', 64=>'-64', 48=>'-48', 32=>'-32', 24=>'-24', 16=>''); - if (preg_match('/\.([a-z0-9]+)$/i', $filename, $match)) { - if (isset($mimeinfo[strtolower($match[1])][$element])) { - return $mimeinfo[strtolower($match[1])][$element]; - } else { - if ($element == 'icon32') { - if (isset($mimeinfo[strtolower($match[1])]['icon'])) { - $filename = $mimeinfo[strtolower($match[1])]['icon']; - } else { - $filename = 'unknown'; + $filetype = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + if (empty($filetype)) { + $filetype = 'xxx'; // file without extension + } + if (preg_match('/^icon(\d*)$/', $element, $iconsizematch)) { + $iconsize = max(array(16, (int)$iconsizematch[1])); + $filenames = array($mimeinfo['xxx']['icon']); + if ($filetype != 'xxx' && isset($mimeinfo[$filetype]['icon'])) { + array_unshift($filenames, $mimeinfo[$filetype]['icon']); + } + // find the file with the closest size, first search for specific icon then for default icon + foreach ($filenames as $filename) { + foreach ($iconpostfixes as $size => $postfix) { + $fullname = $CFG->dirroot.'/pix/f/'.$filename.$postfix; + if ($iconsize >= $size && (file_exists($fullname.'.png') || file_exists($fullname.'.gif'))) { + return $filename.$postfix; } - $filename .= '-32'; - if (file_exists($CFG->dirroot.'/pix/f/'.$filename.'.png') or file_exists($CFG->dirroot.'/pix/f/'.$filename.'.gif')) { - return $filename; - } else { - return 'unknown-32'; - } - } else { - return $mimeinfo['xxx'][$element]; // By default } } - } else { - if ($element == 'icon32') { - return 'unknown-32'; - } + } else if (isset($mimeinfo[$filetype][$element])) { + return $mimeinfo[$filetype][$element]; + } else if (isset($mimeinfo['xxx'][$element])) { return $mimeinfo['xxx'][$element]; // By default + } else { + return null; } } @@ -1556,66 +1581,115 @@ function mimeinfo($element, $filename) { * the other way around. * * @category files - * @param string $element Desired information (usually 'icon') + * @param string $element Desired information ('extension', 'icon', 'icon-24', etc.) * @param string $mimetype MIME type we're looking up * @return string Requested piece of information from array */ function mimeinfo_from_type($element, $mimetype) { - $mimeinfo = get_mimetypes_array(); + /* array of cached mimetype->extension associations */ + static $cached = array(); + $mimeinfo = & get_mimetypes_array(); - foreach($mimeinfo as $values) { - if ($values['type']==$mimetype) { - if (isset($values[$element])) { - return $values[$element]; + if (!array_key_exists($mimetype, $cached)) { + $cached[$mimetype] = null; + foreach($mimeinfo as $filetype => $values) { + if ($values['type'] == $mimetype) { + if ($cached[$mimetype] === null) { + $cached[$mimetype] = $filetype; + } + if (!empty($values['defaulticon'])) { + $cached[$mimetype] = $filetype; + break; + } } - break; } } - return $mimeinfo['xxx'][$element]; // Default + if ($cached[$mimetype] !== null && $cached[$mimetype] !== 'xxx') { + if ($element = 'extension') { + return $cached[$mimetype]; + } else { + return mimeinfo($element, '.'.$cached[$mimetype]); + } + } else { + return mimeinfo($element, ''); + } } /** - * Get information about a filetype based on the icon file. + * Return the relative icon path for a given file * - * @category files - * @param string $element Desired information (usually 'icon') - * @param string $icon Icon file name without extension - * @param bool $all return all matching entries (defaults to false - best (by ext)/last match) - * @return string Requested piece of information from array + * Usage: + * + * // $file - instance of stored_file or file_info + * $icon = $OUTPUT->pix_url(file_file_icon($file))->out(); + * echo html_writer::empty_tag('img', array('src' => $icon, 'alt' => get_mimetype_description($file))); + * + * or + * + * echo $OUTPUT->pix_icon(file_file_icon($file), get_mimetype_description($file)); + * + * + * @param stored_file|file_info|stdClass|array $file (in case of object attributes $file->filename + * and $file->mimetype are expected) + * @param int $size The size of the icon. Defaults to 16 can also be 24, 32, 64, 128, 256 + * @return string */ -function mimeinfo_from_icon($element, $icon, $all=false) { - $mimeinfo = get_mimetypes_array(); +function file_file_icon($file, $size = null) { + if (!is_object($file)) { + $file = (object)$file; + } + if (isset($file->filename)) { + $filename = $file->filename; + } else if (method_exists($file, 'get_filename')) { + $filename = $file->get_filename(); + } else if (method_exists($file, 'get_visible_name')) { + $filename = $file->get_visible_name(); + } else { + $filename = ''; + } + if (isset($file->mimetype)) { + $mimetype = $file->mimetype; + } else if (method_exists($file, 'get_mimetype')) { + $mimetype = $file->get_mimetype(); + } else { + $mimetype = ''; + } + if ($filename && pathinfo($filename, PATHINFO_EXTENSION) && + (!$mimetype || mimeinfo('type', $filename) === $mimetype)) { + // files with different extensions sharing the same mimetype (i.e. 'text/plain') may have different icons + return file_extension_icon($filename, $size); + } else { + // if mimetype and extension do not match we assume that mimetype is more correct + return file_mimetype_icon($mimetype, $size); + } +} - if (preg_match("/\/(.*)/", $icon, $matches)) { - $icon = $matches[1]; - } - // Try to get the extension - $extension = ''; - if (($cutat = strrpos($icon, '.')) !== false && $cutat < strlen($icon)-1) { - $extension = substr($icon, $cutat + 1); - } - $info = array($mimeinfo['xxx'][$element]); // Default - foreach($mimeinfo as $key => $values) { - if ($values['icon']==$icon) { - if (isset($values[$element])) { - $info[$key] = $values[$element]; - } - //No break, for example for 'excel' we don't want 'csv'! +/** + * Return the relative icon path for a folder image + * + * Usage: + * + * $icon = $OUTPUT->pix_url(file_folder_icon())->out(); + * echo html_writer::empty_tag('img', array('src' => $icon)); + * + * or + * + * echo $OUTPUT->pix_icon(file_folder_icon(32)); + * + * + * @param int $iconsize The size of the icon. Defaults to 16 can also be 24, 32, 48, 64, 72, 80, 96, 128, 256 + * @return string + */ +function file_folder_icon($iconsize = null) { + global $CFG; + static $iconpostfixes = array(256=>'-256', 128=>'-128', 96=>'-96', 80=>'-80', 72=>'-72', 64=>'-64', 48=>'-48', 32=>'-32', 24=>'-24', 16=>''); + $iconsize = max(array(16, (int)$iconsize)); + foreach ($iconpostfixes as $size => $postfix) { + $fullname = $CFG->dirroot.'/pix/f/folder'.$postfix; + if ($iconsize >= $size && (file_exists($fullname.'.png') || file_exists($fullname.'.gif'))) { + return 'f/folder'.$postfix; } } - if ($all) { - if (count($info) > 1) { - array_shift($info); // take off document/unknown if we have better options - } - return array_values($info); // Keep keys out when requesting all - } - - // Requested only one, try to get the best by extension coincidence, else return the last - if ($extension && isset($info[$extension])) { - return $info[$extension]; - } - - return array_pop($info); // Return last match (mimicking behaviour/comment inside foreach loop) } /** @@ -1626,27 +1700,19 @@ function mimeinfo_from_icon($element, $icon, $all=false) { * * * $mimetype = 'image/jpg'; - * $icon = $OUTPUT->pix_url(file_mimetype_icon($mimetype)); - * echo ''.$mimetype.''; + * $icon = $OUTPUT->pix_url(file_mimetype_icon($mimetype))->out(); + * echo html_writer::empty_tag('img', array('src' => $icon, 'alt' => get_mimetype_description($mimetype))); * * * @category files * @todo MDL-31074 When an $OUTPUT->icon method is available this function should be altered * to conform with that. * @param string $mimetype The mimetype to fetch an icon for - * @param int $size The size of the icon. Not yet implemented + * @param int $size The size of the icon. Defaults to 16 can also be 24, 32, 64, 128, 256 * @return string The relative path to the icon */ function file_mimetype_icon($mimetype, $size = NULL) { - global $CFG; - - $icon = mimeinfo_from_type('icon', $mimetype); - if ($size) { - if (file_exists("$CFG->dirroot/pix/f/$icon-$size.png") or file_exists("$CFG->dirroot/pix/f/$icon-$size.gif")) { - $icon = "$icon-$size"; - } - } - return 'f/'.$icon; + return 'f/'.mimeinfo_from_type('icon'.$size, $mimetype); } /** @@ -1656,9 +1722,9 @@ function file_mimetype_icon($mimetype, $size = NULL) { * a return the full path to an icon. * * - * $filename = 'jpg'; - * $icon = $OUTPUT->pix_url(file_extension_icon($filename)); - * echo 'blah'; + * $filename = '.jpg'; + * $icon = $OUTPUT->pix_url(file_extension_icon($filename))->out(); + * echo html_writer::empty_tag('img', array('src' => $icon, 'alt' => '...')); * * * @todo MDL-31074 When an $OUTPUT->icon method is available this function should be altered @@ -1666,34 +1732,77 @@ function file_mimetype_icon($mimetype, $size = NULL) { * @todo MDL-31074 Implement $size * @category files * @param string $filename The filename to get the icon for - * @param int $size The size of the icon. Defaults to null can also be 32 + * @param int $size The size of the icon. Defaults to 16 can also be 24, 32, 64, 128, 256 * @return string */ function file_extension_icon($filename, $size = NULL) { - global $CFG; - - $icon = mimeinfo('icon', $filename); - if ($size) { - if (file_exists("$CFG->dirroot/pix/f/$icon-$size.png") or file_exists("$CFG->dirroot/pix/f/$icon-$size.gif")) { - $icon = "$icon-$size"; - } - } - return 'f/'.$icon; + return 'f/'.mimeinfo('icon'.$size, $filename); } /** * Obtains descriptions for file types (e.g. 'Microsoft Word document') from the * mimetypes.php language file. * - * @param string $mimetype MIME type (can be obtained using the mimeinfo function) + * @param mixed $obj - instance of stored_file or file_info or array/stdClass with field + * 'filename' and 'mimetype', or just a string with mimetype (though it is recommended to + * have filename); In case of array/stdClass the field 'mimetype' is optional. * @param bool $capitalise If true, capitalises first character of result * @return string Text description */ -function get_mimetype_description($mimetype, $capitalise=false) { - if (get_string_manager()->string_exists($mimetype, 'mimetypes')) { - $result = get_string($mimetype, 'mimetypes'); +function get_mimetype_description($obj, $capitalise=false) { + if (is_object($obj) && method_exists($obj, 'get_filename') && method_exists($obj, 'get_mimetype')) { + // this is an instance of stored_file + $mimetype = $obj->get_mimetype(); + $filename = $obj->get_filename(); + } else if (is_object($obj) && method_exists($obj, 'get_visible_name') && method_exists($obj, 'get_mimetype')) { + // this is an instance of file_info + $mimetype = $obj->get_mimetype(); + $filename = $obj->get_visible_name(); + } else if (is_array($obj) || is_object ($obj)) { + $obj = (array)$obj; + if (!empty($obj['filename'])) { + $filename = $obj['filename']; + } else { + $filename = ''; + } + if (!empty($obj['mimetype'])) { + $mimetype = $obj['mimetype']; + } else { + $mimetype = mimeinfo('type', $filename); + } } else { - $result = get_string('document/unknown','mimetypes'); + $mimetype = $obj; + $filename = ''; + } + $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); + if (empty($extension)) { + $mimetypestr = mimeinfo_from_type('string', $mimetype); + $extension = mimeinfo_from_type('extension', $mimetype); + } else { + $mimetypestr = mimeinfo('string', $filename); + } + $chunks = explode('/', $mimetype, 2); + $chunks[] = ''; + $attr = array( + 'mimetype' => $mimetype, + 'ext' => $extension, + 'mimetype1' => $chunks[0], + 'mimetype2' => $chunks[1], + ); + $a = array(); + foreach ($attr as $key => $value) { + $a[$key] = $value; + $a[strtoupper($key)] = strtoupper($value); + $a[ucfirst($key)] = ucfirst($value); + } + if (get_string_manager()->string_exists($mimetype, 'mimetypes')) { + $result = get_string($mimetype, 'mimetypes', (object)$a); + } else if (get_string_manager()->string_exists($mimetypestr, 'mimetypes')) { + $result = get_string($mimetypestr, 'mimetypes', (object)$a); + } else if (get_string_manager()->string_exists('default', 'mimetypes')) { + $result = get_string('default', 'mimetypes', (object)$a); + } else { + $result = $mimetype; } if ($capitalise) { $result=ucfirst($result); @@ -1701,6 +1810,74 @@ function get_mimetype_description($mimetype, $capitalise=false) { return $result; } +/** + * Returns array of elements of type $element in type group(s) + * + * @param string $element name of the element we are interested in, usually 'type' or 'extension' + * @param string|array $groups one group or array of groups/extensions/mimetypes + * @return array + */ +function file_get_typegroup($element, $groups) { + static $cached = array(); + if (!is_array($groups)) { + $groups = array($groups); + } + if (!array_key_exists($element, $cached)) { + $cached[$element] = array(); + } + $result = array(); + foreach ($groups as $group) { + if (!array_key_exists($group, $cached[$element])) { + // retrieive and cache all elements of type $element for group $group + $mimeinfo = & get_mimetypes_array(); + $cached[$element][$group] = array(); + foreach ($mimeinfo as $extension => $value) { + $value['extension'] = $extension; + if (empty($value[$element])) { + continue; + } + if (($group === $extension || $group === $value['type'] || + (!empty($value['groups']) && in_array($group, $value['groups']))) && + !in_array($value[$element], $cached[$element][$group])) { + $cached[$element][$group][] = $value[$element]; + } + } + } + $result = array_merge($result, $cached[$element][$group]); + } + return array_unique($result); +} + +/** + * Checks if file with name $filename has one of the extensions in groups $groups + * + * @see get_mimetypes_array() + * @param string $filename name of the file to check + * @param string|array $groups one group or array of groups to check + * @param bool $checktype if true and extension check fails, find the mimetype and check if + * file mimetype is in mimetypes in groups $groups + * @return bool + */ +function file_extension_in_typegroup($filename, $groups, $checktype = false) { + $extension = pathinfo($filename, PATHINFO_EXTENSION); + if (!empty($extension) && in_array(strtolower($extension), file_get_typegroup('extension', $groups))) { + return true; + } + return $checktype && file_mimetype_in_typegroup(mimeinfo('type', $filename), $groups); +} + +/** + * Checks if mimetype $mimetype belongs to one of the groups $groups + * + * @see get_mimetypes_array() + * @param string $mimetype + * @param string|array $groups one group or array of groups to check + * @return bool + */ +function file_mimetype_in_typegroup($mimetype, $groups) { + return !empty($mimetype) && in_array($mimetype, file_get_typegroup('type', $groups)); +} + /** * Requested file is not found or not accessible, does not return, terminates script * @@ -3165,109 +3342,6 @@ class curl_cache { } } -/** - * This class is used to parse lib/file/file_types.mm which help get file extensions by file types. - * - * The file_types.mm file can be edited by freemind in graphic environment. - * - * @package core_files - * @category files - * @copyright 2009 Dongsheng Cai - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class filetype_parser { - /** - * Check file_types.mm file, setup variables - * - * @global stdClass $CFG - * @param string $file - */ - public function __construct($file = '') { - global $CFG; - if (empty($file)) { - $this->file = $CFG->libdir.'/filestorage/file_types.mm'; - } else { - $this->file = $file; - } - $this->tree = array(); - $this->result = array(); - } - - /** - * A private function to browse xml nodes - * - * @param array $parent - * @param array $types - */ - private function _browse_nodes($parent, $types) { - $key = (string)$parent['TEXT']; - if(isset($parent->node)) { - $this->tree[$key] = array(); - if (in_array((string)$parent['TEXT'], $types)) { - $this->_select_nodes($parent, $this->result); - } else { - foreach($parent->node as $v){ - $this->_browse_nodes($v, $types); - } - } - } else { - $this->tree[] = $key; - } - } - - /** - * A private function to select text nodes - * - * @param array $parent - */ - private function _select_nodes($parent){ - if(isset($parent->node)) { - foreach($parent->node as $v){ - $this->_select_nodes($v, $this->result); - } - } else { - $this->result[] = (string)$parent['TEXT']; - } - } - - - /** - * Get file extensions by file types names. - * - * @param array $types - * @return mixed - */ - public function get_extensions($types) { - if (!is_array($types)) { - $types = array($types); - } - $this->result = array(); - if ((is_array($types) && in_array('*', $types)) || - $types == '*' || empty($types)) { - return array('*'); - } - foreach ($types as $key=>$value){ - if (strpos($value, '.') !== false) { - $this->result[] = $value; - unset($types[$key]); - } - } - if (file_exists($this->file)) { - $xml = simplexml_load_file($this->file); - foreach($xml->node->node as $v){ - if (in_array((string)$v['TEXT'], $types)) { - $this->_select_nodes($v); - } else { - $this->_browse_nodes($v, $types); - } - } - } else { - exit('Failed to open file lib/filestorage/file_types.mm'); - } - return $this->result; - } -} - /** * This function delegates file serving to individual plugins * diff --git a/lib/filestorage/file_types.mm b/lib/filestorage/file_types.mm deleted file mode 100644 index 71ff4fbdc09..00000000000 --- a/lib/filestorage/file_types.mm +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/filestorage/stored_file.php b/lib/filestorage/stored_file.php index e9b2e3f5c67..1885026f2f6 100644 --- a/lib/filestorage/stored_file.php +++ b/lib/filestorage/stored_file.php @@ -25,7 +25,6 @@ defined('MOODLE_INTERNAL') || die(); -require_once("$CFG->libdir/filestorage/stored_file.php"); require_once("$CFG->dirroot/repository/lib.php"); /** @@ -444,7 +443,7 @@ class stored_file { */ public function is_valid_image() { $mimetype = $this->get_mimetype(); - if ($mimetype !== 'image/gif' and $mimetype !== 'image/jpeg' and $mimetype !== 'image/png') { + if (!file_mimetype_in_typegroup($mimetype, 'web_image')) { return false; } if (!$info = $this->get_imageinfo()) { diff --git a/lib/portfolio/formats.php b/lib/portfolio/formats.php index 56f6ecea8c6..09c45e72ebe 100644 --- a/lib/portfolio/formats.php +++ b/lib/portfolio/formats.php @@ -198,7 +198,7 @@ class portfolio_format_image extends portfolio_format_file { * @return string */ public static function mimetypes() { - return mimeinfo_from_icon('type', 'image', true); + return file_get_typegroup('type', 'image'); } /** @@ -286,10 +286,7 @@ class portfolio_format_video extends portfolio_format_file { * @return array */ public static function mimetypes() { - return array_merge( - mimeinfo_from_icon('type', 'video', true), - mimeinfo_from_icon('type', 'avi', true) - ); + return file_get_typegroup('type', 'video'); } } @@ -561,12 +558,7 @@ class portfolio_format_document extends portfolio_format_file { * @return array of documents mimetypes */ public static function mimetypes() { - return array_merge( - array('text/plain', 'text/rtf'), - mimeinfo_from_icon('type', 'word', true), - mimeinfo_from_icon('type', 'docx', true), - mimeinfo_from_icon('type', 'odt', true) - ); + return file_get_typegroup('type', 'document'); } } @@ -588,11 +580,7 @@ class portfolio_format_spreadsheet extends portfolio_format_file { * @return array of documents mimetypes */ public static function mimetypes() { - return array_merge( - mimeinfo_from_icon('type', 'excel', true), - mimeinfo_from_icon('type', 'xlsm', true), - mimeinfo_from_icon('type', 'ods', true) - ); + return file_get_typegroup('type', 'spreadsheet'); } } @@ -614,6 +602,6 @@ class portfolio_format_presentation extends portfolio_format_file { * @return array presentation document mimetypes */ public static function mimetypes() { - return mimeinfo_from_icon('type', 'powerpoint', true); + return file_get_typegroup('type', 'presentation'); } } diff --git a/mod/assign/renderer.php b/mod/assign/renderer.php index 8fca9b03864..598969e88e1 100644 --- a/mod/assign/renderer.php +++ b/mod/assign/renderer.php @@ -579,20 +579,19 @@ class mod_assign_renderer extends plugin_renderer_base { $result = '
                          '; // Begin table $content .= ''; // Header row: day names diff --git a/lang/en/access.php b/lang/en/access.php index b338d424d16..ee81afc8a35 100644 --- a/lang/en/access.php +++ b/lang/en/access.php @@ -39,8 +39,6 @@ $string['skipa'] = 'Skip {$a}'; $string['skipblock'] = 'Skip block'; $string['skipnavigation'] = 'Skip navigation'; $string['skipto'] = 'Skip to {$a}'; -$string['tabledata'] = 'Data table, {$a}'; -$string['tablelayout'] = 'Layout table, {$a}'; $string['tocontent'] = 'Skip to main content'; $string['tonavigation'] = 'Go to navigation'; $string['youarehere'] = 'You are here'; From eef67fe8c55a71b7853976efaaefef23db459c43 Mon Sep 17 00:00:00 2001 From: Dan Marsden Date: Thu, 24 May 2012 14:08:01 +1200 Subject: [PATCH 349/455] MDL-33318 use $CFG->admin in path correctly - thanks to Clarence Prudhoe for report/fix --- lib/cronlib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cronlib.php b/lib/cronlib.php index 0e47a655c32..3bbab293b79 100644 --- a/lib/cronlib.php +++ b/lib/cronlib.php @@ -376,7 +376,7 @@ function cron_run() { //Run registration updated cron mtrace(get_string('siteupdatesstart', 'hub')); - require_once($CFG->dirroot . '/admin/registration/lib.php'); + require_once($CFG->dirroot . "/$CFG->admin/registration/lib.php"); $registrationmanager = new registration_manager(); $registrationmanager->cron(); mtrace(get_string('siteupdatesend', 'hub')); From c53a64449ad16ae6c672d5cf80020e9903a02d8b Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Thu, 24 May 2012 09:40:59 +0700 Subject: [PATCH 350/455] MDL-33315 blog: fixed up the navigation for when youre viewing another users blog --- blog/index.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blog/index.php b/blog/index.php index 8d28dbcc6f1..77476a98242 100644 --- a/blog/index.php +++ b/blog/index.php @@ -192,6 +192,8 @@ if (!empty($userid)) { if (!blog_user_can_view_user_entry($userid)) { print_error('cannotviewcourseblog', 'blog'); } + + $PAGE->navigation->extend_for_user($user); } } From 1e98e05f037d04224075714d3a37c036ccaba34a Mon Sep 17 00:00:00 2001 From: Rossiani Wijaya Date: Thu, 24 May 2012 13:43:01 +0800 Subject: [PATCH 351/455] MDL-33196 filepicker: fixed link output error --- repository/filepicker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repository/filepicker.php b/repository/filepicker.php index 853111ccc14..407b3ddd35e 100644 --- a/repository/filepicker.php +++ b/repository/filepicker.php @@ -316,7 +316,7 @@ case 'download': case 'confirm': echo $OUTPUT->header(); - echo ''; + echo ''; echo ''; echo ''; echo '
                          '; From 7eea889b76e436b25b8516bf8decc5ccd39cc07e Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Wed, 23 May 2012 15:06:17 +0800 Subject: [PATCH 352/455] MDL-30905 Accessibility: recent activity list is XHTML compliant --- course/recent.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/course/recent.php b/course/recent.php index f33ef54c617..8b31e29835f 100644 --- a/course/recent.php +++ b/course/recent.php @@ -221,7 +221,9 @@ if (!empty($activities)) { echo $OUTPUT->spacer(array('height'=>30, 'br'=>true)); // should be done with CSS instead } echo $OUTPUT->box_start(); - echo "

                          $activity->name

                          "; + if (!empty($activity->name)) { + echo html_writer::tag('h2', $activity->name); + } $inbox = true; } else if ($activity->type == 'activity') { @@ -230,16 +232,17 @@ if (!empty($activities)) { $cm = $modinfo->cms[$activity->cmid]; if ($cm->visible) { - $linkformat = ''; + $class = ''; } else { - $linkformat = 'class="dimmed"'; + $class = 'dimmed'; } $name = format_string($cm->name); $modfullname = $modnames[$cm->modname]; - $image = "pix_url('icon', $cm->modname) . "\" class=\"icon\" alt=\"$modfullname\" />"; - echo "

                          $image $modfullname". - " wwwroot/mod/$cm->modname/view.php?id=$cm->id\" $linkformat>$name

                          "; + $image = $OUTPUT->pix_icon('icon', $modfullname, $cm->modname, array('class' => 'icon smallicon')); + $link = html_writer::link(new moodle_url("/mod/$cm->modname/view.php", + array("id" => $cm->id)), $name, array('class' => $class)); + echo html_writer::tag('h3', "$image $modfullname $link"); } } else { @@ -269,7 +272,7 @@ if (!empty($activities)) { } else { - echo '

                          ' . get_string('norecentactivity') . '

                          '; + echo html_writer::tag('h3', get_string('norecentactivity'), array('class' => 'mdl-align')); } From 9213f5476fdb1784b66518a2fb136063306568a6 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Thu, 24 May 2012 13:43:01 +0800 Subject: [PATCH 353/455] MDL-33324 fixed bugs with icons in filepicker/filemanager treeview - in treeview the icons for parent folders did not appear - in treeview after refreshing (expanding subtrees) the image previews were replaced back to filetype icons - also fixed a mistype in icon url in repository_local --- lib/form/filemanager.js | 3 +- repository/filepicker.js | 87 +++++++++++++++++++++++++++++++++------- repository/lib.php | 22 +++++++++- repository/local/lib.php | 2 +- 4 files changed, 96 insertions(+), 18 deletions(-) diff --git a/lib/form/filemanager.js b/lib/form/filemanager.js index 881d1819e4b..592dc1c876a 100644 --- a/lib/form/filemanager.js +++ b/lib/form/filemanager.js @@ -478,8 +478,7 @@ M.form_filemanager.init = function(Y, options) { if (scope.lazyloading) { fpcontent.all('img').each( function(node) { if (node.get('id') && scope.lazyloading[node.get('id')] && is_node_visible(node)) { - node.set('src', scope.lazyloading[node.get('id')]); - delete scope.lazyloading[node.get('id')]; + node.setImgRealSrc(scope.lazyloading); } }); } diff --git a/repository/filepicker.js b/repository/filepicker.js index 3e6005a4847..3c79232d66f 100644 --- a/repository/filepicker.js +++ b/repository/filepicker.js @@ -74,6 +74,67 @@ YUI.add('moodle-core_filepicker', function(Y) { return this; } + /** set image source to src, if there is preview, remember it in lazyloading. + * If there is a preview and it was already loaded, use it. */ + Y.Node.prototype.setImgSrc = function(src, realsrc, lazyloading) { + if (realsrc) { + if (M.core_filepicker.loadedpreviews[realsrc]) { + this.set('src', realsrc).addClass('realpreview'); + return this; + } else { + if (!this.get('id')) { + this.generateID(); + } + lazyloading[this.get('id')] = realsrc; + } + } + this.set('src', src); + return this; + } + + /** + * Replaces the image source with preview. If the image is inside the treeview, we need + * also to update the html property of corresponding YAHOO.widget.HTMLNode + * @param array lazyloading array containing associations of imgnodeid->realsrc + */ + Y.Node.prototype.setImgRealSrc = function(lazyloading) { + if (this.get('id') && lazyloading[this.get('id')]) { + var newsrc = lazyloading[this.get('id')]; + M.core_filepicker.loadedpreviews[newsrc] = true; + this.set('src', newsrc).addClass('realpreview'); + delete lazyloading[this.get('id')]; + var treenode = this.ancestor('.fp-treeview') + if (treenode && treenode.get('parentNode').treeview) { + treenode.get('parentNode').treeview.getRoot().refreshPreviews(this.get('id'), newsrc); + } + } + return this; + } + + /** scan TreeView to find which node contains image with id=imgid and replace it's html + * with the new image source. */ + YAHOO.widget.Node.prototype.refreshPreviews = function(imgid, newsrc, regex) { + if (!regex) { + regex = new RegExp("]*id=\""+imgid+"\"[^>]*?(/?)>", "im"); + } + if (this.expanded || this.isLeaf) { + var html = this.getContentHtml(); + if (html && this.setHtml && regex.test(html)) { + var newhtml = this.html.replace(regex, "", html); + this.setHtml(newhtml); + return true; + } + if (!this.isLeaf && this.children) { + for(var c in this.children) { + if (this.children[c].refreshPreviews(imgid, newsrc, regex)) { + return true; + } + } + } + } + return false; + } + /** * Displays a list of files (used by filepicker, filemanager) inside the Node * @@ -133,10 +194,8 @@ YUI.add('moodle-core_filepicker', function(Y) { var tmpnodedata = {className:options.classnamecallback(node)}; el.get('children').addClass(tmpnodedata.className); if (node.icon) { - el.one('.fp-icon').appendChild(Y.Node.create('').set('src', node.icon)); - if (node.realicon) { - lazyloading[el.one('.fp-icon img').generateID()] = node.realicon; - } + el.one('.fp-icon').appendChild(Y.Node.create('')); + el.one('.fp-icon img').setImgSrc(node.icon, node.realicon, lazyloading); } // create node tmpnodedata.html = el.getContent(); @@ -181,6 +240,7 @@ YUI.add('moodle-core_filepicker', function(Y) { var pathelement = options.filepath[i]; mytreeel.path = pathelement.path; mytreeel.title = pathelement.name; + mytreeel.icon = pathelement.icon; mytreeel.dynamicLoadComplete = true; // we will call it manually mytreeel.expanded = true; } @@ -238,10 +298,8 @@ YUI.add('moodle-core_filepicker', function(Y) { el.get('children').addClass(o.data['classname']); el.one('.fp-filename').setContent(o.value); if (o.data['icon']) { - el.one('.fp-icon').appendChild(Y.Node.create('').set('src', o.data['icon'])); - if (o.data['realicon']) { - lazyloading[el.one('.fp-icon img').generateID()] = o.data['realicon']; - } + el.one('.fp-icon').appendChild(Y.Node.create('')); + el.one('.fp-icon img').setImgSrc(o.data['icon'], o.data['realicon'], lazyloading); } if (options.rightclickcallback) { el.get('children').addClass('fp-hascontextmenu'); @@ -342,14 +400,11 @@ YUI.add('moodle-core_filepicker', function(Y) { filenamediv.setStyleAdv('width', width); imgdiv.setStyleAdv('width', width).setStyleAdv('height', height); var img = Y.Node.create('').setAttrs({ - src: src, title: file_get_description(node), alt: node.thumbnail_alt ? node.thumbnail_alt : file_get_filename(node)}). setStyle('maxWidth', ''+width+'px'). setStyle('maxHeight', ''+height+'px'); - if (node.realthumbnail) { - lazyloading[img.generateID()] = node.realthumbnail; - } + img.setImgSrc(src, node.realthumbnail, lazyloading); imgdiv.appendChild(img); element.on('click', function(e, nd) { if (options.rightclickcallback && e.target.ancestor('.fp-iconview .fp-contextmenu', true)) { @@ -405,6 +460,11 @@ M.core_filepicker.active_filepicker = null; */ M.core_filepicker.templates = M.core_filepicker.templates || {}; +/** + * Array of image sources for real previews (realicon or realthumbnail) that are already loaded + */ +M.core_filepicker.loadedpreviews = M.core_filepicker.loadedpreviews || {}; + /** * Set selected file info * @@ -761,8 +821,7 @@ M.core_filepicker.init = function(Y, options) { if (scope.lazyloading) { fpcontent.all('img').each( function(node) { if (node.get('id') && scope.lazyloading[node.get('id')] && is_node_visible(node)) { - node.set('src', scope.lazyloading[node.get('id')]); - delete scope.lazyloading[node.get('id')]; + node.setImgRealSrc(scope.lazyloading); } }); } diff --git a/repository/lib.php b/repository/lib.php index 4d867fd68a6..d97b7521207 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1772,6 +1772,26 @@ abstract class repository { */ public static function prepare_listing($listing) { global $OUTPUT; + + $defaultfoldericon = $OUTPUT->pix_url(file_folder_icon(24))->out(false); + // prepare $listing['path'] or $listing->path + if (is_array($listing) && isset($listing['path']) && is_array(($listing['path']))) { + $path = &$listing['path']; + } else if (is_object($listing) && isset($listing->path) && is_array(($listing->path))) { + $path = &$listing->path; + } + if (isset($path)) { + $len = count($path); + for ($i=0; $i<$len; $i++) { + if (is_array($path[$i]) && !isset($path[$i]['icon'])) { + $path[$i]['icon'] = $defaultfoldericon; + } else if (is_object($path[$i]) && !isset($path[$i]->icon)) { + $path[$i]->icon = $defaultfoldericon; + } + } + } + + // prepare $listing['list'] or $listing->list if (is_array($listing) && isset($listing['list']) && is_array(($listing['list']))) { $listing['list'] = array_values($listing['list']); // convert to array $files = &$listing['list']; @@ -1830,7 +1850,7 @@ abstract class repository { } if (!isset($file['icon'])) { if ($isfolder) { - $file['icon'] = $OUTPUT->pix_url(file_folder_icon(24))->out(false); + $file['icon'] = $defaultfoldericon; } else if ($filename) { $file['icon'] = $OUTPUT->pix_url(file_extension_icon($filename, 24))->out(false); } diff --git a/repository/local/lib.php b/repository/local/lib.php index 72ba3d3c571..47f17520b75 100644 --- a/repository/local/lib.php +++ b/repository/local/lib.php @@ -221,7 +221,7 @@ class repository_local_file { $node['license'] = $this->fileinfo->get_license(); $node['source'] = $encodedpath; $node['thumbnail'] = $OUTPUT->pix_url(file_file_icon($this->fileinfo, 90))->out(false); - $node['icon'] = $OUTPUT->pix_url(file_file_icon($this->fileinfo), 24)->out(false); + $node['icon'] = $OUTPUT->pix_url(file_file_icon($this->fileinfo, 24))->out(false); if ($imageinfo = $this->fileinfo->get_imageinfo()) { // what a beautiful picture, isn't it $fileurl = new moodle_url($this->fileinfo->get_url()); From a9352f1f3c62675765b25e099c3deab032fcc0d4 Mon Sep 17 00:00:00 2001 From: Barbara Ramiro Date: Thu, 24 May 2012 15:02:52 +0800 Subject: [PATCH 354/455] MDL-33162, MDL-33183, MDL-33150 Adjusted styles filemanager, file picker and file picker form element - MDL-33162 Vertical align text to the middle of 24px icon for table view and tree view both on filemanager and filepicker - MDL-33183 Layout file picker on form element on edit profile for drag and drop with dashed border and animated arrow consistent with filemanager (outputrenderers.php) - MDL-33150 Added more space in between tool buttons both for file manager and filepicker --- files/renderer.php | 11 +++++-- lib/outputrenderers.php | 8 +++-- pix/f/folder-128.png | Bin 2796 -> 3511 bytes pix/f/folder-24.png | Bin 1438 -> 1436 bytes pix/f/folder-32.png | Bin 695 -> 1462 bytes pix/f/folder-48.png | Bin 1037 -> 1790 bytes pix/f/folder-64.png | Bin 1315 -> 2059 bytes pix/f/folder-open-128.png | Bin 2858 -> 3517 bytes pix/f/folder-open-24.png | Bin 1417 -> 1415 bytes pix/f/folder-open-32.png | Bin 752 -> 1533 bytes pix/f/folder-open-48.png | Bin 1168 -> 1918 bytes pix/f/folder-open-64.png | Bin 1499 -> 2231 bytes pix/f/folder-open.png | Bin 446 -> 1227 bytes pix/f/folder.png | Bin 471 -> 1256 bytes theme/base/style/filemanager.css | 50 +++++++++++++++++-------------- 15 files changed, 42 insertions(+), 27 deletions(-) diff --git a/files/renderer.php b/files/renderer.php index e6f0a225cd6..ac8e5829463 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -277,7 +277,7 @@ class core_files_renderer extends plugin_renderer_base { */ private function fm_js_template_listfilename() { $rv = ' - + @@ -535,6 +535,7 @@ class core_files_renderer extends plugin_renderer_base { +
                          @@ -591,7 +592,13 @@ class core_files_renderer extends plugin_renderer_base { * @return string */ private function fp_js_template_listfilename() { - $rv = ' '; + $rv = ' + + + + + +'; return preg_replace('/\{\!\}/', '', $rv); } diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 09bd6d6d4d8..198eef2a355 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -2054,9 +2054,11 @@ $icon_progress EOD; if ($options->env != 'url') { $html .= << -
                          $currentfile - $strdndenabled
                          -
                          {$strdroptoupload}
                          +
                          +
                          +
                          $currentfile - $strdndenabled
                          +
                          +
                          {$strdroptoupload}
                          EOD; } diff --git a/pix/f/folder-128.png b/pix/f/folder-128.png index 8cb63830c0f75912606b070961308dc9f39a971f..e2e48fdda98ccb91a32be533e4bc29d3a65badda 100644 GIT binary patch literal 3511 zcmb7HdpMMN`~N;O!!X56QlivjL=tl#XOnS^oQF{DGGk_(=U`?WLQJ--iZ{_lZ>r%f z=|I-8ob6hYQX7>*NKV^?jzW0HzT3XPKYsnL>-SvO^L+2`echkW{kaeSJjc8|b}L~t zFaQ807iR~W>=duO3i7h=ue%tXvO`_u7$EZDg^1!90yeN^@q*c~3x^TPrm-2UgV7yq zYXFd2!+irp0q$;=Odf~8ScxITbNDhe0M<6~dc=$3CBAFH}yv;7yI^I%7z+sCRa6Bi9E3}NK;Q!>cl-Vn8A|C!T zL=;KE|3_4SyBBQF6R=?u0?Cj`G9|;NI|<~SB#WIE2Cxx{Od^tvh$J&ZGRe}!%#uWg z|9bGUYywt@CC$OE|8H8Z@UJ$>8b*v~@QGvsX{DsE zf$r}AcPNMRceGGMWB*t0|4J1`cM!=K}E<}4J72nccz-EYe0$(04>T4Ih z!gwN{FpS5C?R`uLWZ0d-4Ck(R{zSODTe@(CA_kYqc5$HKWgLX?aF(T+g{g_TlbxA` zorxWp>`1mV*-3IVG9i;p9qpV*JMF(>9eB(b4x20bie>#5YyM5_$}({Hvdj)_L3k{i zc8&%Jy9# zTkKDp_Gkit+3wl^=Edfq)_lmD9b>(>%PVq-NE<62%bY+QVSVHn#)p2Y-)F3&$ryqTDF)^=oA$rq@C1`I}=hL9A1Fg>90|1;a{ zk9!tG!7i90KjM(QvvlgOcnicz!;!CWCkHMJWJ zyDMD0n`hNI)1sa@V%0=b@K6#{6g(pDQ4pAxtJQ~_4va>sd8RxHW1|@d53J2qJJwQn z?5KapHr>XL($H-i*~z-QXo_W5mM`X?XQ}@)%JU3?V>TQacjlkjS37u{h~TVZ&xSX7 z*Ia1Y@zzT-A%5!4W~O8T>2bEleCLU~TJU-uu6 zm0%4{n~iH1w}lLqB}`X^jV$^XI9&r;t$shyV@9hKh7!gDK>Wg#@}XO`$oyi&5nQB_ zo6zqrGU?sXrUx;WGu;(AZ$Bm+EjnbCoL*L%YYJ5JL>7EtVe?2oDqMY@G2kD(>cni_BSMN~hFU46wk`F6@(F~V8Ptl~aeJZr6aXYs{xNB!sb zdUvQ#lx$D%{$V@xJ(g7O2C97kYxT`(43#uYJF4?;R6x9Z{y83P4|&Nc+*lLCaRaFFpMSE`aI`P9XMB1xvyi;}}1pJM$Box>yj@E|; z)-k`!y!?rHf*~=gIIN*{xyk(ERtq(3nMz$yzo}$6$96xe%?0XLd;|>I$=$*F^1lMQ z986L(@6l0lJQ1yQZT5LsST8G!tGL>5d8fg0Sj11iedv&!vk4l^zxFit1XQN>v0PrR zxuI~R?*5aW6G3M!a(AgwCyz@4D}TI-NZ)k{n|TSOBcr;rZrhgtW(c%(oC5R)*2|lG z1lUsu`W7(oy=_1@fu9r{aNwkQF<4gf);PQ!wAcdY@xyIyP@3kIMir_~Es&$vyTO~i z#KQ}SeTo})VEI(&)vGfJ;verLH<1q4=ak6DpQBs{898YF+TZFH0FLYONfQbLBF`{7 z#;Z)VS^8v|aUD%PQkFJ=c6zfsGaH^!gn;8!2Z~%<%AO6%-H2NUPUtFsxF$aeVFVr0 z3-UqJ??IV-z!&4^C{!q-0W(y-y^+UmLg5U3YF#TOA$ouTdBF(j5WK&S2;J!nC7E;G=9d{YxW)RYGsy2G~L75;6_M3w3XMTv$lR z-vnU08KPo^2NE?7VSKIb`XR9T)Y-k{y%+QKppjQlJPy?0ol$!|)x?*G80;#rXMEwk z+<7uqjKGR-Y=-L(0^Y!Sf?yA@z21!a!}y4)Lq-@Z6*bEf1xmfJXzIm*2Q1#-C5e44uQob|a5$w0IAsrfIbt z)ZD!Z6D1BF4gxgt_+#s}xBBJar{0B)c)eQ$*dOXo^E&mTEzm1m$48TE@+TT+W(=s@ zuKv|OCynZfe{-x6(+zeS%;V%qTX>xRXk)Z-VI4}Z9Fm|P+J1WzKalZ6)=wx z^uV}>Q_I4n&yt?`yF)>3mwZ|Zpsb6=bAFwxs7D@_TYy{WV?A>6yQx#Ic7;;8Qx{Z# zrse6dSkLT`iLfJA5HxwI7FO0uI^R>wu5pv78Mo4F?j%l}#|FHD`d`~;TI9WHHBvv1 zRyI<3y?$1CtaOhYaIVa;?`yJ>ztfwsEmMLKcMeb|2?!vBhKiXcb6V@csVTisN;6ih zcgP;_(=Hk#(@R=u?Grv)jN{@S*7W5OT_~ru0|;F*6JspqAok( zMs1Xs9fwRSMbWKB25pblmJf7w^`hZ(#u+ba-?we)3R;}Vt)AMJD$d;cwnqh&r%KdJ zcVZs4W%nOX7dzsODQnuN>*uBi?Q4;wb&!XRvED*|ucG>R%0f-1|6ru=_-NN|2%g$n zRH|m&U)=ipAqc+e7rfN$n>ab?>6Wsm@y!ct&*}a?^ST8exh(R*1@vJ3;&103yr?Io z%;~pPX+#cS`<3aLIcN3-#lJq^XEQ&1g3x~U-RuR;Un;Gno8x`kOw>@#g>|E@0X4K_hB#GFRt|+^GhWL zS0eZQBZr&YG!2nlKcCL9P|s!E>&*Kp+9_?px?s;1R52-o_2@Qnj{Eq*$1hg+l$%lE;%-jaJ^Dx9{bVs^IfxWdZO9P*ad_+ zGH$GM0+0FUt1AOqVPfNi<=iZYVq1 z(hOy}kJ2g7M=1lO8zW-mqEC}rIou*6(*(Kz(zgI|@dyppx z3k%b_boENGhkJmhmVb~pd(KoA0O3m%tD{cg_h)k`$#UM3?c3Xby#GY>Xzzk*vA#-* z57GprCsM_1#9M@vQM>U9%8DImOqu{o!4`vhg*;=?DH-H0u1EOO#)vs_V@w*Jb;`&f7P^42%E7q`tM5!Kr6{eGg2caar_#)Cy|sp_ zmab0;sm4|Gxd36_)YksTslfXd8`VY*h7rb`#J(C{v-;8ZW$w*tjECaDl~AhCz&utb z{C*@#HBPs;4#T;2#ni^$6p=RfX2SgGfbtD^dPcv*pMUVZyVQd_Ed)rdCt@kFkV7NAqIbqD39fje}7J;K!xqrGkaJr>Yz zHoQFYi3zH>xQ9c}&o?Gv0~RQpzT^;G{aFu~;Sv~0n`?1sd<~oX9+e!`Hmiuxm&HVn zBRhr)j!(58$%sx{)mupnbB$%~_bPrErw3T7wUF}QBIR5h0alWu`>s5~?_HPxy#Wh$(uXQJR z=SKc!)$54zd>x(p;y)l4&e*iJG4Oh6S=B5NOnk8AUx5o#;&(Qt z852wI9$Jy2LSLQx4k_q-l**oE80t$zsw3!I^ZuWv{K(UvogNUJNrrQSoVMI_!&%8F zdu$2xt=fi^$}F<<4hK$?89M9cj%mx8E5*RnW??99?Xor)c$$jpO~iQlrPqn z0IOJOI~q^UF+(QAM!KVztatA)n($v_KVf__bRJk7Q#PiGxnRa{HS&-Eyu%Aw;Rrs6 zEGIQwH8YxqU6vmxFd(il&x+xtrAV_rd1#)-^o&|YEEd1(I!qOm`Hb}mnUOZ1^BVe8 zJSq#T_-R7eN^c`xJUI%ZlYy9?jnwBnVdKOUQ)e23k(+rnhpq-RPf5#SZ}0 z0l_9|L6D2*Gg`H;m^52+Oy-(rZTX-v6iXAR>lbn9G9}fI`cz-<$dXp~D^gePhi2u# z6WUMW2lRr7b2z~6nbzwSgDD<|Yv$mJg@>vGxHP7OLmc)D@>x4PB=L?sNfRC}SoBCC z2XY8OcObDh&pFs$((rE>9>|hoOw<7Dw0C4Yj+F5XH&jxsj@Dm_5Y(8wmQFK4`@`!& z^fEJGf?xLNQOR&~5E#XG`Kf~1(l5C}JKy}Xo=|VdOPEIxjf~>p>wkx20RcEFVNt=o zMi270VfJGdStMGo0R3ERb&`Cc#%`J0*8jn93gFnv1928G0;wXUr6~@csrl2vlLgd+ zK=A~~Weq+Z@QKUE;t4qtBn@PQHB}|e5f6%N;1|euTe9qm8)6BzaAb1V?Hhtg)+vek zonDRv=q48b$W6)JPQ7Juu}O*vc896o!0w!)^_}i#T)WS%3N|6c7`hd(sFC9l)qPd5 zpT6aZhJ(^Omv2<3C`J`TM&{wIk=V2=!l(q+CLGD>7G6nu<5(WIr*!qC&@^bUh0Z>d zJ-e^Nq*D$YEiPR?DRi6n$PN_rppwiDRB>uW0uEHXv?PS66s4+7&$A9|4;ys)9z!<6 zVZDK|@P>3O?I@3Edn^Enr%G+`Kf+Px>WWJ1CbggG?CeY@!5FZsD?PQyg>{GDzd?_ZAGv7s1(oR@vEl#tTr;d@SZE(PW7M~Qe^DK)}^VHo2>>Y1sKArM-l}XE>hoQ4vr`* zcNiqhR4F0wnfq=yzqhlQgguXUP%zSG2L~8SmlF}R5PRq}LTY={Dwf926?@tVBP72G z85l}DO)0_5s3gYE%)F?1WC1`vy?uG!kogc({wXdhKH+q7=E@TU&jRLyH6gx;At=A+ z&`de!fo+I{(B+X~>Yb)nl>0-)SZxKQqNSU#t=g1e`qwAh_Wnl5+j}5&$xecOe6=?C zs5dOOSXXwFWX0gby(0ns@?kZn?qs8Hu&lqPZUi629+-B@DKtJ7xZAiN$BW)R&=$pN z-+V_Qv_N}QT6L9k8qTflTScVxi^kWMHLX3C;G3`2bT?A+|3Us^G}TJU5@HCfxg~Ef z!39*MiejqbR7JK<gEqAo7`J|Q^WS>Moc_5zlP??>Gg1%LKA>8cL4>p15@EK1ayYpQf`};M}YS5F3?N1 zWT6;X`2IoHW-TXbcOzO2(t@a43W%EkpRWTvKUjW zzyJs^+kPrSljpgEee?oGl=!lkM^JC964|Rq9{SiJ8Y7YIXRvfd7|gW)G8GqPG2;qA zs(_*3m;(I)=e8Rz>&F2}~Tm*lLDkLgG(~K)wsX&^GZzU@-zoT7)ukCvUFug8xiQ8$yL&o)4$H0V2>YQzc_kYG^yF0w-9v< zQ64ou!ld`a!#>vGtdn1TVwmfBLp8@PCH< Z?a0O_SSL>znH^^eC}ex9QVUw#e*wJ;-r4{F diff --git a/pix/f/folder-24.png b/pix/f/folder-24.png index def135938b544405c4b5cb8c75eb823571b16e29..b5b25fb287098aa1e2d56aa124466ba51b04e2c4 100644 GIT binary patch delta 723 zcmbQoJ%@XP2a|%So1vwtp^LMnlc|%Tp{t>jsfmHBk*T49nX8kVfr<0v3?>tbzIZn>kClb0!b@7&hA`h0U* zl&!M*@9!yi(=W=Qq~KI}QkMH6oex81*S z`k7MG++Frw7r!wc*PH)R#y3=rsW?=+;px;xU%xzEUY9>nCxiv*m~xs+M_$pKk}0HU*uZ;lCg7|c1N0n zH%sy%2EAu<#Jsk?sd88qI$MBUxHsTxVq({kG*+GfUH%u|Pr|=Ft2rYa6BNNZDfz`4 zzq!lUGcLxQ_r7w8%{+1=TjSD*diS%j4mx(vq**<+D&uEt;JU%sXSMO!pLa3=9~~#C zs%p9OziDLLe(6TzfwQx#qp5+prKypHo2Aj@3?><HpiG^N;I9WiOmB?l^z_KITP#XV1R8 zS-x(~^yJ;YUAnJ*tbh3A)ZFae>HoP8{I#61=X>4fS3f!~6vG&bqDn zyQcT@7Y5bTP7kGPU7ID@Hmun&Pu%I`icbv@r|0AGI?+8n^j-k5TWyAHmj#rW!#Jn95)#CN|Vn1+-tYs(PRa0 zuaG{u8O+RiOEyZ&+b*~~XQuc~iJJFf0oM}+InFiCW()oPTIWFL+sKk{mySI6dYeC7 zYH_4L--4r0`zpUZ2>bTyjY?+>vxl8>1d;61j10%!nzWt)Vjgl3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVip%-F=-#m(5#$<)cv(ACh%)WpEm$kfol z%+<-wz{DA**Cju>G&eP`1g19yq1ObbUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnqfX zG!Lpb1-Dy_aO%|uIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zu4`#`WME*@@N{tu zskrrKx^2F&qd;4FTKe~QLL5^y9Yjn#-I+bUbhO!Ztq?FV`NLpkRp+GfA|udBYK5k5 z;1UO?1tyH04v!Mf%&o01KYgZ?Lvgv!G2gJLxwTQRE6exwYN|#&QHuCrC0wA^&~Il` zvG4ab?}GGq4b6c)FYlc`9)5358-tD4;oq}&zkK&K>D_^YOIjZ;ukvbmtuGf_SG$TS zFaC7Dt%;s>#eU(1nf}Ytbe?}H{QPj~*8edJvc+~M*H5Tyh+h5gNZ#Lf&U>xInRk`# z3wK-i{NK(8&n7?I9+{)3r^IY@zFKFZeZ{VgW{OUeDk3&HCTp*Gb@SSDM)tC|*9wA8 zT^4NYWa#`|CKjFgOoqw)(6I-$3b#t!mTr+vIL~+HVkg6TrUk}A4Fa=UPCa{2`Rv3* z7MD%4cmsmxMFnl+D7buJLkx>g*8K25+R5a#ZU^MmY&hq^-3nLl=lrEoPJr%O;3Zv9yE)IoN zXJQ&og_u1*`1i_5jp+(gl5(Cg>Ha;HwzA3SW67lENz!HYf(E4;NBiBB8u(t#*ifI@ zI{o&k+Q6G;JT)5!DF6Tf delta 671 zcmV;Q0$}~N3%3Q3B!2{RLP=Bz2nYy#2xN!=000SaNLh0L00VXa00VXbebs`@0000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$SG)Y83R9J=WS1oT;Q4l?6 zX6}9OwNO+M5Co=m7$CtD489>K0tUkmz~T4_Mc}Zc4g(sw34fx3gg|Oa6H41{x7)Y- z_I(V3lu+8BwzmR~8ZkHLWX{}~d+F{tOURkB1F*y3;fwWmo#W221Vz8D{r;;bSKgk6 z03KTKV0qo|UN4R%>tw`OT>cxP2`@F=h0uH5SckRb>bP#L2f{`T~f$aYnP+Vz5d@B@5=M_J0BaRMJWeR#^->j)vJHGMNB? z7*D_$bZl9$ktxp=nV?PM07$|{WEN~>S&-5cEHa{LnMeR&3T8n{%c32qK=ME~iIy`- zsz9=62bKrjS0Rf`ST~89kc0}E2i>hC#!%Hbf=hb+tg$W zbaoC+R{;zm__~u+8{JL9N*QINMxkAOnH?3{T)vNPad0{3$pNt(qe>kc)b|cmqxgG%mlxQ3R25aOAh!l}4 zQ58P0; zNs+ht{wJ|Pma0SOQpA9!=oR?j;+NY)>9~PqCCS%BzOMnoypqZ;s4(OlKcxv*#CdxKTZoQv;_ zSUR2z-9FlXje5$2>&L#G7A}66mOi4z^{&T-9rUcW5x+0GU_pS)-1+p&dNnzKeB*I* z%eEGu?K#DBvZILXJYz&Ar9o0E_?viMCKO~wMD#6ltFCI7ghzD}I|+i_1by1?hdVgX@5Mp^qMmE68%6Bqv8v&5OB2Cui|e0vc3f?BizPx%3uloWCI|8h=6+qL z{(cGd{2FKDKEw8mm_x~OW8aG-KN74DeJmqsgMC@=n@^AB9y8iTHaYese6zX7L*YFv zZ=VN>oJ+E2!uwG27u zUYVep{NV_{{48B*X^ZB5;$BPoXrxu}G6U&_BwiU8&u1ldEi3V@u{mtL#2nq{Sl+U$ z4$eq=ff}NL~79yReO7U3I3okGjRB6)>0Y zUJNJ#Z%Ch~ajj3;=UC4j!lEzbo+gnQK3;%3`B;cLz?4sb?R=}?^QJ=?$6v(2e(*ZB4;yG6VDZAFm= zk4^{hgtcpx(rF)LFRqlZ+vJy{fK zEBiL_%0d1Kv}pSz7;(xyZQN5$_qyA(fAL^Ib~}|^nVaI1Bz28FxRfz}Y}r+jg;3cT zu%Y3r691CDo>jjBy^RR~h>832SF~$acb&UeHllO9bm#?1H}5P!JT3mnrEtL~>DYrg z-ZrmJvv2aI6^=(kFGe%c4lsI$KF(>$f9~DTk$zqE4#}D&y9t!!?0k@wm>W$fa+zhO zcJoPY*UPB5f{PoHU9b9gTrC7V%O39{=B86EUX2y&6SMN3xdGoTeW;mz+gNy*AaLCr(Z|<%vSXJ95>RxH3GndN?gEuTHUlalw4-KZR`=?IBck9=`D;E%&`91?>fUsG^uy*QatwSY)&U6wLH zUPG=I?Tl+bzVJP#3%BQ1kwkv9^rJsbZg?4EbpXWD;&Ns#`?md$6dWWGl=EXV{{i)t BvEKjy delta 1015 zcmV;hy<;y%s(J%XMd%grm##S#CAb+(ST1k z?2qi5$?ltbkHwqW_cm&F7fogY`NA#cUKqY#&N<(6&x|612N|hv0{;~cya2y*zi-Ba86&PBgAF5A%5G?<%_SMeg7Wv zI}`_~mZGycf`4f~d?kg>uax&b{$}IDzR1HJDO3tf^U+;NLg&upOINPmy!5{_`v>eb z{ItH2U;5~+r~c^n{wAO~h5!HorfV@043>_)N0=K}(& z-SWu#_VoTTIwmI7=+xq~UcLO|8|NQ8@fwfWACco{ru+} z=gyp1ZqFT9>5<=2unjZ-zP8?!-?!KWkO&`mZ*B_H2=)MWr%iD;pSbx7fCQ#~ z2_6bT*L!ne;%-*E*-CrHQMz!SP=U@TbBWsBy>g$KkpOAfHky*=0)oojymFgc>->0_ z2qU{Y* z8GHmJH$kA0Mq^*T&3L+ukciOWBVef$5E|WLtcc)?AM&pVn>OY2w8@Y5P4aFSx!oFh z+J7O)@4RTw_-s>k!08e^04aprgrJ7@yO0}I!0B928Td$P3Aurwf_(w10%)=n1E1=< z8aOB*MO6?<(OK+ZkrZYL5>bI>0;Wav?JTN2QXcq3X_-`#Shj^4sHaiw?3FaB_G~uL z4D~)Clw_HdVo4QtzV9^1*1dAZe; zgUtA#KENd~L<H4WX!10BOp?RCLxee zqewv{h(dKB{T>nq0CBxqCdcHW?OY|Qp($)JG?PY$qX7sDH|Z40Gz5c^kQB9+M;W`` zNP*NU9%UC>#1QGCkW}@yOg$pa6w8#EX-bZY621irGjVYO4T32klV+dRz%}tGOT1kC zY;)5o&{7DN#-sdFlw1@KMWK2GV$&E@B_jleLRd7I#o(|wZ$nH5%%H2#yfNHYf0P<;v==5RQ429wTYQt=3?;eZxX zn5bHV-!g*$F(~zF9i~RLkd0B1gl1qo3SQ|iEogMFXtjoy*Mwgf-K5abVH(5M(sH0k z^#4OOnpe>VOoIGc?{5+tWCwHzU4j_U480N`T(X}nm5v*wM-&*Um!assq61557r)gp1UG~Xd!fhRKNmjfs1*`EUfLQ#X35Cq?gw&{P4~Es%PINFvoXYFIbrD z>i>))tz{MWYqOR{pFxH#vV2X z|8ArCNohk0kw>@PhHziIh8N$B9;#Qjn%Xk4lEgtyEFcW%}HJH#lAT7wqW0F;NmM^AJQ}sn+(qLP6%^!Yry+T`L zbV2&L{O$`+XM}^h4^^!?n)z9mPwQlO|J0w$hgN?2du825;O>;Tj(p^3cf;0cxkT@} z$Oe5=0rpIitdhXbUw^G9c~B(aG(B(!e1fIc?r@z~qMX16vHrkq2k7hR@qFwR@0PiN zcC}LjD-NG3gaA1)q;Sa_3S9n18t-Lm=H9Js_@8cZhM zmQ{h(PyTI&2wv|TZrdE<(3HAzM34_=Lk8a4L$LTds+!WX-7kUXuvdAAb_KgFrq@44y4+Cq_GXay{}U-sz^q zigF)M%&$O5o-VxNAOJ}9w+WzIACVOI4VlWex5U@e@IO#dMwLy0n|Jm$`}wM!p`b&3DHIUC>MNc&Z;iQZ&Q0smmKEevab`V{*TC^V4mdT{ z&qps7rH9U3uRk@cx?5g7@zkxcT0||)Dia?Xz42a=|3~izjx_hze>gk-DDBzM=uTJj z$lJa5Rau|bRZj1zIx~5k&J=qJl4p^?+MYd<)BQbL|JH6vq$ zUhg`Wy2h57900!ePPx#pBw6~57gb5c>!Li5P<=c|tv^4#TnE(?s=5L=3*~?aTKMF& S*70)NBM*epVnGc*G55cvODfR- delta 1296 zcmV+r1@HQc5Tgo^B!2{RLP=Bz2nYy#2xN!=000SaNLh0L00!&;00!&<9(6c10000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$Uph-kQRCt{2n>}b`RTRhn z|8wqS%ojxR0c*fcWknlpwzjj0s~~J^XJI3Df|0D1f@ou7V}HAq7!X!LEUav_P$DS1 zjrg%i$nIpbnfo&H-aQsC@6DSxQ^X`Yv$@G19?ZO#8Seef|D1d7M`&g^&ysOBVBER@ zFzyD7TW;9R55I0*n|TbYDt7rOUlI)aNyl!slI(-)uP**_x=nnz;;|nqF3laS z^Hts1#ou>!!+$H+Uz`8wR9ZIz4G#g@4n0hZ>PD{gx)boV-$R{yY}!xP3?S2we? z`aU@bnST?}L`A2o4+eOpQ`NSr)*g(mQ6p8&*{Y%K zBzHjHgV<_-QnlC?5$_tJiK{t)kpd9w2hfm^ICbJxY5))?0AoJ@b(wdL+SY-f4~SF! z{dCl}Qo#QHEO^vIlIQ>3q2AbThDluselC>FvQB29`aC;O1sMjgJ~@g-N|wct z5eZNNK)dKN(W4ZbRC?|; zg@7Y`G5;~EP>M`KEAtzx4sgnLC>=o7XHBt4g(U!~<$$E9gF^r!-5P|j=WeZrfT;Ll zE|>|tWKn{JQ0NU)Gp^<2Z0kG_wi1l&+fFwDzfPe2o z(k#v;q0~%^y^+R5B?klx`@X9%Gq#gVg9SvlJ4QfgY7~;R=||nIDhNP0CWND1Na@lHvqP2W+2%FungcS0G9wfj{K-x zECXUdKJ48C@GpQ{0RA$wg8~4N|KgJXn#dg>7&ugNW@X4BbPg{MAT=}VJ1)<73xGaZ zrPD+IU*J3`mKZ;_E&zXa2Ea(w^*00{s|MNUMn GLSTZabW5-R diff --git a/pix/f/folder-open-128.png b/pix/f/folder-open-128.png index abb6b493be00134ae363e601463dce22488a8446..392947e943ed21c6374505fc1d1410e8d9fad4ba 100644 GIT binary patch literal 3517 zcmb_fX;@R&*4_z8NP=i2h=5j(0c6g=OqdBoz<_|DASwwV%#e_TNv0skAc#1$;J{Es zL1c)aIMtF`5vA0TS_%~qL1s`y5J9-1xAuNNKJTx4p68ss_j=y%v}n|&~XZ4pGUwSlY>s8WF_j*tZo$L~$@NCOa9LP{^iE4s^0H?F-kD%Z`oWL<_%ggZ{&H_$qhR3{gC3W=9S` zERGXI=X0Z=znZ3oeZ3a*uj>8H4f=X57GLF(q{Wa{NBe(9{Us#z&+7Ic<4O6fFU&ExOd zUzgUs`&cy*cQa{pJ~+HPu4igXT0qM5of^Ih&Qo01;PNAa0Zg}nO?c5!jO0Fo$%cz5 zu&!bd`9BRuX&QtsW}0!oN#@)paS^V`&*qENUgn)>+%~7B+qbm*J8>oT0_Mr|L$yro zQig58y_YfifVm(2)=$^0`Umkdgoi@?0;;w1lZi~*jBT&#l8mkkv*aByfU8e$3eEO%8ACEX;rrKn>Jg}aoptBt;d#r@P-{& z8S*EY$@JyRde01)=81Opq>&Fly!zD6H)HgdZxJ}Td{fxemHB9~uYX=#4vcB1@c!xj zfC82N-v%Az?NL2gI4(y9EB9mPDUjb1j}aj|*@d*~TKb4(-VH#1&;-}-htG(utH7Nw zh&X8m($x!=U3Shep z zn2R6UkGb35zMFVE<@G}RD5oVCUR;kPZrRb4RsLCVSDSLbV>oJdSP)C|Rsz$0pwqn> zyOgE_J0x*Ny&#BGHZbmMCmI{g+IYk^Q2xBM6BNqS`juhQ`i&(Grx!^+zq+E(@`{pK zjJD6olG)#GXi7-12N;A&OuFy7BM&{vw46)r0UsYt`VXR-_uGb6sU1*9O^_MO40RhT zt24{jP)qBU-;Px^sK3z~IgDkly|G;L?whygj4bhNUyz)f!A=!Ai zD7_5RZ-&ARhDIFyLuc}(fu^0dPo3Qp@3g6PGx{LsTBE2Dh))3fo$^=XLNdPR&7>o@Q9s{DI1d2L>=8O}huz9UFq|$=)TxuRd=|YGM6f4`sS}i7r92cFv>_pjn4t&3vx^@O#hKto&%UzC3(nIfN}(_Oh35cOYORXNKp|UcfxE1f*jSa=shYe@m5)pg_g}d3gWb zNj#`jwx_@j=BEv>8S&gk*6|2hM}%-Rzs{a2rw5O*qvrt2Q@8r340z$amH_j`3{Q|% z>3=@rfHGQPcOAZ5>mu9WeaJd>785z5x}tzY^Qdtt^_fPn`YjU^Eh%9&PQ5osyG1@; zASE^}q$L*F)r0@^p|9Al=2c+yCSX(^q2~d9Xt_RY(h-1tb{>W@P3o0JaJP?oFrGts84zGecN3%m^L0lnlC0^x!C;}*5BB16}dUY z3mn6O1kzdbqe4S~3e>qc+WoxM)D8P z1w^T)U1h7Oo`m1AFA0n2d+eCKj0Rp?g0izT5loc+F<^KZJ0l6eDd*%KwRI`fu)X?_ z$PA-MfK5NT$Ohe&%=yToYGqjF(!GGH2p#PMqlvkG;+6u$aOVK!2%C+sO!!9`g z`Di=8bf^`vj24OTmU20SwV=pdq>Vv5W)70%yow1I`#)6c!DLY(w!YXhy>J8b5|+8N@(R%qnccLmLrXb7^nG@<@*W;T`O(PA(FifKv8qol zYCqhvv=G1ZUeoJd4KK^%-<>T?oo>Ak7sK_p$UgX0cKf^RMf+rDW$V)e^i13vo!6=z zCzG*L0K0j;q1MF9q!10QE8W)lrX<0q>wD?N`_}U`k~FZWpd+T_8#xtSEgu zc{TDvjrjO?Pjv0~P7Eckp{y7_BPjXyG>u37;_y;%HKxH*DUvpRXW~|K^Y~TAu+yCH zhKI}zwjq<9hwS%u%*33Qt0sU-(Iv%>QlH53q|wIDsiBiq&j@vUPW$aq@(e;!YL@6F zDVObNZSym8zryS4em8$#BWP~Z>3Xg>a>?h-xG7~~{`|sCF(RnyENvG-ge>R~ZSd95 z(bJ{nR1E2RdS{`1#$YDRxre$(ZW(aP5_9!L2L1)Q?a68-o_Pz@3Yi=3lVCLWjaHtK z;BE-1wqt8v&6Qfi%EleNA*Z7BbPcy-CRE3~gssiyyDCncnQq)Schl7UTJ6(&?g=)> z+G`GLLpc$Xr!1o3*n#Yex*ivRTSSZ4uD$*C0XvRr#-CJJc;R_+v2J3cqmsU-5vm%m z)_D{*b`O!rR6201Ieot>ObI$7n7vbTOw&&(C$DP-p$yR2ki41;bo%NKm5YbPyWegsaq>@aMQL-t7`W&E@FyUGYHrw`C>~_t7-Q{x|O!{b#vVI#- zPNHRDxt}PZ@Aq=qT3PWA$}~~^-#k<#n+b6U1f&JL91!>v8;?)dSGWVX6n;%vF$s3$ z>?0`_AtUVZf_zpP-L;riP_R?FFux=|ysVN{(p>!fTEk?!%emll=QGIod5x9@S!%h6 zFrI!I3X=N2AdkAlQ+26%jkTlf!p+m>82Z_Z&8NVWH9sj@tFa|aj71X$z4$Ov`qe z@3n=CCv`h#c?4a4N%yq01@?_(5-Vh2vLm3%Z%#_tt`wSm>{d77Mml;x*is1f$QCYonH#S4G3h9YYQX_seDuuc~E*>)p7ux+9cZS~WwU&D2GA?3YL@SCB zec$HPiSI8CT9j9TLwitn26kiJgJ!XcGJ2vhyCd zjw{y}Oh1>5kqn+KajPMExCif}j>zt%Z3vRGFn(>XSRKam_61ZmPJU)Vc6U=+pasLY zc$;Y(_w&U1md*jeXS-m=@3vwhA#8C|Gip}vWiN_vrDxeV43(M8=fmbHWc?%Pd9Q2p zio{*@lkrAejLb6-i87}AM3H^h?Dd2ISE;%h#H?}1{6N+xuL|PE{uPo-I$Z` zAe*mW((wZ{c4 zL{ss=l*9(B0W+-tZ6SeMjrXFI}EJd#T-awKK_3 zKU{w&cauM8_gz)guNtcmE~5`fGG3$oKM^46eZ8u?17E)m;=2!$`Bhw2^`W5WC=>D* z1zO&cRAM$Qp>>uil(Hm(k#n1Vk9Bk3)kvDUO%7W}BuT({3WzNjs~>UpeX_SA*z{E_ z&^|9pV|SOBME)Ewq5DTlQ7A#SR$Xc2Q+oa_!K?FpcLanm43_k0Rg+dz=BpnWs1I!N1T=71NAgI&YiypXKWR zEB2C~S=u+j4?cOQ{;n`jgNSvU{5tSeM9Ijdt@f|C3iKhG!sdp*SkCo`5ZBsz1AsaUBjh8+X zk?6zaD989LV1qY97aZTlDtxnIV9?p7@%FFt`tv}xCwaJf<;CNY{j|)1D?O``_8Btp zjNAmjA%A@MY89tC+AK#DnDRz`U&*D@|FUVv;yEN2Acr`#ZuSiwQ7*53B%Cl`60LZr zEgXK2CH{DbiypF+@IhkN@_!6h_dc%LPx~VeIh*pgO=l#!DB@_UUeWy3!aiQY)e_|- zZ+1$8<@T*dOz5#;q-4zW43lv>-Zxf*`x)VzTP*7>Zh%)#eAA6_08Z1g?c3@LFg@OE zE)tdDiT>-60fc_3I<}9j;0r2qR0$?GE$ysw{y~sBwNymzCLQ{HVYli*ooIpoXdV}i zFO}Y6AT5xhjIN+^K@Y;^RJGKJ0-LEjqBBetr=qpZ`Gl=#%&B)foc_%^z+1^DdiOd6I&swinwg%Sk4r{w` zgN}i{IcCf4b#?*DhKtfKeoIu@0G;)rm24;yLldKE@#mARmcj|YG?TL{f4bqKoPUXf zlF8`h2^D1(dh2O7TZ;#cp6uqV+er`(}t|AajUpZ%I7~Gt@@8fAQW;`sJXYs zk#<5-PK2<`7%@&&o_%w=F8ES&^kVlOp&w~{ek|?cwGJMs%HmGTF86aZPS_W06GwZ7 z)qUO&ve6xflp3dX&9|;xp0`tQW4+tHUt{tDnlxMp8!=MnvyLy1$|X0}V&8UJUpvN2 zuf-u&0BxHX1{h7H7*#>wdJPv>rWHX+(+RrXkiTVY^F+IrMmc56q8G;B>~P~QD*wD< zovR#07~IcUSm$N-@x`3dx|jBpO14Bqa@iv~1-qPC+<0h3Bb>w-^)xRlbgH6PQ!{aH(33t5&3{p{ZnKWAhyo%uV#lxRGH`zMC2Rwb@5B z^Vl|0O|14Fz-V8*sM+x9{Y%Gk<*BeN!^lCfbiTnmXVl7Tqrk&3E1)?2h-7&Pq%WG+ zUhO~bIPd$UVQABs6?Z6d@z>+!!Jaoq-6j52Fe|qKud6Go4iGc>v%c(}0mq}hvGP)i g5a0CG;QxtTq;;=r!pXjmfBwM0+QQbnl0b_6FFrCN;Q#;t diff --git a/pix/f/folder-open-24.png b/pix/f/folder-open-24.png index a38a9cac8f759a6cd19f7f228f192049eb07fbf9..be120b0008b4649299ba52798420b247dd42a024 100644 GIT binary patch delta 702 zcmeC=Zs*?M!K7g3Z0cxf?BZnUWa?~a=xXR>YGUAOWNK(&=IZ2TVB$PEgGmOa$Qh@i zB}@jIP?IciDN<4>E(uCavr3s<$RrFi(h-;H$p*|$^$WN<_c1Uq{`7Ql45_&FCTw@! z6$g>Mf6U`M91XS%O=r3@ZqWw>?R7%ROK}lDLRVhki z@tQr-nv9!ve>;=g-7Ud+^GGp^|M0p;KPVDf6gv^%P*7h|3U*7lfBx4&kYaE zb%Z}Yxg^M`=}O0ysh1ra9>z4?vs2M{$l5>Omdk4LoolDcSGYV+=UQ(&v+;bt z`~iWR-ShI_*=%Ln_QR7zd^EJJ%Ee;30nLIU&V_NBidZ{f%Nn)SWH;Ob)QCY=eWwugrW$CsVJ2QEs7I~&$ zP;Kn_dO+s3OMANb|4zA(kW(SPb52^Ft+iBR?Cc3y$vE%d>Kk{K`5(Kq_mU_7x7!Za zuCjitjj)*KUgGqrW6s6E#a|6{Kg8C3SnylO{FzY5>O;3x&U=dg&8eHbsCQ?%#D7!C c_4Q0V4DQTproPGiXUYHsp00i_>zopr0P}Jzj{pDw delta 704 zcmZqY?&RL!!K7g5>g?=fX>M%kWNc|@=xXR_;Oy+`Xlh_?X=-HQW@$7zgGmOa$ONaN zB}@jIP?HRCDN<4>E(uCavr3s<$RrFi(g>I8$p*|$^)GVg@i8zk{`Pcn45_&FCUke6 zu%pP{^0cyaarWbpI*hEWPKP>_w$wODb%jh^H05Vw4WsCyEkD|?n3&Wsu<8o2Dj7}D zxOQtIlj64W^t@+%*JmG>nv*j{FI?{Y8u{mM<`h5I5fZ$U!nxz&F4c&LSC80t&;Pfl z*ZIc0Soz+QHUH~PC2x9vVPYz~pQG~rpLce%%E$xMo*_rqMfiVLyF!;3jr#Xd})^nFQp<+lBvhR1BId+OW7@7YOz e5x?5Wz|7!exPBtTO3yw9Anl3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s00+w{G(#^lGsVi()yc`&!qCjp$<*1<(ACh%)WpEm$kfol z%+<-wz{DA**Cju>G&eP`1g19yq1POzUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnv1= zG!Lpb1-DyFaq86vIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zHmh*ZVPIg&_jGX# zskrrK+TJ{2M}da)Z|~0?KN-QbKtq&CMM^-I-@&(C;}hGJFCA@Nv&?PgaYX6X-**rW`MI&-SW(RT*wfDvcI=i|aDTp(%iV*m)A!|b zE#tYc{|0-LgH-Q}qYuSYe3$dvRQ!C&Ec9k4tLDW!Z@$a@Vz8KbZr>BjrB8eN_U)_v zvt>hrg2m#k3k8?TGmE58mkWKdCWcY&)3Lush8&7}ROg;L>6gx_z#^Nt^Y|^p&2>Hx z&V_C1lCR#v_G0!Afip$!iyYQY6>qQ*nlU-n?@|}*lFt71t}~SrzA`QSQp_HdvBjI= z7w@Yb(>TB1@3s4saiGrV!PDJ!dm8o?Kb!S|)&Ji98`VLlnG5fDTZph*Hg0-yl6}II zZUZ~JOw~meJVN(&Z$IIge(myUb%$)V1n=#PO3a))Jz^UU-RWoDq9U4cjqwWG0}&fB z*I665TI3m&9bFePcpKy~eqox;;5j2bsIrJLfJb0QIp61PtWKIjeGV4$o7v(S{w(_b z!%|7xiou7m!6|Ts?M#M=hbGAX_G3u?VzJ#U$@uD)d@jCKBI>g%!_RK0JUhGCuY^fy zrOR#hG#RPLtn#T->iw0s@`tsHX62mMert2KJaorKhqY=?KAjZhStqfVRZqL9U`mn~ zr_|q72RyuIn*X|b<7CTIb?-w~*HdrGGqN$nFTEiDxRJvER3Ll0`njxgN@xNAb}cp$ delta 728 zcmV;}0w?|b3-ASyB!2{RLP=Bz2nYy#2xN!=000SaNLh0L00VXa00VXbebs`@0000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$SZAnByR9J=Wm$_~fK@f(& zzxtT1tVs?$U}lPASARS8$76tg?yZs!SAt9_HRh+k zmR{FXd3`t;PI(~Y-rAY&$N`y5A+&P`!IJ7j0RK*0gQ-mT@WsY!hh?N?(6v?w@K3mJ z3$|ZAx_lR=@<6Y*RLWVdoLGBHF(8jY;G#UzO#nJYDY$-6c^cKN*e4n(1>rORbTg$R zbU;+qj(-PI@K_`vd=a21!lntFI%4erudM+fTPc$)dMCBy0?9j_EHwh;oHnbv?#3{C{z<{%ljr0y zZ(?ldXLDpmH$+>Efqf`P!}?MT;io5&~ zmMsp4!}CMAB5VaskF^!{jy507#Fm*TF9wZ3V$me27QzK95E%sU)lwxSf~1N~8=IgY z9L{2qN*sg62*T)cL`{;KFeHOogRybApk)S)R2~nZfDBTqU*xjs@v|-++ndZ}BJdf4#xsb2 z2Nfd-2RMip0;nX=OAh)`06$+6#TTUc(mVlgkOGn^-el0AuwQ4l*$l2${=Eq{+)taGa(D>zLW_o7}+4zkSQe4l+rj*Aozc%T0Mc*p(5yO zy#Fbz6K~Q$WD%r8^jbOAxY&gzR~kA;3rSH#D@Krn@hXPLAt<7YLo@&rg2yhxl9u5z`>4R0_HuhZ;=t;ri3qR1Ss0qp+#IAkUjh0sVOF5YU%1 z&gCLvaH+<=msfmlu-MQ&v^o&E75*)AkU4bN za$DJoS}Qvl%P}l03%{U!rivPCY{aKELyjND@R^JI;@U=%qG+dvUq38w+rA2KbV)7JO`_kFl`{(847 zceZ8}^aj;klB{|9fM>gn}U6_6fNa13W^Hflja9>`R^``x;sk} z>tI{joQsxt^1XbV%IK{#4wm|v*}Hghnww~m11({mc_j(vj#q~iYsB4z=G^xinu1-6 zZ&y#NbnRQRE`E$554Yd_;CZ&g_qx~p>kbK6kwtET?Pka8rsGxyvpm{XSDlz*th6ao zZm2HnsgXE7&joIA__h0W z!bJ}1p0F9)%UY|H)xQo@xM$k(7d_X&p;pfl^I30WSz=}9Em5(^b(6(x*~ZR*yu-<` zaLBzh(=6*%XL6I)uFnt_Key{$ig~xxvDiJkbWa8=E5q5zrNe0vaH6%N@!?ugzG50T zfHw8fn>l9zGmod)IJe&$9>e;Idkoi_C^*aF#i{5PJ7MMWUUM`2vtD{@Xs$(JUe|^{ zn3lau`tj!3Tl3_I-aIx@cr%%lKKSxV|6cNZ$<&WW;t$lhc^iqShxuqTbVE9~(^$DH zf4YwCu_L^DZ*~9k?lVclckDNZ6sDHH;?5=W&Sf9%U)VCOVWWRt6``@ZYRtAel6o;R z#~51cdwk4v-0uB!2{RLP=Bz2nYy#2xN!=000SaNLh0L00l7s00l7tx9uoW0000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$U4M{{nRA_D^kbfwUD5+3{L?R*40F9F< zvf?vIP;hW^#<|^#JkVqFUOg9Kl{`2zm2 z0Px`#H!i92qj2!r*~Y7}t9P&KB>uJi_R}k2J*f|W{e1H~3jms?cVNa>N<<}e3X6t_ zPMkqa(>p-#5jrRK))T-Zc!UU0Y8JrBuFjtmdkg3hzJ7J{2*mFA=(^{>gafgA{p#is zQ1C)RvwyAdFBki%lBu6N#Y(7>p$1a6`}ROUBX-+>UMhC9&eB$d5(|NNHXGqqz;OZ1 z*xZDU#x%}2*3F*;n^72EWHiutnvg+e+KYr!yet9I6Xn!{27J!XmP4!t|L9n@pAD|U94$+LF zU2q^kGS6i=a*D|}vs{Iay8BT94ch|p7g<$Z5*`I=f-`U=J9#N9UxC=VR)62~o>prQ zrE^4qeeB`uEV9gj>yBzN@jG>JTphnwa+qeLWHb_VZZjR}m{{#^@ z=K$yo0$jv4l>pIP76Bldkp+~PVFiTk)PExu(k{s>005TM*a>G?0VC~hhLvey^e{U& zsjNja$KY(pigNjkdF6^TGpvAfIP4s9-Bb!ts1{GFqva9uK@zWuGz%%m5S;|;&#&m= zQ~^KVmYoL={`fshp2j{+oT?X94SqE&Pe3?^oWZA!_93aHc(E=quF*Mv{>7d5-gF2@ zO!&}E(jlJ;17NjxMaZ*caqr&0qTt@QErwaO1V9R)+q08`U93xxe-r4}AM~yafU4?P znr)(hKnyXS&7G9pt*R^jiOx_rxa$;xQw1zLmf^tiOgI%#H%`2Oe*s2{Pp6K>&hG#K N002ovPDHLkV1h`M8&m)Q diff --git a/pix/f/folder-open-64.png b/pix/f/folder-open-64.png index 92f81db0c19e492eb3a5eb17994113c4c1bf1d20..bdcc19325a16a6cfa418b793d29b11af28fa5185 100644 GIT binary patch literal 2231 zcmaJ@d00~U8a_&zx!dMQR)|_z0S5vN5(Nbd6!%hFRD`2Y0w*{I*<`4dPC2RNXqmUP zeH=AKTeQ5Acf3wbF6m6uV%jq02*Z)^6QEFtFWkNJ zHslEaC>L>fBofIBpb2CWJl}x9t0b_V4FI0rDwr?W0U?+;C_yZxV+U_EU@>AL9UDR6 zfjrn35{Wk?%b~F3z;HqG4gpn&_4dMes%Uxv354)5DoLVLK~vGOA9QK@yTMJsVm?5S z9dztpNk#I4F}^Z6grVR;oB(tuV%*7iA{nHTsjD$0kO&fpBm(GxBZ4%F2Mr`*rXQ?6 znp_x93uXCD$I@GLtO!A18iAlxD)GuSc$qwbK%`Qs1dv1^k#KqhPO)2x@Krde!g)r4 z1t|n_F^q_1Qj9^7A16yf=vaNGf0ZDCKgvoK({0i>jG*Gf1R@?Zlr#h6@%}$lBKe3` zAfeFT`F>JZ5xyIS2%(TdmLwPG2N&;b2nEx8p^!l~i9!V3 z**<{G^k_nO|kQABW3jgL(KFc*Mg9O$`W~CwimfV00#uLYd6b$oy8hogQ$e^~hF zi~<9)9yhKlL3b~y&%4qCu51(?2hqZ(K?~FTLo_S$d$+P{xPbd=@fszQ7*XME*R~r1 zY8F0XY<=u%RAH?Sy>$EECXCDl#<9L(+}LoyvUszDdVg@lL!&9)?b_{VkZM*xG*li` ztJ1WeGArEjRSI?)(3gJe6cLW>xVdMb{9<=ehk7vOpEtH$y<^3`UQNm3qLRf+C)QtJ zt?L@enp14Mr%PU;6IoS7X+^E)CDHdCmc~{!nGS_U6+8fR)B^Y2QNutHj6o9R<}U!sb6OS_%wiyq7naqy5cX{a z&Os3u6ZRHXj_h(%$7^am;OdOo&v~HNJVx}DsJ8Ol5%cWETRWbf&rZ2{y9iAMvfp~C zyecBKNm)q~wJ65>@yGVjFg*8hkXS9dUY3-xF6Q{vMNTg)4i@FLzIq+AOVeoYm%h2w zy^#zo@q>2V-EefH@rB8JR3gDL!=q;VmZD_|tGSs2nEftpy{P^34jb8qY+?~TjNCY&a~TK*h9m~s7Cq;)^z**auiM2df->q>yW+O;*ygDT5z)ia3^9H+h{WSaDBLk+3GEk$ItmB2~ z2K!&fOCIeV{P}Bt3rcLw0`n1+k+!{R+#)L^#Y;Ps8l0H|9~x+MR_t8gmGL&|driMB zmOGaE!o#h3s_R(_1aJ#~GWj;+h@d3W$jsFCxl_%ua!Up`_ejHXOO-{|CY0(8H$b%7 zNDVID7y5!ZzsW*_Dm6-ZLpFL^iVEJ)w|0atUsSbSeR|^iIh#wZ z8E5@*qrZxdIzC{r>a5h(Gk3wZ;Q_=hUT3yUU>~Pc@JI=R{LYWmCwrRC>n&z`T6o zRl;dFy(Bd?qu%sx%hajBTe24kRmEP)va~9b*2}%a+QzE|O+SWTa%NX)TOSU$?bEUQ zhmi-KsQ0Ngt~UGj^j>L>8Jv7HRyr5h^xa~7pu+3rgd$}{9&gY&{Z(-LMmthGcYoi> zu(2)SV;wDS!)&8+@W`>1=p39R j)igkywk5Q0z=ekYp(3d%8hF=K|JCIf36PxxYv*3L2snM*fe1u2SM>LP0=D-67Af`UrQ!5(2jGYZ@Ydbj zD)J_RLIDLZYJosVF5qyADKwEux`{M^>@-YBCJ;d5)_?f=s7Yg4E*O;Htt(?%DFW7l zI6rehDOXny337AP7%S#d&z3cG?^hpsZ~wSn0Ti9>6m^Kv|~==(|C?*)Loj)EhK+{QE6@M?~Z?VQurCZwvfHj61k^LJH+S&dD z0S#-T1UPGmx#I2Zf^e2db=nDL6CiRcL`K>Oapn8_1!01+y6Kq4A>5jf%XV7LW19n= zP9B7*hEsruc{*}ClFe*?;!KbLy71Yr*8y&1g@ow|B09S)WtRa}?fRhGlUGCk+WY5U zQGXon?I%1y0lny4S5?nvuM@GUTOy#U#^_`eBr@Hs@jzrZ=#1?UCJ6|Dt=}tzU>TEf zOF^By)D!`0&UOM#GUo%CnjHuMBt~*EfR*PHAR--`i}=GKOzrFkjLBISJmwQ{tic_n zNdkyqLd|kvCNeH(9T`8L04uhmxhXL4YJa6}K@e)KOzKQ(OT>U1&8_|m_rl?JQblUG z83u?%AOIzajfTdL&8;b^*t@|GzxnqXfHMFPJT>+Q`uuX0T@G4~erC~r(%t&#&9w`8 zndqUYWA11|z);mn%}#_<2*VoYJ^&D=10Ya9fG}+%IUNZgQ?o313>FxZ#&f0Zn14)^ z0Bd|t6RU>`BXuQ!VN9|gqTqWmnJ59qa4$Vi7!c~~0R&@H-I*64K&Y1DV6CnmpupNV2nH!nfFtb%BhUa*geKQ? z8B}Ofn1vXg4;Bc5zNtN@z`Y?_b$`tPMj#9WTE`6b2F(SgfC;W=Y=G~hRq7xl`?(8{ z`D7;6*Ys(3?N!Rj5^;|03lPSZJ)FU z0QNCj_wOe49)Q19b?VJm5dnlze2}DYrfmTc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=$rJ1RPo0F5Jlc|%Tp{t>jsfmHBk*T49 znX8kVfr&FruSMv>2~2MaLa#GUy`aR9TL84#CABECEH%ZgC_h&L>}jh^+-|YN zX&zK>3U0SJ;?%1Tbc{YIYLTKECIn1BASOKF0y*%cpPC0u??u3by+HD|Bm)DZt*47) zNX4x?lQ()XI|{U=r+xo+PNm#%qiC*rkKT~kKtQ|2X?**A!9JnQ^~_Y1GdUKUT) zstFARo*gc#Rl6U@ny`Bch+X=rf5y*P-um--CF8?NN)ZA785Gn#_ZqHwDmr&rHFQ2=l+B)?( z$Eqa{{p4az!z4FG>Fvn243A*E=U%njTxRM7%PFUVbsJfNtTFozJcU(A|qw`xtb?c>wf2)^-M}AX0#o)8VR{Uzs`pFjNvPX|tG24`+OrDUR p#`tXekM!ru1=}{xymz08hoS#{nsIQTi9D!y@pScbS?83{1OSBPr)dBH delta 420 zcmV;V0bBmd3BCi6B!2{RLP=Bz2nYy#2xN!=000SaNLh0L00FxI00FxJI_%@(0000P zbVXQnQ*UN;cVTj60C#tHE@^ISb7Ns}WiD@WXPfRk8UO$RJ4r-AR5*>r(?3c>K@bM; zZ|2S07xU-E#8$Mi6fF!0dIZtR$^)d+1K5k$<`B7o-ayk!kbhL7fdqua5Q$1OyJM3) z@QJVx!7Y|8c76=s?2@Wtp2c%j{{UU z0^Y`U^LaEbk$-AiOvbbVVu*wU_5(zivKhdtYsr4J)xIr0PMDbq_5^m%4!qft}9I@y-EXaS_}Z3A|0Gk69DMnf8!ToC222O9Lr(= O0000c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=GnX!qvi>sTZlc|%Tp{t>jsfmHBk*T49 znX8kVfr&FruSMv>2~2MaT(6q}PQ9SSkXrz>*(J3ovn(~mttdZN0qkk3Ox$j9 z!D${;ZwgMgxVqxhs}FRHJ}7FDq8cUyOg|tdJmCU4@T8xb2Tbopz=ZvE?(#AQ2F55) z7srr_TT6n@dL4EUn0NC`-lVV<^N!4){Nmtb{R_=q=JE#?{}5}nYxpH}&$d#OMgNgw z$Onxu?F|04^+&wc+){a+B5m337rhU1C`?YC%;=in& zM=H+f)V@Bz?A_pPmZ)xb!!ApG)|t=I&%Ph`U$)@P*HRC`Lx0{FOyO$!yCm@M)eX8I z{s{18pFhCDbi!#zMwzct@aq}XH7yNSnP;}170K0(|2^ZVNO(}g6b|P+yC#YB(=Lt9 zJY}DJmuT-7F=$+^vu$F(gVDJgvX^M7HJiLlD$d;K@^40 zy>n-FHxZ(h_*01%R=z+A6+0imQhbX*9zcBwdn;Q(un`MU!GBVWM$i=Tml#>2W;0{4 zt1O~nms}Wznc<%MG3StT4ucdA)D1uYU~%K}6M#-XXhkQsXIJ(rGxdG~(d@!zbd(7g9}##$5KjoA z7)4KI>rP6TV1yw?GqffQ1^EPwW_UUw@I?WBzC;H4n?MMGQ4p0+Knulx;A@VIkoYEF zs;zbKG({2^-fgztm#0RHB<-ool*F00000NkvXXu0mjfqpP=u diff --git a/theme/base/style/filemanager.css b/theme/base/style/filemanager.css index 09f898379fa..506706880ac 100644 --- a/theme/base/style/filemanager.css +++ b/theme/base/style/filemanager.css @@ -43,10 +43,10 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st /* * Tools, Path & View on fp-navbar (File Picker and File Manager) */ -.fp-toolbar {display: table-row;line-height: 22px;float:left;} +.fp-toolbar {/*display: table-row;*/display: block;line-height: 22px;float:left;} .fp-toolbar.empty {display:none;} .fp-toolbar .disabled {display:none;} -.fp-toolbar div {display: inline-block;padding: 0px 2px;} +.fp-toolbar div {display: inline-block;padding: 0px 2px;padding-right: 10px;} .fp-toolbar img {vertical-align: -15%; margin-right: 5px;} .file-picker .search-entry {background:#FFF url('[[pix:a/search]]') no-repeat 3px 3px;height:18px;width:230px;border: 1px solid #BBB;padding-left:20px;} @@ -64,6 +64,7 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_active]]') no-repeat 0px 0px;width:23px;height:22px;display: inline-block;margin-left: -4px;} .fp-vb-tree.checked {background:url('[[pix:theme|fp/view_tree_selected]]');} .fp-viewbar.disabled .fp-vb-tree {background:url('[[pix:theme|fp/view_tree_inactive]]');} +.file-picker .fp-clear-right {clear: right;} /* * Icon view (File Picker and File Manager) @@ -86,37 +87,36 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st .file-picker .yui3-datatable-data .yui3-datatable-odd .yui3-datatable-sorted {background-color: #F6F6F6;} .file-picker .yui3-datatable-even .yui3-datatable-cell {background-color: #FFF;border-left: 0px solid #FFF;} .file-picker .yui3-datatable-data .yui3-datatable-even .yui3-datatable-sorted {background-color: #FFF;} -.file-picker .fp-icon img {max-height:16px;max-width:16px;} /* - * Tree view (File Picker and File Manager) + * Tree view (File Manager only) */ /*.file-picker .fp-treeview .fp-folder .fp-icon, .filemanager .fp-treeview .fp-folder .fp-icon {}*/ /* first or middle sibling, no children */ -/*.file-picker .ygtvtn, .filemanager*/ .ygtvtn {background: url('[[pix:moodle|y/tn]]') 0 0 no-repeat;width:17px;height:22px;} +.file-picker .ygtvtn, .filemanager .ygtvtn {background: url('[[pix:moodle|y/tn]]') 0px 0px no-repeat;width:17px;height:22px;} /* first or middle sibling, collapsable */ -/*.file-picker .ygtvtm, .filemanager*/ .ygtvtm {background: url('[[pix:moodle|y/tm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvtm, .filemanager .ygtvtm {background: url('[[pix:moodle|y/tm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* first or middle sibling, collapsable, hover */ -/*.file-picker .ygtvtmh, .filemanager*/ .ygtvtmh {background: url('[[pix:moodle|y/tm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvtmh, .filemanager .ygtvtmh {background: url('[[pix:moodle|y/tm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* first or middle sibling, expandable */ -/*.file-picker .ygtvtp, .filemanager*/ .ygtvtp {background: url('[[pix:moodle|y/tp]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvtp, .filemanager .ygtvtp {background: url('[[pix:moodle|y/tp]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* first or middle sibling, expandable, hover */ -/*.file-picker .ygtvtph, .filemanager*/ .ygtvtph {background: url('[[pix:moodle|y/tp]]') 0 0 no-repeat;width:13px;height:22px;cursor:pointer;} +.file-picker .ygtvtph, .filemanager .ygtvtph {background: url('[[pix:moodle|y/tp]]') 0px 10px no-repeat;width:13px;height:22px;cursor:pointer;} /* last sibling, no children */ -/*.file-picker .ygtvln, .filemanager*/ .ygtvln {background: url('[[pix:moodle|y/ln]]') 0 0 no-repeat;width:17px;height:22px;} +.file-picker .ygtvln, .filemanager .ygtvln {background: url('[[pix:moodle|y/ln]]') 0px 0px no-repeat;width:17px;height:22px;} /* Last sibling, collapsable */ -/*.file-picker .ygtvlm, .filemanager*/ .ygtvlm {background: url('[[pix:moodle|y/lm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvlm, .filemanager .ygtvlm {background: url('[[pix:moodle|y/lm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* Last sibling, collapsable, hover */ -/*.file-picker .ygtvlmh, .filemanager*/ .ygtvlmh {background: url('[[pix:moodle|y/lm]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvlmh, .filemanager .ygtvlmh {background: url('[[pix:moodle|y/lm]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* Last sibling, expandable */ -/*.file-picker .ygtvlp, .filemanager*/ .ygtvlp {background: url('[[pix:moodle|y/lp]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvlp, .filemanager .ygtvlp {background: url('[[pix:moodle|y/lp]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* Last sibling, expandable, hover */ -/*.file-picker .ygtvlph, .filemanager*/ .ygtvlph {background: url('[[pix:moodle|y/lp]]') 0 0 no-repeat;width:13px;height:12px;cursor:pointer;} +.file-picker .ygtvlph, .filemanager .ygtvlph {background: url('[[pix:moodle|y/lp]]') 0px 10px no-repeat;width:13px;height:12px;cursor:pointer;} /* Loading icon */ -/*.file-picker .ygtvloading, .filemanager*/ .ygtvloading {background: url('[[pix:moodle|y/loading]]') 0 0 no-repeat;width:16px;height:22px;} +.file-picker .ygtvloading, .filemanager .ygtvloading {background: transparent url('[[pix:moodle|y/loading]]') 0 0 no-repeat;width:16px;height:22px;} /* the style for the empty cells that are used for rendering the depth* of the node */ -/*.file-picker .ygtvdepthcell, .filemanager*/ .ygtvdepthcell {background: url('[[pix:moodle|y/vline]]') 0 0 no-repeat;width:17px;height:22px;} -/*.file-picker .ygtvblankdepthcell, .filemanager*/ .ygtvblankdepthcell {width:17px;height:22px;} +.file-picker .ygtvdepthcell, .filemanager .ygtvdepthcell {background: url('[[pix:moodle|y/vline]]') 0 0 no-repeat;width:17px;height:/*22px;*/32px;} +.file-picker .ygtvblankdepthcell, .filemanager .ygtvblankdepthcell {width:17px;height:22px;} /* the style of the div around each node */ /*.file-picker .ygtvitem table, .filemanager .ygtvitem table{margin-bottom:0;}*/ /*.file-picker .ygtvitem td, .filemanager .ygtvitem td {border:none;padding:0;}*/ @@ -127,7 +127,12 @@ background: #CCC!important;filter: progid:DXImageTransform.Microsoft.gradient(st .filemanager .ygtvlabel,.filemanager .ygtvlabel:link,.filemanager .ygtvlabel:visited,.filemanager .ygtvlabel:hover {margin-left:2px;text-decoration: none;}*/ a.ygtvspacer:hover {color: transparent;text-decoration: none;} .ygtvlabel, .ygtvlabel:link, .ygtvlabel:visited, .ygtvlabel:hover {background-color: transparent;cursor: pointer;margin-left: 2px;text-decoration: none;} -/*.file-picker*/ .ygtvfocus {background-color: #DDD;} +.file-picker .ygtvfocus, .filemanager .ygtvfocus {background-color: #EEE;} + +.fp-filename-icon {margin-top: 10px;display: block;/*top: -10px;position: relative;*/} +.fp-icon {float: left;margin-top: -7px;width: 24px;height: 24px;margin-right: 10px;text-align: center;line-height: 24px;} +.fp-icon img {max-height:24px;max-width:24px;vertical-align: middle;} +.fp-filename {padding-right: 10px;} /* * Repositories Login on fp-content (File Picker only) @@ -228,7 +233,7 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} /*.filemanager-container ul{margin:0;padding:0;} .filemanager-container ul li{white-space:nowrap;list-style-type:none;} .filemanager-container ul li a{padding:0}*/ -.filemanager .fp-content{overflow: auto;max-height: 400px;} +.filemanager .fp-content{overflow: auto;max-height: 472px;} .filemanager-container, .filepicker-filelist {overflow:hidden;} /* @@ -256,14 +261,15 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} .filemanager .fp-contextmenu {display:none;} .filemanager .fp-iconview .fp-folder.fp-hascontextmenu .fp-contextmenu {display:block;position:absolute;right:7px;bottom:5px;z-index: 2000;} .filemanager .fp-treeview .fp-folder.fp-hascontextmenu .fp-contextmenu, -.filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu {display:inline;} +.filemanager .fp-tableview .fp-folder.fp-hascontextmenu .fp-contextmenu {/*display: inline;*//*position: relative;left: 14px;margin-right: -20px;top: 6px;background: yellow;*/} /* * Drag and drop support (File Manager only) */ +.filepicker-filelist .filepicker-container, .filemanager.fm-noitems .fm-empty-container {display:block;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #BBB;padding-top:85px;text-align:center;z-index: 3000;} .filepicker-filelist .dndupload-target, -.filemanager-container .dndupload-target {background:#FFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #fb7979;padding-top:85px;text-align:center;z-index:3000;-webkit-box-shadow: 0px 0px 0px 10px #FFF;-moz-box-shadow: 0px 0px 0px 10px #FFF;box-shadow: 0px 0px 0px 10px #FFF;z-index: 3000;} +.filemanager-container .dndupload-target {background:#FFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #fb7979;padding-top:85px;text-align:center;z-index:3000;-webkit-box-shadow: 0px 0px 0px 10px #FFF;-moz-box-shadow: 0px 0px 0px 10px #FFF;box-shadow: 0px 0px 0px 10px #FFF;} .filepicker-filelist.dndupload-over .dndupload-target, .filemanager-container.dndupload-over .dndupload-target {background:#FFF;position:absolute;top:10px;bottom:10px;left:10px;right:10px;border: 2px dashed #6c8cd3;padding-top:85px;text-align:center;z-index: 3000;} .dndupload-message {display:none;} @@ -310,7 +316,7 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} /* * Create folder dialogue (File Manager only) */ -.filemanager .fp-mkdir-dlg {text-align: center;} +.filemanager.fp-mkdir-dlg {text-align: center;z-index: 999999} .filemanager .fp-mkdir-dlg p {text-align: left;margin: 40px 20px 0px;} .filemanager .fp-mkdir-dlg input {margin: 0px 20px 20px;} From ee45a48b9c39e409340c245eaf7c6c0ae2c902c8 Mon Sep 17 00:00:00 2001 From: Kevin Wiliarty Date: Thu, 24 May 2012 03:07:46 -0400 Subject: [PATCH 355/455] turning off the hspace attribute on move icon image... --- lib/yui/dragdrop/dragdrop.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/yui/dragdrop/dragdrop.js b/lib/yui/dragdrop/dragdrop.js index 930f60042f3..3b37b4a888f 100644 --- a/lib/yui/dragdrop/dragdrop.js +++ b/lib/yui/dragdrop/dragdrop.js @@ -34,8 +34,7 @@ YUI.add('moodle-core-dragdrop', function(Y) { .setAttrs({ 'src' : M.util.image_url(MOVEICON.pix, MOVEICON.component), 'alt' : title, - 'title' : M.str.moodle.move, - 'hspace' : '3' + 'title' : M.str.moodle.move }); if (iconclass) { dragicon.addClass(iconclass); From 6a9949a48910ea7be31e1e9b0d68d18bf15e8492 Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Thu, 24 May 2012 15:13:22 +0800 Subject: [PATCH 356/455] MDL-33325 folder: 'set as main file' option removed, from filepicker when editing a file in a folder resource --- mod/folder/edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/folder/edit.php b/mod/folder/edit.php index 918568575ba..0b74e47a144 100644 --- a/mod/folder/edit.php +++ b/mod/folder/edit.php @@ -48,7 +48,7 @@ $PAGE->set_activity_record($folder); $data = new stdClass(); $data->id = $cm->id; -$options = array('mainfile'=>true, 'subdirs'=>1, 'maxbytes'=>$CFG->maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*'); +$options = array('subdirs'=>1, 'maxbytes'=>$CFG->maxbytes, 'maxfiles'=>-1, 'accepted_types'=>'*'); file_prepare_standard_filemanager($data, 'files', $options, $context, 'mod_folder', 'content', 0); $mform = new mod_folder_edit_form(null, array('data'=>$data, 'options'=>$options)); From a91b4aa661c66fa075cc0e7204fc3da450831e26 Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Thu, 24 May 2012 15:40:06 +0800 Subject: [PATCH 357/455] MDL-33318 lib : code style fix --- lib/cronlib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cronlib.php b/lib/cronlib.php index 3bbab293b79..f89adbd6d06 100644 --- a/lib/cronlib.php +++ b/lib/cronlib.php @@ -376,7 +376,7 @@ function cron_run() { //Run registration updated cron mtrace(get_string('siteupdatesstart', 'hub')); - require_once($CFG->dirroot . "/$CFG->admin/registration/lib.php"); + require_once($CFG->dirroot . '/' . $CFG->admin . '/registration/lib.php'); $registrationmanager = new registration_manager(); $registrationmanager->cron(); mtrace(get_string('siteupdatesend', 'hub')); From 505978801f3343bd9aed2f63d92d313972ed1869 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Thu, 24 May 2012 16:12:15 +0800 Subject: [PATCH 358/455] MDL-33162 filepicker: fix trailingw hitespace --- lib/outputrenderers.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 198eef2a355..80f20c65824 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -2054,9 +2054,9 @@ $icon_progress EOD; if ($options->env != 'url') { $html .= << +
                          -
                          $currentfile - $strdndenabled
                          +
                          $currentfile - $strdndenabled
                          {$strdroptoupload}
                          From 2d7c1117341863dea0d1545420fdc71744cd2b50 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Thu, 24 May 2012 16:14:02 +0800 Subject: [PATCH 359/455] MDL-33329 Filepicker form element can not link by reference. Also better handling of maxbytes --- lib/form/filepicker.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/form/filepicker.php b/lib/form/filepicker.php index 09071fb3cea..c3fad282485 100644 --- a/lib/form/filepicker.php +++ b/lib/form/filepicker.php @@ -60,7 +60,7 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { * @param array $options set of options to initalize filepicker */ function MoodleQuickForm_filepicker($elementName=null, $elementLabel=null, $attributes=null, $options=null) { - global $CFG; + global $CFG, $PAGE; $options = (array)$options; foreach ($options as $name=>$value) { @@ -68,12 +68,18 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { $this->_options[$name] = $value; } } - if (!empty($options['return_types'])) { - $this->_options['return_types'] = FILE_INTERNAL | FILE_REFERENCE; + if (empty($options['return_types'])) { + $this->_options['return_types'] = FILE_INTERNAL; } + $fpmaxbytes = 0; if (!empty($options['maxbytes'])) { - $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $options['maxbytes']); + $fpmaxbytes = $options['maxbytes']; } + $coursemaxbytes = 0; + if (!empty($PAGE->course)) { + $coursemaxbytes = $PAGE->course->maxbytes; + } + $this->_options['maxbytes'] = get_max_upload_file_size($CFG->maxbytes, $coursemaxbytes, $fpmaxbytes); $this->_type = 'filepicker'; parent::HTML_QuickForm_input($elementName, $elementLabel, $attributes); } @@ -143,7 +149,7 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { $args = new stdClass(); // need these three to filter repositories list $args->accepted_types = $this->_options['accepted_types']?$this->_options['accepted_types']:'*'; - $args->return_types = FILE_INTERNAL | FILE_REFERENCE; + $args->return_types = $this->_options['return_types']; $args->itemid = $draftitemid; $args->maxbytes = $this->_options['maxbytes']; $args->context = $PAGE->context; From 5536f2fccf199d4693429445403d1907de0c71a3 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 24 May 2012 11:49:36 +0200 Subject: [PATCH 360/455] MDL-32339 improving the layout for narrow screens --- theme/base/style/admin.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme/base/style/admin.css b/theme/base/style/admin.css index 58ba4e7a451..e22e8027923 100644 --- a/theme/base/style/admin.css +++ b/theme/base/style/admin.css @@ -88,7 +88,7 @@ #page-admin-index .adminwarning.maturityinfo.maturity100, #page-admin-index .adminwarning.maturityinfo.maturity150 {background-color:#f3f2aa;} -#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo {margin:10px auto;width:60%;text-align:left;} +#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo {line-height:1.8;margin:20px auto;width:60%;text-align:left;} #page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo .info.release {margin-right:10px;padding:5px 10px;-moz-border-radius: 10px;-webkit-border-radius: 10px;border-radius: 10px;} #page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity50 .info.release {background-color:#ffd3d9;} #page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity100 .info.release, From 7dfe4b92d0da0362449c3412375b752e65c80dff Mon Sep 17 00:00:00 2001 From: Michael Aherne Date: Thu, 24 May 2012 13:04:21 +0100 Subject: [PATCH 361/455] MDL-33331 Strict warning in Shibboleth auth --- auth/shibboleth/index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/auth/shibboleth/index.php b/auth/shibboleth/index.php index 7bc8f90c892..a1e4a1c3840 100644 --- a/auth/shibboleth/index.php +++ b/auth/shibboleth/index.php @@ -30,6 +30,7 @@ /// If we can find the Shibboleth attribute, save it in session and return to main login page if (!empty($_SERVER[$pluginconfig->user_attribute])) { // Shibboleth auto-login + $frm = new stdClass(); $frm->username = strtolower($_SERVER[$pluginconfig->user_attribute]); $frm->password = substr(base64_encode($_SERVER[$pluginconfig->user_attribute]),0,8); // The random password consists of the first 8 letters of the base 64 encoded user ID From 5744ea36820f7768bd3049e77b38f3593febec06 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Thu, 24 May 2012 20:42:58 +0800 Subject: [PATCH 362/455] Revert "MDL-33063 course: Reuse get_all_sections()" This reverts commit 66b494771ffc731472a374bef1b5cd12befd53b2. --- course/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course/lib.php b/course/lib.php index 371666fd55f..8e073737607 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1070,7 +1070,7 @@ function get_array_of_activities($courseid) { return $mod; // always return array } - if ($sections = get_all_sections($courseid)) { + if ($sections = $DB->get_records("course_sections", array("course"=>$courseid), "section ASC")) { foreach ($sections as $section) { if (!empty($section->sequence)) { $sequence = explode(",", $section->sequence); From c2c071a27446e0bdbf3ec56a4d71156841ef6b8b Mon Sep 17 00:00:00 2001 From: Charles Fulton Date: Mon, 21 May 2012 05:39:27 -0700 Subject: [PATCH 363/455] MDL-33139 forum: indicate which user's post was edited --- mod/forum/lang/en/forum.php | 1 + mod/forum/post.php | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mod/forum/lang/en/forum.php b/mod/forum/lang/en/forum.php index 48e5d76a925..138ac53a46b 100644 --- a/mod/forum/lang/en/forum.php +++ b/mod/forum/lang/en/forum.php @@ -137,6 +137,7 @@ $string['displaystart_help'] = 'This setting specifies whether a forum post shou $string['eachuserforum'] = 'Each person posts one discussion'; $string['edit'] = 'Edit'; $string['editedby'] = 'Edited by {$a->name} - original submission {$a->date}'; +$string['editedpostupdated'] = '{$a}\'s post was updated'; $string['editing'] = 'Editing'; $string['emptymessage'] = 'Something was wrong with your post. Perhaps you left it blank, or the attachment was too big. Your changes have NOT been saved.'; $string['erroremptymessage'] = 'Post message cannot be empty'; diff --git a/mod/forum/post.php b/mod/forum/post.php index 6301c7ec5d0..a57633f29a2 100644 --- a/mod/forum/post.php +++ b/mod/forum/post.php @@ -647,7 +647,13 @@ if ($fromform = $mform_post->get_data()) { if (!empty($message)) { // if we're printing stuff about the file upload $timemessage = 4; } - $message .= '
                          '.get_string("postupdated", "forum"); + + if ($realpost->userid == $USER->id) { + $message .= '
                          '.get_string("postupdated", "forum"); + } else { + $realuser = $DB->get_record('user', array('id' => $realpost->userid)); + $message .= '
                          '.get_string("editedpostupdated", "forum", fullname($realuser)); + } if ($subscribemessage = forum_post_subscription($fromform, $forum)) { $timemessage = 4; From 2ea6533a366a39cc19385292a4d1b650f025a067 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Thu, 24 May 2012 22:24:30 +0800 Subject: [PATCH 364/455] MDL-33307 format_weeks - highlight current week --- course/format/renderer.php | 16 ++++++++++++++-- course/format/weeks/renderer.php | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/course/format/renderer.php b/course/format/renderer.php index d969e8bc7c7..fb59c386a52 100644 --- a/course/format/renderer.php +++ b/course/format/renderer.php @@ -92,7 +92,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base { if ($section->section != 0) { // Only in the non-general sections. - if ($course->marker == $section->section) { + if ($this->is_section_current($section, $course)) { $o = get_accesshide(get_string('currentsection', 'format_'.$course->format)); } } @@ -121,7 +121,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base { // Only in the non-general sections. if (!$section->visible) { $sectionstyle = ' hidden'; - } else if ($course->marker == $section->section) { + } else if ($this->is_section_current($section, $course)) { $sectionstyle = ' current'; } $linktitle = ($course->coursedisplay == COURSE_DISPLAY_MULTIPAGE); @@ -669,4 +669,16 @@ abstract class format_section_renderer_base extends plugin_renderer_base { $options->overflowdiv = true; return format_text($summarytext, $section->summaryformat, $options); } + + /** + * Is the section passed in the current section? (Note this isn't strictly + * a renderering method, but neater here). + * + * @param stdClass $course The course entry from DB + * @param stdClass $section The course_section entry from the DB + * @return bool true if the section is current + */ + protected function is_section_current($section, $course) { + return ($course->marker == $section->section); + } } diff --git a/course/format/weeks/renderer.php b/course/format/weeks/renderer.php index 33d640281b6..5184f04abfc 100644 --- a/course/format/weeks/renderer.php +++ b/course/format/weeks/renderer.php @@ -58,4 +58,24 @@ class format_weeks_renderer extends format_section_renderer_base { protected function page_title() { return get_string('weeklyoutline'); } + + /** + * Is the section passed in the current section? + * + * @param stdClass $course The course entry from DB + * @param stdClass $section The course_section entry from the DB + * @return bool true if the section is current + */ + protected function is_section_current($section, $course) { + if ($section->section < 1) { + return false; + } + $oneweekseconds = 604800; + $startdate = $course->startdate + ($oneweekseconds * ($section->section - 1)); + $enddate = $startdate + $oneweekseconds; + + $timenow = time(); + + return (($timenow >= $startdate) && ($timenow < $enddate)); + } } From b6283a49709fb137620cd8eb652f230ac8b0b115 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Thu, 24 May 2012 22:51:53 +0800 Subject: [PATCH 365/455] MDL-33307 format_weeks - sort out week date display * Introduce function format_weeks_get_section_dates which is used as the consistent place to calculate the current section start and end date * Rework callback_weeks_get_section_name to not use the above function rather than do crazy needless looping through all sections to work out the current week title. * Change the just introduced is_current renderer function to share the format_weeks_get_section_dates function to ensure both the title and 'current week' are using the same dates to do their job --- course/format/weeks/lib.php | 47 +++++++++++++++++++++----------- course/format/weeks/renderer.php | 9 +++--- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/course/format/weeks/lib.php b/course/format/weeks/lib.php index 9201c9e2d6f..834addadec4 100644 --- a/course/format/weeks/lib.php +++ b/course/format/weeks/lib.php @@ -67,25 +67,20 @@ function callback_weeks_definition() { function callback_weeks_get_section_name($course, $section) { // We can't add a node without text if (!empty($section->name)) { - // Return the name the user set - return format_string($section->name, true, array('context' => get_context_instance(CONTEXT_COURSE, $course->id))); + // Return the name the user set. + return format_string($section->name, true, array('context' => context_course::instance($course->id))); } else if ($section->section == 0) { - // Return the section0name + // Return the general section. return get_string('section0name', 'format_weeks'); } else { - // Got to work out the date of the week so that we can show it - $sections = get_all_sections($course->id); - $weekdate = $course->startdate+7200; - foreach ($sections as $sec) { - if ($sec->id == $section->id) { - break; - } else if ($sec->section != 0) { - $weekdate += 604800; - } - } - $strftimedateshort = ' '.get_string('strftimedateshort'); - $weekday = userdate($weekdate, $strftimedateshort); - $endweekday = userdate($weekdate+518400, $strftimedateshort); + $dates = format_weeks_get_section_dates($section, $course); + + // We subtract 24 hours for display purposes. + $dates->end = ($dates->end - 86400); + + $dateformat = ' '.get_string('strftimedateshort'); + $weekday = userdate($dates->start, $dateformat); + $endweekday = userdate($dates->end, $dateformat); return $weekday.' - '.$endweekday; } } @@ -102,3 +97,23 @@ function callback_weeks_ajax_support() { $ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0); return $ajaxsupport; } + +/** + * Return the start and end date of the passed section + * + * @param stdClass $section The course_section entry from the DB + * @param stdClass $course The course entry from DB + * @return stdClass property start for startdate, property end for enddate + */ +function format_weeks_get_section_dates($section, $course) { + $oneweekseconds = 604800; + // Hack alert. We add 2 hours to avoid possible DST problems. (e.g. we go into daylight + // savings and the date changes. + $startdate = $course->startdate + 7200; + + $dates = new stdClass(); + $dates->start = $startdate + ($oneweekseconds * ($section->section - 1)); + $dates->end = $dates->start + $oneweekseconds; + + return $dates; +} diff --git a/course/format/weeks/renderer.php b/course/format/weeks/renderer.php index 5184f04abfc..e87936ccbf5 100644 --- a/course/format/weeks/renderer.php +++ b/course/format/weeks/renderer.php @@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot.'/course/format/renderer.php'); +require_once($CFG->dirroot.'/course/format/weeks/lib.php'); /** @@ -62,20 +63,18 @@ class format_weeks_renderer extends format_section_renderer_base { /** * Is the section passed in the current section? * - * @param stdClass $course The course entry from DB * @param stdClass $section The course_section entry from the DB + * @param stdClass $course The course entry from DB * @return bool true if the section is current */ protected function is_section_current($section, $course) { if ($section->section < 1) { return false; } - $oneweekseconds = 604800; - $startdate = $course->startdate + ($oneweekseconds * ($section->section - 1)); - $enddate = $startdate + $oneweekseconds; $timenow = time(); + $dates = format_weeks_get_section_dates($section, $course); - return (($timenow >= $startdate) && ($timenow < $enddate)); + return (($timenow >= $dates->start) && ($timenow < $dates->end)); } } From 798f0dece21400ecca9cd9060ce1e3cd3d64d55d Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Thu, 24 May 2012 23:15:52 +0200 Subject: [PATCH 366/455] MDL-33114 import TinyMCE 3.5.1.1 and fix preview --- lib/editor/tinymce/lib.php | 2 +- .../{3.5 => 3.5.1.1}/jquery.tinymce.js | 0 .../tiny_mce/{3.5 => 3.5.1.1}/langs/en.js | 0 .../tiny_mce/{3.5 => 3.5.1.1}/license.txt | 0 .../plugins/advhr/css/advhr.css | 0 .../plugins/advhr/editor_plugin.js | 0 .../plugins/advhr/editor_plugin_src.js | 0 .../{3.5 => 3.5.1.1}/plugins/advhr/js/rule.js | 0 .../plugins/advhr/langs/en_dlg.js | 0 .../{3.5 => 3.5.1.1}/plugins/advhr/rule.htm | 0 .../plugins/advimage/css/advimage.css | 0 .../plugins/advimage/editor_plugin.js | 0 .../plugins/advimage/editor_plugin_src.js | 0 .../plugins/advimage/image.htm | 0 .../plugins/advimage/img/sample.gif | Bin .../plugins/advimage/js/image.js | 0 .../plugins/advimage/langs/en_dlg.js | 0 .../plugins/advlink/css/advlink.css | 0 .../plugins/advlink/editor_plugin.js | 0 .../plugins/advlink/editor_plugin_src.js | 0 .../plugins/advlink/js/advlink.js | 0 .../plugins/advlink/langs/en_dlg.js | 0 .../{3.5 => 3.5.1.1}/plugins/advlink/link.htm | 0 .../plugins/advlist/editor_plugin.js | 0 .../plugins/advlist/editor_plugin_src.js | 0 .../3.5.1.1/plugins/autolink/editor_plugin.js | 1 + .../plugins/autolink/editor_plugin_src.js | 12 +- .../plugins/autoresize/editor_plugin.js | 0 .../plugins/autoresize/editor_plugin_src.js | 0 .../plugins/autosave/editor_plugin.js | 0 .../plugins/autosave/editor_plugin_src.js | 0 .../plugins/autosave/langs/en.js | 0 .../plugins/bbcode/editor_plugin.js | 0 .../plugins/bbcode/editor_plugin_src.js | 0 .../plugins/contextmenu/editor_plugin.js | 0 .../plugins/contextmenu/editor_plugin_src.js | 0 .../plugins/directionality/editor_plugin.js | 0 .../directionality/editor_plugin_src.js | 0 .../plugins/dragmath/dragmath.php | 0 .../plugins/dragmath/editor_plugin.js | 0 .../plugins/dragmath/editor_plugin_src.js | 0 .../plugins/dragmath/img/dragmath.gif | Bin .../plugins/dragmath/js/dragmath.js | 0 .../plugins/dragmath/langs/en_dlg.js | 0 .../plugins/emotions/editor_plugin.js | 0 .../plugins/emotions/editor_plugin_src.js | 0 .../plugins/emotions/emotions.htm | 0 .../plugins/emotions/img/smiley-cool.gif | Bin .../plugins/emotions/img/smiley-cry.gif | Bin .../emotions/img/smiley-embarassed.gif | Bin .../emotions/img/smiley-foot-in-mouth.gif | Bin .../plugins/emotions/img/smiley-frown.gif | Bin .../plugins/emotions/img/smiley-innocent.gif | Bin .../plugins/emotions/img/smiley-kiss.gif | Bin .../plugins/emotions/img/smiley-laughing.gif | Bin .../emotions/img/smiley-money-mouth.gif | Bin .../plugins/emotions/img/smiley-sealed.gif | Bin .../plugins/emotions/img/smiley-smile.gif | Bin .../plugins/emotions/img/smiley-surprised.gif | Bin .../emotions/img/smiley-tongue-out.gif | Bin .../plugins/emotions/img/smiley-undecided.gif | Bin .../plugins/emotions/img/smiley-wink.gif | Bin .../plugins/emotions/img/smiley-yell.gif | Bin .../plugins/emotions/js/emotions.js | 0 .../plugins/emotions/langs/en_dlg.js | 0 .../plugins/example/dialog.htm | 0 .../plugins/example/editor_plugin.js | 0 .../plugins/example/editor_plugin_src.js | 0 .../plugins/example/img/example.gif | Bin .../plugins/example/js/dialog.js | 0 .../plugins/example/langs/en.js | 0 .../plugins/example/langs/en_dlg.js | 0 .../example_dependency/editor_plugin.js | 0 .../example_dependency/editor_plugin_src.js | 0 .../plugins/fullpage/css/fullpage.css | 0 .../plugins/fullpage/editor_plugin.js | 0 .../plugins/fullpage/editor_plugin_src.js | 0 .../plugins/fullpage/fullpage.htm | 0 .../plugins/fullpage/js/fullpage.js | 0 .../plugins/fullpage/langs/en_dlg.js | 0 .../plugins/fullscreen/editor_plugin.js | 0 .../plugins/fullscreen/editor_plugin_src.js | 0 .../plugins/fullscreen/fullscreen.htm | 0 .../plugins/iespell/editor_plugin.js | 0 .../plugins/iespell/editor_plugin_src.js | 0 .../plugins/inlinepopups/editor_plugin.js | 0 .../plugins/inlinepopups/editor_plugin_src.js | 0 .../skins/clearlooks2/img/alert.gif | Bin .../skins/clearlooks2/img/button.gif | Bin .../skins/clearlooks2/img/buttons.gif | Bin .../skins/clearlooks2/img/confirm.gif | Bin .../skins/clearlooks2/img/corners.gif | Bin .../skins/clearlooks2/img/horizontal.gif | Bin .../skins/clearlooks2/img/vertical.gif | Bin .../inlinepopups/skins/clearlooks2/window.css | 0 .../plugins/inlinepopups/template.htm | 0 .../plugins/insertdatetime/editor_plugin.js | 0 .../insertdatetime/editor_plugin_src.js | 0 .../plugins/layer/editor_plugin.js | 0 .../plugins/layer/editor_plugin_src.js | 0 .../plugins/legacyoutput/editor_plugin.js | 0 .../plugins/legacyoutput/editor_plugin_src.js | 0 .../plugins/lists/editor_plugin.js | 0 .../plugins/lists/editor_plugin_src.js | 0 .../plugins/media/css/media.css | 0 .../plugins/media/editor_plugin.js | 0 .../plugins/media/editor_plugin_src.js | 0 .../plugins/media/js/embed.js | 0 .../plugins/media/js/media.js | 0 .../plugins/media/langs/en_dlg.js | 0 .../{3.5 => 3.5.1.1}/plugins/media/media.htm | 0 .../plugins/media/moxieplayer.swf | Bin .../plugins/moodleemoticon/dialog.php | 0 .../plugins/moodleemoticon/editor_plugin.js | 0 .../moodleemoticon/editor_plugin_src.js | 0 .../moodleemoticon/img/moodleemoticon.gif | Bin .../plugins/moodleemoticon/js/dialog.js | 0 .../plugins/moodlemedia/css/media.css | 0 .../plugins/moodlemedia/editor_plugin.js | 0 .../plugins/moodlemedia/editor_plugin_src.js | 0 .../plugins/moodlemedia/img/icon.gif | Bin .../plugins/moodlemedia/js/media.js | 0 .../plugins/moodlemedia/moodlemedia.htm | 0 .../plugins/moodlemedia/preview.php | 16 +- .../plugins/moodlenolink/editor_plugin.js | 0 .../plugins/moodlenolink/editor_plugin_src.js | 0 .../plugins/moodlenolink/img/ed_nolink.gif | Bin .../plugins/moodlenolink/langs/en.js | 0 .../plugins/nonbreaking/editor_plugin.js | 0 .../plugins/nonbreaking/editor_plugin_src.js | 0 .../plugins/noneditable/editor_plugin.js | 0 .../plugins/noneditable/editor_plugin_src.js | 0 .../plugins/pagebreak/editor_plugin.js | 0 .../plugins/pagebreak/editor_plugin_src.js | 0 .../plugins/paste/editor_plugin.js | 0 .../plugins/paste/editor_plugin_src.js | 0 .../plugins/paste/js/pastetext.js | 0 .../plugins/paste/js/pasteword.js | 0 .../plugins/paste/langs/en_dlg.js | 0 .../plugins/paste/pastetext.htm | 0 .../plugins/paste/pasteword.htm | 0 .../plugins/preview/editor_plugin.js | 0 .../plugins/preview/editor_plugin_src.js | 0 .../plugins/preview/example.html | 0 .../plugins/preview/jscripts/embed.js | 0 .../plugins/preview/preview.html | 0 .../plugins/print/editor_plugin.js | 0 .../plugins/print/editor_plugin_src.js | 0 .../plugins/save/editor_plugin.js | 0 .../plugins/save/editor_plugin_src.js | 0 .../searchreplace/css/searchreplace.css | 0 .../plugins/searchreplace/editor_plugin.js | 0 .../searchreplace/editor_plugin_src.js | 0 .../plugins/searchreplace/js/searchreplace.js | 0 .../plugins/searchreplace/langs/en_dlg.js | 0 .../plugins/searchreplace/searchreplace.htm | 2 +- .../plugins/spellchecker/changelog.txt | 0 .../spellchecker/classes/EnchantSpell.php | 0 .../spellchecker/classes/GoogleSpell.php | 0 .../plugins/spellchecker/classes/PSpell.php | 0 .../spellchecker/classes/PSpellShell.php | 0 .../spellchecker/classes/SpellChecker.php | 0 .../spellchecker/classes/utils/JSON.php | 0 .../spellchecker/classes/utils/Logger.php | 0 .../plugins/spellchecker/config.php | 0 .../plugins/spellchecker/css/content.css | 0 .../plugins/spellchecker/editor_plugin.js | 0 .../plugins/spellchecker/editor_plugin_src.js | 0 .../plugins/spellchecker/img/wline.gif | Bin .../plugins/spellchecker/includes/general.php | 0 .../plugins/spellchecker/rpc.php | 0 .../plugins/style/css/props.css | 0 .../plugins/style/editor_plugin.js | 0 .../plugins/style/editor_plugin_src.js | 0 .../plugins/style/js/props.js | 0 .../plugins/style/langs/en_dlg.js | 0 .../{3.5 => 3.5.1.1}/plugins/style/props.htm | 0 .../{3.5 => 3.5.1.1}/plugins/style/readme.txt | 0 .../plugins/tabfocus/editor_plugin.js | 0 .../plugins/tabfocus/editor_plugin_src.js | 0 .../{3.5 => 3.5.1.1}/plugins/table/cell.htm | 0 .../plugins/table/css/cell.css | 0 .../plugins/table/css/row.css | 0 .../plugins/table/css/table.css | 0 .../plugins/table/editor_plugin.js | 0 .../plugins/table/editor_plugin_src.js | 0 .../{3.5 => 3.5.1.1}/plugins/table/js/cell.js | 0 .../plugins/table/js/merge_cells.js | 0 .../{3.5 => 3.5.1.1}/plugins/table/js/row.js | 0 .../plugins/table/js/table.js | 0 .../plugins/table/langs/en_dlg.js | 0 .../plugins/table/merge_cells.htm | 0 .../{3.5 => 3.5.1.1}/plugins/table/row.htm | 0 .../{3.5 => 3.5.1.1}/plugins/table/table.htm | 0 .../plugins/template/blank.htm | 0 .../plugins/template/css/template.css | 0 .../plugins/template/editor_plugin.js | 0 .../plugins/template/editor_plugin_src.js | 0 .../plugins/template/js/template.js | 0 .../plugins/template/langs/en_dlg.js | 0 .../plugins/template/template.htm | 0 .../plugins/visualblocks/css/visualblocks.css | 0 .../plugins/visualblocks/editor_plugin.js | 0 .../plugins/visualblocks/editor_plugin_src.js | 0 .../plugins/visualblocks/img/address.gif | Bin .../plugins/visualblocks/img/article.gif | Bin .../plugins/visualblocks/img/aside.gif | Bin .../plugins/visualblocks/img/blockquote.gif | Bin .../plugins/visualblocks/img/div.gif | Bin .../plugins/visualblocks/img/figure.gif | Bin .../plugins/visualblocks/img/h1.gif | Bin .../plugins/visualblocks/img/h2.gif | Bin .../plugins/visualblocks/img/h3.gif | Bin .../plugins/visualblocks/img/h4.gif | Bin .../plugins/visualblocks/img/h5.gif | Bin .../plugins/visualblocks/img/h6.gif | Bin .../plugins/visualblocks/img/hgroup.gif | Bin .../plugins/visualblocks/img/p.gif | Bin .../plugins/visualblocks/img/pre.gif | Bin .../plugins/visualblocks/img/section.gif | Bin .../plugins/visualchars/editor_plugin.js | 0 .../plugins/visualchars/editor_plugin_src.js | 0 .../plugins/wordcount/editor_plugin.js | 0 .../plugins/wordcount/editor_plugin_src.js | 0 .../plugins/xhtmlxtras/abbr.htm | 0 .../plugins/xhtmlxtras/acronym.htm | 0 .../plugins/xhtmlxtras/attributes.htm | 0 .../plugins/xhtmlxtras/cite.htm | 0 .../plugins/xhtmlxtras/css/attributes.css | 0 .../plugins/xhtmlxtras/css/popup.css | 0 .../plugins/xhtmlxtras/del.htm | 0 .../plugins/xhtmlxtras/editor_plugin.js | 0 .../plugins/xhtmlxtras/editor_plugin_src.js | 0 .../plugins/xhtmlxtras/ins.htm | 0 .../plugins/xhtmlxtras/js/abbr.js | 0 .../plugins/xhtmlxtras/js/acronym.js | 0 .../plugins/xhtmlxtras/js/attributes.js | 0 .../plugins/xhtmlxtras/js/cite.js | 0 .../plugins/xhtmlxtras/js/del.js | 0 .../plugins/xhtmlxtras/js/element_common.js | 0 .../plugins/xhtmlxtras/js/ins.js | 0 .../plugins/xhtmlxtras/langs/en_dlg.js | 0 .../themes/advanced/about.htm | 0 .../themes/advanced/anchor.htm | 0 .../themes/advanced/charmap.htm | 0 .../themes/advanced/color_picker.htm | 0 .../themes/advanced/editor_template.js | 2 +- .../themes/advanced/editor_template_src.js | 10 +- .../themes/advanced/image.htm | 0 .../themes/advanced/img/colorpicker.jpg | Bin .../themes/advanced/img/flash.gif | Bin .../themes/advanced/img/icons.gif | Bin .../themes/advanced/img/iframe.gif | Bin .../themes/advanced/img/pagebreak.gif | Bin .../themes/advanced/img/quicktime.gif | Bin .../themes/advanced/img/realmedia.gif | Bin .../themes/advanced/img/shockwave.gif | Bin .../themes/advanced/img/trans.gif | Bin .../themes/advanced/img/video.gif | Bin .../themes/advanced/img/windowsmedia.gif | Bin .../themes/advanced/js/about.js | 0 .../themes/advanced/js/anchor.js | 22 +- .../themes/advanced/js/charmap.js | 0 .../themes/advanced/js/color_picker.js | 0 .../themes/advanced/js/image.js | 0 .../themes/advanced/js/link.js | 0 .../themes/advanced/js/source_editor.js | 0 .../themes/advanced/langs/en.js | 0 .../themes/advanced/langs/en_dlg.js | 0 .../{3.5 => 3.5.1.1}/themes/advanced/link.htm | 0 .../themes/advanced/shortcuts.htm | 0 .../themes/advanced/skins/default/content.css | 0 .../themes/advanced/skins/default/dialog.css | 0 .../advanced/skins/default/img/buttons.png | Bin .../advanced/skins/default/img/items.gif | Bin .../advanced/skins/default/img/menu_arrow.gif | Bin .../advanced/skins/default/img/menu_check.gif | Bin .../advanced/skins/default/img/progress.gif | Bin .../advanced/skins/default/img/tabs.gif | Bin .../themes/advanced/skins/default/ui.css | 0 .../advanced/skins/highcontrast/content.css | 0 .../advanced/skins/highcontrast/dialog.css | 0 .../themes/advanced/skins/highcontrast/ui.css | 0 .../themes/advanced/skins/o2k7/content.css | 0 .../themes/advanced/skins/o2k7/dialog.css | 0 .../advanced/skins/o2k7/img/button_bg.png | Bin .../skins/o2k7/img/button_bg_black.png | Bin .../skins/o2k7/img/button_bg_silver.png | Bin .../themes/advanced/skins/o2k7/ui.css | 0 .../themes/advanced/skins/o2k7/ui_black.css | 0 .../themes/advanced/skins/o2k7/ui_silver.css | 0 .../themes/advanced/source_editor.htm | 0 .../themes/simple/editor_template.js | 0 .../themes/simple/editor_template_src.js | 0 .../themes/simple/img/icons.gif | Bin .../themes/simple/langs/en.js | 0 .../themes/simple/skins/default/content.css | 0 .../themes/simple/skins/default/ui.css | 0 .../themes/simple/skins/o2k7/content.css | 0 .../simple/skins/o2k7/img/button_bg.png | Bin .../themes/simple/skins/o2k7/ui.css | 0 .../tinymce/tiny_mce/3.5.1.1/tiny_mce.js | 1 + .../tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_dev.js | 0 .../tiny_mce/3.5.1.1/tiny_mce_jquery.js | 1 + .../{3.5 => 3.5.1.1}/tiny_mce_jquery_src.js | 341 ++++++++++++------ .../{3.5 => 3.5.1.1}/tiny_mce_popup.js | 0 .../{3.5 => 3.5.1.1}/tiny_mce_popup_src.js | 0 .../tiny_mce/3.5.1.1/tiny_mce_prototype.js | 1 + .../tiny_mce_prototype_src.js | 341 ++++++++++++------ .../tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_src.js | 341 ++++++++++++------ .../utils/editable_selects.js | 0 .../{3.5 => 3.5.1.1}/utils/form_utils.js | 0 .../tiny_mce/{3.5 => 3.5.1.1}/utils/mctabs.js | 0 .../{3.5 => 3.5.1.1}/utils/validate.js | 0 .../3.5/plugins/autolink/editor_plugin.js | 1 - lib/editor/tinymce/tiny_mce/3.5/tiny_mce.js | 1 - .../tinymce/tiny_mce/3.5/tiny_mce_jquery.js | 1 - .../tiny_mce/3.5/tiny_mce_prototype.js | 1 - lib/editor/tinymce/version.php | 4 +- lib/thirdpartylibs.xml | 2 +- 320 files changed, 755 insertions(+), 348 deletions(-) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/jquery.tinymce.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/langs/en.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/license.txt (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advhr/css/advhr.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advhr/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advhr/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advhr/js/rule.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advhr/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advhr/rule.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/css/advimage.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/image.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/img/sample.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/js/image.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advimage/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlink/css/advlink.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlink/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlink/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlink/js/advlink.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlink/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlink/link.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlist/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/advlist/editor_plugin_src.js (100%) create mode 100644 lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin.js rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/autolink/editor_plugin_src.js (93%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/autoresize/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/autoresize/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/autosave/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/autosave/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/autosave/langs/en.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/bbcode/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/bbcode/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/contextmenu/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/contextmenu/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/directionality/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/directionality/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/dragmath/dragmath.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/dragmath/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/dragmath/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/dragmath/img/dragmath.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/dragmath/js/dragmath.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/dragmath/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/emotions.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-cool.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-cry.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-embarassed.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-foot-in-mouth.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-frown.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-innocent.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-kiss.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-laughing.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-money-mouth.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-sealed.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-smile.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-surprised.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-tongue-out.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-undecided.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-wink.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/img/smiley-yell.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/js/emotions.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/emotions/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/dialog.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/img/example.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/js/dialog.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/langs/en.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example_dependency/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/example_dependency/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullpage/css/fullpage.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullpage/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullpage/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullpage/fullpage.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullpage/js/fullpage.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullpage/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullscreen/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullscreen/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/fullscreen/fullscreen.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/iespell/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/iespell/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/alert.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/button.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/corners.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/skins/clearlooks2/window.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/inlinepopups/template.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/insertdatetime/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/insertdatetime/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/layer/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/layer/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/legacyoutput/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/legacyoutput/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/lists/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/lists/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/css/media.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/js/embed.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/js/media.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/media.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/media/moxieplayer.swf (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodleemoticon/dialog.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodleemoticon/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodleemoticon/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodleemoticon/img/moodleemoticon.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodleemoticon/js/dialog.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/css/media.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/img/icon.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/js/media.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/moodlemedia.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlemedia/preview.php (77%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlenolink/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlenolink/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlenolink/img/ed_nolink.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/moodlenolink/langs/en.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/nonbreaking/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/nonbreaking/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/noneditable/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/noneditable/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/pagebreak/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/pagebreak/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/js/pastetext.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/js/pasteword.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/pastetext.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/paste/pasteword.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/preview/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/preview/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/preview/example.html (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/preview/jscripts/embed.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/preview/preview.html (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/print/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/print/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/save/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/save/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/searchreplace/css/searchreplace.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/searchreplace/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/searchreplace/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/searchreplace/js/searchreplace.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/searchreplace/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/searchreplace/searchreplace.htm (96%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/changelog.txt (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/EnchantSpell.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/GoogleSpell.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/PSpell.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/PSpellShell.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/SpellChecker.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/utils/JSON.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/classes/utils/Logger.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/config.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/css/content.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/img/wline.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/includes/general.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/spellchecker/rpc.php (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/css/props.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/js/props.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/props.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/style/readme.txt (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/tabfocus/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/tabfocus/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/cell.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/css/cell.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/css/row.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/css/table.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/js/cell.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/js/merge_cells.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/js/row.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/js/table.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/merge_cells.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/row.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/table/table.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/blank.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/css/template.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/js/template.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/template/template.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/css/visualblocks.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/address.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/article.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/aside.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/blockquote.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/div.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/figure.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/h1.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/h2.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/h3.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/h4.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/h5.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/h6.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/hgroup.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/p.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/pre.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualblocks/img/section.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualchars/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/visualchars/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/wordcount/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/wordcount/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/abbr.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/acronym.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/attributes.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/cite.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/css/attributes.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/css/popup.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/del.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/editor_plugin.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/editor_plugin_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/ins.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/abbr.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/acronym.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/attributes.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/cite.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/del.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/element_common.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/js/ins.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/plugins/xhtmlxtras/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/about.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/anchor.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/charmap.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/color_picker.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/editor_template.js (76%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/editor_template_src.js (96%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/image.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/colorpicker.jpg (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/flash.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/icons.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/iframe.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/pagebreak.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/quicktime.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/realmedia.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/shockwave.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/trans.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/video.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/img/windowsmedia.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/about.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/anchor.js (68%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/charmap.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/color_picker.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/image.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/link.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/js/source_editor.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/langs/en.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/langs/en_dlg.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/link.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/shortcuts.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/content.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/dialog.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/img/buttons.png (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/img/items.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/img/menu_arrow.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/img/menu_check.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/img/progress.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/img/tabs.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/default/ui.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/highcontrast/content.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/highcontrast/dialog.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/highcontrast/ui.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/content.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/dialog.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/img/button_bg.png (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/img/button_bg_black.png (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/img/button_bg_silver.png (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/ui.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/ui_black.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/skins/o2k7/ui_silver.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/advanced/source_editor.htm (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/editor_template.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/editor_template_src.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/img/icons.gif (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/langs/en.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/skins/default/content.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/skins/default/ui.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/skins/o2k7/content.css (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/skins/o2k7/img/button_bg.png (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/themes/simple/skins/o2k7/ui.css (100%) create mode 100644 lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce.js rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_dev.js (100%) create mode 100644 lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery.js rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_jquery_src.js (98%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_popup.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_popup_src.js (100%) create mode 100644 lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype.js rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_prototype_src.js (98%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/tiny_mce_src.js (98%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/utils/editable_selects.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/utils/form_utils.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/utils/mctabs.js (100%) rename lib/editor/tinymce/tiny_mce/{3.5 => 3.5.1.1}/utils/validate.js (100%) delete mode 100644 lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin.js delete mode 100644 lib/editor/tinymce/tiny_mce/3.5/tiny_mce.js delete mode 100644 lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery.js delete mode 100644 lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype.js diff --git a/lib/editor/tinymce/lib.php b/lib/editor/tinymce/lib.php index 885af159a10..01537e912e7 100644 --- a/lib/editor/tinymce/lib.php +++ b/lib/editor/tinymce/lib.php @@ -28,7 +28,7 @@ defined('MOODLE_INTERNAL') || die(); class tinymce_texteditor extends texteditor { /** @var string active version - directory name */ - public $version = '3.5'; + public $version = '3.5.1.1'; public function supported_by_browser() { if (check_browser_version('MSIE', 6)) { diff --git a/lib/editor/tinymce/tiny_mce/3.5/jquery.tinymce.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/jquery.tinymce.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/jquery.tinymce.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/jquery.tinymce.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/langs/en.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/langs/en.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/langs/en.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/langs/en.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/license.txt b/lib/editor/tinymce/tiny_mce/3.5.1.1/license.txt similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/license.txt rename to lib/editor/tinymce/tiny_mce/3.5.1.1/license.txt diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/css/advhr.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/css/advhr.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/css/advhr.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/css/advhr.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/js/rule.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/js/rule.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/js/rule.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/js/rule.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/rule.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/rule.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advhr/rule.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advhr/rule.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/css/advimage.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/css/advimage.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/css/advimage.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/css/advimage.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/image.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/image.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/image.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/image.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/img/sample.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/img/sample.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/img/sample.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/img/sample.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/js/image.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/js/image.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/js/image.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/js/image.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advimage/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advimage/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/css/advlink.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/css/advlink.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/css/advlink.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/css/advlink.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/js/advlink.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/js/advlink.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/js/advlink.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/js/advlink.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/link.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/link.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlink/link.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlink/link.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlist/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlist/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlist/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlist/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/advlist/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlist/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/advlist/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/advlist/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin.js new file mode 100644 index 00000000000..17f825b1bdb --- /dev/null +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AutolinkPlugin",{init:function(a,b){var c=this;a.onKeyDown.addToTop(function(d,f){if(f.keyCode==13){return c.handleEnter(d)}});if(tinyMCE.isIE){return}a.onKeyPress.add(function(d,f){if(f.which==41){return c.handleEclipse(d)}});a.onKeyUp.add(function(d,f){if(f.keyCode==32){return c.handleSpacebar(d)}})},handleEclipse:function(a){this.parseCurrentLine(a,-1,"(",true)},handleSpacebar:function(a){this.parseCurrentLine(a,0,"",true)},handleEnter:function(a){this.parseCurrentLine(a,-1,"",false)},parseCurrentLine:function(i,d,b,g){var a,f,c,n,k,m,h,e,j;a=i.selection.getRng(true).cloneRange();if(a.startOffset<5){e=a.endContainer.previousSibling;if(e==null){if(a.endContainer.firstChild==null||a.endContainer.firstChild.nextSibling==null){return}e=a.endContainer.firstChild.nextSibling}j=e.length;a.setStart(e,j);a.setEnd(e,j);if(a.endOffset<5){return}f=a.endOffset;n=e}else{n=a.endContainer;if(n.nodeType!=3&&n.firstChild){while(n.nodeType!=3&&n.firstChild){n=n.firstChild}a.setStart(n,0);a.setEnd(n,n.nodeValue.length)}if(a.endOffset==1){f=2}else{f=a.endOffset-1-d}}c=f;do{a.setStart(n,f-2);a.setEnd(n,f-1);f-=1}while(a.toString()!=" "&&a.toString()!=""&&a.toString().charCodeAt(0)!=160&&(f-2)>=0&&a.toString()!=b);if(a.toString()==b||a.toString().charCodeAt(0)==160){a.setStart(n,f);a.setEnd(n,c);f+=1}else{if(a.startOffset==0){a.setStart(n,0);a.setEnd(n,c)}else{a.setStart(n,f);a.setEnd(n,c)}}var m=a.toString();if(m.charAt(m.length-1)=="."){a.setEnd(n,c-1)}m=a.toString();h=m.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+-]+@)(.+)$/i);if(h){if(h[1]=="www."){h[1]="http://www."}else{if(/@$/.test(h[1])&&!/^mailto:/.test(h[1])){h[1]="mailto:"+h[1]}}k=i.selection.getBookmark();i.selection.setRng(a);tinyMCE.execCommand("createlink",false,h[1]+h[2]);i.selection.moveToBookmark(k);if(tinyMCE.isWebKit){i.selection.collapse(false);var l=Math.min(n.length,c+1);a.setStart(n,l);a.setEnd(n,l);i.selection.setRng(a)}}},getInfo:function(){return{longname:"Autolink",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autolink",tinymce.plugins.AutolinkPlugin)})(); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin_src.js similarity index 93% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin_src.js index 2dd4c696034..87670517192 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin_src.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autolink/editor_plugin_src.js @@ -61,7 +61,7 @@ // We need at least five characters to form a URL, // hence, at minimum, five characters from the beginning of the line. - r = ed.selection.getRng().cloneRange(); + r = ed.selection.getRng(true).cloneRange(); if (r.startOffset < 5) { // During testing, the caret is placed inbetween two text nodes. // The previous text node contains the URL. @@ -124,13 +124,19 @@ r.setEnd(endContainer, start); } + // Exclude last . from word like "www.site.com." + var text = r.toString(); + if (text.charAt(text.length - 1) == '.') { + r.setEnd(endContainer, start - 1); + } + text = r.toString(); - matches = text.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|[A-Z0-9._%+-]+@)(.+)$/i); + matches = text.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+-]+@)(.+)$/i); if (matches) { if (matches[1] == 'www.') { matches[1] = 'http://www.'; - } else if (/@$/.test(matches[1])) { + } else if (/@$/.test(matches[1]) && !/^mailto:/.test(matches[1])) { matches[1] = 'mailto:' + matches[1]; } diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autoresize/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autoresize/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/autoresize/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autoresize/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autoresize/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autoresize/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/autoresize/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autoresize/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autosave/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autosave/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/autosave/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autosave/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autosave/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autosave/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/autosave/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autosave/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autosave/langs/en.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autosave/langs/en.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/autosave/langs/en.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/autosave/langs/en.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/bbcode/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/bbcode/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/bbcode/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/bbcode/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/bbcode/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/bbcode/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/bbcode/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/bbcode/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/contextmenu/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/contextmenu/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/contextmenu/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/contextmenu/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/contextmenu/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/contextmenu/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/contextmenu/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/contextmenu/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/directionality/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/directionality/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/directionality/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/directionality/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/directionality/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/directionality/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/directionality/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/directionality/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/dragmath.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/dragmath.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/dragmath.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/dragmath.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/img/dragmath.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/img/dragmath.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/img/dragmath.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/img/dragmath.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/js/dragmath.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/js/dragmath.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/js/dragmath.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/js/dragmath.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/dragmath/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/dragmath/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/emotions.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/emotions.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/emotions.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/emotions.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-cool.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-cool.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-cool.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-cool.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-cry.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-cry.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-cry.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-cry.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-embarassed.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-embarassed.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-embarassed.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-embarassed.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-foot-in-mouth.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-foot-in-mouth.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-foot-in-mouth.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-foot-in-mouth.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-frown.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-frown.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-frown.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-frown.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-innocent.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-innocent.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-innocent.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-innocent.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-kiss.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-kiss.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-kiss.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-kiss.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-laughing.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-laughing.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-laughing.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-laughing.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-money-mouth.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-money-mouth.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-money-mouth.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-money-mouth.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-sealed.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-sealed.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-sealed.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-sealed.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-smile.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-smile.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-smile.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-smile.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-surprised.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-surprised.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-surprised.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-surprised.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-tongue-out.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-tongue-out.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-tongue-out.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-tongue-out.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-undecided.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-undecided.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-undecided.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-undecided.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-wink.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-wink.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-wink.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-wink.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-yell.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-yell.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/img/smiley-yell.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/img/smiley-yell.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/js/emotions.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/js/emotions.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/js/emotions.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/js/emotions.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/emotions/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/emotions/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/dialog.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/dialog.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/dialog.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/dialog.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/img/example.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/img/example.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/img/example.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/img/example.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/js/dialog.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/js/dialog.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/js/dialog.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/js/dialog.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/langs/en.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/langs/en.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/langs/en.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/langs/en.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example_dependency/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example_dependency/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example_dependency/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example_dependency/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/example_dependency/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example_dependency/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/example_dependency/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/example_dependency/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/css/fullpage.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/css/fullpage.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/css/fullpage.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/css/fullpage.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/fullpage.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/fullpage.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/fullpage.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/fullpage.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/js/fullpage.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/js/fullpage.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/js/fullpage.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/js/fullpage.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullpage/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullpage/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullscreen/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullscreen/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullscreen/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullscreen/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullscreen/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullscreen/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullscreen/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullscreen/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/fullscreen/fullscreen.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullscreen/fullscreen.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/fullscreen/fullscreen.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/fullscreen/fullscreen.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/iespell/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/iespell/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/iespell/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/iespell/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/iespell/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/iespell/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/iespell/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/iespell/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/alert.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/alert.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/alert.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/alert.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/button.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/button.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/button.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/button.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/corners.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/corners.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/corners.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/corners.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/window.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/window.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/skins/clearlooks2/window.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/skins/clearlooks2/window.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/template.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/template.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/inlinepopups/template.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/inlinepopups/template.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/insertdatetime/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/insertdatetime/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/insertdatetime/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/insertdatetime/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/insertdatetime/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/insertdatetime/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/insertdatetime/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/insertdatetime/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/layer/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/layer/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/layer/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/layer/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/layer/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/layer/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/layer/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/layer/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/legacyoutput/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/legacyoutput/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/legacyoutput/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/legacyoutput/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/legacyoutput/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/legacyoutput/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/legacyoutput/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/legacyoutput/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/lists/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/lists/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/lists/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/lists/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/lists/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/lists/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/lists/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/lists/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/css/media.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/css/media.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/css/media.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/css/media.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/js/embed.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/js/embed.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/js/embed.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/js/embed.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/js/media.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/js/media.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/js/media.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/js/media.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/media.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/media.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/media.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/media.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/media/moxieplayer.swf b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/moxieplayer.swf similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/media/moxieplayer.swf rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/media/moxieplayer.swf diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/dialog.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/dialog.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/dialog.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/dialog.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/img/moodleemoticon.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/img/moodleemoticon.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/img/moodleemoticon.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/img/moodleemoticon.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/js/dialog.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/js/dialog.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodleemoticon/js/dialog.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodleemoticon/js/dialog.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/css/media.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/css/media.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/css/media.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/css/media.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/img/icon.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/img/icon.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/img/icon.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/img/icon.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/js/media.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/js/media.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/js/media.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/js/media.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/moodlemedia.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/moodlemedia.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/moodlemedia.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/moodlemedia.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/preview.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/preview.php similarity index 77% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/preview.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/preview.php index 431b077687c..f26251a5c81 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlemedia/preview.php +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlemedia/preview.php @@ -25,6 +25,8 @@ require(dirname(__FILE__) . '/../../../../../../../config.php'); require_once($CFG->libdir . '/filelib.php'); +require_once($CFG->libdir . '/editorlib.php'); +require_once($CFG->libdir . '/editor/tinymce/lib.php'); // Must be logged in require_login(); @@ -32,9 +34,11 @@ require_login(); // Require path to draftfile.php file $path = required_param('path', PARAM_PATH); +$editor = new tinymce_texteditor(); + // Now output this file which is super-simple $PAGE->set_pagelayout('embedded'); -$PAGE->set_url(new moodle_url('/lib/editor/tinymce/tiny_mce/3.4.6/plugins/moodlemedia/preview.php', +$PAGE->set_url(new moodle_url('/lib/editor/tinymce/tiny_mce/'.$editor->version.'/plugins/moodlemedia/preview.php', array('path' => $path))); $PAGE->set_context(context_system::instance()); $PAGE->add_body_class('core_media_preview'); @@ -42,7 +46,15 @@ $PAGE->add_body_class('core_media_preview'); echo $OUTPUT->header(); $mediarenderer = $PAGE->get_renderer('core', 'media'); -$url = new moodle_url('/draftfile.php/' . $path); + +$path = '/'.trim($path, '/'); + +if (empty($CFG->slasharguments)) { + $url = new moodle_url('/draftfile.php', array('file'=>$path)); +} else { + $url = new moodle_url('/draftfile.php'); + $url->set_slashargument($path); +} if ($mediarenderer->can_embed_url($url)) { echo $mediarenderer->embed_url($url); } diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/img/ed_nolink.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/img/ed_nolink.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/img/ed_nolink.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/img/ed_nolink.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/langs/en.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/langs/en.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/moodlenolink/langs/en.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/moodlenolink/langs/en.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/nonbreaking/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/nonbreaking/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/nonbreaking/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/nonbreaking/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/nonbreaking/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/nonbreaking/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/nonbreaking/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/nonbreaking/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/noneditable/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/noneditable/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/noneditable/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/noneditable/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/noneditable/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/noneditable/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/noneditable/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/noneditable/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/pagebreak/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/pagebreak/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/pagebreak/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/pagebreak/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/pagebreak/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/pagebreak/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/pagebreak/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/pagebreak/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/js/pastetext.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/js/pastetext.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/js/pastetext.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/js/pastetext.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/js/pasteword.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/js/pasteword.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/js/pasteword.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/js/pasteword.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/pastetext.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/pastetext.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/pastetext.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/pastetext.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/paste/pasteword.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/pasteword.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/paste/pasteword.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/paste/pasteword.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/preview/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/preview/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/preview/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/preview/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/preview/example.html b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/example.html similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/preview/example.html rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/example.html diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/preview/jscripts/embed.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/jscripts/embed.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/preview/jscripts/embed.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/jscripts/embed.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/preview/preview.html b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/preview.html similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/preview/preview.html rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/preview/preview.html diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/print/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/print/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/print/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/print/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/print/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/print/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/print/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/print/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/save/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/save/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/save/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/save/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/save/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/save/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/save/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/save/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/css/searchreplace.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/css/searchreplace.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/css/searchreplace.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/css/searchreplace.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/js/searchreplace.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/js/searchreplace.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/js/searchreplace.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/js/searchreplace.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/searchreplace.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/searchreplace.htm similarity index 96% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/searchreplace.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/searchreplace.htm index fe711759598..ae81d40dccc 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/plugins/searchreplace/searchreplace.htm +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/searchreplace/searchreplace.htm @@ -93,7 +93,7 @@ - +
                          diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/changelog.txt b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/changelog.txt similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/changelog.txt rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/changelog.txt diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/EnchantSpell.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/EnchantSpell.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/EnchantSpell.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/EnchantSpell.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/GoogleSpell.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/GoogleSpell.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/GoogleSpell.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/GoogleSpell.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/PSpell.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/PSpell.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/PSpell.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/PSpell.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/PSpellShell.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/PSpellShell.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/PSpellShell.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/PSpellShell.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/SpellChecker.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/SpellChecker.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/SpellChecker.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/SpellChecker.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/utils/JSON.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/utils/JSON.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/utils/JSON.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/utils/JSON.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/utils/Logger.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/utils/Logger.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/classes/utils/Logger.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/classes/utils/Logger.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/config.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/config.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/config.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/config.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/css/content.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/css/content.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/css/content.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/css/content.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/img/wline.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/img/wline.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/img/wline.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/img/wline.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/includes/general.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/includes/general.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/includes/general.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/includes/general.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/rpc.php b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/rpc.php similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/spellchecker/rpc.php rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/spellchecker/rpc.php diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/css/props.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/css/props.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/css/props.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/css/props.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/js/props.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/js/props.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/js/props.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/js/props.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/props.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/props.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/props.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/props.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/style/readme.txt b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/readme.txt similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/style/readme.txt rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/style/readme.txt diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/tabfocus/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/tabfocus/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/tabfocus/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/tabfocus/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/tabfocus/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/tabfocus/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/tabfocus/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/tabfocus/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/cell.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/cell.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/cell.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/cell.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/css/cell.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/css/cell.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/css/cell.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/css/cell.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/css/row.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/css/row.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/css/row.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/css/row.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/css/table.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/css/table.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/css/table.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/css/table.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/cell.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/cell.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/cell.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/cell.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/merge_cells.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/merge_cells.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/merge_cells.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/merge_cells.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/row.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/row.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/row.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/row.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/table.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/table.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/js/table.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/js/table.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/merge_cells.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/merge_cells.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/merge_cells.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/merge_cells.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/row.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/row.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/row.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/row.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/table/table.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/table.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/table/table.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/table/table.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/blank.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/blank.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/blank.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/blank.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/css/template.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/css/template.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/css/template.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/css/template.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/js/template.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/js/template.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/js/template.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/js/template.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/template/template.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/template.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/template/template.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/template/template.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/css/visualblocks.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/css/visualblocks.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/css/visualblocks.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/css/visualblocks.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/address.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/address.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/address.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/address.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/article.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/article.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/article.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/article.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/aside.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/aside.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/aside.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/aside.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/blockquote.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/blockquote.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/blockquote.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/blockquote.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/div.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/div.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/div.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/div.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/figure.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/figure.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/figure.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/figure.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h1.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h1.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h1.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h1.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h2.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h2.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h2.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h2.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h3.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h3.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h3.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h3.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h4.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h4.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h4.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h4.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h5.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h5.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h5.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h5.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h6.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h6.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/h6.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/h6.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/hgroup.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/hgroup.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/hgroup.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/hgroup.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/p.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/p.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/p.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/p.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/pre.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/pre.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/pre.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/pre.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/section.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/section.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualblocks/img/section.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualblocks/img/section.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualchars/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualchars/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualchars/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualchars/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/visualchars/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualchars/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/visualchars/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/visualchars/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/wordcount/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/wordcount/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/wordcount/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/wordcount/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/wordcount/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/wordcount/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/wordcount/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/wordcount/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/abbr.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/abbr.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/abbr.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/abbr.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/acronym.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/acronym.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/acronym.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/acronym.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/attributes.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/attributes.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/attributes.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/attributes.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/cite.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/cite.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/cite.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/cite.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/css/attributes.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/css/attributes.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/css/attributes.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/css/attributes.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/css/popup.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/css/popup.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/css/popup.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/css/popup.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/del.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/del.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/del.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/del.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/editor_plugin.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/editor_plugin.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/editor_plugin.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/editor_plugin_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/editor_plugin_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/editor_plugin_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/editor_plugin_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/ins.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/ins.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/ins.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/ins.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/abbr.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/abbr.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/abbr.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/abbr.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/acronym.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/acronym.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/acronym.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/acronym.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/attributes.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/attributes.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/attributes.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/attributes.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/cite.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/cite.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/cite.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/cite.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/del.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/del.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/del.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/del.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/element_common.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/element_common.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/element_common.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/element_common.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/ins.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/ins.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/js/ins.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/js/ins.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/plugins/xhtmlxtras/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/plugins/xhtmlxtras/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/about.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/about.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/about.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/about.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/anchor.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/anchor.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/anchor.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/anchor.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/charmap.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/charmap.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/charmap.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/charmap.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/color_picker.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/color_picker.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/color_picker.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/color_picker.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/editor_template.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/editor_template.js similarity index 76% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/editor_template.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/editor_template.js index 5e9deec8926..e7ae8ab0910 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/editor_template.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/editor_template.js @@ -1 +1 @@ -(function(h){var i=h.DOM,g=h.dom.Event,c=h.extend,f=h.each,a=h.util.Cookie,e,d=h.explode;function b(m,k){var q,p=m.dom,n="",o,l;previewStyles=m.settings.preview_styles;if(previewStyles===false){return""}if(!previewStyles){previewStyles="font-family font-size font-weight text-decoration text-transform color background-color"}function j(r){return r.replace(/%(\w+)/g,"")}name=k.block||k.inline||"span";q=p.create(name);f(k.styles,function(s,r){s=j(s);if(s){p.setStyle(q,r,s)}});f(k.attributes,function(s,r){s=j(s);if(s){p.setAttrib(q,r,s)}});f(k.classes,function(r){r=j(r);if(!p.hasClass(q,r)){p.addClass(q,r)}});p.setStyles(q,{position:"absolute",left:-65535});m.getBody().appendChild(q);o=p.getStyle(m.getBody(),"fontSize",true);o=/px$/.test(o)?parseInt(o,10):0;f(previewStyles.split(" "),function(r){var s=p.getStyle(q,r,true);if(r=="background-color"&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(s)){s=p.getStyle(m.getBody(),r,true);if(p.toHex(s).toLowerCase()=="#ffffff"){return}}if(r=="font-size"){if(/em|%$/.test(s)){if(o===0){return}s=parseFloat(s,10)/(/%$/.test(s)?100:1);s=(s*o)+"px"}}n+=r+":"+s+";"});p.remove(q);return n}h.ThemeManager.requireLangPack("advanced");h.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(k,l){var m=this,n,j,p;m.editor=k;m.url=l;m.onResolveName=new h.util.Dispatcher(this);k.forcedHighContrastMode=k.settings.detect_highcontrast&&m._isHighContrast();k.settings.skin=k.forcedHighContrastMode?"highcontrast":k.settings.skin;m.settings=n=c({theme_advanced_path:true,theme_advanced_toolbar_location:"bottom",theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:k.settings.readonly},k.settings);if(!n.font_size_style_values){n.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(h.is(n.theme_advanced_font_sizes,"string")){n.font_size_style_values=h.explode(n.font_size_style_values);n.font_size_classes=h.explode(n.font_size_classes||"");p={};k.settings.theme_advanced_font_sizes=n.theme_advanced_font_sizes;f(k.getParam("theme_advanced_font_sizes","","hash"),function(r,q){var o;if(q==r&&r>=1&&r<=7){q=r+" ("+m.sizes[r-1]+"pt)";o=n.font_size_classes[r-1];r=n.font_size_style_values[r-1]||(m.sizes[r-1]+"pt")}if(/^\s*\./.test(r)){o=r.replace(/\./g,"")}p[q]=o?{"class":o}:{fontSize:r}});n.theme_advanced_font_sizes=p}if((j=n.theme_advanced_path_location)&&j!="none"){n.theme_advanced_statusbar_location=n.theme_advanced_path_location}if(n.theme_advanced_statusbar_location=="none"){n.theme_advanced_statusbar_location=0}if(k.settings.content_css!==false){k.contentCSS.push(k.baseURI.toAbsolute(l+"/skins/"+k.settings.skin+"/content.css"))}k.onInit.add(function(){if(!k.settings.readonly){k.onNodeChange.add(m._nodeChanged,m);k.onKeyUp.add(m._updateUndoStatus,m);k.onMouseUp.add(m._updateUndoStatus,m);k.dom.bind(k.dom.getRoot(),"dragend",function(){m._updateUndoStatus(k)})}});k.onSetProgressState.add(function(r,o,s){var t,u=r.id,q;if(o){m.progressTimer=setTimeout(function(){t=r.getContainer();t=t.insertBefore(i.create("DIV",{style:"position:relative"}),t.firstChild);q=i.get(r.id+"_tbl");i.add(t,"div",{id:u+"_blocker","class":"mceBlocker",style:{width:q.clientWidth+2,height:q.clientHeight+2}});i.add(t,"div",{id:u+"_progress","class":"mceProgress",style:{left:q.clientWidth/2,top:q.clientHeight/2}})},s||0)}else{i.remove(u+"_blocker");i.remove(u+"_progress");clearTimeout(m.progressTimer)}});i.loadCSS(n.editor_css?k.documentBaseURI.toAbsolute(n.editor_css):l+"/skins/"+k.settings.skin+"/ui.css");if(n.skin_variant){i.loadCSS(l+"/skins/"+k.settings.skin+"/ui_"+n.skin_variant+".css")}},_isHighContrast:function(){var j,k=i.add(i.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});j=(i.getStyle(k,"background-color",true)+"").toLowerCase().replace(/ /g,"");i.remove(k);return j!="rgb(171,239,86)"&&j!="#abef56"},createControl:function(m,j){var k,l;if(l=j.createControl(m)){return l}switch(m){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((k=this.controls[m])){return j.createButton(m,{title:"advanced."+k[0],cmd:k[1],ui:k[2],value:k[3]})}},execCommand:function(l,k,m){var j=this["_"+l];if(j){j.call(this,k,m);return true}return false},_importClasses:function(l){var j=this.editor,k=j.controlManager.get("styleselect");if(k.getLength()==0){f(j.dom.getClasses(),function(q,m){var p="style_"+m,n;n={inline:"span",attributes:{"class":q["class"]},selector:"*"};j.formatter.register(p,n);k.add(q["class"],p,{style:function(){return b(j,n)}})})}},_createStyleSelect:function(o){var l=this,j=l.editor,k=j.controlManager,m;m=k.createListBox("styleselect",{title:"advanced.style_select",onselect:function(q){var r,n=[],p;f(m.items,function(s){n.push(s.value)});j.focus();j.undoManager.add();r=j.formatter.matchAll(n);h.each(r,function(s){if(!q||s==q){if(s){j.formatter.remove(s)}p=true}});if(!p){j.formatter.apply(q)}j.undoManager.add();j.nodeChanged();return false}});j.onPreInit.add(function(){var p=0,n=j.getParam("style_formats");if(n){f(n,function(q){var r,s=0;f(q,function(){s++});if(s>1){r=q.name=q.name||"style_"+(p++);j.formatter.register(r,q);m.add(q.title,r,{style:function(){return b(j,q)}})}else{m.add(q.title)}})}else{f(j.getParam("theme_advanced_styles","","hash"),function(t,s){var r,q;if(t){r="style_"+(p++);q={inline:"span",classes:t,selector:"*"};j.formatter.register(r,q);m.add(l.editor.translate(s),r,{style:function(){return b(j,q)}})}})}});if(m.getLength()==0){m.onPostRender.add(function(p,q){if(!m.NativeListBox){g.add(q.id+"_text","focus",l._importClasses,l);g.add(q.id+"_text","mousedown",l._importClasses,l);g.add(q.id+"_open","focus",l._importClasses,l);g.add(q.id+"_open","mousedown",l._importClasses,l)}else{g.add(q.id,"focus",l._importClasses,l)}})}return m},_createFontSelect:function(){var l,k=this,j=k.editor;l=j.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(m){var n=l.items[l.selectedIndex];if(!m&&n){j.execCommand("FontName",false,n.value);return}j.execCommand("FontName",false,m);l.select(function(o){return m==o});if(n&&n.value==m){l.select(null)}return false}});if(l){f(j.getParam("theme_advanced_fonts",k.settings.theme_advanced_fonts,"hash"),function(n,m){l.add(j.translate(m),n,{style:n.indexOf("dings")==-1?"font-family:"+n:""})})}return l},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(o){var p=n.items[n.selectedIndex];if(!o&&p){p=p.value;if(p["class"]){k.formatter.toggle("fontsize_class",{value:p["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,p.fontSize)}return}if(o["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}n.select(function(q){return o==q});if(p&&(p.value.fontSize==o.fontSize||p.value["class"]&&p.value["class"]==o["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(p,o){var q=p.fontSize;if(q>=1&&q<=7){q=m.sizes[parseInt(q)-1]+"pt"}n.add(o,p,{style:"font-size:"+q,"class":"mceFontSize"+(l++)+(" "+(p["class"]||""))})})}return n},_createBlockFormats:function(){var l,j={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},k=this;l=k.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(m){k.editor.execCommand("FormatBlock",false,m);return false}});if(l){f(k.editor.getParam("theme_advanced_blockformats",k.settings.theme_advanced_blockformats,"hash"),function(n,m){l.add(k.editor.translate(m!=n?m:j[n]),n,{"class":"mce_formatPreview mce_"+n,style:function(){return b(k.editor,{block:n})}})})}return l},_createForeColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_text_colors){m.colors=j}if(l.theme_advanced_default_foreground_color){m.default_color=l.theme_advanced_default_foreground_color}m.title="advanced.forecolor_desc";m.cmd="ForeColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("forecolor",m);return n},_createBackColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_background_colors){m.colors=j}if(l.theme_advanced_default_background_color){m.default_color=l.theme_advanced_default_background_color}m.title="advanced.backcolor_desc";m.cmd="HiliteColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("backcolor",m);return n},renderUI:function(l){var q,m,r,w=this,u=w.editor,x=w.settings,v,k,j;if(u.settings){u.settings.aria_label=x.aria_label+u.getLang("advanced.help_shortcut")}q=k=i.create("span",{role:"application","aria-labelledby":u.id+"_voice",id:u.id+"_parent","class":"mceEditor "+u.settings.skin+"Skin"+(x.skin_variant?" "+u.settings.skin+"Skin"+w._ufirst(x.skin_variant):"")+(u.settings.directionality=="rtl"?" mceRtl":"")});i.add(q,"span",{"class":"mceVoiceLabel",style:"display:none;",id:u.id+"_voice"},x.aria_label);if(!i.boxModel){q=i.add(q,"div",{"class":"mceOldBoxModel"})}q=v=i.add(q,"table",{role:"presentation",id:u.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});q=r=i.add(q,"tbody");switch((x.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":m=w._rowLayout(x,r,l);break;case"customlayout":m=u.execCallback("theme_advanced_custom_layout",x,r,l,k);break;default:m=w._simpleLayout(x,r,l,k)}q=l.targetNode;j=v.rows;i.addClass(j[0],"mceFirst");i.addClass(j[j.length-1],"mceLast");f(i.select("tr",r),function(o){i.addClass(o.firstChild,"mceFirst");i.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(i.get(x.theme_advanced_toolbar_container)){i.get(x.theme_advanced_toolbar_container).appendChild(k)}else{i.insertAfter(k,q)}g.add(u.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){w._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return false}});if(!u.getParam("accessibility_focus")){g.add(i.add(k,"a",{href:"#"},""),"focus",function(){tinyMCE.get(u.id).focus()})}if(x.theme_advanced_toolbar_location=="external"){l.deltaHeight=0}w.deltaHeight=l.deltaHeight;l.targetNode=null;u.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){if(h.isWebKit){window.focus()}w.toolbarGroup.focus();return g.cancel(n)}else{if(n.keyCode===o){i.get(p.id+"_path_row").focus();return g.cancel(n)}}}});u.addShortcut("alt+0","","mceShortcuts",w);return{iframeContainer:m,editorContainer:u.id+"_parent",sizeContainer:v,deltaHeight:l.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:h.majorVersion+"."+h.minorVersion}},resizeBy:function(j,k){var l=i.get(this.editor.id+"_ifr");this.resizeTo(l.clientWidth+j,l.clientHeight+k)},resizeTo:function(j,n,l){var k=this.editor,m=this.settings,o=i.get(k.id+"_tbl"),p=i.get(k.id+"_ifr");j=Math.max(m.theme_advanced_resizing_min_width||100,j);n=Math.max(m.theme_advanced_resizing_min_height||100,n);j=Math.min(m.theme_advanced_resizing_max_width||65535,j);n=Math.min(m.theme_advanced_resizing_max_height||65535,n);i.setStyle(o,"height","");i.setStyle(p,"height",n);if(m.theme_advanced_resize_horizontal){i.setStyle(o,"width","");i.setStyle(p,"width",j);if(j"));i.setHTML(l,r.join(""))},_addStatusBar:function(p,k){var l,w=this,q=w.editor,x=w.settings,j,u,v,m;l=i.add(p,"tr");l=m=i.add(l,"td",{"class":"mceStatusbar"});l=i.add(l,"div",{id:q.id+"_path_row",role:"group","aria-labelledby":q.id+"_path_voice"});if(x.theme_advanced_path){i.add(l,"span",{id:q.id+"_path_voice"},q.translate("advanced.path"));i.add(l,"span",{},": ")}else{i.add(l,"span",{}," ")}if(x.theme_advanced_resizing){i.add(m,"a",{id:q.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(x.theme_advanced_resizing_use_cookie){q.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+q.id+"_size"),r=i.get(q.id+"_tbl");if(!n){return}w.resizeTo(n.cw,n.ch)})}q.onPostRender.add(function(){g.add(q.id+"_resize","click",function(n){n.preventDefault()});g.add(q.id+"_resize","mousedown",function(E){var t,r,s,o,D,A,B,G,n,F,y;function z(H){H.preventDefault();n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F)}function C(H){g.remove(i.doc,"mousemove",t);g.remove(q.getDoc(),"mousemove",r);g.remove(i.doc,"mouseup",s);g.remove(q.getDoc(),"mouseup",o);n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F,true)}E.preventDefault();D=E.screenX;A=E.screenY;y=i.get(w.editor.id+"_ifr");B=n=y.clientWidth;G=F=y.clientHeight;t=g.add(i.doc,"mousemove",z);r=g.add(q.getDoc(),"mousemove",z);s=g.add(i.doc,"mouseup",C);o=g.add(q.getDoc(),"mouseup",C)})})}k.deltaHeight-=21;l=p=null},_updateUndoStatus:function(k){var j=k.controlManager,l=k.undoManager;j.setDisabled("undo",!l.hasUndo()&&!l.typing);j.setDisabled("redo",!l.hasRedo())},_nodeChanged:function(o,u,E,r,F){var z=this,D,G=0,y,H,A=z.settings,x,l,w,C,m,k,j;h.each(z.stateControls,function(n){u.setActive(n,o.queryCommandState(z.controls[n][1]))});function q(p){var s,n=F.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s0){H.mark(p)}})}if(H=u.get("formatselect")){D=q(o.dom.isBlock);if(D){H.select(D.nodeName.toLowerCase())}}q(function(p){if(p.nodeName==="SPAN"){if(!x&&p.className){x=p.className}}if(o.dom.is(p,A.theme_advanced_font_selector)){if(!l&&p.style.fontSize){l=p.style.fontSize}if(!w&&p.style.fontFamily){w=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!C&&p.style.color){C=p.style.color}if(!m&&p.style.backgroundColor){m=p.style.backgroundColor}}return false});if(H=u.get("fontselect")){H.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==w})}if(H=u.get("fontsizeselect")){if(A.theme_advanced_runtime_fontsize&&!l&&!x){l=o.dom.getStyle(E,"fontSize",true)}H.select(function(n){if(n.fontSize&&n.fontSize===l){return true}if(n["class"]&&n["class"]===x){return true}})}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_path&&A.theme_advanced_statusbar_location){D=i.get(o.id+"_path")||i.add(o.id+"_path_row","span",{id:o.id+"_path"});if(z.statusKeyboardNavigation){z.statusKeyboardNavigation.destroy();z.statusKeyboardNavigation=null}i.setHTML(D,"");q(function(I){var p=I.nodeName.toLowerCase(),s,v,t="";if(I.nodeType!=1||p==="br"||I.getAttribute("data-mce-bogus")||i.hasClass(I,"mceItemHidden")||i.hasClass(I,"mceItemRemoved")){return}if(h.isIE&&I.scopeName!=="HTML"&&I.scopeName){p=I.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(y=i.getAttrib(I,"src")){t+="src: "+y+" "}break;case"a":if(y=i.getAttrib(I,"name")){t+="name: "+y+" ";p+="#"+y}if(y=i.getAttrib(I,"href")){t+="href: "+y+" "}break;case"font":if(y=i.getAttrib(I,"face")){t+="font: "+y+" "}if(y=i.getAttrib(I,"size")){t+="size: "+y+" "}if(y=i.getAttrib(I,"color")){t+="color: "+y+" "}break;case"span":if(y=i.getAttrib(I,"style")){t+="style: "+y+" "}break}if(y=i.getAttrib(I,"id")){t+="id: "+y+" "}if(y=I.className){y=y.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(y){t+="class: "+y+" ";if(o.dom.isBlock(I)||p=="img"||p=="span"){p+="."+y}}}p=p.replace(/(html:)/g,"");p={name:p,node:I,title:t};z.onResolveName.dispatch(z,p);t=p.title;p=p.name;v=i.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(G++)},p);if(D.hasChildNodes()){D.insertBefore(i.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),D.firstChild);D.insertBefore(v,D.firstChild)}else{D.appendChild(v)}},o.getBody());if(i.select("a",D).length>0){z.statusKeyboardNavigation=new h.ui.KeyboardNavigation({root:o.id+"_path_row",items:i.select("a",D),excludeFromTabOrder:true,onCancel:function(){o.focus()}},i)}}},_sel:function(j){this.editor.execCommand("mceSelectNodeDepth",false,j)},_mceInsertAnchor:function(l,k){var j=this.editor;j.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(j.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(j.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var j=this.editor;j.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(j.getLang("advanced.charmap_delta_width",0)),height:265+parseInt(j.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var j=this.editor;j.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var j=this.editor;j.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(l,k){var j=this.editor;k=k||{};j.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(j.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(j.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:k.color,func:k.func,theme_url:this.url})},_mceCodeEditor:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(j.getParam("theme_advanced_source_editor_width",720)),height:parseInt(j.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(k,l){var j=this.editor;if(j.dom.getAttrib(j.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}j.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(j.getLang("advanced.image_delta_width",0)),height:275+parseInt(j.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(j.getLang("advanced.link_delta_width",0)),height:200+parseInt(j.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var j=this.editor;j.windowManager.confirm("advanced.newdocument",function(k){if(k){j.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var j=this;this._mceColorPicker(0,{color:j.fgColor,func:function(k){j.fgColor=k;j.editor.execCommand("ForeColor",false,k)}})},_mceBackColor:function(){var j=this;this._mceColorPicker(0,{color:j.bgColor,func:function(k){j.bgColor=k;j.editor.execCommand("HiliteColor",false,k)}})},_ufirst:function(j){return j.substring(0,1).toUpperCase()+j.substring(1)}});h.ThemeManager.add("advanced",h.themes.AdvancedTheme)}(tinymce)); \ No newline at end of file +(function(h){var i=h.DOM,g=h.dom.Event,c=h.extend,f=h.each,a=h.util.Cookie,e,d=h.explode;function b(m,k){var q,p=m.dom,n="",o,l;previewStyles=m.settings.preview_styles;if(previewStyles===false){return""}if(!previewStyles){previewStyles="font-family font-size font-weight text-decoration text-transform color background-color"}function j(r){return r.replace(/%(\w+)/g,"")}name=k.block||k.inline||"span";q=p.create(name);f(k.styles,function(s,r){s=j(s);if(s){p.setStyle(q,r,s)}});f(k.attributes,function(s,r){s=j(s);if(s){p.setAttrib(q,r,s)}});f(k.classes,function(r){r=j(r);if(!p.hasClass(q,r)){p.addClass(q,r)}});p.setStyles(q,{position:"absolute",left:-65535});m.getBody().appendChild(q);o=p.getStyle(m.getBody(),"fontSize",true);o=/px$/.test(o)?parseInt(o,10):0;f(previewStyles.split(" "),function(r){var s=p.getStyle(q,r,true);if(r=="background-color"&&/transparent|rgba\s*\([^)]+,\s*0\)/.test(s)){s=p.getStyle(m.getBody(),r,true);if(p.toHex(s).toLowerCase()=="#ffffff"){return}}if(r=="font-size"){if(/em|%$/.test(s)){if(o===0){return}s=parseFloat(s,10)/(/%$/.test(s)?100:1);s=(s*o)+"px"}}n+=r+":"+s+";"});p.remove(q);return n}h.ThemeManager.requireLangPack("advanced");h.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(k,l){var m=this,n,j,p;m.editor=k;m.url=l;m.onResolveName=new h.util.Dispatcher(this);k.forcedHighContrastMode=k.settings.detect_highcontrast&&m._isHighContrast();k.settings.skin=k.forcedHighContrastMode?"highcontrast":k.settings.skin;m.settings=n=c({theme_advanced_path:true,theme_advanced_toolbar_location:"bottom",theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:k.settings.readonly},k.settings);if(!n.font_size_style_values){n.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(h.is(n.theme_advanced_font_sizes,"string")){n.font_size_style_values=h.explode(n.font_size_style_values);n.font_size_classes=h.explode(n.font_size_classes||"");p={};k.settings.theme_advanced_font_sizes=n.theme_advanced_font_sizes;f(k.getParam("theme_advanced_font_sizes","","hash"),function(r,q){var o;if(q==r&&r>=1&&r<=7){q=r+" ("+m.sizes[r-1]+"pt)";o=n.font_size_classes[r-1];r=n.font_size_style_values[r-1]||(m.sizes[r-1]+"pt")}if(/^\s*\./.test(r)){o=r.replace(/\./g,"")}p[q]=o?{"class":o}:{fontSize:r}});n.theme_advanced_font_sizes=p}if((j=n.theme_advanced_path_location)&&j!="none"){n.theme_advanced_statusbar_location=n.theme_advanced_path_location}if(n.theme_advanced_statusbar_location=="none"){n.theme_advanced_statusbar_location=0}if(k.settings.content_css!==false){k.contentCSS.push(k.baseURI.toAbsolute(l+"/skins/"+k.settings.skin+"/content.css"))}k.onInit.add(function(){if(!k.settings.readonly){k.onNodeChange.add(m._nodeChanged,m);k.onKeyUp.add(m._updateUndoStatus,m);k.onMouseUp.add(m._updateUndoStatus,m);k.dom.bind(k.dom.getRoot(),"dragend",function(){m._updateUndoStatus(k)})}});k.onSetProgressState.add(function(r,o,s){var t,u=r.id,q;if(o){m.progressTimer=setTimeout(function(){t=r.getContainer();t=t.insertBefore(i.create("DIV",{style:"position:relative"}),t.firstChild);q=i.get(r.id+"_tbl");i.add(t,"div",{id:u+"_blocker","class":"mceBlocker",style:{width:q.clientWidth+2,height:q.clientHeight+2}});i.add(t,"div",{id:u+"_progress","class":"mceProgress",style:{left:q.clientWidth/2,top:q.clientHeight/2}})},s||0)}else{i.remove(u+"_blocker");i.remove(u+"_progress");clearTimeout(m.progressTimer)}});i.loadCSS(n.editor_css?k.documentBaseURI.toAbsolute(n.editor_css):l+"/skins/"+k.settings.skin+"/ui.css");if(n.skin_variant){i.loadCSS(l+"/skins/"+k.settings.skin+"/ui_"+n.skin_variant+".css")}},_isHighContrast:function(){var j,k=i.add(i.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});j=(i.getStyle(k,"background-color",true)+"").toLowerCase().replace(/ /g,"");i.remove(k);return j!="rgb(171,239,86)"&&j!="#abef56"},createControl:function(m,j){var k,l;if(l=j.createControl(m)){return l}switch(m){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((k=this.controls[m])){return j.createButton(m,{title:"advanced."+k[0],cmd:k[1],ui:k[2],value:k[3]})}},execCommand:function(l,k,m){var j=this["_"+l];if(j){j.call(this,k,m);return true}return false},_importClasses:function(l){var j=this.editor,k=j.controlManager.get("styleselect");if(k.getLength()==0){f(j.dom.getClasses(),function(q,m){var p="style_"+m,n;n={inline:"span",attributes:{"class":q["class"]},selector:"*"};j.formatter.register(p,n);k.add(q["class"],p,{style:function(){return b(j,n)}})})}},_createStyleSelect:function(o){var l=this,j=l.editor,k=j.controlManager,m;m=k.createListBox("styleselect",{title:"advanced.style_select",onselect:function(q){var r,n=[],p;f(m.items,function(s){n.push(s.value)});j.focus();j.undoManager.add();r=j.formatter.matchAll(n);h.each(r,function(s){if(!q||s==q){if(s){j.formatter.remove(s)}p=true}});if(!p){j.formatter.apply(q)}j.undoManager.add();j.nodeChanged();return false}});j.onPreInit.add(function(){var p=0,n=j.getParam("style_formats");if(n){f(n,function(q){var r,s=0;f(q,function(){s++});if(s>1){r=q.name=q.name||"style_"+(p++);j.formatter.register(r,q);m.add(q.title,r,{style:function(){return b(j,q)}})}else{m.add(q.title)}})}else{f(j.getParam("theme_advanced_styles","","hash"),function(t,s){var r,q;if(t){r="style_"+(p++);q={inline:"span",classes:t,selector:"*"};j.formatter.register(r,q);m.add(l.editor.translate(s),r,{style:function(){return b(j,q)}})}})}});if(m.getLength()==0){m.onPostRender.add(function(p,q){if(!m.NativeListBox){g.add(q.id+"_text","focus",l._importClasses,l);g.add(q.id+"_text","mousedown",l._importClasses,l);g.add(q.id+"_open","focus",l._importClasses,l);g.add(q.id+"_open","mousedown",l._importClasses,l)}else{g.add(q.id,"focus",l._importClasses,l)}})}return m},_createFontSelect:function(){var l,k=this,j=k.editor;l=j.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(m){var n=l.items[l.selectedIndex];if(!m&&n){j.execCommand("FontName",false,n.value);return}j.execCommand("FontName",false,m);l.select(function(o){return m==o});if(n&&n.value==m){l.select(null)}return false}});if(l){f(j.getParam("theme_advanced_fonts",k.settings.theme_advanced_fonts,"hash"),function(n,m){l.add(j.translate(m),n,{style:n.indexOf("dings")==-1?"font-family:"+n:""})})}return l},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(o){var p=n.items[n.selectedIndex];if(!o&&p){p=p.value;if(p["class"]){k.formatter.toggle("fontsize_class",{value:p["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,p.fontSize)}return}if(o["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}n.select(function(q){return o==q});if(p&&(p.value.fontSize==o.fontSize||p.value["class"]&&p.value["class"]==o["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(p,o){var q=p.fontSize;if(q>=1&&q<=7){q=m.sizes[parseInt(q)-1]+"pt"}n.add(o,p,{style:"font-size:"+q,"class":"mceFontSize"+(l++)+(" "+(p["class"]||""))})})}return n},_createBlockFormats:function(){var l,j={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},k=this;l=k.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(m){k.editor.execCommand("FormatBlock",false,m);return false}});if(l){f(k.editor.getParam("theme_advanced_blockformats",k.settings.theme_advanced_blockformats,"hash"),function(n,m){l.add(k.editor.translate(m!=n?m:j[n]),n,{"class":"mce_formatPreview mce_"+n,style:function(){return b(k.editor,{block:n})}})})}return l},_createForeColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_text_colors){m.colors=j}if(l.theme_advanced_default_foreground_color){m.default_color=l.theme_advanced_default_foreground_color}m.title="advanced.forecolor_desc";m.cmd="ForeColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("forecolor",m);return n},_createBackColorMenu:function(){var n,k=this,l=k.settings,m={},j;if(l.theme_advanced_more_colors){m.more_colors_func=function(){k._mceColorPicker(0,{color:n.value,func:function(o){n.setColor(o)}})}}if(j=l.theme_advanced_background_colors){m.colors=j}if(l.theme_advanced_default_background_color){m.default_color=l.theme_advanced_default_background_color}m.title="advanced.backcolor_desc";m.cmd="HiliteColor";m.scope=this;n=k.editor.controlManager.createColorSplitButton("backcolor",m);return n},renderUI:function(l){var q,m,r,w=this,u=w.editor,x=w.settings,v,k,j;if(u.settings){u.settings.aria_label=x.aria_label+u.getLang("advanced.help_shortcut")}q=k=i.create("span",{role:"application","aria-labelledby":u.id+"_voice",id:u.id+"_parent","class":"mceEditor "+u.settings.skin+"Skin"+(x.skin_variant?" "+u.settings.skin+"Skin"+w._ufirst(x.skin_variant):"")+(u.settings.directionality=="rtl"?" mceRtl":"")});i.add(q,"span",{"class":"mceVoiceLabel",style:"display:none;",id:u.id+"_voice"},x.aria_label);if(!i.boxModel){q=i.add(q,"div",{"class":"mceOldBoxModel"})}q=v=i.add(q,"table",{role:"presentation",id:u.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});q=r=i.add(q,"tbody");switch((x.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":m=w._rowLayout(x,r,l);break;case"customlayout":m=u.execCallback("theme_advanced_custom_layout",x,r,l,k);break;default:m=w._simpleLayout(x,r,l,k)}q=l.targetNode;j=v.rows;i.addClass(j[0],"mceFirst");i.addClass(j[j.length-1],"mceLast");f(i.select("tr",r),function(o){i.addClass(o.firstChild,"mceFirst");i.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(i.get(x.theme_advanced_toolbar_container)){i.get(x.theme_advanced_toolbar_container).appendChild(k)}else{i.insertAfter(k,q)}g.add(u.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){w._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return false}});if(!u.getParam("accessibility_focus")){g.add(i.add(k,"a",{href:"#"},""),"focus",function(){tinyMCE.get(u.id).focus()})}if(x.theme_advanced_toolbar_location=="external"){l.deltaHeight=0}w.deltaHeight=l.deltaHeight;l.targetNode=null;u.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){if(h.isWebKit){window.focus()}w.toolbarGroup.focus();return g.cancel(n)}else{if(n.keyCode===o){i.get(p.id+"_path_row").focus();return g.cancel(n)}}}});u.addShortcut("alt+0","","mceShortcuts",w);return{iframeContainer:m,editorContainer:u.id+"_parent",sizeContainer:v,deltaHeight:l.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:h.majorVersion+"."+h.minorVersion}},resizeBy:function(j,k){var l=i.get(this.editor.id+"_ifr");this.resizeTo(l.clientWidth+j,l.clientHeight+k)},resizeTo:function(j,n,l){var k=this.editor,m=this.settings,o=i.get(k.id+"_tbl"),p=i.get(k.id+"_ifr");j=Math.max(m.theme_advanced_resizing_min_width||100,j);n=Math.max(m.theme_advanced_resizing_min_height||100,n);j=Math.min(m.theme_advanced_resizing_max_width||65535,j);n=Math.min(m.theme_advanced_resizing_max_height||65535,n);i.setStyle(o,"height","");i.setStyle(p,"height",n);if(m.theme_advanced_resize_horizontal){i.setStyle(o,"width","");i.setStyle(p,"width",j);if(j"));i.setHTML(l,r.join(""))},_addStatusBar:function(p,k){var l,w=this,q=w.editor,x=w.settings,j,u,v,m;l=i.add(p,"tr");l=m=i.add(l,"td",{"class":"mceStatusbar"});l=i.add(l,"div",{id:q.id+"_path_row",role:"group","aria-labelledby":q.id+"_path_voice"});if(x.theme_advanced_path){i.add(l,"span",{id:q.id+"_path_voice"},q.translate("advanced.path"));i.add(l,"span",{},": ")}else{i.add(l,"span",{}," ")}if(x.theme_advanced_resizing){i.add(m,"a",{id:q.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(x.theme_advanced_resizing_use_cookie){q.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+q.id+"_size"),r=i.get(q.id+"_tbl");if(!n){return}w.resizeTo(n.cw,n.ch)})}q.onPostRender.add(function(){g.add(q.id+"_resize","click",function(n){n.preventDefault()});g.add(q.id+"_resize","mousedown",function(E){var t,r,s,o,D,A,B,G,n,F,y;function z(H){H.preventDefault();n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F)}function C(H){g.remove(i.doc,"mousemove",t);g.remove(q.getDoc(),"mousemove",r);g.remove(i.doc,"mouseup",s);g.remove(q.getDoc(),"mouseup",o);n=B+(H.screenX-D);F=G+(H.screenY-A);w.resizeTo(n,F,true)}E.preventDefault();D=E.screenX;A=E.screenY;y=i.get(w.editor.id+"_ifr");B=n=y.clientWidth;G=F=y.clientHeight;t=g.add(i.doc,"mousemove",z);r=g.add(q.getDoc(),"mousemove",z);s=g.add(i.doc,"mouseup",C);o=g.add(q.getDoc(),"mouseup",C)})})}k.deltaHeight-=21;l=p=null},_updateUndoStatus:function(k){var j=k.controlManager,l=k.undoManager;j.setDisabled("undo",!l.hasUndo()&&!l.typing);j.setDisabled("redo",!l.hasRedo())},_nodeChanged:function(o,u,E,r,F){var z=this,D,G=0,y,H,A=z.settings,x,l,w,C,m,k,j;h.each(z.stateControls,function(n){u.setActive(n,o.queryCommandState(z.controls[n][1]))});function q(p){var s,n=F.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s0){H.mark(p)}})}if(H=u.get("formatselect")){D=q(o.dom.isBlock);if(D){H.select(D.nodeName.toLowerCase())}}q(function(p){if(p.nodeName==="SPAN"){if(!x&&p.className){x=p.className}}if(o.dom.is(p,A.theme_advanced_font_selector)){if(!l&&p.style.fontSize){l=p.style.fontSize}if(!w&&p.style.fontFamily){w=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!C&&p.style.color){C=p.style.color}if(!m&&p.style.backgroundColor){m=p.style.backgroundColor}}return false});if(H=u.get("fontselect")){H.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==w})}if(H=u.get("fontsizeselect")){if(A.theme_advanced_runtime_fontsize&&!l&&!x){l=o.dom.getStyle(E,"fontSize",true)}H.select(function(n){if(n.fontSize&&n.fontSize===l){return true}if(n["class"]&&n["class"]===x){return true}})}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_show_current_color){function B(p,n){if(H=u.get(p)){if(!n){n=H.settings.default_color}if(n!==H.value){H.displayColor(n)}}}B("forecolor",C);B("backcolor",m)}if(A.theme_advanced_path&&A.theme_advanced_statusbar_location){D=i.get(o.id+"_path")||i.add(o.id+"_path_row","span",{id:o.id+"_path"});if(z.statusKeyboardNavigation){z.statusKeyboardNavigation.destroy();z.statusKeyboardNavigation=null}i.setHTML(D,"");q(function(I){var p=I.nodeName.toLowerCase(),s,v,t="";if(I.nodeType!=1||p==="br"||I.getAttribute("data-mce-bogus")||i.hasClass(I,"mceItemHidden")||i.hasClass(I,"mceItemRemoved")){return}if(h.isIE&&I.scopeName!=="HTML"&&I.scopeName){p=I.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(y=i.getAttrib(I,"src")){t+="src: "+y+" "}break;case"a":if(y=i.getAttrib(I,"name")){t+="name: "+y+" ";p+="#"+y}if(y=i.getAttrib(I,"href")){t+="href: "+y+" "}break;case"font":if(y=i.getAttrib(I,"face")){t+="font: "+y+" "}if(y=i.getAttrib(I,"size")){t+="size: "+y+" "}if(y=i.getAttrib(I,"color")){t+="color: "+y+" "}break;case"span":if(y=i.getAttrib(I,"style")){t+="style: "+y+" "}break}if(y=i.getAttrib(I,"id")){t+="id: "+y+" "}if(y=I.className){y=y.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(y){t+="class: "+y+" ";if(o.dom.isBlock(I)||p=="img"||p=="span"){p+="."+y}}}p=p.replace(/(html:)/g,"");p={name:p,node:I,title:t};z.onResolveName.dispatch(z,p);t=p.title;p=p.name;v=i.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(G++)},p);if(D.hasChildNodes()){D.insertBefore(i.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),D.firstChild);D.insertBefore(v,D.firstChild)}else{D.appendChild(v)}},o.getBody());if(i.select("a",D).length>0){z.statusKeyboardNavigation=new h.ui.KeyboardNavigation({root:o.id+"_path_row",items:i.select("a",D),excludeFromTabOrder:true,onCancel:function(){o.focus()}},i)}}},_sel:function(j){this.editor.execCommand("mceSelectNodeDepth",false,j)},_mceInsertAnchor:function(l,k){var j=this.editor;j.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(j.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(j.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var j=this.editor;j.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(j.getLang("advanced.charmap_delta_width",0)),height:265+parseInt(j.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var j=this.editor;j.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var j=this.editor;j.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(l,k){var j=this.editor;k=k||{};j.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(j.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(j.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:k.color,func:k.func,theme_url:this.url})},_mceCodeEditor:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(j.getParam("theme_advanced_source_editor_width",720)),height:parseInt(j.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(k,l){var j=this.editor;if(j.dom.getAttrib(j.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}j.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(j.getLang("advanced.image_delta_width",0)),height:275+parseInt(j.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(k,l){var j=this.editor;j.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(j.getLang("advanced.link_delta_width",0)),height:200+parseInt(j.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var j=this.editor;j.windowManager.confirm("advanced.newdocument",function(k){if(k){j.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var j=this;this._mceColorPicker(0,{color:j.fgColor,func:function(k){j.fgColor=k;j.editor.execCommand("ForeColor",false,k)}})},_mceBackColor:function(){var j=this;this._mceColorPicker(0,{color:j.bgColor,func:function(k){j.bgColor=k;j.editor.execCommand("HiliteColor",false,k)}})},_ufirst:function(j){return j.substring(0,1).toUpperCase()+j.substring(1)}});h.ThemeManager.add("advanced",h.themes.AdvancedTheme)}(tinymce)); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/editor_template_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/editor_template_src.js similarity index 96% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/editor_template_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/editor_template_src.js index 61fe537074e..607e820a56f 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/editor_template_src.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/editor_template_src.js @@ -1089,19 +1089,17 @@ p = getParent('A'); if (c = cm.get('link')) { - if (!p || !p.name) { - c.setDisabled(!p && co); - c.setActive(!!p); - } + c.setDisabled((!p && co) || (p && !p.href)); + c.setActive(!!p && (!p.name && !p.id)); } if (c = cm.get('unlink')) { c.setDisabled(!p && co); - c.setActive(!!p && !p.name); + c.setActive(!!p && !p.name && !p.id); } if (c = cm.get('anchor')) { - c.setActive(!co && !!p && p.name); + c.setActive(!co && !!p && (p.name || (p.id && !p.href))); } p = getParent('IMG'); diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/image.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/image.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/image.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/image.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/colorpicker.jpg b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/colorpicker.jpg similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/colorpicker.jpg rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/colorpicker.jpg diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/flash.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/flash.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/flash.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/flash.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/icons.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/icons.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/icons.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/icons.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/iframe.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/iframe.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/iframe.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/iframe.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/pagebreak.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/pagebreak.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/pagebreak.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/pagebreak.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/quicktime.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/quicktime.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/quicktime.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/quicktime.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/realmedia.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/realmedia.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/realmedia.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/realmedia.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/shockwave.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/shockwave.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/shockwave.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/shockwave.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/trans.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/trans.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/trans.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/trans.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/video.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/video.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/video.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/video.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/windowsmedia.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/windowsmedia.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/img/windowsmedia.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/img/windowsmedia.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/about.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/about.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/about.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/about.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/anchor.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/anchor.js similarity index 68% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/anchor.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/anchor.js index 2940db3591f..778d3226679 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/anchor.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/anchor.js @@ -6,7 +6,7 @@ var AnchorDialog = { this.editor = ed; elm = ed.dom.getParent(ed.selection.getNode(), 'A'); - v = ed.dom.getAttrib(elm, 'name'); + v = ed.dom.getAttrib(elm, 'name') || ed.dom.getAttrib(elm, 'id'); if (v) { this.action = 'update'; @@ -17,7 +17,7 @@ var AnchorDialog = { }, update : function() { - var ed = this.editor, elm, name = document.forms[0].anchorName.value; + var ed = this.editor, elm, name = document.forms[0].anchorName.value, attribName; if (!name || !/^[a-z][a-z0-9\-\_:\.]*$/i.test(name)) { tinyMCEPopup.alert('advanced_dlg.anchor_invalid'); @@ -29,13 +29,23 @@ var AnchorDialog = { if (this.action != 'update') ed.selection.collapse(1); + var aRule = ed.schema.getElementRule('a'); + if (!aRule || aRule.attributes.name) { + attribName = 'name'; + } else { + attribName = 'id'; + } + elm = ed.dom.getParent(ed.selection.getNode(), 'A'); if (elm) { - elm.setAttribute('name', name); - elm.name = name; - } else + elm.setAttribute(attribName, name); + elm[attribName] = name; + } else { // create with zero-sized nbsp so that in Webkit where anchor is on last line by itself caret cannot be placed after it - ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', {name : name, 'class' : 'mceItemAnchor'}, '\uFEFF')); + var attrs = {'class' : 'mceItemAnchor'}; + attrs[attribName] = name; + ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', attrs, '\uFEFF')); + } tinyMCEPopup.close(); } diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/charmap.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/charmap.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/charmap.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/charmap.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/color_picker.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/color_picker.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/color_picker.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/color_picker.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/image.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/image.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/image.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/image.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/link.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/link.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/link.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/link.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/source_editor.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/source_editor.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/js/source_editor.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/js/source_editor.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/langs/en.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/langs/en.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/langs/en.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/langs/en.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/langs/en_dlg.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/langs/en_dlg.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/langs/en_dlg.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/langs/en_dlg.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/link.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/link.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/link.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/link.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/shortcuts.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/shortcuts.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/shortcuts.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/shortcuts.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/content.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/content.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/content.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/content.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/dialog.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/dialog.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/dialog.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/dialog.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/buttons.png b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/buttons.png similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/buttons.png rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/buttons.png diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/items.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/items.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/items.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/items.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/menu_arrow.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/menu_arrow.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/menu_arrow.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/menu_arrow.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/menu_check.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/menu_check.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/menu_check.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/menu_check.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/progress.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/progress.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/progress.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/progress.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/tabs.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/tabs.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/img/tabs.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/img/tabs.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/ui.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/ui.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/default/ui.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/default/ui.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/highcontrast/content.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/highcontrast/content.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/highcontrast/content.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/highcontrast/content.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/highcontrast/dialog.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/highcontrast/dialog.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/highcontrast/dialog.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/highcontrast/dialog.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/highcontrast/ui.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/highcontrast/ui.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/highcontrast/ui.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/highcontrast/ui.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/content.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/content.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/content.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/content.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/dialog.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/dialog.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/dialog.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/dialog.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/img/button_bg.png b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/img/button_bg.png similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/img/button_bg.png rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/img/button_bg.png diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/img/button_bg_black.png b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/img/button_bg_black.png similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/img/button_bg_black.png rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/img/button_bg_black.png diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/img/button_bg_silver.png b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/img/button_bg_silver.png similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/img/button_bg_silver.png rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/img/button_bg_silver.png diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/ui.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/ui.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/ui.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/ui.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/ui_black.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/ui_black.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/ui_black.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/ui_black.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/ui_silver.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/ui_silver.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/skins/o2k7/ui_silver.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/skins/o2k7/ui_silver.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/advanced/source_editor.htm b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/source_editor.htm similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/advanced/source_editor.htm rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/advanced/source_editor.htm diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/editor_template.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/editor_template.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/editor_template.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/editor_template.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/editor_template_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/editor_template_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/editor_template_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/editor_template_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/img/icons.gif b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/img/icons.gif similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/img/icons.gif rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/img/icons.gif diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/langs/en.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/langs/en.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/langs/en.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/langs/en.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/default/content.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/default/content.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/default/content.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/default/content.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/default/ui.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/default/ui.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/default/ui.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/default/ui.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/o2k7/content.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/o2k7/content.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/o2k7/content.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/o2k7/content.css diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/o2k7/img/button_bg.png b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/o2k7/img/button_bg.png similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/o2k7/img/button_bg.png rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/o2k7/img/button_bg.png diff --git a/lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/o2k7/ui.css b/lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/o2k7/ui.css similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/themes/simple/skins/o2k7/ui.css rename to lib/editor/tinymce/tiny_mce/3.5.1.1/themes/simple/skins/o2k7/ui.css diff --git a/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce.js new file mode 100644 index 00000000000..173a2e488b6 --- /dev/null +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce.js @@ -0,0 +1 @@ +(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"@@tinymce_major_version@@",minorVersion:"@@tinymce_minor_version@@",releaseDate:"@@tinymce_release_date@@",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey}}})(tinymce);tinymce.util.Quirks=function(d){var l=tinymce.VK,r=l.BACKSPACE,s=l.DELETE,o=d.dom,A=d.selection,q=d.settings;function c(E,D){try{d.getDoc().execCommand(E,false,D)}catch(C){}}function h(){function C(F){var D,H,E,G;D=A.getRng();H=o.getParent(D.startContainer,o.isBlock);if(F){H=o.getNext(H,o.isBlock)}if(H){E=H.firstChild;while(E&&E.nodeType==3&&E.nodeValue.length===0){E=E.nextSibling}if(E&&E.nodeName==="SPAN"){G=E.cloneNode(false)}}d.getDoc().execCommand(F?"ForwardDelete":"Delete",false,null);H=o.getParent(D.startContainer,o.isBlock);tinymce.each(o.select("span.Apple-style-span,font.Apple-style-span",H),function(I){var J=A.getBookmark();if(G){o.replace(G.cloneNode(false),I,true)}else{o.remove(I,true)}A.moveToBookmark(J)})}d.onKeyDown.add(function(D,F){var E;E=F.keyCode==s;if(!F.isDefaultPrevented()&&(E||F.keyCode==r)&&!l.modifierPressed(F)){F.preventDefault();C(E)}});d.addCommand("Delete",function(){C()})}function B(){function D(F,I){var E,H,G=I?"start":"end";E=F[G+"Container"];H=F[G+"Offset"];if(E.nodeType==1&&E.hasChildNodes()){E=E.childNodes[Math.min(I?H:(H>0?H-1:0),E.childNodes.length-1)]}return E}function C(H,L){var G,K,F,I,J=L?"start":"end",E;G=H[J+"Container"];K=H[J+"Offset"];F=o.getRoot();if(G.nodeType==1){E=K>=G.childNodes.length;G=D(H,L);if(G.nodeType==3){K=L&&!E?0:G.nodeValue.length}}if(G.nodeType==3&&((L&&K>0)||(!L&&K7){return}c("RespectVisibilityInDesign",true);o.addClass(d.getBody(),"mceHideBrInPre");d.parser.addNodeFilter("pre",function(D,F){var G=D.length,I,E,J,H;while(G--){I=D[G].getAll("br");E=I.length;while(E--){J=I[E];H=J.prev;if(H&&H.type===3&&H.value.charAt(H.value-1)!="\n"){H.value+="\n"}else{J.parent.insert(new tinymce.html.Node("#text",3),J,true).value="\n"}}}});d.serializer.addNodeFilter("pre",function(D,F){var G=D.length,I,E,J,H;while(G--){I=D[G].getAll("br");E=I.length;while(E--){J=I[E];H=J.prev;if(H&&H.type==3){H.value=H.value.replace(/\r?\n$/,"")}}}})}function f(){o.bind(d.getBody(),"mouseup",function(E){var D,C=A.getNode();if(C.nodeName=="IMG"){if(D=o.getStyle(C,"width")){o.setAttrib(C,"width",D.replace(/[^0-9%]+/g,""));o.setStyle(C,"width","")}if(D=o.getStyle(C,"height")){o.setAttrib(C,"height",D.replace(/[^0-9%]+/g,""));o.setStyle(C,"height","")}}})}function p(){d.onKeyDown.add(function(I,J){var H,C,D,F,G,K,E;H=J.keyCode==s;if(!J.isDefaultPrevented()&&(H||J.keyCode==r)&&!l.modifierPressed(J)){C=A.getRng();D=C.startContainer;F=C.startOffset;E=C.collapsed;if(D.nodeType==3&&D.nodeValue.length>0&&((F===0&&!E)||(E&&F===(H?0:1)))){nonEmptyElements=I.schema.getNonEmptyElements();J.preventDefault();G=o.create("br",{id:"__tmp"});D.parentNode.insertBefore(G,D);I.getDoc().execCommand(H?"ForwardDelete":"Delete",false,null);D=A.getRng().startContainer;K=D.previousSibling;if(K&&K.nodeType==1&&!o.isBlock(K)&&o.isEmpty(K)&&!nonEmptyElements[K.nodeName.toLowerCase()]){o.remove(K)}o.remove("__tmp")}}})}function e(){d.onKeyDown.add(function(G,H){var E,D,I,C,F;if(H.isDefaultPrevented()||H.keyCode!=l.BACKSPACE){return}E=A.getRng();D=E.startContainer;I=E.startOffset;C=o.getRoot();F=D;if(!E.collapsed||I!==0){return}while(F&&F.parentNode&&F.parentNode.firstChild==F&&F.parentNode!=C){F=F.parentNode}if(F.tagName==="BLOCKQUOTE"){G.formatter.toggle("blockquote",null,F);E.setStart(D,0);E.setEnd(D,0);A.setRng(E);A.collapse(false)}})}function k(){function C(){d._refreshContentEditable();c("StyleWithCSS",false);c("enableInlineTableEditing",false);if(!q.object_resizing){c("enableObjectResizing",false)}}if(!q.readonly){d.onBeforeExecCommand.add(C);d.onMouseDown.add(C)}}function n(){function C(D,E){tinymce.each(o.select("a"),function(H){var F=H.parentNode,G=o.getRoot();if(F.lastChild===H){while(F&&!o.isBlock(F)){if(F.parentNode.lastChild!==F||F===G){return}F=F.parentNode}o.add(F,"br",{"data-mce-bogus":1})}})}d.onExecCommand.add(function(D,E){if(E==="CreateLink"){C(D)}});d.onSetContent.add(A.onSetContent.add(C))}function t(){if(q.forced_root_block){d.onInit.add(function(){c("DefaultParagraphSeparator",q.forced_root_block)})}}function a(){function C(E,D){if(!E||!D.initial){d.execCommand("mceRepaint")}}d.onUndo.add(C);d.onRedo.add(C);d.onSetContent.add(C)}function j(){d.onKeyDown.add(function(C,D){if(!D.isDefaultPrevented()&&D.keyCode==8&&A.getNode().nodeName=="IMG"){D.preventDefault();C.undoManager.beforeChange();o.remove(A.getNode());C.undoManager.add()}})}v();e();B();if(tinymce.isWebKit){p();h();u();x();t();if(tinymce.isIDevice){i()}}if(tinymce.isIE){m();z();g();f();j()}if(tinymce.isGecko){m();b();y();k();n();a()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][B]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script style textarea");q=m("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object",z);v=m("block_elements","h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot th tr td li ol ul caption blockquote center dl dt dd dir fieldset noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup");function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=c.self_closing_elements||e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t0){Q.value=l;Q=Q.prev}else{O=Q.prev;Q.remove();Q=O}}}function H(O){var P,l={};for(P in O){if(P!=="li"&&P!="p"){l[P]=O[P]}}return l}n=new b.html.SaxParser({validate:z,self_closing_elements:H(h.getSelfClosingElements()),cdata:function(l){B.append(K("#cdata",4)).value=l},text:function(P,l){var O;if(!L){P=P.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){P=P.replace(E,"")}}if(P.length!==0){O=K("#text",3);O.raw=!!l;B.append(O).value=P}},comment:function(l){B.append(K("#comment",8)).value=l},pi:function(l,O){B.append(K(l,7)).value=O;I(B)},doctype:function(O){var l;l=B.append(K("#doctype",10));l.value=O;I(B)},start:function(l,W,P){var U,R,Q,O,S,X,V,T;Q=z?h.getElementRule(l):{};if(Q){U=K(Q.outputName||l,1);U.attributes=W;U.shortEnded=P;B.append(U);T=p[B.name];if(T&&p[U.name]&&!T[U.name]){M.push(U)}R=d.length;while(R--){S=d[R].name;if(S in W.map){F=c[S];if(F){F.push(U)}else{c[S]=[U]}}}if(o[l]){I(U)}if(!P){B=U}if(!L&&s[l]){L=true}}},end:function(l){var S,P,R,O,Q;P=z?h.getElementRule(l):{};if(P){if(o[l]){if(!L){S=B.firstChild;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R;S=S.next}else{O=S.next;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.next;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}S=B.lastChild;if(S&&S.type===3){R=S.value.replace(t,"");if(R.length>0){S.value=R;S=S.prev}else{O=S.prev;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.prev;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}}S=B.prev;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R}else{S.remove()}}}if(L&&s[l]){L=false}if(P.removeEmpty||P.paddEmpty){if(B.isEmpty(u)){if(P.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name&&!B.attributes.map.id){Q=B.parent;B.empty().remove();B=Q;return}}}}B=B.parent}}},h);J=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&M.length){if(!m.context){j(M)}else{m.invalid=true}}if(q&&J.name=="body"){G()}if(!m.invalid){for(N in i){F=e[N];A=i[N];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},select:function(k,j){var i=this;return e.dom.Sizzle(k,i.get(j)||i.get(i.settings.root_element)||i.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(c.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return e.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":b?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
                          "+j;m.removeChild(m.firstChild)}catch(l){m=i.create("div");m.innerHTML="
                          "+j;g(m.childNodes,function(o,n){if(n){m.appendChild(o)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){g(s.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:q(s.styleSheet);break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,U=0,F=1,j=2,E=true,S=false,W="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L,toStringIE:T});function x(){return e.createDocumentFragment()}function q(X,t){C(E,X,t)}function s(X,t){C(S,X,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[W]}else{O[h]=O[Q];O[W]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(aa,t){var ad=O[h],Y=O[W],ac=O[Q],X=O[A],ab=t.startContainer,af=t.startOffset,Z=t.endContainer,ae=t.endOffset;if(aa===0){return H(ad,Y,ab,af)}if(aa===1){return H(ac,X,ab,af)}if(aa===2){return H(ac,X,Z,ae)}if(aa===3){return H(ad,Y,Z,ae)}}function p(){l(j)}function I(){return l(U)}function d(){return l(F)}function D(aa){var X=this[h],t=this[W],Z,Y;if((X.nodeType===3||X.nodeType===4)&&X.nodeValue){if(!t){X.parentNode.insertBefore(aa,X)}else{if(t>=X.nodeValue.length){c.insertAfter(aa,X)}else{Z=X.splitText(t);X.parentNode.insertBefore(aa,Z)}}}else{if(X.childNodes.length>0){Y=X.childNodes[t]}if(Y){X.insertBefore(aa,Y)}else{X.appendChild(aa)}}}function N(X){var t=O.extractContents();O.insertNode(X);X.appendChild(t);O.selectNode(X)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[W],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,X){var Y;if(t.nodeType==3){return t}if(X<0){return t}Y=t.firstChild;while(Y&&X>0){--X;Y=Y.nextSibling}if(Y){return Y}return t}function m(){return(O[h]==O[Q]&&O[W]==O[A])}function H(Z,ab,X,aa){var ac,Y,t,ad,af,ae;if(Z==X){if(ab==aa){return 0}if(ab0){O.collapse(X)}}else{O.collapse(X)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ad){var ac,Z=0,af=0,X,ab,Y,aa,t,ae;if(O[h]==O[Q]){return f(ad)}for(ac=O[Q],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[h]){return r(ac,ad)}++Z}for(ac=O[h],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[Q]){return V(ac,ad)}++af}ab=af-Z;Y=O[h];while(ab>0){Y=Y.parentNode;ab--}aa=O[Q];while(ab<0){aa=aa.parentNode;ab++}for(t=Y.parentNode,ae=aa.parentNode;t!=ae;t=t.parentNode,ae=ae.parentNode){Y=t;aa=ae}return o(Y,aa,ad)}function f(ac){var ae,af,t,Y,Z,ad,aa,X,ab;if(ac!=j){ae=x()}if(O[W]==O[A]){return ae}if(O[h].nodeType==3){af=O[h].nodeValue;t=af.substring(O[W],O[A]);if(ac!=F){Y=O[h];X=O[W];ab=O[A]-O[W];if(X===0&&ab>=Y.nodeValue.length-1){Y.parentNode.removeChild(Y)}else{Y.deleteData(X,ab)}O.collapse(E)}if(ac==j){return}if(t.length>0){ae.appendChild(e.createTextNode(t))}return ae}Y=P(O[h],O[W]);Z=O[A]-O[W];while(Y&&Z>0){ad=Y.nextSibling;aa=z(Y,ac);if(ae){ae.appendChild(aa)}--Z;Y=ad}if(ac!=F){O.collapse(E)}return ae}function r(ad,aa){var ac,ab,X,t,Z,Y;if(aa!=j){ac=x()}ab=i(ad,aa);if(ac){ac.appendChild(ab)}X=n(ad);t=X-O[W];if(t<=0){if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}ab=ad.previousSibling;while(t>0){Z=ab.previousSibling;Y=z(ab,aa);if(ac){ac.insertBefore(Y,ac.firstChild)}--t;ab=Z}if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}function V(ab,aa){var ad,X,ac,t,Z,Y;if(aa!=j){ad=x()}ac=R(ab,aa);if(ad){ad.appendChild(ac)}X=n(ab);++X;t=O[A]-X;ac=ab.nextSibling;while(ac&&t>0){Z=ac.nextSibling;Y=z(ac,aa);if(ad){ad.appendChild(Y)}--t;ac=Z}if(aa!=F){O.setStartAfter(ab);O.collapse(E)}return ad}function o(ab,t,ae){var Y,ag,aa,ac,ad,X,af,Z;if(ae!=j){ag=x()}Y=R(ab,ae);if(ag){ag.appendChild(Y)}aa=ab.parentNode;ac=n(ab);ad=n(t);++ac;X=ad-ac;af=ab.nextSibling;while(X>0){Z=af.nextSibling;Y=z(af,ae);if(ag){ag.appendChild(Y)}af=Z;--X}Y=i(t,ae);if(ag){ag.appendChild(Y)}if(ae!=F){O.setStartAfter(ab);O.collapse(E)}return ag}function i(ac,ad){var Y=P(O[Q],O[A]-1),ae,ab,aa,t,X,Z=Y!=O[Q];if(Y==ac){return M(Y,Z,S,ad)}ae=Y.parentNode;ab=M(ae,S,S,ad);while(ae){while(Y){aa=Y.previousSibling;t=M(Y,Z,S,ad);if(ad!=j){ab.insertBefore(t,ab.firstChild)}Z=E;Y=aa}if(ae==ac){return ab}Y=ae.previousSibling;ae=ae.parentNode;X=M(ae,S,S,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function R(ac,ad){var Z=P(O[h],O[W]),aa=Z!=O[h],ae,ab,Y,t,X;if(Z==ac){return M(Z,aa,E,ad)}ae=Z.parentNode;ab=M(ae,S,E,ad);while(ae){while(Z){Y=Z.nextSibling;t=M(Z,aa,E,ad);if(ad!=j){ab.appendChild(t)}aa=E;Z=Y}if(ae==ac){return ab}Z=ae.nextSibling;ae=ae.parentNode;X=M(ae,S,E,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function M(t,aa,ad,ae){var Z,Y,ab,X,ac;if(aa){return z(t,ae)}if(t.nodeType==3){Z=t.nodeValue;if(ad){X=O[W];Y=Z.substring(X);ab=Z.substring(0,X)}else{X=O[A];Y=Z.substring(0,X);ab=Z.substring(X)}if(ae!=F){t.nodeValue=ab}if(ae==j){return}ac=c.clone(t,S);ac.nodeValue=Y;return ac}if(ae==j){return}return c.clone(t,S)}function z(X,t){if(t!=j){return t==F?c.clone(X,E):X}X.parentNode.removeChild(X)}function T(){return c.create("body",null,d()).outerText}return O}a.Range=b;b.prototype.toString=function(){return this.toStringIE()}})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,t,q,s,r=d.dom.doc,m=r.body;function j(A){var v,z,u,y,x;u=h.create("a");v=A?k:t;z=A?p:q;y=n.duplicate();if(v==r||v==r.documentElement){v=m;z=0}if(v.nodeType==3){v.parentNode.insertBefore(u,v);y.moveToElementText(u);y.moveStart("character",z);h.remove(u);n.setEndPoint(A?"StartToStart":"EndToEnd",y)}else{x=v.childNodes;if(x.length){if(z>=x.length){h.insertAfter(u,x[x.length-1])}else{v.insertBefore(u,x[z])}y.moveToElementText(u)}else{if(v.canHaveHTML){v.innerHTML="\uFEFF";u=v.firstChild;y.moveToElementText(u);y.collapse(f)}}n.setEndPoint(A?"StartToStart":"EndToEnd",y);h.remove(u)}}k=i.startContainer;p=i.startOffset;t=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==t&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){s=k.previousSibling;if(s&&!s.hasChildNodes()&&h.isBlock(s)){s.innerHTML="\uFEFF"}else{s=null}k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";if(s){s.innerHTML=""}return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var n=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i="sizcache",o=0,r=Object.prototype.toString,h=false,g=true,q=/\\/g,u=/\r\n/g,x=/\W/;[0,0].sort(function(){g=false;return 0});var d=function(C,e,F,G){F=F||[];e=e||document;var I=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!C||typeof C!=="string"){return F}var z,K,N,y,J,M,L,E,B=true,A=d.isXML(e),D=[],H=C;do{n.exec("");z=n.exec(H);if(z){H=z[3];D.push(z[1]);if(z[2]){y=z[3];break}}}while(z);if(D.length>1&&j.exec(C)){if(D.length===2&&k.relative[D[0]]){K=s(D[0]+D[1],e,G)}else{K=k.relative[D[0]]?[e]:d(D.shift(),e);while(D.length){C=D.shift();if(k.relative[C]){C+=D.shift()}K=s(C,K,G)}}}else{if(!G&&D.length>1&&e.nodeType===9&&!A&&k.match.ID.test(D[0])&&!k.match.ID.test(D[D.length-1])){J=d.find(D.shift(),e,A);e=J.expr?d.filter(J.expr,J.set)[0]:J.set[0]}if(e){J=G?{expr:D.pop(),set:l(G)}:d.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&e.parentNode?e.parentNode:e,A);K=J.expr?d.filter(J.expr,J.set):J.set;if(D.length>0){N=l(K)}else{B=false}while(D.length){M=D.pop();L=M;if(!k.relative[M]){M=""}else{L=D.pop()}if(L==null){L=e}k.relative[M](N,L,A)}}else{N=D=[]}}if(!N){N=K}if(!N){d.error(M||C)}if(r.call(N)==="[object Array]"){if(!B){F.push.apply(F,N)}else{if(e&&e.nodeType===1){for(E=0;N[E]!=null;E++){if(N[E]&&(N[E]===true||N[E].nodeType===1&&d.contains(e,N[E]))){F.push(K[E])}}}else{for(E=0;N[E]!=null;E++){if(N[E]&&N[E].nodeType===1){F.push(K[E])}}}}}else{l(N,F)}if(y){d(y,I,F,G);d.uniqueSort(F)}return F};d.uniqueSort=function(y){if(p){h=g;y.sort(p);if(h){for(var e=1;e0};d.find=function(E,e,F){var D,z,B,A,C,y;if(!E){return[]}for(z=0,B=k.order.length;z":function(D,y){var C,B=typeof y==="string",z=0,e=D.length;if(B&&!x.test(y)){y=y.toLowerCase();for(;z=0)){if(!z){e.push(C)}}else{if(z){y[B]=false}}}}return false},ID:function(e){return e[1].replace(q,"")},TAG:function(y,e){return y[1].replace(q,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){d.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var y=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(y[1]+(y[2]||1))-0;e[3]=y[3]-0}else{if(e[2]){d.error(e[0])}}e[0]=o++;return e},ATTR:function(B,y,z,e,C,D){var A=B[1]=B[1].replace(q,"");if(!D&&k.attrMap[A]){B[1]=k.attrMap[A]}B[4]=(B[4]||B[5]||"").replace(q,"");if(B[2]==="~="){B[4]=" "+B[4]+" "}return B},PSEUDO:function(B,y,z,e,C){if(B[1]==="not"){if((n.exec(B[3])||"").length>1||/^\w/.test(B[3])){B[3]=d(B[3],null,null,y)}else{var A=d.filter(B[3],y,z,true^C);if(!z){e.push.apply(e,A)}return false}}else{if(k.match.POS.test(B[0])||k.match.CHILD.test(B[0])){return true}}return B},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(z,y,e){return !!d(e[3],z).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(z){var e=z.getAttribute("type"),y=z.type;return z.nodeName.toLowerCase()==="input"&&"text"===y&&(e===y||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===y.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===y.type},button:function(y){var e=y.nodeName.toLowerCase();return e==="input"&&"button"===y.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(y,e){return e===0},last:function(z,y,e,A){return y===A.length-1},even:function(y,e){return e%2===0},odd:function(y,e){return e%2===1},lt:function(z,y,e){return ye[3]-0},nth:function(z,y,e){return e[3]-0===y},eq:function(z,y,e){return e[3]-0===y}},filter:{PSEUDO:function(z,E,D,F){var e=E[1],y=k.filters[e];if(y){return y(z,D,E,F)}else{if(e==="contains"){return(z.textContent||z.innerText||b([z])||"").indexOf(E[3])>=0}else{if(e==="not"){var A=E[3];for(var C=0,B=A.length;C=0)}}},ID:function(y,e){return y.nodeType===1&&y.getAttribute("id")===e},TAG:function(y,e){return(e==="*"&&y.nodeType===1)||!!y.nodeName&&y.nodeName.toLowerCase()===e},CLASS:function(y,e){return(" "+(y.className||y.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(C,A){var z=A[1],e=d.attr?d.attr(C,z):k.attrHandle[z]?k.attrHandle[z](C):C[z]!=null?C[z]:C.getAttribute(z),D=e+"",B=A[2],y=A[4];return e==null?B==="!=":!B&&d.attr?e!=null:B==="="?D===y:B==="*="?D.indexOf(y)>=0:B==="~="?(" "+D+" ").indexOf(y)>=0:!y?D&&e!==false:B==="!="?D!==y:B==="^="?D.indexOf(y)===0:B==="$="?D.substr(D.length-y.length)===y:B==="|="?D===y||D.substr(0,y.length+1)===y+"-":false},POS:function(B,y,z,C){var e=y[2],A=k.setFilters[e];if(A){return A(B,z,y,C)}}}};var j=k.match.POS,c=function(y,e){return"\\"+(e-0+1)};for(var f in k.match){k.match[f]=new RegExp(k.match[f].source+(/(?![^\[]*\])(?![^\(]*\))/.source));k.leftMatch[f]=new RegExp(/(^(?:.|\r|\n)*?)/.source+k.match[f].source.replace(/\\(\d+)/g,c))}k.match.globalPOS=j;var l=function(y,e){y=Array.prototype.slice.call(y,0);if(e){e.push.apply(e,y);return e}return y};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(v){l=function(B,A){var z=0,y=A||[];if(r.call(B)==="[object Array]"){Array.prototype.push.apply(y,B)}else{if(typeof B.length==="number"){for(var e=B.length;z";e.insertBefore(y,e.firstChild);if(document.getElementById(z)){k.find.ID=function(B,C,D){if(typeof C.getElementById!=="undefined"&&!D){var A=C.getElementById(B[1]);return A?A.id===B[1]||typeof A.getAttributeNode!=="undefined"&&A.getAttributeNode("id").nodeValue===B[1]?[A]:undefined:[]}};k.filter.ID=function(C,A){var B=typeof C.getAttributeNode!=="undefined"&&C.getAttributeNode("id");return C.nodeType===1&&B&&B.nodeValue===A}}e.removeChild(y);e=y=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){k.find.TAG=function(y,C){var B=C.getElementsByTagName(y[1]);if(y[1]==="*"){var A=[];for(var z=0;B[z];z++){if(B[z].nodeType===1){A.push(B[z])}}B=A}return B}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){k.attrHandle.href=function(y){return y.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div"),z="__sizzle__";A.innerHTML="

                          ";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(L,C,G,K){C=C||document;if(!K&&!d.isXML(C)){var J=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(L);if(J&&(C.nodeType===1||C.nodeType===9)){if(J[1]){return l(C.getElementsByTagName(L),G)}else{if(J[2]&&k.find.CLASS&&C.getElementsByClassName){return l(C.getElementsByClassName(J[2]),G)}}}if(C.nodeType===9){if(L==="body"&&C.body){return l([C.body],G)}else{if(J&&J[3]){var F=C.getElementById(J[3]);if(F&&F.parentNode){if(F.id===J[3]){return l([F],G)}}else{return l([],G)}}}try{return l(C.querySelectorAll(L),G)}catch(H){}}else{if(C.nodeType===1&&C.nodeName.toLowerCase()!=="object"){var D=C,E=C.getAttribute("id"),B=E||z,N=C.parentNode,M=/^\s*[+~]/.test(L);if(!E){C.setAttribute("id",B)}else{B=B.replace(/'/g,"\\$&")}if(M&&N){C=C.parentNode}try{if(!M||N){return l(C.querySelectorAll("[id='"+B+"'] "+L),G)}}catch(I){}finally{if(!E){D.removeAttribute("id")}}}}}return e(L,C,G,K)};for(var y in e){d[y]=e[y]}A=null})()}(function(){var e=document.documentElement,z=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(z){var B=!z.call(document.createElement("div"),"div"),y=false;try{z.call(document.documentElement,"[test!='']:sizzle")}catch(A){y=true}d.matchesSelector=function(D,F){F=F.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!d.isXML(D)){try{if(y||!k.match.PSEUDO.test(F)&&!/!=/.test(F)){var C=z.call(D,F);if(C||!B||D.document&&D.document.nodeType!==11){return C}}}catch(E){}}return d(F,null,null,[D]).length>0}}})();(function(){var e=document.createElement("div");e.innerHTML="
                          ";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}k.order.splice(1,0,"CLASS");k.find.CLASS=function(y,z,A){if(typeof z.getElementsByClassName!=="undefined"&&!A){return z.getElementsByClassName(y[1])}};e=null})();function a(y,D,C,G,E,F){for(var A=0,z=G.length;A0){B=e;break}}}e=e[y]}G[A]=B}}}if(document.documentElement.contains){d.contains=function(y,e){return y!==e&&(y.contains?y.contains(e):true)}}else{if(document.documentElement.compareDocumentPosition){d.contains=function(y,e){return !!(y.compareDocumentPosition(e)&16)}}else{d.contains=function(){return false}}}d.isXML=function(e){var y=(e?e.ownerDocument||e:0).documentElement;return y?y.nodeName!=="HTML":false};var s=function(z,e,D){var C,E=[],B="",F=e.nodeType?[e]:e;while((C=k.match.PSEUDO.exec(z))){B+=C[0];z=z.replace(k.match.PSEUDO,"")}z=k.relative[z]?z+"*":z;for(var A=0,y=F.length;A"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var h=this.getRng(),i,g,k,j;if(h.duplicate||h.item){if(h.item){return h.item(0)}k=h.duplicate();k.collapse(1);i=k.parentElement();g=j=h.parentElement();while(j=j.parentNode){if(j==i){i=g;break}}return i}else{i=h.startContainer;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[Math.min(i.childNodes.length-1,h.startOffset)]}if(i&&i.nodeType==3){return i.parentNode}return i}},getEnd:function(){var h=this,i=h.getRng(),j,g;if(i.duplicate||i.item){if(i.item){return i.item(0)}i=i.duplicate();i.collapse(0);j=i.parentElement();if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=i.endContainer;g=i.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[g>0?g-1:g]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){return{rng:y.getRng()}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(o){var s=this,m=s.dom,j,i,g,r,k,u,p,q;function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t.length-1;x>=1;x--){v=y.childNodes;if(t[x]>v.length-1){return}y=v[t[x]]}if(y.nodeType===3){z=Math.min(t[0],y.nodeValue.length)}if(y.nodeType===1){z=Math.min(t[0],y.childNodes.length)}if(A){g.setStart(y,z)}else{g.setEnd(y,z)}}return true}function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentNode;if(B=="start"){if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}k=u=A;p=q=t}else{if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}u=A;q=t}if(!x){z=v.previousSibling;y=v.nextSibling;e(d.grep(v.childNodes),function(C){if(C.nodeType==3){C.nodeValue=C.nodeValue.replace(/\uFEFF/g,"")}});while(v=m.get(o.id+"_"+B)){m.remove(v,1)}if(z&&y&&z.nodeType==y.nodeType&&z.nodeType==3&&!d.isOpera){t=z.nodeValue.length;z.appendData(y.nodeValue);m.remove(y);if(B=="start"){k=u=z;p=q=t}else{u=z;q=t}}}}}function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
                          '}return t}if(o){if(o.start){g=m.createRng();r=m.getRoot();if(s.tridentSel){return s.tridentSel.moveToBookmark(o)}if(h(true)&&h()){s.setRng(g)}}else{if(o.id){l("start");l("end");if(k){g=m.createRng();g.setStart(n(k),p);g.setEnd(n(u),q);s.setRng(g)}}else{if(o.name){s.select(m.select(o.name)[o.index])}else{if(o.rng){s.setRng(o.rng)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},destroy:function(h){var g=this;g.win=null;if(!h){d.removeUnload(g.destroy)}},_fixIESelection:function(){var h=this.dom,n=h.doc,i=n.body,k,o,g;function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r){q=null}return q}function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoints("StartToStart",o)>0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=document.createElement("script");s.id=n;s.type="text/javascript";s.src=a._addVer(m);if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=m.length){r=0}}t=m[r];f.setAttrib(g,"tabindex","-1");f.setAttrib(t.id,"tabindex","0");f.get(t.id).focus();if(e.actOnFocus){e.onAction(t.id)}if(s){a.cancel(s)}};p=function(z){var v=37,u=39,y=38,A=40,r=27,t=14,s=13,x=32;switch(z.keyCode){case v:if(i){q.moveFocus(-1)}break;case u:if(i){q.moveFocus(1)}break;case y:if(o){q.moveFocus(-1)}break;case A:if(o){q.moveFocus(1)}break;case r:if(e.onCancel){e.onCancel();a.cancel(z)}break;case t:case s:case x:if(e.onAction){e.onAction(g);a.cancel(z)}break}};c(m,function(t,r){var s,u;if(!t.id){t.id=f.uniqueId("_mce_item_")}u=f.get(t.id);if(l){f.bind(u,"blur",h);s="-1"}else{s=(r===0?"0":"-1")}u.setAttribute("tabindex",s);f.bind(u,"focus",k)});if(m[0]){g=m[0].id}f.setAttrib(n,"tabindex","-1");var j=f.get(n);f.bind(j,"focus",d);f.bind(j,"keydown",p)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+c}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keyup",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='
                          ';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(l){var k;b.remove(h.id,"change",i);j=false;k=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",k)});if(e.isWebKit&&(l.keyCode==37||l.keyCode==39)){return b.prevent(l)}if(l.keyCode==13||l.keyCode==32){g(l);return b.cancel(l)}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
                          ');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
                          ");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){return;var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}x=d({theme:"simple",language:"en"},x);v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}p.orgVisibility=p.getElement().style.visibility;p.getElement().style.visibility="hidden";if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/../../extra/strings.php?elanguage="+q.language+"ðeme="+q.theme)}if(q.theme&&typeof q.theme!="function"&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,F=this,G=F.settings,C,y,B=F.getElement(),p,m,D,v,A,E,x,r=[];k.add(F);G.aria_label=G.aria_label||l.getAttrib(B,"aria-label",F.getLang("aria.rich_text_area"));if(G.theme){if(typeof G.theme!="function"){G.theme=G.theme.replace(/-/,"");p=h.get(G.theme);F.theme=new p();if(F.theme.init){F.theme.init(F,h.urls[G.theme]||k.documentBaseURL.replace(/\/$/,""))}}else{F.theme=G.theme}}function z(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){z(u)});n=new t(F,o);F.plugins[s]=n;if(n.init){n.init(F,o);r.push(s)}}}i(g(G.plugins.replace(/\-/g,"")),z);if(G.popup_css!==false){if(G.popup_css){G.popup_css=F.documentBaseURI.toAbsolute(G.popup_css)}else{G.popup_css=F.baseURI.toAbsolute("themes/"+G.theme+"/skins/"+G.skin+"/dialog.css")}}if(G.popup_css_add){G.popup_css+=","+F.documentBaseURI.toAbsolute(G.popup_css_add)}F.controlManager=new k.ControlManager(F);F.onExecCommand.add(function(n,o){if(!/^(FontName|FontSize)$/.test(o)){F.nodeChanged()}});F.onBeforeRenderUI.dispatch(F,F.controlManager);if(G.render_ui&&F.theme){F.orgDisplay=B.style.display;if(typeof G.theme!="function"){C=G.width||B.style.width||B.offsetWidth;y=G.height||B.style.height||B.offsetHeight;E=/^[0-9\.]+(|px)$/i;if(E.test(""+C)){C=Math.max(parseInt(C,10)+(p.deltaWidth||0),100)}if(E.test(""+y)){y=Math.max(parseInt(y)+(p.deltaHeight||0),G.theme_advanced_resizing_min_height||100)}p=F.theme.renderUI({targetNode:B,width:C,height:y,deltaWidth:G.delta_width,deltaHeight:G.delta_height});l.setStyles(p.sizeContainer||p.editorContainer,{width:C,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y<(G.theme_advanced_resizing_min_height||100)){y=G.theme_advanced_resizing_min_height||100}}else{p=G.theme(F,B);if(p.editorContainer.nodeType){p.editorContainer=p.editorContainer.id=p.editorContainer.id||F.id+"_parent"}if(p.iframeContainer.nodeType){p.iframeContainer=p.iframeContainer.id=p.iframeContainer.id||F.id+"_iframecontainer"}y=p.iframeHeight||B.offsetHeight}F.editorContainer=p.editorContainer}if(G.content_css){i(g(G.content_css),function(n){F.contentCSS.push(F.documentBaseURI.toAbsolute(n))})}if(G.content_editable){B=q=p=null;return F.initContentBody()}if(document.domain&&location.hostname!=document.domain){k.relaxedDomain=document.domain}F.iframeHTML=G.doctype+'';if(G.document_base_url!=k.documentBaseURL){F.iframeHTML+=''}if(G.ie7_compat){F.iframeHTML+=''}else{F.iframeHTML+=''}F.iframeHTML+='';for(x=0;x'}F.contentCSS=[];v=G.body_id||"tinymce";if(v.indexOf("=")!=-1){v=F.getParam("body_id","","hash");v=v[F.id]||v}A=G.body_class||"";if(A.indexOf("=")!=-1){A=F.getParam("body_class","","hash");A=A[F.id]||""}F.iframeHTML+='
                          ";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){D='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+F.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:F.id+"_ifr",src:D||'javascript:""',frameBorder:"0",allowTransparency:"true",title:G.aria_label,style:{width:"100%",height:y,display:"block"}});F.contentAreaContainer=p.iframeContainer;if(p.editorContainer){l.get(p.editorContainer).style.display=F.orgDisplay}B.style.visibility=F.orgVisibility;l.get(F.id).style.display="none";l.setAttrib(F.id,"aria-hidden",true);if(!k.relaxedDomain||!D){F.initContentBody()}B=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(s,t){var u=s.length,x,z=n.dom,y,v;while(u--){x=s[u];y=x.attr(t);v="data-mce-"+t;if(!x.attributes.map[v]){if(t==="style"){x.attr(v,z.serializeStyle(z.parseStyle(y),x.name))}else{x.attr(v,n.convertURL(y,t,x.name))}}}});n.parser.addNodeFilter("script",function(s,t){var u=s.length,v;while(u--){v=s[u];v.attr("type","mce-"+(v.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(s,t){var u=s.length,v;while(u--){v=s[u];v.type=8;v.name="#comment";v.value="[CDATA["+v.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,u){var v=t.length,x,s=n.schema.getNonEmptyElements();while(v--){x=t[v];if(x.isEmpty(s)){x.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.serializer.onPreProcess.add(function(s,t){return n.onPreProcess.dispatch(n,t,s)});n.serializer.onPostProcess.add(function(s,t){return n.onPostProcess.dispatch(n,t,s)});n.onPreInit.dispatch(n);if(!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(s,t){i(p.protect,function(u){t.content=t.content.replace(u,function(v){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
                          [\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});i(n.contentCSS,function(s){n.dom.loadCSS(s)});if(p.auto_focus){setTimeout(function(){var s=k.get(p.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
                          "}else{r='
                          '}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}o.selection.normalize();return p.content},getContent:function(n){var m=this,o;n=n||{};n.format=n.format||"html";n.get=true;n.getInner=true;if(!n.no_events){m.onBeforeGetContent.dispatch(m,n)}if(n.format=="raw"){o=m.getBody().innerHTML}else{o=m.serializer.serialize(m.getBody(),n)}n.content=k.trim(o);if(!n.no_events){m.onGetContent.dispatch(m,n)}return n.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":if(!s.href){r=p.getAttrib(s,"name")||s.id;m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,n=m.getContainer();if(!m.removed){m.removed=1;m.hide();if(!m.settings.content_editable){j.clear(m.getWin());j.clear(m.getDoc())}j.clear(m.getBody());j.clear(m.formElement);j.unbind(n);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(n)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){Event.cancel(g)}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var l=this,f,d=l.settings,e=l.dom,h;h={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function c(i,m){var n=i.type;if(l.removed){return}if(l.onEvent.dispatch(l,i,m)!==false){l[h[i.fakeType||i.type]].dispatch(l,i,m)}}function j(i){l.focus(true)}function k(){l.selection.normalize();l.nodeChanged()}b(h,function(m,n){var i=d.content_editable?l.getBody():l.getDoc();switch(n){case"contextmenu":e.bind(i,n,c);break;case"paste":e.bind(l.getBody(),n,c);break;case"submit":case"reset":e.bind(l.getElement().form||a.DOM.getParent(l.id,"form"),n,c);break;default:e.bind(i,n,c)}});e.bind(d.content_editable?l.getBody():(a.isGecko?l.getDoc():l.getWin()),"focus",function(i){l.focus(true)});if(d.content_editable&&a.isOpera){e.bind(l.getBody(),"click",j);e.bind(l.getBody(),"keydown",j)}l.onMouseUp.add(k);l.onKeyUp.add(function(i,n){var m=n.keyCode;if((m>=33&&m<=36)||(m>=37&&m<=40)||m==13||m==45||m==46||m==8||(a.isMac&&(m==91||m==93))||n.ctrlKey){k()}});l.onReset.add(function(){l.setContent(l.startContent,{format:"raw"})});function g(m,i){if(m.altKey||m.ctrlKey||m.metaKey){b(l.shortcuts,function(n){var o=a.isMac?m.metaKey:m.ctrlKey;if(n.ctrl!=o||n.alt!=m.altKey||n.shift!=m.shiftKey){return}if(m.keyCode==n.keyCode||(m.charCode&&m.charCode==n.charCode)){m.preventDefault();if(i){n.func.call(n.scope)}return true}})}}l.onKeyUp.add(function(i,m){g(m)});l.onKeyPress.add(function(i,m){g(m)});l.onKeyDown.add(function(i,m){g(m,true)});if(a.isOpera){l.onClick.add(function(i,m){m.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}onBeforeAdd=new a(l);k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getDoc(),b.isGecko?"blur":"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onBeforeAdd:onBeforeAdd,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();l.onBeforeAdd.dispatch(l,p);o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}if(p){c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(j){var o,k,g,h=this,m=h.editor,n,f;if(!h.controlFactories){h.controlFactories=[];d(m.plugins,function(i){if(i.createControl){h.controlFactories.push(i)}})}n=h.controlFactories;for(k=0,g=n.length;k1||ae==aw||ae.tagName=="BR"){return ae}}}var ao=Y.selection.getRng();var at=ao.startContainer;var an=ao.endContainer;if(at!=an&&ao.endOffset===0){var ar=ap(at,an);var aq=ar.nodeType==3?ar.length:ar.childNodes.length;ao.setEnd(ar,aq)}return ao}function ab(aq,aw,au,at,ao){var an=[],ap=-1,av,ay=-1,ar=-1,ax;R(aq.childNodes,function(aA,az){if(aA.nodeName==="UL"||aA.nodeName==="OL"){ap=az;av=aA;return false}});R(aq.childNodes,function(aA,az){if(aA.nodeName==="SPAN"&&c.getAttrib(aA,"data-mce-type")=="bookmark"){if(aA.id==aw.id+"_start"){ay=az}else{if(aA.id==aw.id+"_end"){ar=az}}}});if(ap<=0||(ayap)){R(a.grep(aq.childNodes),ao);return 0}else{ax=c.clone(au,V);R(a.grep(aq.childNodes),function(aA,az){if((ayap&&az>ap)){an.push(aA);aA.parentNode.removeChild(aA)}});if(ayap){aq.insertBefore(ax,av.nextSibling)}}at.push(ax);R(an,function(az){ax.appendChild(az)});return ax}}function al(ao,aq,au){var an=[],at,ap,ar=true;at=ak.inline||ak.block;ap=c.create(at);Z(ap);M.walk(ao,function(av){var aw;function ax(ay){var aD,aB,az,aA,aC;aC=ar;aD=ay.nodeName.toLowerCase();aB=ay.parentNode.nodeName.toLowerCase();if(ay.nodeType===1&&x(ay)){aC=ar;ar=x(ay)==="true";aA=true}if(g(aD,"br")){aw=0;if(ak.block){c.remove(ay)}return}if(ak.wrapper&&y(ay,ac,aj)){aw=0;return}if(ar&&!aA&&ak.block&&!ak.wrapper&&I(aD)){ay=c.rename(ay,at);Z(ay);an.push(ay);aw=0;return}if(ak.selector){R(af,function(aE){if("collapsed" in aE&&aE.collapsed!==ag){return}if(c.is(ay,aE.selector)&&!b(ay)){Z(ay,aE);az=true}});if(!ak.inline||az){aw=0;return}}if(ar&&!aA&&d(at,aD)&&d(aB,at)&&!(!au&&ay.nodeType===3&&ay.nodeValue.length===1&&ay.nodeValue.charCodeAt(0)===65279)&&!b(ay)){if(!aw){aw=c.clone(ap,V);ay.parentNode.insertBefore(aw,ay);an.push(aw)}aw.appendChild(ay)}else{if(aD=="li"&&aq){aw=ab(ay,aq,ap,an,ax)}else{aw=0;R(a.grep(ay.childNodes),ax);if(aA){ar=aC}aw=0}}}R(av,ax)});if(ak.wrap_links===false){R(an,function(av){function aw(aA){var az,ay,ax;if(aA.nodeName==="A"){ay=c.clone(ap,V);an.push(ay);ax=a.grep(aA.childNodes);for(az=0;az1||!H(ax))&&av===0){c.remove(ax,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&av===1){ax=aw(ax)}R(af,function(az){R(c.select(az.inline,ax),function(aB){var aA;if(az.wrap_links===false){aA=aB.parentNode;do{if(aA.nodeName==="A"){return}}while(aA=aA.parentNode)}X(az,aj,aB,az.exact?aB:null)})});if(y(ax.parentNode,ac,aj)){c.remove(ax,1);ax=0;return C}if(ak.merge_with_parents){c.getParent(ax.parentNode,function(az){if(y(az,ac,aj)){c.remove(ax,1);ax=0;return C}})}if(ax&&ak.merge_siblings!==false){ax=u(E(ax),ax);ax=u(ax,E(ax,C))}}})}if(ak){if(ae){if(ae.nodeType){aa=c.createRng();aa.setStartBefore(ae);aa.setEndAfter(ae);al(p(aa,af),null,true)}else{al(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var am=Y.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(am,c.isBlock)){W(af[0].defaultBlock)}Y.selection.setRng(ad());ai=r.getBookmark();al(p(r.getRng(C),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(am,K,"childNodes");K(am)}r.moveToBookmark(ai);P(r.getRng(C));Y.nodeChanged()}else{S("apply",ac,aj)}}}}function B(ab,ak,ad){var ae=T(ab),am=ae[0],ai,ah,aa,aj=true;function ac(at){var ar,aq,ap,ao,av,au;if(at.nodeType===1&&x(at)){av=aj;aj=x(at)==="true";au=true}ar=a.grep(at.childNodes);if(aj&&!au){for(aq=0,ap=ae.length;aq=0;aa--){Z=af[aa].selector;if(!Z){return C}for(ae=ab.length-1;ae>=0;ae--){if(c.is(ab[ae],Z)){return C}}}}return V}a.extend(this,{get:T,register:l,apply:W,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z});j();U();function h(Z,aa){if(g(Z,aa.inline)){return C}if(g(Z,aa.block)){return C}if(aa.selector){return c.is(Z,aa.selector)}}function g(aa,Z){aa=aa||"";Z=Z||"";aa=""+(aa.nodeName||aa);Z=""+(Z.nodeName||Z);return aa.toLowerCase()==Z.toLowerCase()}function N(aa,Z){var ab=c.getStyle(aa,Z);if(Z=="color"||Z=="backgroundColor"){ab=c.toHex(ab)}if(Z=="fontWeight"&&ab==700){ab="bold"}return""+ab}function q(Z,aa){if(typeof(Z)!="string"){Z=Z(aa)}else{if(aa){Z=Z.replace(/%(\w+)/g,function(ac,ab){return aa[ab]||ac})}}return Z}function f(Z){return Z&&Z.nodeType===3&&/^([\t \r\n]+|)$/.test(Z.nodeValue)}function Q(ab,aa,Z){var ac=c.create(aa,Z);ab.parentNode.insertBefore(ac,ab);ac.appendChild(ab);return ac}function p(Z,ak,ac){var an,al,af,aj,ab=Z.startContainer,ag=Z.startOffset,ap=Z.endContainer,ai=Z.endOffset;function am(ax){var ar,av,aw,au,at,aq;ar=av=ax?ab:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();if(ar.nodeType==3&&!f(ar)){if(ax?ag>0:aial?al:ag];if(ab.nodeType==3){ag=0}}if(ap.nodeType==1&&ap.hasChildNodes()){al=ap.childNodes.length-1;ap=ap.childNodes[ai>al?al:ai-1];if(ap.nodeType==3){ai=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ah(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ac){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&af.node.nodeType===3&&af.node.nodeValue.charAt(af.offset-1)===" "){if(af.offset>1){ap=af.node;ap.splitText(af.offset-1)}}}}if(ak[0].inline||ak[0].block_expand){if(!ak[0].inline||(ab.nodeType!=3||ag===0)){ab=am(true)}if(!ak[0].inline||(ap.nodeType!=3||ai===ap.nodeValue.length)){ap=am()}}if(ak[0].selector&&ak[0].expand!==V&&!ak[0].inline){ab=ad(ab,"previousSibling");ap=ad(ap,"nextSibling")}if(ak[0].block||ak[0].selector){ab=aa(ab,"previousSibling");ap=aa(ap,"nextSibling");if(ak[0].block){if(!H(ab)){ab=am(true)}if(!H(ap)){ap=am()}}}if(ab.nodeType==1){ag=s(ab);ab=ab.parentNode}if(ap.nodeType==1){ai=s(ap)+1;ap=ap.parentNode}return{startContainer:ab,startOffset:ag,endContainer:ap,endOffset:ai}}function X(af,ae,ac,Z){var ab,aa,ad;if(!h(ac,af)){return V}if(af.remove!="all"){R(af.styles,function(ah,ag){ah=q(ah,ae);if(typeof(ag)==="number"){ag=ah;Z=0}if(!Z||g(N(Z,ag),ah)){c.setStyle(ac,ag,"")}ad=1});if(ad&&c.getAttrib(ac,"style")==""){ac.removeAttribute("style");ac.removeAttribute("data-mce-style")}R(af.attributes,function(ai,ag){var ah;ai=q(ai,ae);if(typeof(ag)==="number"){ag=ai;Z=0}if(!Z||g(c.getAttrib(Z,ag),ai)){if(ag=="class"){ai=c.getAttrib(ac,ag);if(ai){ah="";R(ai.split(/\s+/),function(aj){if(/mce\w+/.test(aj)){ah+=(ah?" ":"")+aj}});if(ah){c.setAttrib(ac,ag,ah);return}}}if(ag=="class"){ac.removeAttribute("className")}if(e.test(ag)){ac.removeAttribute("data-mce-"+ag)}ac.removeAttribute(ag)}});R(af.classes,function(ag){ag=q(ag,ae);if(!Z||c.hasClass(Z,ag)){c.removeClass(ac,ag)}});aa=c.getAttribs(ac);for(ab=0;abab?ab:ad]}if(Z.nodeType===3&&ae&&ad>=Z.nodeValue.length){Z=new t(Z,Y.getBody()).next()||Z}if(Z.nodeType===3&&!ae&&ad===0){Z=new t(Z,Y.getBody()).prev()||Z}return Z}function S(ai,Z,ag){var aj="_mce_caret",aa=Y.settings.caret_debug;function ab(an){var am=c.create("span",{id:aj,"data-mce-bogus":true,style:aa?"color:red":""});if(an){am.appendChild(Y.getDoc().createTextNode(G))}return am}function ah(an,am){while(an){if((an.nodeType===3&&an.nodeValue!==G)||an.childNodes.length>1){return false}if(am&&an.nodeType===1){am.push(an)}an=an.firstChild}return true}function ae(am){while(am){if(am.id===aj){return am}am=am.parentNode}}function ad(am){var an;if(am){an=new t(am,am);for(am=an.current();am;am=an.next()){if(am.nodeType===3){return am}}}}function ac(ao,an){var ap,am;if(!ao){ao=ae(r.getStart());if(!ao){while(ao=c.get(aj)){ac(ao,false)}}}else{am=r.getRng(true);if(ah(ao)){if(an!==false){am.setStartBefore(ao);am.setEndBefore(ao)}c.remove(ao)}else{ap=ad(ao);if(ap.nodeValue.charAt(0)===G){ap=ap.deleteData(0,1)}c.remove(ao,1)}r.setRng(am)}}function af(){var ao,am,at,ar,ap,an,aq;ao=r.getRng(true);ar=ao.startOffset;an=ao.startContainer;aq=an.nodeValue;am=ae(r.getStart());if(am){at=ad(am)}if(aq&&ar>0&&ar=0;aq--){ao.appendChild(c.clone(av[aq],false));ao=ao.firstChild}ao.appendChild(c.doc.createTextNode(G));ao=ao.firstChild;c.insertAfter(au,aw);r.setCursorLocation(ao,1)}}function al(){var an,am,ao;am=ae(r.getStart());if(am&&!c.isEmpty(am)){a.walk(am,function(ap){if(ap.nodeType==1&&ap.id!==aj&&!c.isEmpty(ap)){c.setAttrib(ap,"data-mce-bogus",null)}},"childNodes")}}if(!self._hasCaretEvents){Y.onBeforeGetContent.addToTop(function(){var am=[],an;if(ah(ae(r.getStart()),am)){an=am.length;while(an--){c.setAttrib(am[an],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(am){Y[am].addToTop(function(){ac();al()})});Y.onKeyDown.addToTop(function(am,ao){var an=ao.keyCode;if(an==8||an==37||an==39){ac(ae(r.getStart()))}al()});r.onSetContent.add(al);self._hasCaretEvents=true}if(ai=="apply"){af()}else{ak()}}function P(aa){var Z=aa.startContainer,ag=aa.startOffset,ac,af,ae,ab,ad;if(Z.nodeType==3&&ag>=Z.nodeValue.length){ag=s(Z);Z=Z.parentNode;ac=true}if(Z.nodeType==1){ab=Z.childNodes;Z=ab[Math.min(ag,ab.length-1)];af=new t(Z,c.getParent(Z,c.isBlock));if(ag>ab.length-1||ac){af.next()}for(ae=af.current();ae;ae=af.next()){if(ae.nodeType==3&&!f(ae)){ad=c.create("a",null,G);ae.parentNode.insertBefore(ad,ae);aa.setStart(ae,0);r.setRng(aa);c.remove(ad);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(e){var h=e.dom,d=e.selection,c=e.settings,g=e.undoManager;function f(y){var u=d.getRng(true),C,i,x,t,o,H,n,j,l,s,E,v,z;function B(I){return I&&h.isBlock(I)&&!/^(TD|TH|CAPTION)$/.test(I.nodeName)&&!/^(fixed|absolute)/i.test(I.style.position)&&h.getContentEditable(I)!=="true"}function m(J){var O,M,I,P,N,L=J,K;I=h.createRng();if(J.hasChildNodes()){O=new a(J,J);while(M=O.current()){if(M.nodeType==3){I.setStart(M,0);I.setEnd(M,0);break}if(/^(BR|IMG)$/.test(M.nodeName)){I.setStartBefore(M);I.setEndBefore(M);break}L=M;M=O.next()}if(!M){I.setStart(L,0);I.setEnd(L,0)}}else{if(J.nodeName=="BR"){if(J.nextSibling&&h.isBlock(J.nextSibling)){if(!H||H<9){K=h.create("br");J.parentNode.insertBefore(K,J)}I.setStartBefore(J);I.setEndBefore(J)}else{I.setStartAfter(J);I.setEndAfter(J)}}else{I.setStart(J,0);I.setEnd(J,0)}}d.setRng(I);h.remove(K);N=h.getViewPort(e.getWin());P=h.getPos(J).y;if(PN.y+N.h){e.getWin().scrollTo(0,P"}return M}function p(L){var K,J,I;if(x.nodeType==3&&(L?t>0:t=x.nodeValue.length){if(!b.isIE&&!A()){J=h.create("br");u.insertNode(J);u.setStartAfter(J);u.setEndAfter(J);I=true}}J=h.create("br");u.insertNode(J);if(b.isIE&&s=="PRE"&&(!H||H<8)){J.parentNode.insertBefore(h.doc.createTextNode("\r"),J)}if(!I){u.setStartAfter(J);u.setEndAfter(J)}else{u.setStartBefore(J);u.setEndBefore(J)}d.setRng(u);g.add()}function r(I){do{if(I.nodeType===3){I.nodeValue=I.nodeValue.replace(/^[\r\n]+/,"")}I=I.firstChild}while(I)}function F(K){var I=h.getRoot(),J,L;J=K;while(J!==I&&h.getContentEditable(J)!=="false"){if(h.getContentEditable(J)==="true"){L=J}J=J.parentNode}return J!==I?L:I}if(!u.collapsed){e.execCommand("Delete");return}if(y.isDefaultPrevented()){return}x=u.startContainer;t=u.startOffset;v=c.forced_root_block;v=v?v.toUpperCase():"";H=h.doc.documentMode;if(x.nodeType==1&&x.hasChildNodes()){z=t>x.childNodes.length-1;x=x.childNodes[Math.min(t,x.childNodes.length-1)]||x;t=0}i=F(x);if(!i){return}g.beforeChange();if(!h.isBlock(i)&&i!=h.getRoot()){if(!v||y.shiftKey){G()}return}if((v&&!y.shiftKey)||(!v&&y.shiftKey)){x=k(x,t)}o=h.getParent(x,h.isBlock);l=o?h.getParent(o.parentNode,h.isBlock):null;s=o?o.nodeName.toUpperCase():"";E=l?l.nodeName.toUpperCase():"";if(s=="LI"&&h.isEmpty(o)){if(/^(UL|OL|LI)$/.test(l.parentNode.nodeName)){return false}D();return}if(s=="PRE"&&c.br_in_pre!==false){if(!y.shiftKey){G();return}}else{if((!v&&!y.shiftKey&&s!="LI")||(v&&y.shiftKey)){G();return}}v=v||"P";if(p()){if(/^(H[1-6]|PRE)$/.test(s)&&E!="HGROUP"){n=q(v)}else{n=q()}if(c.end_container_on_empty_block&&B(l)&&h.isEmpty(o)){n=h.split(l,o)}else{h.insertAfter(n,o)}}else{if(p(true)){n=o.parentNode.insertBefore(q(),o)}else{C=u.cloneRange();C.setEndAfter(o);j=C.extractContents();r(j);n=j.firstChild;h.insertAfter(j,o)}}h.setAttrib(n,"id","");m(n);g.add()}e.onKeyDown.add(function(j,i){if(i.keyCode==13){if(f(i)!==false){i.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_dev.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_dev.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/tiny_mce_dev.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_dev.js diff --git a/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery.js new file mode 100644 index 00000000000..e29f2ce9491 --- /dev/null +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery.js @@ -0,0 +1 @@ +(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"@@tinymce_major_version@@",minorVersion:"@@tinymce_minor_version@@",releaseDate:"@@tinymce_release_date@@",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey}}})(tinymce);tinymce.util.Quirks=function(d){var l=tinymce.VK,r=l.BACKSPACE,s=l.DELETE,o=d.dom,A=d.selection,q=d.settings;function c(E,D){try{d.getDoc().execCommand(E,false,D)}catch(C){}}function h(){function C(F){var D,H,E,G;D=A.getRng();H=o.getParent(D.startContainer,o.isBlock);if(F){H=o.getNext(H,o.isBlock)}if(H){E=H.firstChild;while(E&&E.nodeType==3&&E.nodeValue.length===0){E=E.nextSibling}if(E&&E.nodeName==="SPAN"){G=E.cloneNode(false)}}d.getDoc().execCommand(F?"ForwardDelete":"Delete",false,null);H=o.getParent(D.startContainer,o.isBlock);tinymce.each(o.select("span.Apple-style-span,font.Apple-style-span",H),function(I){var J=A.getBookmark();if(G){o.replace(G.cloneNode(false),I,true)}else{o.remove(I,true)}A.moveToBookmark(J)})}d.onKeyDown.add(function(D,F){var E;E=F.keyCode==s;if(!F.isDefaultPrevented()&&(E||F.keyCode==r)&&!l.modifierPressed(F)){F.preventDefault();C(E)}});d.addCommand("Delete",function(){C()})}function B(){function D(F,I){var E,H,G=I?"start":"end";E=F[G+"Container"];H=F[G+"Offset"];if(E.nodeType==1&&E.hasChildNodes()){E=E.childNodes[Math.min(I?H:(H>0?H-1:0),E.childNodes.length-1)]}return E}function C(H,L){var G,K,F,I,J=L?"start":"end",E;G=H[J+"Container"];K=H[J+"Offset"];F=o.getRoot();if(G.nodeType==1){E=K>=G.childNodes.length;G=D(H,L);if(G.nodeType==3){K=L&&!E?0:G.nodeValue.length}}if(G.nodeType==3&&((L&&K>0)||(!L&&K7){return}c("RespectVisibilityInDesign",true);o.addClass(d.getBody(),"mceHideBrInPre");d.parser.addNodeFilter("pre",function(D,F){var G=D.length,I,E,J,H;while(G--){I=D[G].getAll("br");E=I.length;while(E--){J=I[E];H=J.prev;if(H&&H.type===3&&H.value.charAt(H.value-1)!="\n"){H.value+="\n"}else{J.parent.insert(new tinymce.html.Node("#text",3),J,true).value="\n"}}}});d.serializer.addNodeFilter("pre",function(D,F){var G=D.length,I,E,J,H;while(G--){I=D[G].getAll("br");E=I.length;while(E--){J=I[E];H=J.prev;if(H&&H.type==3){H.value=H.value.replace(/\r?\n$/,"")}}}})}function f(){o.bind(d.getBody(),"mouseup",function(E){var D,C=A.getNode();if(C.nodeName=="IMG"){if(D=o.getStyle(C,"width")){o.setAttrib(C,"width",D.replace(/[^0-9%]+/g,""));o.setStyle(C,"width","")}if(D=o.getStyle(C,"height")){o.setAttrib(C,"height",D.replace(/[^0-9%]+/g,""));o.setStyle(C,"height","")}}})}function p(){d.onKeyDown.add(function(I,J){var H,C,D,F,G,K,E;H=J.keyCode==s;if(!J.isDefaultPrevented()&&(H||J.keyCode==r)&&!l.modifierPressed(J)){C=A.getRng();D=C.startContainer;F=C.startOffset;E=C.collapsed;if(D.nodeType==3&&D.nodeValue.length>0&&((F===0&&!E)||(E&&F===(H?0:1)))){nonEmptyElements=I.schema.getNonEmptyElements();J.preventDefault();G=o.create("br",{id:"__tmp"});D.parentNode.insertBefore(G,D);I.getDoc().execCommand(H?"ForwardDelete":"Delete",false,null);D=A.getRng().startContainer;K=D.previousSibling;if(K&&K.nodeType==1&&!o.isBlock(K)&&o.isEmpty(K)&&!nonEmptyElements[K.nodeName.toLowerCase()]){o.remove(K)}o.remove("__tmp")}}})}function e(){d.onKeyDown.add(function(G,H){var E,D,I,C,F;if(H.isDefaultPrevented()||H.keyCode!=l.BACKSPACE){return}E=A.getRng();D=E.startContainer;I=E.startOffset;C=o.getRoot();F=D;if(!E.collapsed||I!==0){return}while(F&&F.parentNode&&F.parentNode.firstChild==F&&F.parentNode!=C){F=F.parentNode}if(F.tagName==="BLOCKQUOTE"){G.formatter.toggle("blockquote",null,F);E.setStart(D,0);E.setEnd(D,0);A.setRng(E);A.collapse(false)}})}function k(){function C(){d._refreshContentEditable();c("StyleWithCSS",false);c("enableInlineTableEditing",false);if(!q.object_resizing){c("enableObjectResizing",false)}}if(!q.readonly){d.onBeforeExecCommand.add(C);d.onMouseDown.add(C)}}function n(){function C(D,E){tinymce.each(o.select("a"),function(H){var F=H.parentNode,G=o.getRoot();if(F.lastChild===H){while(F&&!o.isBlock(F)){if(F.parentNode.lastChild!==F||F===G){return}F=F.parentNode}o.add(F,"br",{"data-mce-bogus":1})}})}d.onExecCommand.add(function(D,E){if(E==="CreateLink"){C(D)}});d.onSetContent.add(A.onSetContent.add(C))}function t(){if(q.forced_root_block){d.onInit.add(function(){c("DefaultParagraphSeparator",q.forced_root_block)})}}function a(){function C(E,D){if(!E||!D.initial){d.execCommand("mceRepaint")}}d.onUndo.add(C);d.onRedo.add(C);d.onSetContent.add(C)}function j(){d.onKeyDown.add(function(C,D){if(!D.isDefaultPrevented()&&D.keyCode==8&&A.getNode().nodeName=="IMG"){D.preventDefault();C.undoManager.beforeChange();o.remove(A.getNode());C.undoManager.add()}})}v();e();B();if(tinymce.isWebKit){p();h();u();x();t();if(tinymce.isIDevice){i()}}if(tinymce.isIE){m();z();g();f();j()}if(tinymce.isGecko){m();b();y();k();n();a()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][B]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script style textarea");q=m("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object",z);v=m("block_elements","h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot th tr td li ol ul caption blockquote center dl dt dd dir fieldset noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup");function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=c.self_closing_elements||e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t0){Q.value=l;Q=Q.prev}else{O=Q.prev;Q.remove();Q=O}}}function H(O){var P,l={};for(P in O){if(P!=="li"&&P!="p"){l[P]=O[P]}}return l}n=new b.html.SaxParser({validate:z,self_closing_elements:H(h.getSelfClosingElements()),cdata:function(l){B.append(K("#cdata",4)).value=l},text:function(P,l){var O;if(!L){P=P.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){P=P.replace(E,"")}}if(P.length!==0){O=K("#text",3);O.raw=!!l;B.append(O).value=P}},comment:function(l){B.append(K("#comment",8)).value=l},pi:function(l,O){B.append(K(l,7)).value=O;I(B)},doctype:function(O){var l;l=B.append(K("#doctype",10));l.value=O;I(B)},start:function(l,W,P){var U,R,Q,O,S,X,V,T;Q=z?h.getElementRule(l):{};if(Q){U=K(Q.outputName||l,1);U.attributes=W;U.shortEnded=P;B.append(U);T=p[B.name];if(T&&p[U.name]&&!T[U.name]){M.push(U)}R=d.length;while(R--){S=d[R].name;if(S in W.map){F=c[S];if(F){F.push(U)}else{c[S]=[U]}}}if(o[l]){I(U)}if(!P){B=U}if(!L&&s[l]){L=true}}},end:function(l){var S,P,R,O,Q;P=z?h.getElementRule(l):{};if(P){if(o[l]){if(!L){S=B.firstChild;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R;S=S.next}else{O=S.next;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.next;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}S=B.lastChild;if(S&&S.type===3){R=S.value.replace(t,"");if(R.length>0){S.value=R;S=S.prev}else{O=S.prev;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.prev;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}}S=B.prev;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R}else{S.remove()}}}if(L&&s[l]){L=false}if(P.removeEmpty||P.paddEmpty){if(B.isEmpty(u)){if(P.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name&&!B.attributes.map.id){Q=B.parent;B.empty().remove();B=Q;return}}}}B=B.parent}}},h);J=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&M.length){if(!m.context){j(M)}else{m.invalid=true}}if(q&&J.name=="body"){G()}if(!m.invalid){for(N in i){F=e[N];A=i[N];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":b?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
                          "+j;m.removeChild(m.firstChild)}catch(l){m=i.create("div");m.innerHTML="
                          "+j;g(m.childNodes,function(o,n){if(n){m.appendChild(o)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){g(s.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:q(s.styleSheet);break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,U=0,F=1,j=2,E=true,S=false,W="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L,toStringIE:T});function x(){return e.createDocumentFragment()}function q(X,t){C(E,X,t)}function s(X,t){C(S,X,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[W]}else{O[h]=O[Q];O[W]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(aa,t){var ad=O[h],Y=O[W],ac=O[Q],X=O[A],ab=t.startContainer,af=t.startOffset,Z=t.endContainer,ae=t.endOffset;if(aa===0){return H(ad,Y,ab,af)}if(aa===1){return H(ac,X,ab,af)}if(aa===2){return H(ac,X,Z,ae)}if(aa===3){return H(ad,Y,Z,ae)}}function p(){l(j)}function I(){return l(U)}function d(){return l(F)}function D(aa){var X=this[h],t=this[W],Z,Y;if((X.nodeType===3||X.nodeType===4)&&X.nodeValue){if(!t){X.parentNode.insertBefore(aa,X)}else{if(t>=X.nodeValue.length){c.insertAfter(aa,X)}else{Z=X.splitText(t);X.parentNode.insertBefore(aa,Z)}}}else{if(X.childNodes.length>0){Y=X.childNodes[t]}if(Y){X.insertBefore(aa,Y)}else{X.appendChild(aa)}}}function N(X){var t=O.extractContents();O.insertNode(X);X.appendChild(t);O.selectNode(X)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[W],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,X){var Y;if(t.nodeType==3){return t}if(X<0){return t}Y=t.firstChild;while(Y&&X>0){--X;Y=Y.nextSibling}if(Y){return Y}return t}function m(){return(O[h]==O[Q]&&O[W]==O[A])}function H(Z,ab,X,aa){var ac,Y,t,ad,af,ae;if(Z==X){if(ab==aa){return 0}if(ab0){O.collapse(X)}}else{O.collapse(X)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ad){var ac,Z=0,af=0,X,ab,Y,aa,t,ae;if(O[h]==O[Q]){return f(ad)}for(ac=O[Q],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[h]){return r(ac,ad)}++Z}for(ac=O[h],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[Q]){return V(ac,ad)}++af}ab=af-Z;Y=O[h];while(ab>0){Y=Y.parentNode;ab--}aa=O[Q];while(ab<0){aa=aa.parentNode;ab++}for(t=Y.parentNode,ae=aa.parentNode;t!=ae;t=t.parentNode,ae=ae.parentNode){Y=t;aa=ae}return o(Y,aa,ad)}function f(ac){var ae,af,t,Y,Z,ad,aa,X,ab;if(ac!=j){ae=x()}if(O[W]==O[A]){return ae}if(O[h].nodeType==3){af=O[h].nodeValue;t=af.substring(O[W],O[A]);if(ac!=F){Y=O[h];X=O[W];ab=O[A]-O[W];if(X===0&&ab>=Y.nodeValue.length-1){Y.parentNode.removeChild(Y)}else{Y.deleteData(X,ab)}O.collapse(E)}if(ac==j){return}if(t.length>0){ae.appendChild(e.createTextNode(t))}return ae}Y=P(O[h],O[W]);Z=O[A]-O[W];while(Y&&Z>0){ad=Y.nextSibling;aa=z(Y,ac);if(ae){ae.appendChild(aa)}--Z;Y=ad}if(ac!=F){O.collapse(E)}return ae}function r(ad,aa){var ac,ab,X,t,Z,Y;if(aa!=j){ac=x()}ab=i(ad,aa);if(ac){ac.appendChild(ab)}X=n(ad);t=X-O[W];if(t<=0){if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}ab=ad.previousSibling;while(t>0){Z=ab.previousSibling;Y=z(ab,aa);if(ac){ac.insertBefore(Y,ac.firstChild)}--t;ab=Z}if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}function V(ab,aa){var ad,X,ac,t,Z,Y;if(aa!=j){ad=x()}ac=R(ab,aa);if(ad){ad.appendChild(ac)}X=n(ab);++X;t=O[A]-X;ac=ab.nextSibling;while(ac&&t>0){Z=ac.nextSibling;Y=z(ac,aa);if(ad){ad.appendChild(Y)}--t;ac=Z}if(aa!=F){O.setStartAfter(ab);O.collapse(E)}return ad}function o(ab,t,ae){var Y,ag,aa,ac,ad,X,af,Z;if(ae!=j){ag=x()}Y=R(ab,ae);if(ag){ag.appendChild(Y)}aa=ab.parentNode;ac=n(ab);ad=n(t);++ac;X=ad-ac;af=ab.nextSibling;while(X>0){Z=af.nextSibling;Y=z(af,ae);if(ag){ag.appendChild(Y)}af=Z;--X}Y=i(t,ae);if(ag){ag.appendChild(Y)}if(ae!=F){O.setStartAfter(ab);O.collapse(E)}return ag}function i(ac,ad){var Y=P(O[Q],O[A]-1),ae,ab,aa,t,X,Z=Y!=O[Q];if(Y==ac){return M(Y,Z,S,ad)}ae=Y.parentNode;ab=M(ae,S,S,ad);while(ae){while(Y){aa=Y.previousSibling;t=M(Y,Z,S,ad);if(ad!=j){ab.insertBefore(t,ab.firstChild)}Z=E;Y=aa}if(ae==ac){return ab}Y=ae.previousSibling;ae=ae.parentNode;X=M(ae,S,S,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function R(ac,ad){var Z=P(O[h],O[W]),aa=Z!=O[h],ae,ab,Y,t,X;if(Z==ac){return M(Z,aa,E,ad)}ae=Z.parentNode;ab=M(ae,S,E,ad);while(ae){while(Z){Y=Z.nextSibling;t=M(Z,aa,E,ad);if(ad!=j){ab.appendChild(t)}aa=E;Z=Y}if(ae==ac){return ab}Z=ae.nextSibling;ae=ae.parentNode;X=M(ae,S,E,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function M(t,aa,ad,ae){var Z,Y,ab,X,ac;if(aa){return z(t,ae)}if(t.nodeType==3){Z=t.nodeValue;if(ad){X=O[W];Y=Z.substring(X);ab=Z.substring(0,X)}else{X=O[A];Y=Z.substring(0,X);ab=Z.substring(X)}if(ae!=F){t.nodeValue=ab}if(ae==j){return}ac=c.clone(t,S);ac.nodeValue=Y;return ac}if(ae==j){return}return c.clone(t,S)}function z(X,t){if(t!=j){return t==F?c.clone(X,E):X}X.parentNode.removeChild(X)}function T(){return c.create("body",null,d()).outerText}return O}a.Range=b;b.prototype.toString=function(){return this.toStringIE()}})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,t,q,s,r=d.dom.doc,m=r.body;function j(A){var v,z,u,y,x;u=h.create("a");v=A?k:t;z=A?p:q;y=n.duplicate();if(v==r||v==r.documentElement){v=m;z=0}if(v.nodeType==3){v.parentNode.insertBefore(u,v);y.moveToElementText(u);y.moveStart("character",z);h.remove(u);n.setEndPoint(A?"StartToStart":"EndToEnd",y)}else{x=v.childNodes;if(x.length){if(z>=x.length){h.insertAfter(u,x[x.length-1])}else{v.insertBefore(u,x[z])}y.moveToElementText(u)}else{if(v.canHaveHTML){v.innerHTML="\uFEFF";u=v.firstChild;y.moveToElementText(u);y.collapse(f)}}n.setEndPoint(A?"StartToStart":"EndToEnd",y);h.remove(u)}}k=i.startContainer;p=i.startOffset;t=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==t&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){s=k.previousSibling;if(s&&!s.hasChildNodes()&&h.isBlock(s)){s.innerHTML="\uFEFF"}else{s=null}k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";if(s){s.innerHTML=""}return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(a){a.dom.Element=function(f,d){var b=this,e,c;b.settings=d=d||{};b.id=f;b.dom=e=d.dom||a.DOM;if(!a.isIE){c=e.get(b.id)}a.each(("getPos,getRect,getParent,add,setStyle,getStyle,setStyles,setAttrib,setAttribs,getAttrib,addClass,removeClass,hasClass,getOuterHTML,setOuterHTML,remove,show,hide,isHidden,setHTML,get").split(/,/),function(g){b[g]=function(){var h=[f],j;for(j=0;j"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var h=this.getRng(),i,g,k,j;if(h.duplicate||h.item){if(h.item){return h.item(0)}k=h.duplicate();k.collapse(1);i=k.parentElement();g=j=h.parentElement();while(j=j.parentNode){if(j==i){i=g;break}}return i}else{i=h.startContainer;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[Math.min(i.childNodes.length-1,h.startOffset)]}if(i&&i.nodeType==3){return i.parentNode}return i}},getEnd:function(){var h=this,i=h.getRng(),j,g;if(i.duplicate||i.item){if(i.item){return i.item(0)}i=i.duplicate();i.collapse(0);j=i.parentElement();if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=i.endContainer;g=i.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[g>0?g-1:g]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){return{rng:y.getRng()}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(o){var s=this,m=s.dom,j,i,g,r,k,u,p,q;function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t.length-1;x>=1;x--){v=y.childNodes;if(t[x]>v.length-1){return}y=v[t[x]]}if(y.nodeType===3){z=Math.min(t[0],y.nodeValue.length)}if(y.nodeType===1){z=Math.min(t[0],y.childNodes.length)}if(A){g.setStart(y,z)}else{g.setEnd(y,z)}}return true}function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentNode;if(B=="start"){if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}k=u=A;p=q=t}else{if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}u=A;q=t}if(!x){z=v.previousSibling;y=v.nextSibling;e(d.grep(v.childNodes),function(C){if(C.nodeType==3){C.nodeValue=C.nodeValue.replace(/\uFEFF/g,"")}});while(v=m.get(o.id+"_"+B)){m.remove(v,1)}if(z&&y&&z.nodeType==y.nodeType&&z.nodeType==3&&!d.isOpera){t=z.nodeValue.length;z.appendData(y.nodeValue);m.remove(y);if(B=="start"){k=u=z;p=q=t}else{u=z;q=t}}}}}function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
                          '}return t}if(o){if(o.start){g=m.createRng();r=m.getRoot();if(s.tridentSel){return s.tridentSel.moveToBookmark(o)}if(h(true)&&h()){s.setRng(g)}}else{if(o.id){l("start");l("end");if(k){g=m.createRng();g.setStart(n(k),p);g.setEnd(n(u),q);s.setRng(g)}}else{if(o.name){s.select(m.select(o.name)[o.index])}else{if(o.rng){s.setRng(o.rng)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},destroy:function(h){var g=this;g.win=null;if(!h){d.removeUnload(g.destroy)}},_fixIESelection:function(){var h=this.dom,n=h.doc,i=n.body,k,o,g;function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r){q=null}return q}function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoints("StartToStart",o)>0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=document.createElement("script");s.id=n;s.type="text/javascript";s.src=a._addVer(m);if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=m.length){r=0}}t=m[r];f.setAttrib(g,"tabindex","-1");f.setAttrib(t.id,"tabindex","0");f.get(t.id).focus();if(e.actOnFocus){e.onAction(t.id)}if(s){a.cancel(s)}};p=function(z){var v=37,u=39,y=38,A=40,r=27,t=14,s=13,x=32;switch(z.keyCode){case v:if(i){q.moveFocus(-1)}break;case u:if(i){q.moveFocus(1)}break;case y:if(o){q.moveFocus(-1)}break;case A:if(o){q.moveFocus(1)}break;case r:if(e.onCancel){e.onCancel();a.cancel(z)}break;case t:case s:case x:if(e.onAction){e.onAction(g);a.cancel(z)}break}};c(m,function(t,r){var s,u;if(!t.id){t.id=f.uniqueId("_mce_item_")}u=f.get(t.id);if(l){f.bind(u,"blur",h);s="-1"}else{s=(r===0?"0":"-1")}u.setAttribute("tabindex",s);f.bind(u,"focus",k)});if(m[0]){g=m[0].id}f.setAttrib(n,"tabindex","-1");var j=f.get(n);f.bind(j,"focus",d);f.bind(j,"keydown",p)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+c}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keyup",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(l){var k;b.remove(h.id,"change",i);j=false;k=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",k)});if(e.isWebKit&&(l.keyCode==37||l.keyCode==39)){return b.prevent(l)}if(l.keyCode==13||l.keyCode==32){g(l);return b.cancel(l)}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
                          ');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
                          ");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){return;var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}x=d({theme:"simple",language:"en"},x);v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);if(j.adapter){j.adapter.patchEditor(m)}return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}p.orgVisibility=p.getElement().style.visibility;p.getElement().style.visibility="hidden";if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/../../extra/strings.php?elanguage="+q.language+"ðeme="+q.theme)}if(q.theme&&typeof q.theme!="function"&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,F=this,G=F.settings,C,y,B=F.getElement(),p,m,D,v,A,E,x,r=[];k.add(F);G.aria_label=G.aria_label||l.getAttrib(B,"aria-label",F.getLang("aria.rich_text_area"));if(G.theme){if(typeof G.theme!="function"){G.theme=G.theme.replace(/-/,"");p=h.get(G.theme);F.theme=new p();if(F.theme.init){F.theme.init(F,h.urls[G.theme]||k.documentBaseURL.replace(/\/$/,""))}}else{F.theme=G.theme}}function z(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){z(u)});n=new t(F,o);F.plugins[s]=n;if(n.init){n.init(F,o);r.push(s)}}}i(g(G.plugins.replace(/\-/g,"")),z);if(G.popup_css!==false){if(G.popup_css){G.popup_css=F.documentBaseURI.toAbsolute(G.popup_css)}else{G.popup_css=F.baseURI.toAbsolute("themes/"+G.theme+"/skins/"+G.skin+"/dialog.css")}}if(G.popup_css_add){G.popup_css+=","+F.documentBaseURI.toAbsolute(G.popup_css_add)}F.controlManager=new k.ControlManager(F);F.onExecCommand.add(function(n,o){if(!/^(FontName|FontSize)$/.test(o)){F.nodeChanged()}});F.onBeforeRenderUI.dispatch(F,F.controlManager);if(G.render_ui&&F.theme){F.orgDisplay=B.style.display;if(typeof G.theme!="function"){C=G.width||B.style.width||B.offsetWidth;y=G.height||B.style.height||B.offsetHeight;E=/^[0-9\.]+(|px)$/i;if(E.test(""+C)){C=Math.max(parseInt(C,10)+(p.deltaWidth||0),100)}if(E.test(""+y)){y=Math.max(parseInt(y)+(p.deltaHeight||0),G.theme_advanced_resizing_min_height||100)}p=F.theme.renderUI({targetNode:B,width:C,height:y,deltaWidth:G.delta_width,deltaHeight:G.delta_height});l.setStyles(p.sizeContainer||p.editorContainer,{width:C,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y<(G.theme_advanced_resizing_min_height||100)){y=G.theme_advanced_resizing_min_height||100}}else{p=G.theme(F,B);if(p.editorContainer.nodeType){p.editorContainer=p.editorContainer.id=p.editorContainer.id||F.id+"_parent"}if(p.iframeContainer.nodeType){p.iframeContainer=p.iframeContainer.id=p.iframeContainer.id||F.id+"_iframecontainer"}y=p.iframeHeight||B.offsetHeight}F.editorContainer=p.editorContainer}if(G.content_css){i(g(G.content_css),function(n){F.contentCSS.push(F.documentBaseURI.toAbsolute(n))})}if(G.content_editable){B=q=p=null;return F.initContentBody()}if(document.domain&&location.hostname!=document.domain){k.relaxedDomain=document.domain}F.iframeHTML=G.doctype+'';if(G.document_base_url!=k.documentBaseURL){F.iframeHTML+=''}if(G.ie7_compat){F.iframeHTML+=''}else{F.iframeHTML+=''}F.iframeHTML+='';for(x=0;x'}F.contentCSS=[];v=G.body_id||"tinymce";if(v.indexOf("=")!=-1){v=F.getParam("body_id","","hash");v=v[F.id]||v}A=G.body_class||"";if(A.indexOf("=")!=-1){A=F.getParam("body_class","","hash");A=A[F.id]||""}F.iframeHTML+='
                          ";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){D='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+F.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:F.id+"_ifr",src:D||'javascript:""',frameBorder:"0",allowTransparency:"true",title:G.aria_label,style:{width:"100%",height:y,display:"block"}});F.contentAreaContainer=p.iframeContainer;if(p.editorContainer){l.get(p.editorContainer).style.display=F.orgDisplay}B.style.visibility=F.orgVisibility;l.get(F.id).style.display="none";l.setAttrib(F.id,"aria-hidden",true);if(!k.relaxedDomain||!D){F.initContentBody()}B=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(s,t){var u=s.length,x,z=n.dom,y,v;while(u--){x=s[u];y=x.attr(t);v="data-mce-"+t;if(!x.attributes.map[v]){if(t==="style"){x.attr(v,z.serializeStyle(z.parseStyle(y),x.name))}else{x.attr(v,n.convertURL(y,t,x.name))}}}});n.parser.addNodeFilter("script",function(s,t){var u=s.length,v;while(u--){v=s[u];v.attr("type","mce-"+(v.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(s,t){var u=s.length,v;while(u--){v=s[u];v.type=8;v.name="#comment";v.value="[CDATA["+v.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,u){var v=t.length,x,s=n.schema.getNonEmptyElements();while(v--){x=t[v];if(x.isEmpty(s)){x.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.serializer.onPreProcess.add(function(s,t){return n.onPreProcess.dispatch(n,t,s)});n.serializer.onPostProcess.add(function(s,t){return n.onPostProcess.dispatch(n,t,s)});n.onPreInit.dispatch(n);if(!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(s,t){i(p.protect,function(u){t.content=t.content.replace(u,function(v){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
                          [\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});i(n.contentCSS,function(s){n.dom.loadCSS(s)});if(p.auto_focus){setTimeout(function(){var s=k.get(p.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
                          "}else{r='
                          '}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}o.selection.normalize();return p.content},getContent:function(n){var m=this,o;n=n||{};n.format=n.format||"html";n.get=true;n.getInner=true;if(!n.no_events){m.onBeforeGetContent.dispatch(m,n)}if(n.format=="raw"){o=m.getBody().innerHTML}else{o=m.serializer.serialize(m.getBody(),n)}n.content=k.trim(o);if(!n.no_events){m.onGetContent.dispatch(m,n)}return n.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":if(!s.href){r=p.getAttrib(s,"name")||s.id;m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,n=m.getContainer();if(!m.removed){m.removed=1;m.hide();if(!m.settings.content_editable){j.clear(m.getWin());j.clear(m.getDoc())}j.clear(m.getBody());j.clear(m.formElement);j.unbind(n);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(n)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){Event.cancel(g)}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var l=this,f,d=l.settings,e=l.dom,h;h={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function c(i,m){var n=i.type;if(l.removed){return}if(l.onEvent.dispatch(l,i,m)!==false){l[h[i.fakeType||i.type]].dispatch(l,i,m)}}function j(i){l.focus(true)}function k(){l.selection.normalize();l.nodeChanged()}b(h,function(m,n){var i=d.content_editable?l.getBody():l.getDoc();switch(n){case"contextmenu":e.bind(i,n,c);break;case"paste":e.bind(l.getBody(),n,c);break;case"submit":case"reset":e.bind(l.getElement().form||a.DOM.getParent(l.id,"form"),n,c);break;default:e.bind(i,n,c)}});e.bind(d.content_editable?l.getBody():(a.isGecko?l.getDoc():l.getWin()),"focus",function(i){l.focus(true)});if(d.content_editable&&a.isOpera){e.bind(l.getBody(),"click",j);e.bind(l.getBody(),"keydown",j)}l.onMouseUp.add(k);l.onKeyUp.add(function(i,n){var m=n.keyCode;if((m>=33&&m<=36)||(m>=37&&m<=40)||m==13||m==45||m==46||m==8||(a.isMac&&(m==91||m==93))||n.ctrlKey){k()}});l.onReset.add(function(){l.setContent(l.startContent,{format:"raw"})});function g(m,i){if(m.altKey||m.ctrlKey||m.metaKey){b(l.shortcuts,function(n){var o=a.isMac?m.metaKey:m.ctrlKey;if(n.ctrl!=o||n.alt!=m.altKey||n.shift!=m.shiftKey){return}if(m.keyCode==n.keyCode||(m.charCode&&m.charCode==n.charCode)){m.preventDefault();if(i){n.func.call(n.scope)}return true}})}}l.onKeyUp.add(function(i,m){g(m)});l.onKeyPress.add(function(i,m){g(m)});l.onKeyDown.add(function(i,m){g(m,true)});if(a.isOpera){l.onClick.add(function(i,m){m.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}onBeforeAdd=new a(l);k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getDoc(),b.isGecko?"blur":"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onBeforeAdd:onBeforeAdd,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();l.onBeforeAdd.dispatch(l,p);o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}if(p){c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(j){var o,k,g,h=this,m=h.editor,n,f;if(!h.controlFactories){h.controlFactories=[];d(m.plugins,function(i){if(i.createControl){h.controlFactories.push(i)}})}n=h.controlFactories;for(k=0,g=n.length;k1||ae==aw||ae.tagName=="BR"){return ae}}}var ao=Y.selection.getRng();var at=ao.startContainer;var an=ao.endContainer;if(at!=an&&ao.endOffset===0){var ar=ap(at,an);var aq=ar.nodeType==3?ar.length:ar.childNodes.length;ao.setEnd(ar,aq)}return ao}function ab(aq,aw,au,at,ao){var an=[],ap=-1,av,ay=-1,ar=-1,ax;R(aq.childNodes,function(aA,az){if(aA.nodeName==="UL"||aA.nodeName==="OL"){ap=az;av=aA;return false}});R(aq.childNodes,function(aA,az){if(aA.nodeName==="SPAN"&&c.getAttrib(aA,"data-mce-type")=="bookmark"){if(aA.id==aw.id+"_start"){ay=az}else{if(aA.id==aw.id+"_end"){ar=az}}}});if(ap<=0||(ayap)){R(a.grep(aq.childNodes),ao);return 0}else{ax=c.clone(au,V);R(a.grep(aq.childNodes),function(aA,az){if((ayap&&az>ap)){an.push(aA);aA.parentNode.removeChild(aA)}});if(ayap){aq.insertBefore(ax,av.nextSibling)}}at.push(ax);R(an,function(az){ax.appendChild(az)});return ax}}function al(ao,aq,au){var an=[],at,ap,ar=true;at=ak.inline||ak.block;ap=c.create(at);Z(ap);M.walk(ao,function(av){var aw;function ax(ay){var aD,aB,az,aA,aC;aC=ar;aD=ay.nodeName.toLowerCase();aB=ay.parentNode.nodeName.toLowerCase();if(ay.nodeType===1&&x(ay)){aC=ar;ar=x(ay)==="true";aA=true}if(g(aD,"br")){aw=0;if(ak.block){c.remove(ay)}return}if(ak.wrapper&&y(ay,ac,aj)){aw=0;return}if(ar&&!aA&&ak.block&&!ak.wrapper&&I(aD)){ay=c.rename(ay,at);Z(ay);an.push(ay);aw=0;return}if(ak.selector){R(af,function(aE){if("collapsed" in aE&&aE.collapsed!==ag){return}if(c.is(ay,aE.selector)&&!b(ay)){Z(ay,aE);az=true}});if(!ak.inline||az){aw=0;return}}if(ar&&!aA&&d(at,aD)&&d(aB,at)&&!(!au&&ay.nodeType===3&&ay.nodeValue.length===1&&ay.nodeValue.charCodeAt(0)===65279)&&!b(ay)){if(!aw){aw=c.clone(ap,V);ay.parentNode.insertBefore(aw,ay);an.push(aw)}aw.appendChild(ay)}else{if(aD=="li"&&aq){aw=ab(ay,aq,ap,an,ax)}else{aw=0;R(a.grep(ay.childNodes),ax);if(aA){ar=aC}aw=0}}}R(av,ax)});if(ak.wrap_links===false){R(an,function(av){function aw(aA){var az,ay,ax;if(aA.nodeName==="A"){ay=c.clone(ap,V);an.push(ay);ax=a.grep(aA.childNodes);for(az=0;az1||!H(ax))&&av===0){c.remove(ax,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&av===1){ax=aw(ax)}R(af,function(az){R(c.select(az.inline,ax),function(aB){var aA;if(az.wrap_links===false){aA=aB.parentNode;do{if(aA.nodeName==="A"){return}}while(aA=aA.parentNode)}X(az,aj,aB,az.exact?aB:null)})});if(y(ax.parentNode,ac,aj)){c.remove(ax,1);ax=0;return C}if(ak.merge_with_parents){c.getParent(ax.parentNode,function(az){if(y(az,ac,aj)){c.remove(ax,1);ax=0;return C}})}if(ax&&ak.merge_siblings!==false){ax=u(E(ax),ax);ax=u(ax,E(ax,C))}}})}if(ak){if(ae){if(ae.nodeType){aa=c.createRng();aa.setStartBefore(ae);aa.setEndAfter(ae);al(p(aa,af),null,true)}else{al(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var am=Y.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(am,c.isBlock)){W(af[0].defaultBlock)}Y.selection.setRng(ad());ai=r.getBookmark();al(p(r.getRng(C),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(am,K,"childNodes");K(am)}r.moveToBookmark(ai);P(r.getRng(C));Y.nodeChanged()}else{S("apply",ac,aj)}}}}function B(ab,ak,ad){var ae=T(ab),am=ae[0],ai,ah,aa,aj=true;function ac(at){var ar,aq,ap,ao,av,au;if(at.nodeType===1&&x(at)){av=aj;aj=x(at)==="true";au=true}ar=a.grep(at.childNodes);if(aj&&!au){for(aq=0,ap=ae.length;aq=0;aa--){Z=af[aa].selector;if(!Z){return C}for(ae=ab.length-1;ae>=0;ae--){if(c.is(ab[ae],Z)){return C}}}}return V}a.extend(this,{get:T,register:l,apply:W,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z});j();U();function h(Z,aa){if(g(Z,aa.inline)){return C}if(g(Z,aa.block)){return C}if(aa.selector){return c.is(Z,aa.selector)}}function g(aa,Z){aa=aa||"";Z=Z||"";aa=""+(aa.nodeName||aa);Z=""+(Z.nodeName||Z);return aa.toLowerCase()==Z.toLowerCase()}function N(aa,Z){var ab=c.getStyle(aa,Z);if(Z=="color"||Z=="backgroundColor"){ab=c.toHex(ab)}if(Z=="fontWeight"&&ab==700){ab="bold"}return""+ab}function q(Z,aa){if(typeof(Z)!="string"){Z=Z(aa)}else{if(aa){Z=Z.replace(/%(\w+)/g,function(ac,ab){return aa[ab]||ac})}}return Z}function f(Z){return Z&&Z.nodeType===3&&/^([\t \r\n]+|)$/.test(Z.nodeValue)}function Q(ab,aa,Z){var ac=c.create(aa,Z);ab.parentNode.insertBefore(ac,ab);ac.appendChild(ab);return ac}function p(Z,ak,ac){var an,al,af,aj,ab=Z.startContainer,ag=Z.startOffset,ap=Z.endContainer,ai=Z.endOffset;function am(ax){var ar,av,aw,au,at,aq;ar=av=ax?ab:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();if(ar.nodeType==3&&!f(ar)){if(ax?ag>0:aial?al:ag];if(ab.nodeType==3){ag=0}}if(ap.nodeType==1&&ap.hasChildNodes()){al=ap.childNodes.length-1;ap=ap.childNodes[ai>al?al:ai-1];if(ap.nodeType==3){ai=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ah(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ac){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&af.node.nodeType===3&&af.node.nodeValue.charAt(af.offset-1)===" "){if(af.offset>1){ap=af.node;ap.splitText(af.offset-1)}}}}if(ak[0].inline||ak[0].block_expand){if(!ak[0].inline||(ab.nodeType!=3||ag===0)){ab=am(true)}if(!ak[0].inline||(ap.nodeType!=3||ai===ap.nodeValue.length)){ap=am()}}if(ak[0].selector&&ak[0].expand!==V&&!ak[0].inline){ab=ad(ab,"previousSibling");ap=ad(ap,"nextSibling")}if(ak[0].block||ak[0].selector){ab=aa(ab,"previousSibling");ap=aa(ap,"nextSibling");if(ak[0].block){if(!H(ab)){ab=am(true)}if(!H(ap)){ap=am()}}}if(ab.nodeType==1){ag=s(ab);ab=ab.parentNode}if(ap.nodeType==1){ai=s(ap)+1;ap=ap.parentNode}return{startContainer:ab,startOffset:ag,endContainer:ap,endOffset:ai}}function X(af,ae,ac,Z){var ab,aa,ad;if(!h(ac,af)){return V}if(af.remove!="all"){R(af.styles,function(ah,ag){ah=q(ah,ae);if(typeof(ag)==="number"){ag=ah;Z=0}if(!Z||g(N(Z,ag),ah)){c.setStyle(ac,ag,"")}ad=1});if(ad&&c.getAttrib(ac,"style")==""){ac.removeAttribute("style");ac.removeAttribute("data-mce-style")}R(af.attributes,function(ai,ag){var ah;ai=q(ai,ae);if(typeof(ag)==="number"){ag=ai;Z=0}if(!Z||g(c.getAttrib(Z,ag),ai)){if(ag=="class"){ai=c.getAttrib(ac,ag);if(ai){ah="";R(ai.split(/\s+/),function(aj){if(/mce\w+/.test(aj)){ah+=(ah?" ":"")+aj}});if(ah){c.setAttrib(ac,ag,ah);return}}}if(ag=="class"){ac.removeAttribute("className")}if(e.test(ag)){ac.removeAttribute("data-mce-"+ag)}ac.removeAttribute(ag)}});R(af.classes,function(ag){ag=q(ag,ae);if(!Z||c.hasClass(Z,ag)){c.removeClass(ac,ag)}});aa=c.getAttribs(ac);for(ab=0;abab?ab:ad]}if(Z.nodeType===3&&ae&&ad>=Z.nodeValue.length){Z=new t(Z,Y.getBody()).next()||Z}if(Z.nodeType===3&&!ae&&ad===0){Z=new t(Z,Y.getBody()).prev()||Z}return Z}function S(ai,Z,ag){var aj="_mce_caret",aa=Y.settings.caret_debug;function ab(an){var am=c.create("span",{id:aj,"data-mce-bogus":true,style:aa?"color:red":""});if(an){am.appendChild(Y.getDoc().createTextNode(G))}return am}function ah(an,am){while(an){if((an.nodeType===3&&an.nodeValue!==G)||an.childNodes.length>1){return false}if(am&&an.nodeType===1){am.push(an)}an=an.firstChild}return true}function ae(am){while(am){if(am.id===aj){return am}am=am.parentNode}}function ad(am){var an;if(am){an=new t(am,am);for(am=an.current();am;am=an.next()){if(am.nodeType===3){return am}}}}function ac(ao,an){var ap,am;if(!ao){ao=ae(r.getStart());if(!ao){while(ao=c.get(aj)){ac(ao,false)}}}else{am=r.getRng(true);if(ah(ao)){if(an!==false){am.setStartBefore(ao);am.setEndBefore(ao)}c.remove(ao)}else{ap=ad(ao);if(ap.nodeValue.charAt(0)===G){ap=ap.deleteData(0,1)}c.remove(ao,1)}r.setRng(am)}}function af(){var ao,am,at,ar,ap,an,aq;ao=r.getRng(true);ar=ao.startOffset;an=ao.startContainer;aq=an.nodeValue;am=ae(r.getStart());if(am){at=ad(am)}if(aq&&ar>0&&ar=0;aq--){ao.appendChild(c.clone(av[aq],false));ao=ao.firstChild}ao.appendChild(c.doc.createTextNode(G));ao=ao.firstChild;c.insertAfter(au,aw);r.setCursorLocation(ao,1)}}function al(){var an,am,ao;am=ae(r.getStart());if(am&&!c.isEmpty(am)){a.walk(am,function(ap){if(ap.nodeType==1&&ap.id!==aj&&!c.isEmpty(ap)){c.setAttrib(ap,"data-mce-bogus",null)}},"childNodes")}}if(!self._hasCaretEvents){Y.onBeforeGetContent.addToTop(function(){var am=[],an;if(ah(ae(r.getStart()),am)){an=am.length;while(an--){c.setAttrib(am[an],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(am){Y[am].addToTop(function(){ac();al()})});Y.onKeyDown.addToTop(function(am,ao){var an=ao.keyCode;if(an==8||an==37||an==39){ac(ae(r.getStart()))}al()});r.onSetContent.add(al);self._hasCaretEvents=true}if(ai=="apply"){af()}else{ak()}}function P(aa){var Z=aa.startContainer,ag=aa.startOffset,ac,af,ae,ab,ad;if(Z.nodeType==3&&ag>=Z.nodeValue.length){ag=s(Z);Z=Z.parentNode;ac=true}if(Z.nodeType==1){ab=Z.childNodes;Z=ab[Math.min(ag,ab.length-1)];af=new t(Z,c.getParent(Z,c.isBlock));if(ag>ab.length-1||ac){af.next()}for(ae=af.current();ae;ae=af.next()){if(ae.nodeType==3&&!f(ae)){ad=c.create("a",null,G);ae.parentNode.insertBefore(ad,ae);aa.setStart(ae,0);r.setRng(aa);c.remove(ad);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(e){var h=e.dom,d=e.selection,c=e.settings,g=e.undoManager;function f(y){var u=d.getRng(true),C,i,x,t,o,H,n,j,l,s,E,v,z;function B(I){return I&&h.isBlock(I)&&!/^(TD|TH|CAPTION)$/.test(I.nodeName)&&!/^(fixed|absolute)/i.test(I.style.position)&&h.getContentEditable(I)!=="true"}function m(J){var O,M,I,P,N,L=J,K;I=h.createRng();if(J.hasChildNodes()){O=new a(J,J);while(M=O.current()){if(M.nodeType==3){I.setStart(M,0);I.setEnd(M,0);break}if(/^(BR|IMG)$/.test(M.nodeName)){I.setStartBefore(M);I.setEndBefore(M);break}L=M;M=O.next()}if(!M){I.setStart(L,0);I.setEnd(L,0)}}else{if(J.nodeName=="BR"){if(J.nextSibling&&h.isBlock(J.nextSibling)){if(!H||H<9){K=h.create("br");J.parentNode.insertBefore(K,J)}I.setStartBefore(J);I.setEndBefore(J)}else{I.setStartAfter(J);I.setEndAfter(J)}}else{I.setStart(J,0);I.setEnd(J,0)}}d.setRng(I);h.remove(K);N=h.getViewPort(e.getWin());P=h.getPos(J).y;if(PN.y+N.h){e.getWin().scrollTo(0,P"}return M}function p(L){var K,J,I;if(x.nodeType==3&&(L?t>0:t=x.nodeValue.length){if(!b.isIE&&!A()){J=h.create("br");u.insertNode(J);u.setStartAfter(J);u.setEndAfter(J);I=true}}J=h.create("br");u.insertNode(J);if(b.isIE&&s=="PRE"&&(!H||H<8)){J.parentNode.insertBefore(h.doc.createTextNode("\r"),J)}if(!I){u.setStartAfter(J);u.setEndAfter(J)}else{u.setStartBefore(J);u.setEndBefore(J)}d.setRng(u);g.add()}function r(I){do{if(I.nodeType===3){I.nodeValue=I.nodeValue.replace(/^[\r\n]+/,"")}I=I.firstChild}while(I)}function F(K){var I=h.getRoot(),J,L;J=K;while(J!==I&&h.getContentEditable(J)!=="false"){if(h.getContentEditable(J)==="true"){L=J}J=J.parentNode}return J!==I?L:I}if(!u.collapsed){e.execCommand("Delete");return}if(y.isDefaultPrevented()){return}x=u.startContainer;t=u.startOffset;v=c.forced_root_block;v=v?v.toUpperCase():"";H=h.doc.documentMode;if(x.nodeType==1&&x.hasChildNodes()){z=t>x.childNodes.length-1;x=x.childNodes[Math.min(t,x.childNodes.length-1)]||x;t=0}i=F(x);if(!i){return}g.beforeChange();if(!h.isBlock(i)&&i!=h.getRoot()){if(!v||y.shiftKey){G()}return}if((v&&!y.shiftKey)||(!v&&y.shiftKey)){x=k(x,t)}o=h.getParent(x,h.isBlock);l=o?h.getParent(o.parentNode,h.isBlock):null;s=o?o.nodeName.toUpperCase():"";E=l?l.nodeName.toUpperCase():"";if(s=="LI"&&h.isEmpty(o)){if(/^(UL|OL|LI)$/.test(l.parentNode.nodeName)){return false}D();return}if(s=="PRE"&&c.br_in_pre!==false){if(!y.shiftKey){G();return}}else{if((!v&&!y.shiftKey&&s!="LI")||(v&&y.shiftKey)){G();return}}v=v||"P";if(p()){if(/^(H[1-6]|PRE)$/.test(s)&&E!="HGROUP"){n=q(v)}else{n=q()}if(c.end_container_on_empty_block&&B(l)&&h.isEmpty(o)){n=h.split(l,o)}else{h.insertAfter(n,o)}}else{if(p(true)){n=o.parentNode.insertBefore(q(),o)}else{C=u.cloneRange();C.setEndAfter(o);j=C.extractContents();r(j);n=j.firstChild;h.insertAfter(j,o)}}h.setAttrib(n,"id","");m(n);g.add()}e.onKeyDown.add(function(j,i){if(i.keyCode==13){if(f(i)!==false){i.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery_src.js similarity index 98% rename from lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery_src.js index 04a6c215d6d..d4e8353b095 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery_src.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_jquery_src.js @@ -1831,6 +1831,14 @@ tinymce.util.Quirks = function(editor) { editor.onSetContent.add(selection.onSetContent.add(fixLinks)); }; + function setDefaultBlockType() { + if (settings.forced_root_block) { + editor.onInit.add(function() { + setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block); + }); + } + } + function removeGhostSelection() { function repaint(sender, args) { if (!sender || !args.initial) { @@ -1865,6 +1873,7 @@ tinymce.util.Quirks = function(editor) { cleanupStylesWhenDeleting(); inputMethodFocus(); selectControlElements(); + setDefaultBlockType(); // iOS if (tinymce.isIDevice) { @@ -2340,8 +2349,11 @@ tinymce.html.Styles = function(settings, schema) { if (!html5) { html5 = mapCache.html5 = unpack({ A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title', - B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video', - C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' + B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|' + + 'meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video', + C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|' + + 'figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|' + + 'p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' }, 'html[A|manifest][body|head]' + 'head[A][base|command|link|meta|noscript|script|style|title]' + 'title[A][#]' + @@ -2377,7 +2389,7 @@ tinymce.html.Styles = function(settings, schema) { 'dl[A][dd|dt]' + 'dt[A][B]' + 'dd[A][C]' + - 'a[A|href|target|ping|rel|media|type][C]' + + 'a[A|href|target|ping|rel|media|type][B]' + 'em[A][B]' + 'strong[A][B]' + 'small[A][B]' + @@ -2423,7 +2435,8 @@ tinymce.html.Styles = function(settings, schema) { 'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' + 'fieldset[A|disabled|form|name][C|legend]' + 'label[A|form|for][B]' + - 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]' + + 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' + + 'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' + 'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' + 'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' + 'datalist[A][B|option]' + @@ -2626,13 +2639,13 @@ tinymce.html.Styles = function(settings, schema) { // Setup map objects whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script style textarea'); - selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li options p td tfoot th thead tr'); + selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr'); shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source'); boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls'); nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object', shortEndedElementsMap); blockElementsMap = createLookupTable('block_elements', 'h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot ' + 'th tr td li ol ul caption blockquote center dl dt dd dir fieldset ' + - 'noscript menu isindex samp header footer article section hgroup aside nav figure'); + 'noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup'); // Converts a wildcard expression string to a regexp for example *a will become /.*a/. function patternToRegExp(str) { @@ -3076,7 +3089,7 @@ tinymce.html.Styles = function(settings, schema) { // Setup lookup tables for empty elements and boolean attributes shortEndedElements = schema.getShortEndedElements(); - selfClosing = schema.getSelfClosingElements(); + selfClosing = settings.self_closing_elements || schema.getSelfClosingElements(); fillAttrsMap = schema.getBoolAttrs(); validate = settings.validate; removeInternalElements = settings.remove_internals; @@ -3822,9 +3835,23 @@ tinymce.html.Styles = function(settings, schema) { } }; + function cloneAndExcludeBlocks(input) { + var name, output = {}; + + for (name in input) { + if (name !== 'li' && name != 'p') { + output[name] = input[name]; + } + } + + return output; + }; + parser = new tinymce.html.SaxParser({ validate : validate, - fix_self_closing : !validate, // Let the DOM parser handle
                        • in
                        • or

                          in

                          for better results + + // Exclude P and LI from DOM parsing since it's treated better by the DOM parser + self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()), cdata: function(text) { node.append(createNode('#cdata', 4)).value = text; @@ -4002,7 +4029,7 @@ tinymce.html.Styles = function(settings, schema) { node.empty().append(new Node('#text', '3')).value = '\u00a0'; else { // Leave nodes that have a name like - if (!node.attributes.map.name) { + if (!node.attributes.map.name && !node.attributes.map.id) { tempNode = node.parent; node.empty().remove(); node = tempNode; @@ -4154,12 +4181,12 @@ tinymce.html.Styles = function(settings, schema) { // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. if (!settings.allow_html_in_named_anchor) { - self.addAttributeFilter('name', function(nodes, name) { + self.addAttributeFilter('id,name', function(nodes, name) { var i = nodes.length, sibling, prevSibling, parent, node; while (i--) { node = nodes[i]; - if (node.name === 'a' && node.firstChild) { + if (node.name === 'a' && node.firstChild && !node.attr('href')) { parent = node.parent; // Move children after current node @@ -6357,7 +6384,8 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { cloneContents : cloneContents, insertNode : insertNode, surroundContents : surroundContents, - cloneRange : cloneRange + cloneRange : cloneRange, + toStringIE : toStringIE }); function createDocumentFragment() { @@ -6997,9 +7025,20 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { n.parentNode.removeChild(n); }; + + function toStringIE() { + return dom.create('body', null, cloneContents()).outerText; + } + + return t; }; ns.Range = Range; + + // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype + Range.prototype.toString = function() { + return this.toStringIE(); + }; })(tinymce.dom); (function() { function Selection(selection) { @@ -7354,7 +7393,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { }; this.addRange = function(rng) { - var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body; + var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling, doc = selection.dom.doc, body = doc.body; function setEndPoint(start) { var container, offset, marker, tmpRng, nodes; @@ -7412,11 +7451,25 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { // Trick to place the caret inside an empty block element like

                          if (startOffset == endOffset && !startContainer.hasChildNodes()) { if (startContainer.canHaveHTML) { + // Check if previous sibling is an empty block if it is then we need to render it + // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236 + // Example this:

                          |

                          would become this:

                          |

                          + sibling = startContainer.previousSibling; + if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) { + sibling.innerHTML = '\uFEFF'; + } else { + sibling = null; + } + startContainer.innerHTML = '\uFEFF\uFEFF'; ieRng.moveToElementText(startContainer.lastChild); ieRng.select(); dom.doc.selection.clear(); startContainer.innerHTML = ''; + + if (sibling) { + sibling.innerHTML = ''; + } return; } else { startOffset = dom.nodeIndex(startContainer); @@ -8958,11 +9011,10 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { } // Create new script element - elm = dom.create('script', { - id : id, - type : 'text/javascript', - src : tinymce._addVer(url) - }); + elm = document.createElement('script'); + elm.id = id; + elm.type = 'text/javascript'; + elm.src = tinymce._addVer(url); // Add onload listener for non IE browsers since IE9 // fires onload event before the script is parsed and executed @@ -9324,12 +9376,15 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { t.destroy = function() { each(items, function(item) { - dom.unbind(dom.get(item.id), 'focus', itemFocussed); - dom.unbind(dom.get(item.id), 'blur', itemBlurred); + var elm = dom.get(item.id); + + dom.unbind(elm, 'focus', itemFocussed); + dom.unbind(elm, 'blur', itemBlurred); }); - dom.unbind(dom.get(root), 'focus', rootFocussed); - dom.unbind(dom.get(root), 'keydown', rootKeydown); + var rootElm = dom.get(root); + dom.unbind(rootElm, 'focus', rootFocussed); + dom.unbind(rootElm, 'keydown', rootKeydown); items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; t.destroy = function() {}; @@ -9408,21 +9463,23 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { // Set up state and listeners for each item. each(items, function(item, idx) { - var tabindex; + var tabindex, elm; if (!item.id) { item.id = dom.uniqueId('_mce_item_'); } + elm = dom.get(item.id); + if (excludeFromTabOrder) { - dom.bind(item.id, 'blur', itemBlurred); + dom.bind(elm, 'blur', itemBlurred); tabindex = '-1'; } else { tabindex = (idx === 0 ? '0' : '-1'); } - dom.setAttrib(item.id, 'tabindex', tabindex); - dom.bind(dom.get(item.id), 'focus', itemFocussed); + elm.setAttribute('tabindex', tabindex); + dom.bind(elm, 'focus', itemFocussed); }); // Setup initial state for root element. @@ -9431,10 +9488,11 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { } dom.setAttrib(root, 'tabindex', '-1'); - + // Setup listeners for root element. - dom.bind(dom.get(root), 'focus', rootFocussed); - dom.bind(dom.get(root), 'keydown', rootKeydown); + var rootElm = dom.get(root); + dom.bind(rootElm, 'focus', rootFocussed); + dom.bind(rootElm, 'keydown', rootKeydown); } }); })(tinymce); @@ -11541,8 +11599,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { inline_styles : TRUE, convert_fonts_to_spans : TRUE, indent : 'simple', - indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure', - indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure', + indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', + indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', validate : TRUE, entity_encoding : 'named', url_converter : self.convertURL, @@ -11602,6 +11660,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); + // Hide target element early to prevent content flashing + t.orgVisibility = t.getElement().style.visibility; + t.getElement().style.visibility = 'hidden'; + if (tinymce.WindowManager) t.windowManager = new tinymce.WindowManager(t); @@ -11664,7 +11726,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { //sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); sl.add(tinymce.baseURL + '/../../extra/strings.php?elanguage=' + s.language + 'ðeme=' + s.theme); // Moodle modification - load one huge strings file - if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) + if (s.theme && typeof s.theme != "function" && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); each(explode(s.plugins), function(p) { @@ -11705,13 +11767,18 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); if (s.theme) { - s.theme = s.theme.replace(/-/, ''); - o = ThemeManager.get(s.theme); - t.theme = new o(); + if (typeof s.theme != "function") { + s.theme = s.theme.replace(/-/, ''); + o = ThemeManager.get(s.theme); + t.theme = new o(); - if (t.theme.init) - t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + if (t.theme.init) + t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + } else { + t.theme = s.theme; + } } + function initPlugin(p) { var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; if (c && tinymce.inArray(initializedPlugins,p) === -1) { @@ -11756,26 +11823,57 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { // Measure box if (s.render_ui && t.theme) { - w = s.width || e.style.width || e.offsetWidth; - h = s.height || e.style.height || e.offsetHeight; t.orgDisplay = e.style.display; - re = /^[0-9\.]+(|px)$/i; - if (re.test('' + w)) - w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); + if (typeof s.theme != "function") { + w = s.width || e.style.width || e.offsetWidth; + h = s.height || e.style.height || e.offsetHeight; + re = /^[0-9\.]+(|px)$/i; - if (re.test('' + h)) - //h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100); - h = Math.max(parseInt(h) + (o.deltaHeight || 0), s.theme_advanced_resizing_min_height || 100); // Moodle hack + if (re.test('' + w)) + w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); - // Render UI - o = t.theme.renderUI({ - targetNode : e, - width : w, - height : h, - deltaWidth : s.delta_width, - deltaHeight : s.delta_height - }); + if (re.test('' + h)) + //h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100); + h = Math.max(parseInt(h) + (o.deltaHeight || 0), s.theme_advanced_resizing_min_height || 100); // Moodle hack + + // Render UI + o = t.theme.renderUI({ + targetNode : e, + width : w, + height : h, + deltaWidth : s.delta_width, + deltaHeight : s.delta_height + }); + + // Resize editor + DOM.setStyles(o.sizeContainer || o.editorContainer, { + width : w, + height : h + }); + + h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); + //if (h < 100) + // h = 100; + if (h < (s.theme_advanced_resizing_min_height || 100)) // Moodle hack + h = s.theme_advanced_resizing_min_height || 100; // Moodle hack + + } else { + o = s.theme(t, e); + + // Convert element type to id:s + if (o.editorContainer.nodeType) { + o.editorContainer = o.editorContainer.id = o.editorContainer.id || t.id + "_parent"; + } + + // Convert element type to id:s + if (o.iframeContainer.nodeType) { + o.iframeContainer = o.iframeContainer.id = o.iframeContainer.id || t.id + "_iframecontainer"; + } + + // Use specified iframe height or the targets offsetHeight + h = o.iframeHeight || e.offsetHeight; + } t.editorContainer = o.editorContainer; } @@ -11797,18 +11895,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (document.domain && location.hostname != document.domain) tinymce.relaxedDomain = document.domain; - // Resize editor - DOM.setStyles(o.sizeContainer || o.editorContainer, { - width : w, - height : h - }); - - h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); - //if (h < 100) - // h = 100; - if (h < (s.theme_advanced_resizing_min_height || 100)) // Moodle hack - h = s.theme_advanced_resizing_min_height || 100; // Moodle hack - t.iframeHTML = s.doctype + ''; // We only need to override paths if we have to @@ -11867,7 +11953,14 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }); t.contentAreaContainer = o.iframeContainer; - DOM.get(o.editorContainer).style.display = t.orgDisplay; + + if (o.editorContainer) { + DOM.get(o.editorContainer).style.display = t.orgDisplay; + } + + // Restore visibility on target element + e.style.visibility = t.orgVisibility; + DOM.get(t.id).style.display = 'none'; DOM.setAttrib(t.id, 'aria-hidden', true); @@ -12192,9 +12285,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (self.initialized) { o = o || {}; - // Normalize selection for example a|a becomes a|a - selection.normalize(); - // Get start node node = selection.getStart() || self.getBody(); node = isIE && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state @@ -12672,14 +12762,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { return; case 'A': - value = dom.getAttrib(elm, 'name'); - cls = 'mceItemAnchor'; + if (!elm.href) { + value = dom.getAttrib(elm, 'name') || elm.id; + cls = 'mceItemAnchor'; - if (value) { - if (self.hasVisual) - dom.addClass(elm, cls); - else - dom.removeClass(elm, cls); + if (value) { + if (self.hasVisual) + dom.addClass(elm, cls); + else + dom.removeClass(elm, cls); + } } return; @@ -12974,6 +13066,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { self.focus(true); }; + function nodeChanged() { + // Normalize selection for example a|a becomes a|a + self.selection.normalize(); + self.nodeChanged(); + } + // Add DOM events each(nativeToDispatcherMap, function(dispatcherName, nativeName) { var root = settings.content_editable ? self.getBody() : self.getDoc(); @@ -13008,13 +13106,13 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { } // Add node change handler - self.onMouseUp.add(self.nodeChanged); + self.onMouseUp.add(nodeChanged); self.onKeyUp.add(function(ed, e) { var keyCode = e.keyCode; if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || keyCode == 46 || keyCode == 8 || (tinymce.isMac && (keyCode == 91 || keyCode == 93)) || e.ctrlKey) - self.nodeChanged(); + nodeChanged(); }); // Add reset handler @@ -13621,9 +13719,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }; // Create event instances - onAdd = new Dispatcher(self); - onUndo = new Dispatcher(self); - onRedo = new Dispatcher(self); + onBeforeAdd = new Dispatcher(self); + onAdd = new Dispatcher(self); + onUndo = new Dispatcher(self); + onRedo = new Dispatcher(self); // Pass though onAdd event from UndoManager to Editor as onChange onAdd.add(function(undoman, level) { @@ -13712,6 +13811,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { data : data, typing : false, + + onBeforeAdd: onBeforeAdd, onAdd : onAdd, @@ -13728,6 +13829,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { level = level || {}; level.content = getContent(); + + self.onBeforeAdd.dispatch(self, level); // Add undo level if needed lastLevel = data[index]; @@ -13828,7 +13931,7 @@ tinymce.ForceBlocks = function(editor) { return; // Check if node is wrapped in block - while (node != rootNode) { + while (node && node != rootNode) { if (blockElements[node.nodeName]) return; @@ -13968,28 +14071,40 @@ tinymce.ForceBlocks = function(editor) { return c; }, - createControl : function(n) { - var c, t = this, ed = t.editor; + createControl : function(name) { + var ctrl, i, l, self = this, editor = self.editor, factories, ctrlName; - each(ed.plugins, function(p) { - if (p.createControl) { - c = p.createControl(n, t); - - if (c) - return false; - } - }); - - switch (n) { - case "|": - case "separator": - return t.createSeparator(); + // Build control factory cache + if (!self.controlFactories) { + self.controlFactories = []; + each(editor.plugins, function(plugin) { + if (plugin.createControl) { + self.controlFactories.push(plugin); + } + }); } - if (!c && ed.buttons && (c = ed.buttons[n])) - return t.createButton(n, c); + // Create controls by asking cached factories + factories = self.controlFactories; + for (i = 0, l = factories.length; i < l; i++) { + ctrl = factories[i].createControl(name, self); - return t.add(c); + if (ctrl) { + return self.add(ctrl); + } + } + + // Create sepearator + if (name === "|" || name === "separator") { + return self.createSeparator(); + } + + // Create control from button collection + if (editor.buttons && (ctrl = editor.buttons[name])) { + return self.createButton(name, ctrl); + } + + return self.add(ctrl); }, createDropMenu : function(id, s, cc) { @@ -16249,6 +16364,21 @@ tinymce.ForceBlocks = function(editor) { } }; + // Checks if the parent caret container node isn't empty if that is the case it + // will remove the bogus state on all children that isn't empty + function unmarkBogusCaretParents() { + var i, caretContainer, node; + + caretContainer = getParentCaretContainer(selection.getStart()); + if (caretContainer && !dom.isEmpty(caretContainer)) { + tinymce.walk(caretContainer, function(node) { + if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) { + dom.setAttrib(node, 'data-mce-bogus', null); + } + }, 'childNodes'); + } + }; + // Only bind the caret events once if (!self._hasCaretEvents) { // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements @@ -16268,6 +16398,7 @@ tinymce.ForceBlocks = function(editor) { tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { ed[name].addToTop(function() { removeCaretContainer(); + unmarkBogusCaretParents(); }); }); @@ -16278,16 +16409,12 @@ tinymce.ForceBlocks = function(editor) { if (keyCode == 8 || keyCode == 37 || keyCode == 39) { removeCaretContainer(getParentCaretContainer(selection.getStart())); } + + unmarkBogusCaretParents(); }); // Remove bogus state if they got filled by contents using editor.selection.setContent - selection.onSetContent.add(function() { - dom.getParent(selection.getStart(), function(node) { - if (node.id !== caretContainerId && dom.getAttrib(node, 'data-mce-bogus') && !dom.isEmpty(node)) { - dom.setAttrib(node, 'data-mce-bogus', null); - } - }); - }); + selection.onSetContent.add(unmarkBogusCaretParents); self._hasCaretEvents = true; } diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_popup.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_popup.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/tiny_mce_popup.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_popup.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_popup_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_popup_src.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/tiny_mce_popup_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_popup_src.js diff --git a/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype.js new file mode 100644 index 00000000000..f0b0b2a4315 --- /dev/null +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype.js @@ -0,0 +1 @@ +(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"@@tinymce_major_version@@",minorVersion:"@@tinymce_minor_version@@",releaseDate:"@@tinymce_release_date@@",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey}}})(tinymce);tinymce.util.Quirks=function(d){var l=tinymce.VK,r=l.BACKSPACE,s=l.DELETE,o=d.dom,A=d.selection,q=d.settings;function c(E,D){try{d.getDoc().execCommand(E,false,D)}catch(C){}}function h(){function C(F){var D,H,E,G;D=A.getRng();H=o.getParent(D.startContainer,o.isBlock);if(F){H=o.getNext(H,o.isBlock)}if(H){E=H.firstChild;while(E&&E.nodeType==3&&E.nodeValue.length===0){E=E.nextSibling}if(E&&E.nodeName==="SPAN"){G=E.cloneNode(false)}}d.getDoc().execCommand(F?"ForwardDelete":"Delete",false,null);H=o.getParent(D.startContainer,o.isBlock);tinymce.each(o.select("span.Apple-style-span,font.Apple-style-span",H),function(I){var J=A.getBookmark();if(G){o.replace(G.cloneNode(false),I,true)}else{o.remove(I,true)}A.moveToBookmark(J)})}d.onKeyDown.add(function(D,F){var E;E=F.keyCode==s;if(!F.isDefaultPrevented()&&(E||F.keyCode==r)&&!l.modifierPressed(F)){F.preventDefault();C(E)}});d.addCommand("Delete",function(){C()})}function B(){function D(F,I){var E,H,G=I?"start":"end";E=F[G+"Container"];H=F[G+"Offset"];if(E.nodeType==1&&E.hasChildNodes()){E=E.childNodes[Math.min(I?H:(H>0?H-1:0),E.childNodes.length-1)]}return E}function C(H,L){var G,K,F,I,J=L?"start":"end",E;G=H[J+"Container"];K=H[J+"Offset"];F=o.getRoot();if(G.nodeType==1){E=K>=G.childNodes.length;G=D(H,L);if(G.nodeType==3){K=L&&!E?0:G.nodeValue.length}}if(G.nodeType==3&&((L&&K>0)||(!L&&K7){return}c("RespectVisibilityInDesign",true);o.addClass(d.getBody(),"mceHideBrInPre");d.parser.addNodeFilter("pre",function(D,F){var G=D.length,I,E,J,H;while(G--){I=D[G].getAll("br");E=I.length;while(E--){J=I[E];H=J.prev;if(H&&H.type===3&&H.value.charAt(H.value-1)!="\n"){H.value+="\n"}else{J.parent.insert(new tinymce.html.Node("#text",3),J,true).value="\n"}}}});d.serializer.addNodeFilter("pre",function(D,F){var G=D.length,I,E,J,H;while(G--){I=D[G].getAll("br");E=I.length;while(E--){J=I[E];H=J.prev;if(H&&H.type==3){H.value=H.value.replace(/\r?\n$/,"")}}}})}function f(){o.bind(d.getBody(),"mouseup",function(E){var D,C=A.getNode();if(C.nodeName=="IMG"){if(D=o.getStyle(C,"width")){o.setAttrib(C,"width",D.replace(/[^0-9%]+/g,""));o.setStyle(C,"width","")}if(D=o.getStyle(C,"height")){o.setAttrib(C,"height",D.replace(/[^0-9%]+/g,""));o.setStyle(C,"height","")}}})}function p(){d.onKeyDown.add(function(I,J){var H,C,D,F,G,K,E;H=J.keyCode==s;if(!J.isDefaultPrevented()&&(H||J.keyCode==r)&&!l.modifierPressed(J)){C=A.getRng();D=C.startContainer;F=C.startOffset;E=C.collapsed;if(D.nodeType==3&&D.nodeValue.length>0&&((F===0&&!E)||(E&&F===(H?0:1)))){nonEmptyElements=I.schema.getNonEmptyElements();J.preventDefault();G=o.create("br",{id:"__tmp"});D.parentNode.insertBefore(G,D);I.getDoc().execCommand(H?"ForwardDelete":"Delete",false,null);D=A.getRng().startContainer;K=D.previousSibling;if(K&&K.nodeType==1&&!o.isBlock(K)&&o.isEmpty(K)&&!nonEmptyElements[K.nodeName.toLowerCase()]){o.remove(K)}o.remove("__tmp")}}})}function e(){d.onKeyDown.add(function(G,H){var E,D,I,C,F;if(H.isDefaultPrevented()||H.keyCode!=l.BACKSPACE){return}E=A.getRng();D=E.startContainer;I=E.startOffset;C=o.getRoot();F=D;if(!E.collapsed||I!==0){return}while(F&&F.parentNode&&F.parentNode.firstChild==F&&F.parentNode!=C){F=F.parentNode}if(F.tagName==="BLOCKQUOTE"){G.formatter.toggle("blockquote",null,F);E.setStart(D,0);E.setEnd(D,0);A.setRng(E);A.collapse(false)}})}function k(){function C(){d._refreshContentEditable();c("StyleWithCSS",false);c("enableInlineTableEditing",false);if(!q.object_resizing){c("enableObjectResizing",false)}}if(!q.readonly){d.onBeforeExecCommand.add(C);d.onMouseDown.add(C)}}function n(){function C(D,E){tinymce.each(o.select("a"),function(H){var F=H.parentNode,G=o.getRoot();if(F.lastChild===H){while(F&&!o.isBlock(F)){if(F.parentNode.lastChild!==F||F===G){return}F=F.parentNode}o.add(F,"br",{"data-mce-bogus":1})}})}d.onExecCommand.add(function(D,E){if(E==="CreateLink"){C(D)}});d.onSetContent.add(A.onSetContent.add(C))}function t(){if(q.forced_root_block){d.onInit.add(function(){c("DefaultParagraphSeparator",q.forced_root_block)})}}function a(){function C(E,D){if(!E||!D.initial){d.execCommand("mceRepaint")}}d.onUndo.add(C);d.onRedo.add(C);d.onSetContent.add(C)}function j(){d.onKeyDown.add(function(C,D){if(!D.isDefaultPrevented()&&D.keyCode==8&&A.getNode().nodeName=="IMG"){D.preventDefault();C.undoManager.beforeChange();o.remove(A.getNode());C.undoManager.add()}})}v();e();B();if(tinymce.isWebKit){p();h();u();x();t();if(tinymce.isIDevice){i()}}if(tinymce.isIE){m();z();g();f();j()}if(tinymce.isGecko){m();b();y();k();n();a()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][B]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script style textarea");q=m("self_closing_elements","colgroup dd dt li option p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object",z);v=m("block_elements","h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot th tr td li ol ul caption blockquote center dl dt dd dir fieldset noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup");function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=c.self_closing_elements||e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t0){Q.value=l;Q=Q.prev}else{O=Q.prev;Q.remove();Q=O}}}function H(O){var P,l={};for(P in O){if(P!=="li"&&P!="p"){l[P]=O[P]}}return l}n=new b.html.SaxParser({validate:z,self_closing_elements:H(h.getSelfClosingElements()),cdata:function(l){B.append(K("#cdata",4)).value=l},text:function(P,l){var O;if(!L){P=P.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){P=P.replace(E,"")}}if(P.length!==0){O=K("#text",3);O.raw=!!l;B.append(O).value=P}},comment:function(l){B.append(K("#comment",8)).value=l},pi:function(l,O){B.append(K(l,7)).value=O;I(B)},doctype:function(O){var l;l=B.append(K("#doctype",10));l.value=O;I(B)},start:function(l,W,P){var U,R,Q,O,S,X,V,T;Q=z?h.getElementRule(l):{};if(Q){U=K(Q.outputName||l,1);U.attributes=W;U.shortEnded=P;B.append(U);T=p[B.name];if(T&&p[U.name]&&!T[U.name]){M.push(U)}R=d.length;while(R--){S=d[R].name;if(S in W.map){F=c[S];if(F){F.push(U)}else{c[S]=[U]}}}if(o[l]){I(U)}if(!P){B=U}if(!L&&s[l]){L=true}}},end:function(l){var S,P,R,O,Q;P=z?h.getElementRule(l):{};if(P){if(o[l]){if(!L){S=B.firstChild;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R;S=S.next}else{O=S.next;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.next;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}S=B.lastChild;if(S&&S.type===3){R=S.value.replace(t,"");if(R.length>0){S.value=R;S=S.prev}else{O=S.prev;S.remove();S=O}while(S&&S.type===3){R=S.value;O=S.prev;if(R.length===0||y.test(R)){S.remove();S=O}S=O}}}S=B.prev;if(S&&S.type===3){R=S.value.replace(E,"");if(R.length>0){S.value=R}else{S.remove()}}}if(L&&s[l]){L=false}if(P.removeEmpty||P.paddEmpty){if(B.isEmpty(u)){if(P.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name&&!B.attributes.map.id){Q=B.parent;B.empty().remove();B=Q;return}}}}B=B.parent}}},h);J=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&M.length){if(!m.context){j(M)}else{m.invalid=true}}if(q&&J.name=="body"){G()}if(!m.invalid){for(N in i){F=e[N];A=i[N];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},select:function(k,j){var i=this;return e.dom.Sizzle(k,i.get(j)||i.get(i.settings.root_element)||i.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(c.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return e.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":b?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
                          "+j;m.removeChild(m.firstChild)}catch(l){m=i.create("div");m.innerHTML="
                          "+j;g(m.childNodes,function(o,n){if(n){m.appendChild(o)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){g(s.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:q(s.styleSheet);break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,U=0,F=1,j=2,E=true,S=false,W="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L,toStringIE:T});function x(){return e.createDocumentFragment()}function q(X,t){C(E,X,t)}function s(X,t){C(S,X,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[W]}else{O[h]=O[Q];O[W]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(aa,t){var ad=O[h],Y=O[W],ac=O[Q],X=O[A],ab=t.startContainer,af=t.startOffset,Z=t.endContainer,ae=t.endOffset;if(aa===0){return H(ad,Y,ab,af)}if(aa===1){return H(ac,X,ab,af)}if(aa===2){return H(ac,X,Z,ae)}if(aa===3){return H(ad,Y,Z,ae)}}function p(){l(j)}function I(){return l(U)}function d(){return l(F)}function D(aa){var X=this[h],t=this[W],Z,Y;if((X.nodeType===3||X.nodeType===4)&&X.nodeValue){if(!t){X.parentNode.insertBefore(aa,X)}else{if(t>=X.nodeValue.length){c.insertAfter(aa,X)}else{Z=X.splitText(t);X.parentNode.insertBefore(aa,Z)}}}else{if(X.childNodes.length>0){Y=X.childNodes[t]}if(Y){X.insertBefore(aa,Y)}else{X.appendChild(aa)}}}function N(X){var t=O.extractContents();O.insertNode(X);X.appendChild(t);O.selectNode(X)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[W],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,X){var Y;if(t.nodeType==3){return t}if(X<0){return t}Y=t.firstChild;while(Y&&X>0){--X;Y=Y.nextSibling}if(Y){return Y}return t}function m(){return(O[h]==O[Q]&&O[W]==O[A])}function H(Z,ab,X,aa){var ac,Y,t,ad,af,ae;if(Z==X){if(ab==aa){return 0}if(ab0){O.collapse(X)}}else{O.collapse(X)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ad){var ac,Z=0,af=0,X,ab,Y,aa,t,ae;if(O[h]==O[Q]){return f(ad)}for(ac=O[Q],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[h]){return r(ac,ad)}++Z}for(ac=O[h],X=ac.parentNode;X;ac=X,X=X.parentNode){if(X==O[Q]){return V(ac,ad)}++af}ab=af-Z;Y=O[h];while(ab>0){Y=Y.parentNode;ab--}aa=O[Q];while(ab<0){aa=aa.parentNode;ab++}for(t=Y.parentNode,ae=aa.parentNode;t!=ae;t=t.parentNode,ae=ae.parentNode){Y=t;aa=ae}return o(Y,aa,ad)}function f(ac){var ae,af,t,Y,Z,ad,aa,X,ab;if(ac!=j){ae=x()}if(O[W]==O[A]){return ae}if(O[h].nodeType==3){af=O[h].nodeValue;t=af.substring(O[W],O[A]);if(ac!=F){Y=O[h];X=O[W];ab=O[A]-O[W];if(X===0&&ab>=Y.nodeValue.length-1){Y.parentNode.removeChild(Y)}else{Y.deleteData(X,ab)}O.collapse(E)}if(ac==j){return}if(t.length>0){ae.appendChild(e.createTextNode(t))}return ae}Y=P(O[h],O[W]);Z=O[A]-O[W];while(Y&&Z>0){ad=Y.nextSibling;aa=z(Y,ac);if(ae){ae.appendChild(aa)}--Z;Y=ad}if(ac!=F){O.collapse(E)}return ae}function r(ad,aa){var ac,ab,X,t,Z,Y;if(aa!=j){ac=x()}ab=i(ad,aa);if(ac){ac.appendChild(ab)}X=n(ad);t=X-O[W];if(t<=0){if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}ab=ad.previousSibling;while(t>0){Z=ab.previousSibling;Y=z(ab,aa);if(ac){ac.insertBefore(Y,ac.firstChild)}--t;ab=Z}if(aa!=F){O.setEndBefore(ad);O.collapse(S)}return ac}function V(ab,aa){var ad,X,ac,t,Z,Y;if(aa!=j){ad=x()}ac=R(ab,aa);if(ad){ad.appendChild(ac)}X=n(ab);++X;t=O[A]-X;ac=ab.nextSibling;while(ac&&t>0){Z=ac.nextSibling;Y=z(ac,aa);if(ad){ad.appendChild(Y)}--t;ac=Z}if(aa!=F){O.setStartAfter(ab);O.collapse(E)}return ad}function o(ab,t,ae){var Y,ag,aa,ac,ad,X,af,Z;if(ae!=j){ag=x()}Y=R(ab,ae);if(ag){ag.appendChild(Y)}aa=ab.parentNode;ac=n(ab);ad=n(t);++ac;X=ad-ac;af=ab.nextSibling;while(X>0){Z=af.nextSibling;Y=z(af,ae);if(ag){ag.appendChild(Y)}af=Z;--X}Y=i(t,ae);if(ag){ag.appendChild(Y)}if(ae!=F){O.setStartAfter(ab);O.collapse(E)}return ag}function i(ac,ad){var Y=P(O[Q],O[A]-1),ae,ab,aa,t,X,Z=Y!=O[Q];if(Y==ac){return M(Y,Z,S,ad)}ae=Y.parentNode;ab=M(ae,S,S,ad);while(ae){while(Y){aa=Y.previousSibling;t=M(Y,Z,S,ad);if(ad!=j){ab.insertBefore(t,ab.firstChild)}Z=E;Y=aa}if(ae==ac){return ab}Y=ae.previousSibling;ae=ae.parentNode;X=M(ae,S,S,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function R(ac,ad){var Z=P(O[h],O[W]),aa=Z!=O[h],ae,ab,Y,t,X;if(Z==ac){return M(Z,aa,E,ad)}ae=Z.parentNode;ab=M(ae,S,E,ad);while(ae){while(Z){Y=Z.nextSibling;t=M(Z,aa,E,ad);if(ad!=j){ab.appendChild(t)}aa=E;Z=Y}if(ae==ac){return ab}Z=ae.nextSibling;ae=ae.parentNode;X=M(ae,S,E,ad);if(ad!=j){X.appendChild(ab)}ab=X}}function M(t,aa,ad,ae){var Z,Y,ab,X,ac;if(aa){return z(t,ae)}if(t.nodeType==3){Z=t.nodeValue;if(ad){X=O[W];Y=Z.substring(X);ab=Z.substring(0,X)}else{X=O[A];Y=Z.substring(0,X);ab=Z.substring(X)}if(ae!=F){t.nodeValue=ab}if(ae==j){return}ac=c.clone(t,S);ac.nodeValue=Y;return ac}if(ae==j){return}return c.clone(t,S)}function z(X,t){if(t!=j){return t==F?c.clone(X,E):X}X.parentNode.removeChild(X)}function T(){return c.create("body",null,d()).outerText}return O}a.Range=b;b.prototype.toString=function(){return this.toStringIE()}})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,t,q,s,r=d.dom.doc,m=r.body;function j(A){var v,z,u,y,x;u=h.create("a");v=A?k:t;z=A?p:q;y=n.duplicate();if(v==r||v==r.documentElement){v=m;z=0}if(v.nodeType==3){v.parentNode.insertBefore(u,v);y.moveToElementText(u);y.moveStart("character",z);h.remove(u);n.setEndPoint(A?"StartToStart":"EndToEnd",y)}else{x=v.childNodes;if(x.length){if(z>=x.length){h.insertAfter(u,x[x.length-1])}else{v.insertBefore(u,x[z])}y.moveToElementText(u)}else{if(v.canHaveHTML){v.innerHTML="\uFEFF";u=v.firstChild;y.moveToElementText(u);y.collapse(f)}}n.setEndPoint(A?"StartToStart":"EndToEnd",y);h.remove(u)}}k=i.startContainer;p=i.startOffset;t=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==t&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){s=k.previousSibling;if(s&&!s.hasChildNodes()&&h.isBlock(s)){s.innerHTML="\uFEFF"}else{s=null}k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";if(s){s.innerHTML=""}return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var n=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i="sizcache",o=0,r=Object.prototype.toString,h=false,g=true,q=/\\/g,u=/\r\n/g,x=/\W/;[0,0].sort(function(){g=false;return 0});var d=function(C,e,F,G){F=F||[];e=e||document;var I=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!C||typeof C!=="string"){return F}var z,K,N,y,J,M,L,E,B=true,A=d.isXML(e),D=[],H=C;do{n.exec("");z=n.exec(H);if(z){H=z[3];D.push(z[1]);if(z[2]){y=z[3];break}}}while(z);if(D.length>1&&j.exec(C)){if(D.length===2&&k.relative[D[0]]){K=s(D[0]+D[1],e,G)}else{K=k.relative[D[0]]?[e]:d(D.shift(),e);while(D.length){C=D.shift();if(k.relative[C]){C+=D.shift()}K=s(C,K,G)}}}else{if(!G&&D.length>1&&e.nodeType===9&&!A&&k.match.ID.test(D[0])&&!k.match.ID.test(D[D.length-1])){J=d.find(D.shift(),e,A);e=J.expr?d.filter(J.expr,J.set)[0]:J.set[0]}if(e){J=G?{expr:D.pop(),set:l(G)}:d.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&e.parentNode?e.parentNode:e,A);K=J.expr?d.filter(J.expr,J.set):J.set;if(D.length>0){N=l(K)}else{B=false}while(D.length){M=D.pop();L=M;if(!k.relative[M]){M=""}else{L=D.pop()}if(L==null){L=e}k.relative[M](N,L,A)}}else{N=D=[]}}if(!N){N=K}if(!N){d.error(M||C)}if(r.call(N)==="[object Array]"){if(!B){F.push.apply(F,N)}else{if(e&&e.nodeType===1){for(E=0;N[E]!=null;E++){if(N[E]&&(N[E]===true||N[E].nodeType===1&&d.contains(e,N[E]))){F.push(K[E])}}}else{for(E=0;N[E]!=null;E++){if(N[E]&&N[E].nodeType===1){F.push(K[E])}}}}}else{l(N,F)}if(y){d(y,I,F,G);d.uniqueSort(F)}return F};d.uniqueSort=function(y){if(p){h=g;y.sort(p);if(h){for(var e=1;e0};d.find=function(E,e,F){var D,z,B,A,C,y;if(!E){return[]}for(z=0,B=k.order.length;z":function(D,y){var C,B=typeof y==="string",z=0,e=D.length;if(B&&!x.test(y)){y=y.toLowerCase();for(;z=0)){if(!z){e.push(C)}}else{if(z){y[B]=false}}}}return false},ID:function(e){return e[1].replace(q,"")},TAG:function(y,e){return y[1].replace(q,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){d.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var y=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(y[1]+(y[2]||1))-0;e[3]=y[3]-0}else{if(e[2]){d.error(e[0])}}e[0]=o++;return e},ATTR:function(B,y,z,e,C,D){var A=B[1]=B[1].replace(q,"");if(!D&&k.attrMap[A]){B[1]=k.attrMap[A]}B[4]=(B[4]||B[5]||"").replace(q,"");if(B[2]==="~="){B[4]=" "+B[4]+" "}return B},PSEUDO:function(B,y,z,e,C){if(B[1]==="not"){if((n.exec(B[3])||"").length>1||/^\w/.test(B[3])){B[3]=d(B[3],null,null,y)}else{var A=d.filter(B[3],y,z,true^C);if(!z){e.push.apply(e,A)}return false}}else{if(k.match.POS.test(B[0])||k.match.CHILD.test(B[0])){return true}}return B},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(z,y,e){return !!d(e[3],z).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(z){var e=z.getAttribute("type"),y=z.type;return z.nodeName.toLowerCase()==="input"&&"text"===y&&(e===y||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===y.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===y.type},button:function(y){var e=y.nodeName.toLowerCase();return e==="input"&&"button"===y.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(y,e){return e===0},last:function(z,y,e,A){return y===A.length-1},even:function(y,e){return e%2===0},odd:function(y,e){return e%2===1},lt:function(z,y,e){return ye[3]-0},nth:function(z,y,e){return e[3]-0===y},eq:function(z,y,e){return e[3]-0===y}},filter:{PSEUDO:function(z,E,D,F){var e=E[1],y=k.filters[e];if(y){return y(z,D,E,F)}else{if(e==="contains"){return(z.textContent||z.innerText||b([z])||"").indexOf(E[3])>=0}else{if(e==="not"){var A=E[3];for(var C=0,B=A.length;C=0)}}},ID:function(y,e){return y.nodeType===1&&y.getAttribute("id")===e},TAG:function(y,e){return(e==="*"&&y.nodeType===1)||!!y.nodeName&&y.nodeName.toLowerCase()===e},CLASS:function(y,e){return(" "+(y.className||y.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(C,A){var z=A[1],e=d.attr?d.attr(C,z):k.attrHandle[z]?k.attrHandle[z](C):C[z]!=null?C[z]:C.getAttribute(z),D=e+"",B=A[2],y=A[4];return e==null?B==="!=":!B&&d.attr?e!=null:B==="="?D===y:B==="*="?D.indexOf(y)>=0:B==="~="?(" "+D+" ").indexOf(y)>=0:!y?D&&e!==false:B==="!="?D!==y:B==="^="?D.indexOf(y)===0:B==="$="?D.substr(D.length-y.length)===y:B==="|="?D===y||D.substr(0,y.length+1)===y+"-":false},POS:function(B,y,z,C){var e=y[2],A=k.setFilters[e];if(A){return A(B,z,y,C)}}}};var j=k.match.POS,c=function(y,e){return"\\"+(e-0+1)};for(var f in k.match){k.match[f]=new RegExp(k.match[f].source+(/(?![^\[]*\])(?![^\(]*\))/.source));k.leftMatch[f]=new RegExp(/(^(?:.|\r|\n)*?)/.source+k.match[f].source.replace(/\\(\d+)/g,c))}k.match.globalPOS=j;var l=function(y,e){y=Array.prototype.slice.call(y,0);if(e){e.push.apply(e,y);return e}return y};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(v){l=function(B,A){var z=0,y=A||[];if(r.call(B)==="[object Array]"){Array.prototype.push.apply(y,B)}else{if(typeof B.length==="number"){for(var e=B.length;z";e.insertBefore(y,e.firstChild);if(document.getElementById(z)){k.find.ID=function(B,C,D){if(typeof C.getElementById!=="undefined"&&!D){var A=C.getElementById(B[1]);return A?A.id===B[1]||typeof A.getAttributeNode!=="undefined"&&A.getAttributeNode("id").nodeValue===B[1]?[A]:undefined:[]}};k.filter.ID=function(C,A){var B=typeof C.getAttributeNode!=="undefined"&&C.getAttributeNode("id");return C.nodeType===1&&B&&B.nodeValue===A}}e.removeChild(y);e=y=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){k.find.TAG=function(y,C){var B=C.getElementsByTagName(y[1]);if(y[1]==="*"){var A=[];for(var z=0;B[z];z++){if(B[z].nodeType===1){A.push(B[z])}}B=A}return B}}e.innerHTML="
                          ";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){k.attrHandle.href=function(y){return y.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div"),z="__sizzle__";A.innerHTML="

                          ";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(L,C,G,K){C=C||document;if(!K&&!d.isXML(C)){var J=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(L);if(J&&(C.nodeType===1||C.nodeType===9)){if(J[1]){return l(C.getElementsByTagName(L),G)}else{if(J[2]&&k.find.CLASS&&C.getElementsByClassName){return l(C.getElementsByClassName(J[2]),G)}}}if(C.nodeType===9){if(L==="body"&&C.body){return l([C.body],G)}else{if(J&&J[3]){var F=C.getElementById(J[3]);if(F&&F.parentNode){if(F.id===J[3]){return l([F],G)}}else{return l([],G)}}}try{return l(C.querySelectorAll(L),G)}catch(H){}}else{if(C.nodeType===1&&C.nodeName.toLowerCase()!=="object"){var D=C,E=C.getAttribute("id"),B=E||z,N=C.parentNode,M=/^\s*[+~]/.test(L);if(!E){C.setAttribute("id",B)}else{B=B.replace(/'/g,"\\$&")}if(M&&N){C=C.parentNode}try{if(!M||N){return l(C.querySelectorAll("[id='"+B+"'] "+L),G)}}catch(I){}finally{if(!E){D.removeAttribute("id")}}}}}return e(L,C,G,K)};for(var y in e){d[y]=e[y]}A=null})()}(function(){var e=document.documentElement,z=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(z){var B=!z.call(document.createElement("div"),"div"),y=false;try{z.call(document.documentElement,"[test!='']:sizzle")}catch(A){y=true}d.matchesSelector=function(D,F){F=F.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!d.isXML(D)){try{if(y||!k.match.PSEUDO.test(F)&&!/!=/.test(F)){var C=z.call(D,F);if(C||!B||D.document&&D.document.nodeType!==11){return C}}}catch(E){}}return d(F,null,null,[D]).length>0}}})();(function(){var e=document.createElement("div");e.innerHTML="
                          ";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}k.order.splice(1,0,"CLASS");k.find.CLASS=function(y,z,A){if(typeof z.getElementsByClassName!=="undefined"&&!A){return z.getElementsByClassName(y[1])}};e=null})();function a(y,D,C,G,E,F){for(var A=0,z=G.length;A0){B=e;break}}}e=e[y]}G[A]=B}}}if(document.documentElement.contains){d.contains=function(y,e){return y!==e&&(y.contains?y.contains(e):true)}}else{if(document.documentElement.compareDocumentPosition){d.contains=function(y,e){return !!(y.compareDocumentPosition(e)&16)}}else{d.contains=function(){return false}}}d.isXML=function(e){var y=(e?e.ownerDocument||e:0).documentElement;return y?y.nodeName!=="HTML":false};var s=function(z,e,D){var C,E=[],B="",F=e.nodeType?[e]:e;while((C=k.match.PSEUDO.exec(z))){B+=C[0];z=z.replace(k.match.PSEUDO,"")}z=k.relative[z]?z+"*":z;for(var A=0,y=F.length;A"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var h=this.getRng(),i,g,k,j;if(h.duplicate||h.item){if(h.item){return h.item(0)}k=h.duplicate();k.collapse(1);i=k.parentElement();g=j=h.parentElement();while(j=j.parentNode){if(j==i){i=g;break}}return i}else{i=h.startContainer;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[Math.min(i.childNodes.length-1,h.startOffset)]}if(i&&i.nodeType==3){return i.parentNode}return i}},getEnd:function(){var h=this,i=h.getRng(),j,g;if(i.duplicate||i.item){if(i.item){return i.item(0)}i=i.duplicate();i.collapse(0);j=i.parentElement();if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=i.endContainer;g=i.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[g>0?g-1:g]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){return{rng:y.getRng()}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(o){var s=this,m=s.dom,j,i,g,r,k,u,p,q;function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t.length-1;x>=1;x--){v=y.childNodes;if(t[x]>v.length-1){return}y=v[t[x]]}if(y.nodeType===3){z=Math.min(t[0],y.nodeValue.length)}if(y.nodeType===1){z=Math.min(t[0],y.childNodes.length)}if(A){g.setStart(y,z)}else{g.setEnd(y,z)}}return true}function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentNode;if(B=="start"){if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}k=u=A;p=q=t}else{if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}u=A;q=t}if(!x){z=v.previousSibling;y=v.nextSibling;e(d.grep(v.childNodes),function(C){if(C.nodeType==3){C.nodeValue=C.nodeValue.replace(/\uFEFF/g,"")}});while(v=m.get(o.id+"_"+B)){m.remove(v,1)}if(z&&y&&z.nodeType==y.nodeType&&z.nodeType==3&&!d.isOpera){t=z.nodeValue.length;z.appendData(y.nodeValue);m.remove(y);if(B=="start"){k=u=z;p=q=t}else{u=z;q=t}}}}}function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
                          '}return t}if(o){if(o.start){g=m.createRng();r=m.getRoot();if(s.tridentSel){return s.tridentSel.moveToBookmark(o)}if(h(true)&&h()){s.setRng(g)}}else{if(o.id){l("start");l("end");if(k){g=m.createRng();g.setStart(n(k),p);g.setEnd(n(u),q);s.setRng(g)}}else{if(o.name){s.select(m.select(o.name)[o.index])}else{if(o.rng){s.setRng(o.rng)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},destroy:function(h){var g=this;g.win=null;if(!h){d.removeUnload(g.destroy)}},_fixIESelection:function(){var h=this.dom,n=h.doc,i=n.body,k,o,g;function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r){q=null}return q}function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoints("StartToStart",o)>0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=document.createElement("script");s.id=n;s.type="text/javascript";s.src=a._addVer(m);if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=m.length){r=0}}t=m[r];f.setAttrib(g,"tabindex","-1");f.setAttrib(t.id,"tabindex","0");f.get(t.id).focus();if(e.actOnFocus){e.onAction(t.id)}if(s){a.cancel(s)}};p=function(z){var v=37,u=39,y=38,A=40,r=27,t=14,s=13,x=32;switch(z.keyCode){case v:if(i){q.moveFocus(-1)}break;case u:if(i){q.moveFocus(1)}break;case y:if(o){q.moveFocus(-1)}break;case A:if(o){q.moveFocus(1)}break;case r:if(e.onCancel){e.onCancel();a.cancel(z)}break;case t:case s:case x:if(e.onAction){e.onAction(g);a.cancel(z)}break}};c(m,function(t,r){var s,u;if(!t.id){t.id=f.uniqueId("_mce_item_")}u=f.get(t.id);if(l){f.bind(u,"blur",h);s="-1"}else{s=(r===0?"0":"-1")}u.setAttribute("tabindex",s);f.bind(u,"focus",k)});if(m[0]){g=m[0].id}f.setAttrib(n,"tabindex","-1");var j=f.get(n);f.bind(j,"focus",d);f.bind(j,"keydown",p)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+c}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keyup",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(l){var k;b.remove(h.id,"change",i);j=false;k=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",k)});if(e.isWebKit&&(l.keyCode==37||l.keyCode==39)){return b.prevent(l)}if(l.keyCode==13||l.keyCode==32){g(l);return b.cancel(l)}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
                          ');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
                          ");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){return;var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}x=d({theme:"simple",language:"en"},x);v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}p.orgVisibility=p.getElement().style.visibility;p.getElement().style.visibility="hidden";if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/../../extra/strings.php?elanguage="+q.language+"ðeme="+q.theme)}if(q.theme&&typeof q.theme!="function"&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,F=this,G=F.settings,C,y,B=F.getElement(),p,m,D,v,A,E,x,r=[];k.add(F);G.aria_label=G.aria_label||l.getAttrib(B,"aria-label",F.getLang("aria.rich_text_area"));if(G.theme){if(typeof G.theme!="function"){G.theme=G.theme.replace(/-/,"");p=h.get(G.theme);F.theme=new p();if(F.theme.init){F.theme.init(F,h.urls[G.theme]||k.documentBaseURL.replace(/\/$/,""))}}else{F.theme=G.theme}}function z(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){z(u)});n=new t(F,o);F.plugins[s]=n;if(n.init){n.init(F,o);r.push(s)}}}i(g(G.plugins.replace(/\-/g,"")),z);if(G.popup_css!==false){if(G.popup_css){G.popup_css=F.documentBaseURI.toAbsolute(G.popup_css)}else{G.popup_css=F.baseURI.toAbsolute("themes/"+G.theme+"/skins/"+G.skin+"/dialog.css")}}if(G.popup_css_add){G.popup_css+=","+F.documentBaseURI.toAbsolute(G.popup_css_add)}F.controlManager=new k.ControlManager(F);F.onExecCommand.add(function(n,o){if(!/^(FontName|FontSize)$/.test(o)){F.nodeChanged()}});F.onBeforeRenderUI.dispatch(F,F.controlManager);if(G.render_ui&&F.theme){F.orgDisplay=B.style.display;if(typeof G.theme!="function"){C=G.width||B.style.width||B.offsetWidth;y=G.height||B.style.height||B.offsetHeight;E=/^[0-9\.]+(|px)$/i;if(E.test(""+C)){C=Math.max(parseInt(C,10)+(p.deltaWidth||0),100)}if(E.test(""+y)){y=Math.max(parseInt(y)+(p.deltaHeight||0),G.theme_advanced_resizing_min_height||100)}p=F.theme.renderUI({targetNode:B,width:C,height:y,deltaWidth:G.delta_width,deltaHeight:G.delta_height});l.setStyles(p.sizeContainer||p.editorContainer,{width:C,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y<(G.theme_advanced_resizing_min_height||100)){y=G.theme_advanced_resizing_min_height||100}}else{p=G.theme(F,B);if(p.editorContainer.nodeType){p.editorContainer=p.editorContainer.id=p.editorContainer.id||F.id+"_parent"}if(p.iframeContainer.nodeType){p.iframeContainer=p.iframeContainer.id=p.iframeContainer.id||F.id+"_iframecontainer"}y=p.iframeHeight||B.offsetHeight}F.editorContainer=p.editorContainer}if(G.content_css){i(g(G.content_css),function(n){F.contentCSS.push(F.documentBaseURI.toAbsolute(n))})}if(G.content_editable){B=q=p=null;return F.initContentBody()}if(document.domain&&location.hostname!=document.domain){k.relaxedDomain=document.domain}F.iframeHTML=G.doctype+'';if(G.document_base_url!=k.documentBaseURL){F.iframeHTML+=''}if(G.ie7_compat){F.iframeHTML+=''}else{F.iframeHTML+=''}F.iframeHTML+='';for(x=0;x'}F.contentCSS=[];v=G.body_id||"tinymce";if(v.indexOf("=")!=-1){v=F.getParam("body_id","","hash");v=v[F.id]||v}A=G.body_class||"";if(A.indexOf("=")!=-1){A=F.getParam("body_class","","hash");A=A[F.id]||""}F.iframeHTML+='
                          ";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){D='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+F.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:F.id+"_ifr",src:D||'javascript:""',frameBorder:"0",allowTransparency:"true",title:G.aria_label,style:{width:"100%",height:y,display:"block"}});F.contentAreaContainer=p.iframeContainer;if(p.editorContainer){l.get(p.editorContainer).style.display=F.orgDisplay}B.style.visibility=F.orgVisibility;l.get(F.id).style.display="none";l.setAttrib(F.id,"aria-hidden",true);if(!k.relaxedDomain||!D){F.initContentBody()}B=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(s,t){var u=s.length,x,z=n.dom,y,v;while(u--){x=s[u];y=x.attr(t);v="data-mce-"+t;if(!x.attributes.map[v]){if(t==="style"){x.attr(v,z.serializeStyle(z.parseStyle(y),x.name))}else{x.attr(v,n.convertURL(y,t,x.name))}}}});n.parser.addNodeFilter("script",function(s,t){var u=s.length,v;while(u--){v=s[u];v.attr("type","mce-"+(v.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(s,t){var u=s.length,v;while(u--){v=s[u];v.type=8;v.name="#comment";v.value="[CDATA["+v.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,u){var v=t.length,x,s=n.schema.getNonEmptyElements();while(v--){x=t[v];if(x.isEmpty(s)){x.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.serializer.onPreProcess.add(function(s,t){return n.onPreProcess.dispatch(n,t,s)});n.serializer.onPostProcess.add(function(s,t){return n.onPostProcess.dispatch(n,t,s)});n.onPreInit.dispatch(n);if(!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(s,t){i(p.protect,function(u){t.content=t.content.replace(u,function(v){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
                          [\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});i(n.contentCSS,function(s){n.dom.loadCSS(s)});if(p.auto_focus){setTimeout(function(){var s=k.get(p.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
                          "}else{r='
                          '}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}o.selection.normalize();return p.content},getContent:function(n){var m=this,o;n=n||{};n.format=n.format||"html";n.get=true;n.getInner=true;if(!n.no_events){m.onBeforeGetContent.dispatch(m,n)}if(n.format=="raw"){o=m.getBody().innerHTML}else{o=m.serializer.serialize(m.getBody(),n)}n.content=k.trim(o);if(!n.no_events){m.onGetContent.dispatch(m,n)}return n.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":if(!s.href){r=p.getAttrib(s,"name")||s.id;m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,n=m.getContainer();if(!m.removed){m.removed=1;m.hide();if(!m.settings.content_editable){j.clear(m.getWin());j.clear(m.getDoc())}j.clear(m.getBody());j.clear(m.formElement);j.unbind(n);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(n)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){Event.cancel(g)}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var l=this,f,d=l.settings,e=l.dom,h;h={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function c(i,m){var n=i.type;if(l.removed){return}if(l.onEvent.dispatch(l,i,m)!==false){l[h[i.fakeType||i.type]].dispatch(l,i,m)}}function j(i){l.focus(true)}function k(){l.selection.normalize();l.nodeChanged()}b(h,function(m,n){var i=d.content_editable?l.getBody():l.getDoc();switch(n){case"contextmenu":e.bind(i,n,c);break;case"paste":e.bind(l.getBody(),n,c);break;case"submit":case"reset":e.bind(l.getElement().form||a.DOM.getParent(l.id,"form"),n,c);break;default:e.bind(i,n,c)}});e.bind(d.content_editable?l.getBody():(a.isGecko?l.getDoc():l.getWin()),"focus",function(i){l.focus(true)});if(d.content_editable&&a.isOpera){e.bind(l.getBody(),"click",j);e.bind(l.getBody(),"keydown",j)}l.onMouseUp.add(k);l.onKeyUp.add(function(i,n){var m=n.keyCode;if((m>=33&&m<=36)||(m>=37&&m<=40)||m==13||m==45||m==46||m==8||(a.isMac&&(m==91||m==93))||n.ctrlKey){k()}});l.onReset.add(function(){l.setContent(l.startContent,{format:"raw"})});function g(m,i){if(m.altKey||m.ctrlKey||m.metaKey){b(l.shortcuts,function(n){var o=a.isMac?m.metaKey:m.ctrlKey;if(n.ctrl!=o||n.alt!=m.altKey||n.shift!=m.shiftKey){return}if(m.keyCode==n.keyCode||(m.charCode&&m.charCode==n.charCode)){m.preventDefault();if(i){n.func.call(n.scope)}return true}})}}l.onKeyUp.add(function(i,m){g(m)});l.onKeyPress.add(function(i,m){g(m)});l.onKeyDown.add(function(i,m){g(m,true)});if(a.isOpera){l.onClick.add(function(i,m){m.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}onBeforeAdd=new a(l);k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getDoc(),b.isGecko?"blur":"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onBeforeAdd:onBeforeAdd,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();l.onBeforeAdd.dispatch(l,p);o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}if(p){c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(j){var o,k,g,h=this,m=h.editor,n,f;if(!h.controlFactories){h.controlFactories=[];d(m.plugins,function(i){if(i.createControl){h.controlFactories.push(i)}})}n=h.controlFactories;for(k=0,g=n.length;k1||ae==aw||ae.tagName=="BR"){return ae}}}var ao=Y.selection.getRng();var at=ao.startContainer;var an=ao.endContainer;if(at!=an&&ao.endOffset===0){var ar=ap(at,an);var aq=ar.nodeType==3?ar.length:ar.childNodes.length;ao.setEnd(ar,aq)}return ao}function ab(aq,aw,au,at,ao){var an=[],ap=-1,av,ay=-1,ar=-1,ax;R(aq.childNodes,function(aA,az){if(aA.nodeName==="UL"||aA.nodeName==="OL"){ap=az;av=aA;return false}});R(aq.childNodes,function(aA,az){if(aA.nodeName==="SPAN"&&c.getAttrib(aA,"data-mce-type")=="bookmark"){if(aA.id==aw.id+"_start"){ay=az}else{if(aA.id==aw.id+"_end"){ar=az}}}});if(ap<=0||(ayap)){R(a.grep(aq.childNodes),ao);return 0}else{ax=c.clone(au,V);R(a.grep(aq.childNodes),function(aA,az){if((ayap&&az>ap)){an.push(aA);aA.parentNode.removeChild(aA)}});if(ayap){aq.insertBefore(ax,av.nextSibling)}}at.push(ax);R(an,function(az){ax.appendChild(az)});return ax}}function al(ao,aq,au){var an=[],at,ap,ar=true;at=ak.inline||ak.block;ap=c.create(at);Z(ap);M.walk(ao,function(av){var aw;function ax(ay){var aD,aB,az,aA,aC;aC=ar;aD=ay.nodeName.toLowerCase();aB=ay.parentNode.nodeName.toLowerCase();if(ay.nodeType===1&&x(ay)){aC=ar;ar=x(ay)==="true";aA=true}if(g(aD,"br")){aw=0;if(ak.block){c.remove(ay)}return}if(ak.wrapper&&y(ay,ac,aj)){aw=0;return}if(ar&&!aA&&ak.block&&!ak.wrapper&&I(aD)){ay=c.rename(ay,at);Z(ay);an.push(ay);aw=0;return}if(ak.selector){R(af,function(aE){if("collapsed" in aE&&aE.collapsed!==ag){return}if(c.is(ay,aE.selector)&&!b(ay)){Z(ay,aE);az=true}});if(!ak.inline||az){aw=0;return}}if(ar&&!aA&&d(at,aD)&&d(aB,at)&&!(!au&&ay.nodeType===3&&ay.nodeValue.length===1&&ay.nodeValue.charCodeAt(0)===65279)&&!b(ay)){if(!aw){aw=c.clone(ap,V);ay.parentNode.insertBefore(aw,ay);an.push(aw)}aw.appendChild(ay)}else{if(aD=="li"&&aq){aw=ab(ay,aq,ap,an,ax)}else{aw=0;R(a.grep(ay.childNodes),ax);if(aA){ar=aC}aw=0}}}R(av,ax)});if(ak.wrap_links===false){R(an,function(av){function aw(aA){var az,ay,ax;if(aA.nodeName==="A"){ay=c.clone(ap,V);an.push(ay);ax=a.grep(aA.childNodes);for(az=0;az1||!H(ax))&&av===0){c.remove(ax,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&av===1){ax=aw(ax)}R(af,function(az){R(c.select(az.inline,ax),function(aB){var aA;if(az.wrap_links===false){aA=aB.parentNode;do{if(aA.nodeName==="A"){return}}while(aA=aA.parentNode)}X(az,aj,aB,az.exact?aB:null)})});if(y(ax.parentNode,ac,aj)){c.remove(ax,1);ax=0;return C}if(ak.merge_with_parents){c.getParent(ax.parentNode,function(az){if(y(az,ac,aj)){c.remove(ax,1);ax=0;return C}})}if(ax&&ak.merge_siblings!==false){ax=u(E(ax),ax);ax=u(ax,E(ax,C))}}})}if(ak){if(ae){if(ae.nodeType){aa=c.createRng();aa.setStartBefore(ae);aa.setEndAfter(ae);al(p(aa,af),null,true)}else{al(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var am=Y.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(am,c.isBlock)){W(af[0].defaultBlock)}Y.selection.setRng(ad());ai=r.getBookmark();al(p(r.getRng(C),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(am,K,"childNodes");K(am)}r.moveToBookmark(ai);P(r.getRng(C));Y.nodeChanged()}else{S("apply",ac,aj)}}}}function B(ab,ak,ad){var ae=T(ab),am=ae[0],ai,ah,aa,aj=true;function ac(at){var ar,aq,ap,ao,av,au;if(at.nodeType===1&&x(at)){av=aj;aj=x(at)==="true";au=true}ar=a.grep(at.childNodes);if(aj&&!au){for(aq=0,ap=ae.length;aq=0;aa--){Z=af[aa].selector;if(!Z){return C}for(ae=ab.length-1;ae>=0;ae--){if(c.is(ab[ae],Z)){return C}}}}return V}a.extend(this,{get:T,register:l,apply:W,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z});j();U();function h(Z,aa){if(g(Z,aa.inline)){return C}if(g(Z,aa.block)){return C}if(aa.selector){return c.is(Z,aa.selector)}}function g(aa,Z){aa=aa||"";Z=Z||"";aa=""+(aa.nodeName||aa);Z=""+(Z.nodeName||Z);return aa.toLowerCase()==Z.toLowerCase()}function N(aa,Z){var ab=c.getStyle(aa,Z);if(Z=="color"||Z=="backgroundColor"){ab=c.toHex(ab)}if(Z=="fontWeight"&&ab==700){ab="bold"}return""+ab}function q(Z,aa){if(typeof(Z)!="string"){Z=Z(aa)}else{if(aa){Z=Z.replace(/%(\w+)/g,function(ac,ab){return aa[ab]||ac})}}return Z}function f(Z){return Z&&Z.nodeType===3&&/^([\t \r\n]+|)$/.test(Z.nodeValue)}function Q(ab,aa,Z){var ac=c.create(aa,Z);ab.parentNode.insertBefore(ac,ab);ac.appendChild(ab);return ac}function p(Z,ak,ac){var an,al,af,aj,ab=Z.startContainer,ag=Z.startOffset,ap=Z.endContainer,ai=Z.endOffset;function am(ax){var ar,av,aw,au,at,aq;ar=av=ax?ab:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();if(ar.nodeType==3&&!f(ar)){if(ax?ag>0:aial?al:ag];if(ab.nodeType==3){ag=0}}if(ap.nodeType==1&&ap.hasChildNodes()){al=ap.childNodes.length-1;ap=ap.childNodes[ai>al?al:ai-1];if(ap.nodeType==3){ai=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ah(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ac){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&af.node.nodeType===3&&af.node.nodeValue.charAt(af.offset-1)===" "){if(af.offset>1){ap=af.node;ap.splitText(af.offset-1)}}}}if(ak[0].inline||ak[0].block_expand){if(!ak[0].inline||(ab.nodeType!=3||ag===0)){ab=am(true)}if(!ak[0].inline||(ap.nodeType!=3||ai===ap.nodeValue.length)){ap=am()}}if(ak[0].selector&&ak[0].expand!==V&&!ak[0].inline){ab=ad(ab,"previousSibling");ap=ad(ap,"nextSibling")}if(ak[0].block||ak[0].selector){ab=aa(ab,"previousSibling");ap=aa(ap,"nextSibling");if(ak[0].block){if(!H(ab)){ab=am(true)}if(!H(ap)){ap=am()}}}if(ab.nodeType==1){ag=s(ab);ab=ab.parentNode}if(ap.nodeType==1){ai=s(ap)+1;ap=ap.parentNode}return{startContainer:ab,startOffset:ag,endContainer:ap,endOffset:ai}}function X(af,ae,ac,Z){var ab,aa,ad;if(!h(ac,af)){return V}if(af.remove!="all"){R(af.styles,function(ah,ag){ah=q(ah,ae);if(typeof(ag)==="number"){ag=ah;Z=0}if(!Z||g(N(Z,ag),ah)){c.setStyle(ac,ag,"")}ad=1});if(ad&&c.getAttrib(ac,"style")==""){ac.removeAttribute("style");ac.removeAttribute("data-mce-style")}R(af.attributes,function(ai,ag){var ah;ai=q(ai,ae);if(typeof(ag)==="number"){ag=ai;Z=0}if(!Z||g(c.getAttrib(Z,ag),ai)){if(ag=="class"){ai=c.getAttrib(ac,ag);if(ai){ah="";R(ai.split(/\s+/),function(aj){if(/mce\w+/.test(aj)){ah+=(ah?" ":"")+aj}});if(ah){c.setAttrib(ac,ag,ah);return}}}if(ag=="class"){ac.removeAttribute("className")}if(e.test(ag)){ac.removeAttribute("data-mce-"+ag)}ac.removeAttribute(ag)}});R(af.classes,function(ag){ag=q(ag,ae);if(!Z||c.hasClass(Z,ag)){c.removeClass(ac,ag)}});aa=c.getAttribs(ac);for(ab=0;abab?ab:ad]}if(Z.nodeType===3&&ae&&ad>=Z.nodeValue.length){Z=new t(Z,Y.getBody()).next()||Z}if(Z.nodeType===3&&!ae&&ad===0){Z=new t(Z,Y.getBody()).prev()||Z}return Z}function S(ai,Z,ag){var aj="_mce_caret",aa=Y.settings.caret_debug;function ab(an){var am=c.create("span",{id:aj,"data-mce-bogus":true,style:aa?"color:red":""});if(an){am.appendChild(Y.getDoc().createTextNode(G))}return am}function ah(an,am){while(an){if((an.nodeType===3&&an.nodeValue!==G)||an.childNodes.length>1){return false}if(am&&an.nodeType===1){am.push(an)}an=an.firstChild}return true}function ae(am){while(am){if(am.id===aj){return am}am=am.parentNode}}function ad(am){var an;if(am){an=new t(am,am);for(am=an.current();am;am=an.next()){if(am.nodeType===3){return am}}}}function ac(ao,an){var ap,am;if(!ao){ao=ae(r.getStart());if(!ao){while(ao=c.get(aj)){ac(ao,false)}}}else{am=r.getRng(true);if(ah(ao)){if(an!==false){am.setStartBefore(ao);am.setEndBefore(ao)}c.remove(ao)}else{ap=ad(ao);if(ap.nodeValue.charAt(0)===G){ap=ap.deleteData(0,1)}c.remove(ao,1)}r.setRng(am)}}function af(){var ao,am,at,ar,ap,an,aq;ao=r.getRng(true);ar=ao.startOffset;an=ao.startContainer;aq=an.nodeValue;am=ae(r.getStart());if(am){at=ad(am)}if(aq&&ar>0&&ar=0;aq--){ao.appendChild(c.clone(av[aq],false));ao=ao.firstChild}ao.appendChild(c.doc.createTextNode(G));ao=ao.firstChild;c.insertAfter(au,aw);r.setCursorLocation(ao,1)}}function al(){var an,am,ao;am=ae(r.getStart());if(am&&!c.isEmpty(am)){a.walk(am,function(ap){if(ap.nodeType==1&&ap.id!==aj&&!c.isEmpty(ap)){c.setAttrib(ap,"data-mce-bogus",null)}},"childNodes")}}if(!self._hasCaretEvents){Y.onBeforeGetContent.addToTop(function(){var am=[],an;if(ah(ae(r.getStart()),am)){an=am.length;while(an--){c.setAttrib(am[an],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(am){Y[am].addToTop(function(){ac();al()})});Y.onKeyDown.addToTop(function(am,ao){var an=ao.keyCode;if(an==8||an==37||an==39){ac(ae(r.getStart()))}al()});r.onSetContent.add(al);self._hasCaretEvents=true}if(ai=="apply"){af()}else{ak()}}function P(aa){var Z=aa.startContainer,ag=aa.startOffset,ac,af,ae,ab,ad;if(Z.nodeType==3&&ag>=Z.nodeValue.length){ag=s(Z);Z=Z.parentNode;ac=true}if(Z.nodeType==1){ab=Z.childNodes;Z=ab[Math.min(ag,ab.length-1)];af=new t(Z,c.getParent(Z,c.isBlock));if(ag>ab.length-1||ac){af.next()}for(ae=af.current();ae;ae=af.next()){if(ae.nodeType==3&&!f(ae)){ad=c.create("a",null,G);ae.parentNode.insertBefore(ad,ae);aa.setStart(ae,0);r.setRng(aa);c.remove(ad);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(e){var h=e.dom,d=e.selection,c=e.settings,g=e.undoManager;function f(y){var u=d.getRng(true),C,i,x,t,o,H,n,j,l,s,E,v,z;function B(I){return I&&h.isBlock(I)&&!/^(TD|TH|CAPTION)$/.test(I.nodeName)&&!/^(fixed|absolute)/i.test(I.style.position)&&h.getContentEditable(I)!=="true"}function m(J){var O,M,I,P,N,L=J,K;I=h.createRng();if(J.hasChildNodes()){O=new a(J,J);while(M=O.current()){if(M.nodeType==3){I.setStart(M,0);I.setEnd(M,0);break}if(/^(BR|IMG)$/.test(M.nodeName)){I.setStartBefore(M);I.setEndBefore(M);break}L=M;M=O.next()}if(!M){I.setStart(L,0);I.setEnd(L,0)}}else{if(J.nodeName=="BR"){if(J.nextSibling&&h.isBlock(J.nextSibling)){if(!H||H<9){K=h.create("br");J.parentNode.insertBefore(K,J)}I.setStartBefore(J);I.setEndBefore(J)}else{I.setStartAfter(J);I.setEndAfter(J)}}else{I.setStart(J,0);I.setEnd(J,0)}}d.setRng(I);h.remove(K);N=h.getViewPort(e.getWin());P=h.getPos(J).y;if(PN.y+N.h){e.getWin().scrollTo(0,P"}return M}function p(L){var K,J,I;if(x.nodeType==3&&(L?t>0:t=x.nodeValue.length){if(!b.isIE&&!A()){J=h.create("br");u.insertNode(J);u.setStartAfter(J);u.setEndAfter(J);I=true}}J=h.create("br");u.insertNode(J);if(b.isIE&&s=="PRE"&&(!H||H<8)){J.parentNode.insertBefore(h.doc.createTextNode("\r"),J)}if(!I){u.setStartAfter(J);u.setEndAfter(J)}else{u.setStartBefore(J);u.setEndBefore(J)}d.setRng(u);g.add()}function r(I){do{if(I.nodeType===3){I.nodeValue=I.nodeValue.replace(/^[\r\n]+/,"")}I=I.firstChild}while(I)}function F(K){var I=h.getRoot(),J,L;J=K;while(J!==I&&h.getContentEditable(J)!=="false"){if(h.getContentEditable(J)==="true"){L=J}J=J.parentNode}return J!==I?L:I}if(!u.collapsed){e.execCommand("Delete");return}if(y.isDefaultPrevented()){return}x=u.startContainer;t=u.startOffset;v=c.forced_root_block;v=v?v.toUpperCase():"";H=h.doc.documentMode;if(x.nodeType==1&&x.hasChildNodes()){z=t>x.childNodes.length-1;x=x.childNodes[Math.min(t,x.childNodes.length-1)]||x;t=0}i=F(x);if(!i){return}g.beforeChange();if(!h.isBlock(i)&&i!=h.getRoot()){if(!v||y.shiftKey){G()}return}if((v&&!y.shiftKey)||(!v&&y.shiftKey)){x=k(x,t)}o=h.getParent(x,h.isBlock);l=o?h.getParent(o.parentNode,h.isBlock):null;s=o?o.nodeName.toUpperCase():"";E=l?l.nodeName.toUpperCase():"";if(s=="LI"&&h.isEmpty(o)){if(/^(UL|OL|LI)$/.test(l.parentNode.nodeName)){return false}D();return}if(s=="PRE"&&c.br_in_pre!==false){if(!y.shiftKey){G();return}}else{if((!v&&!y.shiftKey&&s!="LI")||(v&&y.shiftKey)){G();return}}v=v||"P";if(p()){if(/^(H[1-6]|PRE)$/.test(s)&&E!="HGROUP"){n=q(v)}else{n=q()}if(c.end_container_on_empty_block&&B(l)&&h.isEmpty(o)){n=h.split(l,o)}else{h.insertAfter(n,o)}}else{if(p(true)){n=o.parentNode.insertBefore(q(),o)}else{C=u.cloneRange();C.setEndAfter(o);j=C.extractContents();r(j);n=j.firstChild;h.insertAfter(j,o)}}h.setAttrib(n,"id","");m(n);g.add()}e.onKeyDown.add(function(j,i){if(i.keyCode==13){if(f(i)!==false){i.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype_src.js similarity index 98% rename from lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype_src.js index 7406a2a47b0..e882b7ef9f3 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype_src.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_prototype_src.js @@ -1606,6 +1606,14 @@ tinymce.util.Quirks = function(editor) { editor.onSetContent.add(selection.onSetContent.add(fixLinks)); }; + function setDefaultBlockType() { + if (settings.forced_root_block) { + editor.onInit.add(function() { + setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block); + }); + } + } + function removeGhostSelection() { function repaint(sender, args) { if (!sender || !args.initial) { @@ -1640,6 +1648,7 @@ tinymce.util.Quirks = function(editor) { cleanupStylesWhenDeleting(); inputMethodFocus(); selectControlElements(); + setDefaultBlockType(); // iOS if (tinymce.isIDevice) { @@ -2115,8 +2124,11 @@ tinymce.html.Styles = function(settings, schema) { if (!html5) { html5 = mapCache.html5 = unpack({ A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title', - B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video', - C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' + B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|' + + 'meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video', + C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|' + + 'figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|' + + 'p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' }, 'html[A|manifest][body|head]' + 'head[A][base|command|link|meta|noscript|script|style|title]' + 'title[A][#]' + @@ -2152,7 +2164,7 @@ tinymce.html.Styles = function(settings, schema) { 'dl[A][dd|dt]' + 'dt[A][B]' + 'dd[A][C]' + - 'a[A|href|target|ping|rel|media|type][C]' + + 'a[A|href|target|ping|rel|media|type][B]' + 'em[A][B]' + 'strong[A][B]' + 'small[A][B]' + @@ -2198,7 +2210,8 @@ tinymce.html.Styles = function(settings, schema) { 'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' + 'fieldset[A|disabled|form|name][C|legend]' + 'label[A|form|for][B]' + - 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]' + + 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' + + 'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' + 'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' + 'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' + 'datalist[A][B|option]' + @@ -2401,13 +2414,13 @@ tinymce.html.Styles = function(settings, schema) { // Setup map objects whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script style textarea'); - selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li options p td tfoot th thead tr'); + selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr'); shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source'); boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls'); nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object', shortEndedElementsMap); blockElementsMap = createLookupTable('block_elements', 'h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot ' + 'th tr td li ol ul caption blockquote center dl dt dd dir fieldset ' + - 'noscript menu isindex samp header footer article section hgroup aside nav figure'); + 'noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup'); // Converts a wildcard expression string to a regexp for example *a will become /.*a/. function patternToRegExp(str) { @@ -2851,7 +2864,7 @@ tinymce.html.Styles = function(settings, schema) { // Setup lookup tables for empty elements and boolean attributes shortEndedElements = schema.getShortEndedElements(); - selfClosing = schema.getSelfClosingElements(); + selfClosing = settings.self_closing_elements || schema.getSelfClosingElements(); fillAttrsMap = schema.getBoolAttrs(); validate = settings.validate; removeInternalElements = settings.remove_internals; @@ -3597,9 +3610,23 @@ tinymce.html.Styles = function(settings, schema) { } }; + function cloneAndExcludeBlocks(input) { + var name, output = {}; + + for (name in input) { + if (name !== 'li' && name != 'p') { + output[name] = input[name]; + } + } + + return output; + }; + parser = new tinymce.html.SaxParser({ validate : validate, - fix_self_closing : !validate, // Let the DOM parser handle
                        • in
                        • or

                          in

                          for better results + + // Exclude P and LI from DOM parsing since it's treated better by the DOM parser + self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()), cdata: function(text) { node.append(createNode('#cdata', 4)).value = text; @@ -3777,7 +3804,7 @@ tinymce.html.Styles = function(settings, schema) { node.empty().append(new Node('#text', '3')).value = '\u00a0'; else { // Leave nodes that have a name like - if (!node.attributes.map.name) { + if (!node.attributes.map.name && !node.attributes.map.id) { tempNode = node.parent; node.empty().remove(); node = tempNode; @@ -3929,12 +3956,12 @@ tinymce.html.Styles = function(settings, schema) { // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. if (!settings.allow_html_in_named_anchor) { - self.addAttributeFilter('name', function(nodes, name) { + self.addAttributeFilter('id,name', function(nodes, name) { var i = nodes.length, sibling, prevSibling, parent, node; while (i--) { node = nodes[i]; - if (node.name === 'a' && node.firstChild) { + if (node.name === 'a' && node.firstChild && !node.attr('href')) { parent = node.parent; // Move children after current node @@ -6165,7 +6192,8 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { cloneContents : cloneContents, insertNode : insertNode, surroundContents : surroundContents, - cloneRange : cloneRange + cloneRange : cloneRange, + toStringIE : toStringIE }); function createDocumentFragment() { @@ -6805,9 +6833,20 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { n.parentNode.removeChild(n); }; + + function toStringIE() { + return dom.create('body', null, cloneContents()).outerText; + } + + return t; }; ns.Range = Range; + + // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype + Range.prototype.toString = function() { + return this.toStringIE(); + }; })(tinymce.dom); (function() { function Selection(selection) { @@ -7162,7 +7201,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { }; this.addRange = function(rng) { - var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body; + var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling, doc = selection.dom.doc, body = doc.body; function setEndPoint(start) { var container, offset, marker, tmpRng, nodes; @@ -7220,11 +7259,25 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { // Trick to place the caret inside an empty block element like

                          if (startOffset == endOffset && !startContainer.hasChildNodes()) { if (startContainer.canHaveHTML) { + // Check if previous sibling is an empty block if it is then we need to render it + // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236 + // Example this:

                          |

                          would become this:

                          |

                          + sibling = startContainer.previousSibling; + if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) { + sibling.innerHTML = '\uFEFF'; + } else { + sibling = null; + } + startContainer.innerHTML = '\uFEFF\uFEFF'; ieRng.moveToElementText(startContainer.lastChild); ieRng.select(); dom.doc.selection.clear(); startContainer.innerHTML = ''; + + if (sibling) { + sibling.innerHTML = ''; + } return; } else { startOffset = dom.nodeIndex(startContainer); @@ -10209,11 +10262,10 @@ window.tinymce.dom.Sizzle = Sizzle; } // Create new script element - elm = dom.create('script', { - id : id, - type : 'text/javascript', - src : tinymce._addVer(url) - }); + elm = document.createElement('script'); + elm.id = id; + elm.type = 'text/javascript'; + elm.src = tinymce._addVer(url); // Add onload listener for non IE browsers since IE9 // fires onload event before the script is parsed and executed @@ -10575,12 +10627,15 @@ window.tinymce.dom.Sizzle = Sizzle; t.destroy = function() { each(items, function(item) { - dom.unbind(dom.get(item.id), 'focus', itemFocussed); - dom.unbind(dom.get(item.id), 'blur', itemBlurred); + var elm = dom.get(item.id); + + dom.unbind(elm, 'focus', itemFocussed); + dom.unbind(elm, 'blur', itemBlurred); }); - dom.unbind(dom.get(root), 'focus', rootFocussed); - dom.unbind(dom.get(root), 'keydown', rootKeydown); + var rootElm = dom.get(root); + dom.unbind(rootElm, 'focus', rootFocussed); + dom.unbind(rootElm, 'keydown', rootKeydown); items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; t.destroy = function() {}; @@ -10659,21 +10714,23 @@ window.tinymce.dom.Sizzle = Sizzle; // Set up state and listeners for each item. each(items, function(item, idx) { - var tabindex; + var tabindex, elm; if (!item.id) { item.id = dom.uniqueId('_mce_item_'); } + elm = dom.get(item.id); + if (excludeFromTabOrder) { - dom.bind(item.id, 'blur', itemBlurred); + dom.bind(elm, 'blur', itemBlurred); tabindex = '-1'; } else { tabindex = (idx === 0 ? '0' : '-1'); } - dom.setAttrib(item.id, 'tabindex', tabindex); - dom.bind(dom.get(item.id), 'focus', itemFocussed); + elm.setAttribute('tabindex', tabindex); + dom.bind(elm, 'focus', itemFocussed); }); // Setup initial state for root element. @@ -10682,10 +10739,11 @@ window.tinymce.dom.Sizzle = Sizzle; } dom.setAttrib(root, 'tabindex', '-1'); - + // Setup listeners for root element. - dom.bind(dom.get(root), 'focus', rootFocussed); - dom.bind(dom.get(root), 'keydown', rootKeydown); + var rootElm = dom.get(root); + dom.bind(rootElm, 'focus', rootFocussed); + dom.bind(rootElm, 'keydown', rootKeydown); } }); })(tinymce); @@ -12787,8 +12845,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { inline_styles : TRUE, convert_fonts_to_spans : TRUE, indent : 'simple', - indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure', - indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure', + indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', + indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', validate : TRUE, entity_encoding : 'named', url_converter : self.convertURL, @@ -12848,6 +12906,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); + // Hide target element early to prevent content flashing + t.orgVisibility = t.getElement().style.visibility; + t.getElement().style.visibility = 'hidden'; + if (tinymce.WindowManager) t.windowManager = new tinymce.WindowManager(t); @@ -12910,7 +12972,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { //sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); sl.add(tinymce.baseURL + '/../../extra/strings.php?elanguage=' + s.language + 'ðeme=' + s.theme); // Moodle modification - load one huge strings file - if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) + if (s.theme && typeof s.theme != "function" && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); each(explode(s.plugins), function(p) { @@ -12951,13 +13013,18 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); if (s.theme) { - s.theme = s.theme.replace(/-/, ''); - o = ThemeManager.get(s.theme); - t.theme = new o(); + if (typeof s.theme != "function") { + s.theme = s.theme.replace(/-/, ''); + o = ThemeManager.get(s.theme); + t.theme = new o(); - if (t.theme.init) - t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + if (t.theme.init) + t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + } else { + t.theme = s.theme; + } } + function initPlugin(p) { var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; if (c && tinymce.inArray(initializedPlugins,p) === -1) { @@ -13002,26 +13069,57 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { // Measure box if (s.render_ui && t.theme) { - w = s.width || e.style.width || e.offsetWidth; - h = s.height || e.style.height || e.offsetHeight; t.orgDisplay = e.style.display; - re = /^[0-9\.]+(|px)$/i; - if (re.test('' + w)) - w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); + if (typeof s.theme != "function") { + w = s.width || e.style.width || e.offsetWidth; + h = s.height || e.style.height || e.offsetHeight; + re = /^[0-9\.]+(|px)$/i; - if (re.test('' + h)) - //h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100); - h = Math.max(parseInt(h) + (o.deltaHeight || 0), s.theme_advanced_resizing_min_height || 100); // Moodle hack + if (re.test('' + w)) + w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); - // Render UI - o = t.theme.renderUI({ - targetNode : e, - width : w, - height : h, - deltaWidth : s.delta_width, - deltaHeight : s.delta_height - }); + if (re.test('' + h)) + //h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100); + h = Math.max(parseInt(h) + (o.deltaHeight || 0), s.theme_advanced_resizing_min_height || 100); // Moodle hack + + // Render UI + o = t.theme.renderUI({ + targetNode : e, + width : w, + height : h, + deltaWidth : s.delta_width, + deltaHeight : s.delta_height + }); + + // Resize editor + DOM.setStyles(o.sizeContainer || o.editorContainer, { + width : w, + height : h + }); + + h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); + //if (h < 100) + // h = 100; + if (h < (s.theme_advanced_resizing_min_height || 100)) // Moodle hack + h = s.theme_advanced_resizing_min_height || 100; // Moodle hack + + } else { + o = s.theme(t, e); + + // Convert element type to id:s + if (o.editorContainer.nodeType) { + o.editorContainer = o.editorContainer.id = o.editorContainer.id || t.id + "_parent"; + } + + // Convert element type to id:s + if (o.iframeContainer.nodeType) { + o.iframeContainer = o.iframeContainer.id = o.iframeContainer.id || t.id + "_iframecontainer"; + } + + // Use specified iframe height or the targets offsetHeight + h = o.iframeHeight || e.offsetHeight; + } t.editorContainer = o.editorContainer; } @@ -13043,18 +13141,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (document.domain && location.hostname != document.domain) tinymce.relaxedDomain = document.domain; - // Resize editor - DOM.setStyles(o.sizeContainer || o.editorContainer, { - width : w, - height : h - }); - - h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); - //if (h < 100) - // h = 100; - if (h < (s.theme_advanced_resizing_min_height || 100)) // Moodle hack - h = s.theme_advanced_resizing_min_height || 100; // Moodle hack - t.iframeHTML = s.doctype + ''; // We only need to override paths if we have to @@ -13113,7 +13199,14 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }); t.contentAreaContainer = o.iframeContainer; - DOM.get(o.editorContainer).style.display = t.orgDisplay; + + if (o.editorContainer) { + DOM.get(o.editorContainer).style.display = t.orgDisplay; + } + + // Restore visibility on target element + e.style.visibility = t.orgVisibility; + DOM.get(t.id).style.display = 'none'; DOM.setAttrib(t.id, 'aria-hidden', true); @@ -13438,9 +13531,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (self.initialized) { o = o || {}; - // Normalize selection for example a|a becomes a|a - selection.normalize(); - // Get start node node = selection.getStart() || self.getBody(); node = isIE && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state @@ -13918,14 +14008,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { return; case 'A': - value = dom.getAttrib(elm, 'name'); - cls = 'mceItemAnchor'; + if (!elm.href) { + value = dom.getAttrib(elm, 'name') || elm.id; + cls = 'mceItemAnchor'; - if (value) { - if (self.hasVisual) - dom.addClass(elm, cls); - else - dom.removeClass(elm, cls); + if (value) { + if (self.hasVisual) + dom.addClass(elm, cls); + else + dom.removeClass(elm, cls); + } } return; @@ -14220,6 +14312,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { self.focus(true); }; + function nodeChanged() { + // Normalize selection for example a|a becomes a|a + self.selection.normalize(); + self.nodeChanged(); + } + // Add DOM events each(nativeToDispatcherMap, function(dispatcherName, nativeName) { var root = settings.content_editable ? self.getBody() : self.getDoc(); @@ -14254,13 +14352,13 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { } // Add node change handler - self.onMouseUp.add(self.nodeChanged); + self.onMouseUp.add(nodeChanged); self.onKeyUp.add(function(ed, e) { var keyCode = e.keyCode; if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || keyCode == 46 || keyCode == 8 || (tinymce.isMac && (keyCode == 91 || keyCode == 93)) || e.ctrlKey) - self.nodeChanged(); + nodeChanged(); }); // Add reset handler @@ -14867,9 +14965,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }; // Create event instances - onAdd = new Dispatcher(self); - onUndo = new Dispatcher(self); - onRedo = new Dispatcher(self); + onBeforeAdd = new Dispatcher(self); + onAdd = new Dispatcher(self); + onUndo = new Dispatcher(self); + onRedo = new Dispatcher(self); // Pass though onAdd event from UndoManager to Editor as onChange onAdd.add(function(undoman, level) { @@ -14958,6 +15057,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { data : data, typing : false, + + onBeforeAdd: onBeforeAdd, onAdd : onAdd, @@ -14974,6 +15075,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { level = level || {}; level.content = getContent(); + + self.onBeforeAdd.dispatch(self, level); // Add undo level if needed lastLevel = data[index]; @@ -15074,7 +15177,7 @@ tinymce.ForceBlocks = function(editor) { return; // Check if node is wrapped in block - while (node != rootNode) { + while (node && node != rootNode) { if (blockElements[node.nodeName]) return; @@ -15214,28 +15317,40 @@ tinymce.ForceBlocks = function(editor) { return c; }, - createControl : function(n) { - var c, t = this, ed = t.editor; + createControl : function(name) { + var ctrl, i, l, self = this, editor = self.editor, factories, ctrlName; - each(ed.plugins, function(p) { - if (p.createControl) { - c = p.createControl(n, t); - - if (c) - return false; - } - }); - - switch (n) { - case "|": - case "separator": - return t.createSeparator(); + // Build control factory cache + if (!self.controlFactories) { + self.controlFactories = []; + each(editor.plugins, function(plugin) { + if (plugin.createControl) { + self.controlFactories.push(plugin); + } + }); } - if (!c && ed.buttons && (c = ed.buttons[n])) - return t.createButton(n, c); + // Create controls by asking cached factories + factories = self.controlFactories; + for (i = 0, l = factories.length; i < l; i++) { + ctrl = factories[i].createControl(name, self); - return t.add(c); + if (ctrl) { + return self.add(ctrl); + } + } + + // Create sepearator + if (name === "|" || name === "separator") { + return self.createSeparator(); + } + + // Create control from button collection + if (editor.buttons && (ctrl = editor.buttons[name])) { + return self.createButton(name, ctrl); + } + + return self.add(ctrl); }, createDropMenu : function(id, s, cc) { @@ -17495,6 +17610,21 @@ tinymce.ForceBlocks = function(editor) { } }; + // Checks if the parent caret container node isn't empty if that is the case it + // will remove the bogus state on all children that isn't empty + function unmarkBogusCaretParents() { + var i, caretContainer, node; + + caretContainer = getParentCaretContainer(selection.getStart()); + if (caretContainer && !dom.isEmpty(caretContainer)) { + tinymce.walk(caretContainer, function(node) { + if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) { + dom.setAttrib(node, 'data-mce-bogus', null); + } + }, 'childNodes'); + } + }; + // Only bind the caret events once if (!self._hasCaretEvents) { // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements @@ -17514,6 +17644,7 @@ tinymce.ForceBlocks = function(editor) { tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { ed[name].addToTop(function() { removeCaretContainer(); + unmarkBogusCaretParents(); }); }); @@ -17524,16 +17655,12 @@ tinymce.ForceBlocks = function(editor) { if (keyCode == 8 || keyCode == 37 || keyCode == 39) { removeCaretContainer(getParentCaretContainer(selection.getStart())); } + + unmarkBogusCaretParents(); }); // Remove bogus state if they got filled by contents using editor.selection.setContent - selection.onSetContent.add(function() { - dom.getParent(selection.getStart(), function(node) { - if (node.id !== caretContainerId && dom.getAttrib(node, 'data-mce-bogus') && !dom.isEmpty(node)) { - dom.setAttrib(node, 'data-mce-bogus', null); - } - }); - }); + selection.onSetContent.add(unmarkBogusCaretParents); self._hasCaretEvents = true; } diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_src.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_src.js similarity index 98% rename from lib/editor/tinymce/tiny_mce/3.5/tiny_mce_src.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_src.js index 18b2159a2a7..7c04a56a6a1 100644 --- a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_src.js +++ b/lib/editor/tinymce/tiny_mce/3.5.1.1/tiny_mce_src.js @@ -1579,6 +1579,14 @@ tinymce.util.Quirks = function(editor) { editor.onSetContent.add(selection.onSetContent.add(fixLinks)); }; + function setDefaultBlockType() { + if (settings.forced_root_block) { + editor.onInit.add(function() { + setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block); + }); + } + } + function removeGhostSelection() { function repaint(sender, args) { if (!sender || !args.initial) { @@ -1613,6 +1621,7 @@ tinymce.util.Quirks = function(editor) { cleanupStylesWhenDeleting(); inputMethodFocus(); selectControlElements(); + setDefaultBlockType(); // iOS if (tinymce.isIDevice) { @@ -2088,8 +2097,11 @@ tinymce.html.Styles = function(settings, schema) { if (!html5) { html5 = mapCache.html5 = unpack({ A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title', - B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video', - C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' + B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|' + + 'meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video', + C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|' + + 'figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|' + + 'p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video' }, 'html[A|manifest][body|head]' + 'head[A][base|command|link|meta|noscript|script|style|title]' + 'title[A][#]' + @@ -2125,7 +2137,7 @@ tinymce.html.Styles = function(settings, schema) { 'dl[A][dd|dt]' + 'dt[A][B]' + 'dd[A][C]' + - 'a[A|href|target|ping|rel|media|type][C]' + + 'a[A|href|target|ping|rel|media|type][B]' + 'em[A][B]' + 'strong[A][B]' + 'small[A][B]' + @@ -2171,7 +2183,8 @@ tinymce.html.Styles = function(settings, schema) { 'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' + 'fieldset[A|disabled|form|name][C|legend]' + 'label[A|form|for][B]' + - 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]' + + 'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' + + 'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' + 'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' + 'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' + 'datalist[A][B|option]' + @@ -2374,13 +2387,13 @@ tinymce.html.Styles = function(settings, schema) { // Setup map objects whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script style textarea'); - selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li options p td tfoot th thead tr'); + selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr'); shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source'); boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls'); nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object', shortEndedElementsMap); blockElementsMap = createLookupTable('block_elements', 'h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot ' + 'th tr td li ol ul caption blockquote center dl dt dd dir fieldset ' + - 'noscript menu isindex samp header footer article section hgroup aside nav figure'); + 'noscript menu isindex samp header footer article section hgroup aside nav figure option datalist select optgroup'); // Converts a wildcard expression string to a regexp for example *a will become /.*a/. function patternToRegExp(str) { @@ -2824,7 +2837,7 @@ tinymce.html.Styles = function(settings, schema) { // Setup lookup tables for empty elements and boolean attributes shortEndedElements = schema.getShortEndedElements(); - selfClosing = schema.getSelfClosingElements(); + selfClosing = settings.self_closing_elements || schema.getSelfClosingElements(); fillAttrsMap = schema.getBoolAttrs(); validate = settings.validate; removeInternalElements = settings.remove_internals; @@ -3570,9 +3583,23 @@ tinymce.html.Styles = function(settings, schema) { } }; + function cloneAndExcludeBlocks(input) { + var name, output = {}; + + for (name in input) { + if (name !== 'li' && name != 'p') { + output[name] = input[name]; + } + } + + return output; + }; + parser = new tinymce.html.SaxParser({ validate : validate, - fix_self_closing : !validate, // Let the DOM parser handle
                        • in
                        • or

                          in

                          for better results + + // Exclude P and LI from DOM parsing since it's treated better by the DOM parser + self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()), cdata: function(text) { node.append(createNode('#cdata', 4)).value = text; @@ -3750,7 +3777,7 @@ tinymce.html.Styles = function(settings, schema) { node.empty().append(new Node('#text', '3')).value = '\u00a0'; else { // Leave nodes that have a name like - if (!node.attributes.map.name) { + if (!node.attributes.map.name && !node.attributes.map.id) { tempNode = node.parent; node.empty().remove(); node = tempNode; @@ -3902,12 +3929,12 @@ tinymce.html.Styles = function(settings, schema) { // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. if (!settings.allow_html_in_named_anchor) { - self.addAttributeFilter('name', function(nodes, name) { + self.addAttributeFilter('id,name', function(nodes, name) { var i = nodes.length, sibling, prevSibling, parent, node; while (i--) { node = nodes[i]; - if (node.name === 'a' && node.firstChild) { + if (node.name === 'a' && node.firstChild && !node.attr('href')) { parent = node.parent; // Move children after current node @@ -6138,7 +6165,8 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { cloneContents : cloneContents, insertNode : insertNode, surroundContents : surroundContents, - cloneRange : cloneRange + cloneRange : cloneRange, + toStringIE : toStringIE }); function createDocumentFragment() { @@ -6778,9 +6806,20 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { n.parentNode.removeChild(n); }; + + function toStringIE() { + return dom.create('body', null, cloneContents()).outerText; + } + + return t; }; ns.Range = Range; + + // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype + Range.prototype.toString = function() { + return this.toStringIE(); + }; })(tinymce.dom); (function() { function Selection(selection) { @@ -7135,7 +7174,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { }; this.addRange = function(rng) { - var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body; + var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling, doc = selection.dom.doc, body = doc.body; function setEndPoint(start) { var container, offset, marker, tmpRng, nodes; @@ -7193,11 +7232,25 @@ tinymce.dom.TreeWalker = function(start_node, root_node) { // Trick to place the caret inside an empty block element like

                          if (startOffset == endOffset && !startContainer.hasChildNodes()) { if (startContainer.canHaveHTML) { + // Check if previous sibling is an empty block if it is then we need to render it + // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236 + // Example this:

                          |

                          would become this:

                          |

                          + sibling = startContainer.previousSibling; + if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) { + sibling.innerHTML = '\uFEFF'; + } else { + sibling = null; + } + startContainer.innerHTML = '\uFEFF\uFEFF'; ieRng.moveToElementText(startContainer.lastChild); ieRng.select(); dom.doc.selection.clear(); startContainer.innerHTML = ''; + + if (sibling) { + sibling.innerHTML = ''; + } return; } else { startOffset = dom.nodeIndex(startContainer); @@ -10182,11 +10235,10 @@ window.tinymce.dom.Sizzle = Sizzle; } // Create new script element - elm = dom.create('script', { - id : id, - type : 'text/javascript', - src : tinymce._addVer(url) - }); + elm = document.createElement('script'); + elm.id = id; + elm.type = 'text/javascript'; + elm.src = tinymce._addVer(url); // Add onload listener for non IE browsers since IE9 // fires onload event before the script is parsed and executed @@ -10548,12 +10600,15 @@ window.tinymce.dom.Sizzle = Sizzle; t.destroy = function() { each(items, function(item) { - dom.unbind(dom.get(item.id), 'focus', itemFocussed); - dom.unbind(dom.get(item.id), 'blur', itemBlurred); + var elm = dom.get(item.id); + + dom.unbind(elm, 'focus', itemFocussed); + dom.unbind(elm, 'blur', itemBlurred); }); - dom.unbind(dom.get(root), 'focus', rootFocussed); - dom.unbind(dom.get(root), 'keydown', rootKeydown); + var rootElm = dom.get(root); + dom.unbind(rootElm, 'focus', rootFocussed); + dom.unbind(rootElm, 'keydown', rootKeydown); items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; t.destroy = function() {}; @@ -10632,21 +10687,23 @@ window.tinymce.dom.Sizzle = Sizzle; // Set up state and listeners for each item. each(items, function(item, idx) { - var tabindex; + var tabindex, elm; if (!item.id) { item.id = dom.uniqueId('_mce_item_'); } + elm = dom.get(item.id); + if (excludeFromTabOrder) { - dom.bind(item.id, 'blur', itemBlurred); + dom.bind(elm, 'blur', itemBlurred); tabindex = '-1'; } else { tabindex = (idx === 0 ? '0' : '-1'); } - dom.setAttrib(item.id, 'tabindex', tabindex); - dom.bind(dom.get(item.id), 'focus', itemFocussed); + elm.setAttribute('tabindex', tabindex); + dom.bind(elm, 'focus', itemFocussed); }); // Setup initial state for root element. @@ -10655,10 +10712,11 @@ window.tinymce.dom.Sizzle = Sizzle; } dom.setAttrib(root, 'tabindex', '-1'); - + // Setup listeners for root element. - dom.bind(dom.get(root), 'focus', rootFocussed); - dom.bind(dom.get(root), 'keydown', rootKeydown); + var rootElm = dom.get(root); + dom.bind(rootElm, 'focus', rootFocussed); + dom.bind(rootElm, 'keydown', rootKeydown); } }); })(tinymce); @@ -12760,8 +12818,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { inline_styles : TRUE, convert_fonts_to_spans : TRUE, indent : 'simple', - indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure', - indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure', + indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', + indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist', validate : TRUE, entity_encoding : 'named', url_converter : self.convertURL, @@ -12821,6 +12879,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); + // Hide target element early to prevent content flashing + t.orgVisibility = t.getElement().style.visibility; + t.getElement().style.visibility = 'hidden'; + if (tinymce.WindowManager) t.windowManager = new tinymce.WindowManager(t); @@ -12883,7 +12945,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { //sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); sl.add(tinymce.baseURL + '/../../extra/strings.php?elanguage=' + s.language + 'ðeme=' + s.theme); // Moodle modification - load one huge strings file - if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) + if (s.theme && typeof s.theme != "function" && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); each(explode(s.plugins), function(p) { @@ -12924,13 +12986,18 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); if (s.theme) { - s.theme = s.theme.replace(/-/, ''); - o = ThemeManager.get(s.theme); - t.theme = new o(); + if (typeof s.theme != "function") { + s.theme = s.theme.replace(/-/, ''); + o = ThemeManager.get(s.theme); + t.theme = new o(); - if (t.theme.init) - t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + if (t.theme.init) + t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + } else { + t.theme = s.theme; + } } + function initPlugin(p) { var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; if (c && tinymce.inArray(initializedPlugins,p) === -1) { @@ -12975,26 +13042,57 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { // Measure box if (s.render_ui && t.theme) { - w = s.width || e.style.width || e.offsetWidth; - h = s.height || e.style.height || e.offsetHeight; t.orgDisplay = e.style.display; - re = /^[0-9\.]+(|px)$/i; - if (re.test('' + w)) - w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); + if (typeof s.theme != "function") { + w = s.width || e.style.width || e.offsetWidth; + h = s.height || e.style.height || e.offsetHeight; + re = /^[0-9\.]+(|px)$/i; - if (re.test('' + h)) - //h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100); - h = Math.max(parseInt(h) + (o.deltaHeight || 0), s.theme_advanced_resizing_min_height || 100); // Moodle hack + if (re.test('' + w)) + w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100); - // Render UI - o = t.theme.renderUI({ - targetNode : e, - width : w, - height : h, - deltaWidth : s.delta_width, - deltaHeight : s.delta_height - }); + if (re.test('' + h)) + //h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100); + h = Math.max(parseInt(h) + (o.deltaHeight || 0), s.theme_advanced_resizing_min_height || 100); // Moodle hack + + // Render UI + o = t.theme.renderUI({ + targetNode : e, + width : w, + height : h, + deltaWidth : s.delta_width, + deltaHeight : s.delta_height + }); + + // Resize editor + DOM.setStyles(o.sizeContainer || o.editorContainer, { + width : w, + height : h + }); + + h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); + //if (h < 100) + // h = 100; + if (h < (s.theme_advanced_resizing_min_height || 100)) // Moodle hack + h = s.theme_advanced_resizing_min_height || 100; // Moodle hack + + } else { + o = s.theme(t, e); + + // Convert element type to id:s + if (o.editorContainer.nodeType) { + o.editorContainer = o.editorContainer.id = o.editorContainer.id || t.id + "_parent"; + } + + // Convert element type to id:s + if (o.iframeContainer.nodeType) { + o.iframeContainer = o.iframeContainer.id = o.iframeContainer.id || t.id + "_iframecontainer"; + } + + // Use specified iframe height or the targets offsetHeight + h = o.iframeHeight || e.offsetHeight; + } t.editorContainer = o.editorContainer; } @@ -13016,18 +13114,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (document.domain && location.hostname != document.domain) tinymce.relaxedDomain = document.domain; - // Resize editor - DOM.setStyles(o.sizeContainer || o.editorContainer, { - width : w, - height : h - }); - - h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); - //if (h < 100) - // h = 100; - if (h < (s.theme_advanced_resizing_min_height || 100)) // Moodle hack - h = s.theme_advanced_resizing_min_height || 100; // Moodle hack - t.iframeHTML = s.doctype + ''; // We only need to override paths if we have to @@ -13086,7 +13172,14 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }); t.contentAreaContainer = o.iframeContainer; - DOM.get(o.editorContainer).style.display = t.orgDisplay; + + if (o.editorContainer) { + DOM.get(o.editorContainer).style.display = t.orgDisplay; + } + + // Restore visibility on target element + e.style.visibility = t.orgVisibility; + DOM.get(t.id).style.display = 'none'; DOM.setAttrib(t.id, 'aria-hidden', true); @@ -13411,9 +13504,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { if (self.initialized) { o = o || {}; - // Normalize selection for example a|a becomes a|a - selection.normalize(); - // Get start node node = selection.getStart() || self.getBody(); node = isIE && node.ownerDocument != self.getDoc() ? self.getBody() : node; // Fix for IE initial state @@ -13891,14 +13981,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { return; case 'A': - value = dom.getAttrib(elm, 'name'); - cls = 'mceItemAnchor'; + if (!elm.href) { + value = dom.getAttrib(elm, 'name') || elm.id; + cls = 'mceItemAnchor'; - if (value) { - if (self.hasVisual) - dom.addClass(elm, cls); - else - dom.removeClass(elm, cls); + if (value) { + if (self.hasVisual) + dom.addClass(elm, cls); + else + dom.removeClass(elm, cls); + } } return; @@ -14193,6 +14285,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { self.focus(true); }; + function nodeChanged() { + // Normalize selection for example a|a becomes a|a + self.selection.normalize(); + self.nodeChanged(); + } + // Add DOM events each(nativeToDispatcherMap, function(dispatcherName, nativeName) { var root = settings.content_editable ? self.getBody() : self.getDoc(); @@ -14227,13 +14325,13 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { } // Add node change handler - self.onMouseUp.add(self.nodeChanged); + self.onMouseUp.add(nodeChanged); self.onKeyUp.add(function(ed, e) { var keyCode = e.keyCode; if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || keyCode == 46 || keyCode == 8 || (tinymce.isMac && (keyCode == 91 || keyCode == 93)) || e.ctrlKey) - self.nodeChanged(); + nodeChanged(); }); // Add reset handler @@ -14840,9 +14938,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { }; // Create event instances - onAdd = new Dispatcher(self); - onUndo = new Dispatcher(self); - onRedo = new Dispatcher(self); + onBeforeAdd = new Dispatcher(self); + onAdd = new Dispatcher(self); + onUndo = new Dispatcher(self); + onRedo = new Dispatcher(self); // Pass though onAdd event from UndoManager to Editor as onChange onAdd.add(function(undoman, level) { @@ -14931,6 +15030,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { data : data, typing : false, + + onBeforeAdd: onBeforeAdd, onAdd : onAdd, @@ -14947,6 +15048,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { level = level || {}; level.content = getContent(); + + self.onBeforeAdd.dispatch(self, level); // Add undo level if needed lastLevel = data[index]; @@ -15047,7 +15150,7 @@ tinymce.ForceBlocks = function(editor) { return; // Check if node is wrapped in block - while (node != rootNode) { + while (node && node != rootNode) { if (blockElements[node.nodeName]) return; @@ -15187,28 +15290,40 @@ tinymce.ForceBlocks = function(editor) { return c; }, - createControl : function(n) { - var c, t = this, ed = t.editor; + createControl : function(name) { + var ctrl, i, l, self = this, editor = self.editor, factories, ctrlName; - each(ed.plugins, function(p) { - if (p.createControl) { - c = p.createControl(n, t); - - if (c) - return false; - } - }); - - switch (n) { - case "|": - case "separator": - return t.createSeparator(); + // Build control factory cache + if (!self.controlFactories) { + self.controlFactories = []; + each(editor.plugins, function(plugin) { + if (plugin.createControl) { + self.controlFactories.push(plugin); + } + }); } - if (!c && ed.buttons && (c = ed.buttons[n])) - return t.createButton(n, c); + // Create controls by asking cached factories + factories = self.controlFactories; + for (i = 0, l = factories.length; i < l; i++) { + ctrl = factories[i].createControl(name, self); - return t.add(c); + if (ctrl) { + return self.add(ctrl); + } + } + + // Create sepearator + if (name === "|" || name === "separator") { + return self.createSeparator(); + } + + // Create control from button collection + if (editor.buttons && (ctrl = editor.buttons[name])) { + return self.createButton(name, ctrl); + } + + return self.add(ctrl); }, createDropMenu : function(id, s, cc) { @@ -17468,6 +17583,21 @@ tinymce.ForceBlocks = function(editor) { } }; + // Checks if the parent caret container node isn't empty if that is the case it + // will remove the bogus state on all children that isn't empty + function unmarkBogusCaretParents() { + var i, caretContainer, node; + + caretContainer = getParentCaretContainer(selection.getStart()); + if (caretContainer && !dom.isEmpty(caretContainer)) { + tinymce.walk(caretContainer, function(node) { + if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) { + dom.setAttrib(node, 'data-mce-bogus', null); + } + }, 'childNodes'); + } + }; + // Only bind the caret events once if (!self._hasCaretEvents) { // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements @@ -17487,6 +17617,7 @@ tinymce.ForceBlocks = function(editor) { tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) { ed[name].addToTop(function() { removeCaretContainer(); + unmarkBogusCaretParents(); }); }); @@ -17497,16 +17628,12 @@ tinymce.ForceBlocks = function(editor) { if (keyCode == 8 || keyCode == 37 || keyCode == 39) { removeCaretContainer(getParentCaretContainer(selection.getStart())); } + + unmarkBogusCaretParents(); }); // Remove bogus state if they got filled by contents using editor.selection.setContent - selection.onSetContent.add(function() { - dom.getParent(selection.getStart(), function(node) { - if (node.id !== caretContainerId && dom.getAttrib(node, 'data-mce-bogus') && !dom.isEmpty(node)) { - dom.setAttrib(node, 'data-mce-bogus', null); - } - }); - }); + selection.onSetContent.add(unmarkBogusCaretParents); self._hasCaretEvents = true; } diff --git a/lib/editor/tinymce/tiny_mce/3.5/utils/editable_selects.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/utils/editable_selects.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/utils/editable_selects.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/utils/editable_selects.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/utils/form_utils.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/utils/form_utils.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/utils/form_utils.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/utils/form_utils.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/utils/mctabs.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/utils/mctabs.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/utils/mctabs.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/utils/mctabs.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/utils/validate.js b/lib/editor/tinymce/tiny_mce/3.5.1.1/utils/validate.js similarity index 100% rename from lib/editor/tinymce/tiny_mce/3.5/utils/validate.js rename to lib/editor/tinymce/tiny_mce/3.5.1.1/utils/validate.js diff --git a/lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin.js b/lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin.js deleted file mode 100644 index daac3b32660..00000000000 --- a/lib/editor/tinymce/tiny_mce/3.5/plugins/autolink/editor_plugin.js +++ /dev/null @@ -1 +0,0 @@ -(function(){tinymce.create("tinymce.plugins.AutolinkPlugin",{init:function(a,b){var c=this;a.onKeyDown.addToTop(function(d,f){if(f.keyCode==13){return c.handleEnter(d)}});if(tinyMCE.isIE){return}a.onKeyPress.add(function(d,f){if(f.which==41){return c.handleEclipse(d)}});a.onKeyUp.add(function(d,f){if(f.keyCode==32){return c.handleSpacebar(d)}})},handleEclipse:function(a){this.parseCurrentLine(a,-1,"(",true)},handleSpacebar:function(a){this.parseCurrentLine(a,0,"",true)},handleEnter:function(a){this.parseCurrentLine(a,-1,"",false)},parseCurrentLine:function(i,d,b,g){var a,f,c,n,k,m,h,e,j;a=i.selection.getRng().cloneRange();if(a.startOffset<5){e=a.endContainer.previousSibling;if(e==null){if(a.endContainer.firstChild==null||a.endContainer.firstChild.nextSibling==null){return}e=a.endContainer.firstChild.nextSibling}j=e.length;a.setStart(e,j);a.setEnd(e,j);if(a.endOffset<5){return}f=a.endOffset;n=e}else{n=a.endContainer;if(n.nodeType!=3&&n.firstChild){while(n.nodeType!=3&&n.firstChild){n=n.firstChild}a.setStart(n,0);a.setEnd(n,n.nodeValue.length)}if(a.endOffset==1){f=2}else{f=a.endOffset-1-d}}c=f;do{a.setStart(n,f-2);a.setEnd(n,f-1);f-=1}while(a.toString()!=" "&&a.toString()!=""&&a.toString().charCodeAt(0)!=160&&(f-2)>=0&&a.toString()!=b);if(a.toString()==b||a.toString().charCodeAt(0)==160){a.setStart(n,f);a.setEnd(n,c);f+=1}else{if(a.startOffset==0){a.setStart(n,0);a.setEnd(n,c)}else{a.setStart(n,f);a.setEnd(n,c)}}m=a.toString();h=m.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|[A-Z0-9._%+-]+@)(.+)$/i);if(h){if(h[1]=="www."){h[1]="http://www."}else{if(/@$/.test(h[1])){h[1]="mailto:"+h[1]}}k=i.selection.getBookmark();i.selection.setRng(a);tinyMCE.execCommand("createlink",false,h[1]+h[2]);i.selection.moveToBookmark(k);if(tinyMCE.isWebKit){i.selection.collapse(false);var l=Math.min(n.length,c+1);a.setStart(n,l);a.setEnd(n,l);i.selection.setRng(a)}}},getInfo:function(){return{longname:"Autolink",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autolink",tinymce.plugins.AutolinkPlugin)})(); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce.js b/lib/editor/tinymce/tiny_mce/3.5/tiny_mce.js deleted file mode 100644 index 751c1ab48f3..00000000000 --- a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce.js +++ /dev/null @@ -1 +0,0 @@ -(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"@@tinymce_major_version@@",minorVersion:"@@tinymce_minor_version@@",releaseDate:"@@tinymce_release_date@@",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey}}})(tinymce);tinymce.util.Quirks=function(d){var l=tinymce.VK,r=l.BACKSPACE,s=l.DELETE,o=d.dom,z=d.selection,q=d.settings;function c(D,C){try{d.getDoc().execCommand(D,false,C)}catch(B){}}function h(){function B(E){var C,G,D,F;C=z.getRng();G=o.getParent(C.startContainer,o.isBlock);if(E){G=o.getNext(G,o.isBlock)}if(G){D=G.firstChild;while(D&&D.nodeType==3&&D.nodeValue.length===0){D=D.nextSibling}if(D&&D.nodeName==="SPAN"){F=D.cloneNode(false)}}d.getDoc().execCommand(E?"ForwardDelete":"Delete",false,null);G=o.getParent(C.startContainer,o.isBlock);tinymce.each(o.select("span.Apple-style-span,font.Apple-style-span",G),function(H){var I=z.getBookmark();if(F){o.replace(F.cloneNode(false),H,true)}else{o.remove(H,true)}z.moveToBookmark(I)})}d.onKeyDown.add(function(C,E){var D;D=E.keyCode==s;if(!E.isDefaultPrevented()&&(D||E.keyCode==r)&&!l.modifierPressed(E)){E.preventDefault();B(D)}});d.addCommand("Delete",function(){B()})}function A(){function C(E,H){var D,G,F=H?"start":"end";D=E[F+"Container"];G=E[F+"Offset"];if(D.nodeType==1&&D.hasChildNodes()){D=D.childNodes[Math.min(H?G:(G>0?G-1:0),D.childNodes.length-1)]}return D}function B(G,K){var F,J,E,H,I=K?"start":"end",D;F=G[I+"Container"];J=G[I+"Offset"];E=o.getRoot();if(F.nodeType==1){D=J>=F.childNodes.length;F=C(G,K);if(F.nodeType==3){J=K&&!D?0:F.nodeValue.length}}if(F.nodeType==3&&((K&&J>0)||(!K&&J7){return}c("RespectVisibilityInDesign",true);o.addClass(d.getBody(),"mceHideBrInPre");d.parser.addNodeFilter("pre",function(C,E){var F=C.length,H,D,I,G;while(F--){H=C[F].getAll("br");D=H.length;while(D--){I=H[D];G=I.prev;if(G&&G.type===3&&G.value.charAt(G.value-1)!="\n"){G.value+="\n"}else{I.parent.insert(new tinymce.html.Node("#text",3),I,true).value="\n"}}}});d.serializer.addNodeFilter("pre",function(C,E){var F=C.length,H,D,I,G;while(F--){H=C[F].getAll("br");D=H.length;while(D--){I=H[D];G=I.prev;if(G&&G.type==3){G.value=G.value.replace(/\r?\n$/,"")}}}})}function f(){o.bind(d.getBody(),"mouseup",function(D){var C,B=z.getNode();if(B.nodeName=="IMG"){if(C=o.getStyle(B,"width")){o.setAttrib(B,"width",C.replace(/[^0-9%]+/g,""));o.setStyle(B,"width","")}if(C=o.getStyle(B,"height")){o.setAttrib(B,"height",C.replace(/[^0-9%]+/g,""));o.setStyle(B,"height","")}}})}function p(){d.onKeyDown.add(function(H,I){var G,B,C,E,F,J,D;G=I.keyCode==s;if(!I.isDefaultPrevented()&&(G||I.keyCode==r)&&!l.modifierPressed(I)){B=z.getRng();C=B.startContainer;E=B.startOffset;D=B.collapsed;if(C.nodeType==3&&C.nodeValue.length>0&&((E===0&&!D)||(D&&E===(G?0:1)))){nonEmptyElements=H.schema.getNonEmptyElements();I.preventDefault();F=o.create("br",{id:"__tmp"});C.parentNode.insertBefore(F,C);H.getDoc().execCommand(G?"ForwardDelete":"Delete",false,null);C=z.getRng().startContainer;J=C.previousSibling;if(J&&J.nodeType==1&&!o.isBlock(J)&&o.isEmpty(J)&&!nonEmptyElements[J.nodeName.toLowerCase()]){o.remove(J)}o.remove("__tmp")}}})}function e(){d.onKeyDown.add(function(F,G){var D,C,H,B,E;if(G.isDefaultPrevented()||G.keyCode!=l.BACKSPACE){return}D=z.getRng();C=D.startContainer;H=D.startOffset;B=o.getRoot();E=C;if(!D.collapsed||H!==0){return}while(E&&E.parentNode&&E.parentNode.firstChild==E&&E.parentNode!=B){E=E.parentNode}if(E.tagName==="BLOCKQUOTE"){F.formatter.toggle("blockquote",null,E);D.setStart(C,0);D.setEnd(C,0);z.setRng(D);z.collapse(false)}})}function k(){function B(){d._refreshContentEditable();c("StyleWithCSS",false);c("enableInlineTableEditing",false);if(!q.object_resizing){c("enableObjectResizing",false)}}if(!q.readonly){d.onBeforeExecCommand.add(B);d.onMouseDown.add(B)}}function n(){function B(C,D){tinymce.each(o.select("a"),function(G){var E=G.parentNode,F=o.getRoot();if(E.lastChild===G){while(E&&!o.isBlock(E)){if(E.parentNode.lastChild!==E||E===F){return}E=E.parentNode}o.add(E,"br",{"data-mce-bogus":1})}})}d.onExecCommand.add(function(C,D){if(D==="CreateLink"){B(C)}});d.onSetContent.add(z.onSetContent.add(B))}function a(){function B(D,C){if(!D||!C.initial){d.execCommand("mceRepaint")}}d.onUndo.add(B);d.onRedo.add(B);d.onSetContent.add(B)}function j(){d.onKeyDown.add(function(B,C){if(!C.isDefaultPrevented()&&C.keyCode==8&&z.getNode().nodeName=="IMG"){C.preventDefault();B.undoManager.beforeChange();o.remove(z.getNode());B.undoManager.add()}})}u();e();A();if(tinymce.isWebKit){p();h();t();v();if(tinymce.isIDevice){i()}}if(tinymce.isIE){m();y();g();f();j()}if(tinymce.isGecko){m();b();x();k();n();a()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][C]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script style textarea");q=m("self_closing_elements","colgroup dd dt li options p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object",z);v=m("block_elements","h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot th tr td li ol ul caption blockquote center dl dt dd dir fieldset noscript menu isindex samp header footer article section hgroup aside nav figure");function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t0){P.value=l;P=P.prev}else{N=P.prev;P.remove();P=N}}}n=new b.html.SaxParser({validate:z,fix_self_closing:!z,cdata:function(l){B.append(J("#cdata",4)).value=l},text:function(O,l){var N;if(!K){O=O.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){O=O.replace(E,"")}}if(O.length!==0){N=J("#text",3);N.raw=!!l;B.append(N).value=O}},comment:function(l){B.append(J("#comment",8)).value=l},pi:function(l,N){B.append(J(l,7)).value=N;H(B)},doctype:function(N){var l;l=B.append(J("#doctype",10));l.value=N;H(B)},start:function(l,V,O){var T,Q,P,N,R,W,U,S;P=z?h.getElementRule(l):{};if(P){T=J(P.outputName||l,1);T.attributes=V;T.shortEnded=O;B.append(T);S=p[B.name];if(S&&p[T.name]&&!S[T.name]){L.push(T)}Q=d.length;while(Q--){R=d[Q].name;if(R in V.map){F=c[R];if(F){F.push(T)}else{c[R]=[T]}}}if(o[l]){H(T)}if(!O){B=T}if(!K&&s[l]){K=true}}},end:function(l){var R,O,Q,N,P;O=z?h.getElementRule(l):{};if(O){if(o[l]){if(!K){R=B.firstChild;if(R&&R.type===3){Q=R.value.replace(E,"");if(Q.length>0){R.value=Q;R=R.next}else{N=R.next;R.remove();R=N}while(R&&R.type===3){Q=R.value;N=R.next;if(Q.length===0||y.test(Q)){R.remove();R=N}R=N}}R=B.lastChild;if(R&&R.type===3){Q=R.value.replace(t,"");if(Q.length>0){R.value=Q;R=R.prev}else{N=R.prev;R.remove();R=N}while(R&&R.type===3){Q=R.value;N=R.prev;if(Q.length===0||y.test(Q)){R.remove();R=N}R=N}}}R=B.prev;if(R&&R.type===3){Q=R.value.replace(E,"");if(Q.length>0){R.value=Q}else{R.remove()}}}if(K&&s[l]){K=false}if(O.removeEmpty||O.paddEmpty){if(B.isEmpty(u)){if(O.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name){P=B.parent;B.empty().remove();B=P;return}}}}B=B.parent}}},h);I=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&L.length){if(!m.context){j(L)}else{m.invalid=true}}if(q&&I.name=="body"){G()}if(!m.invalid){for(M in i){F=e[M];A=i[M];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},select:function(k,j){var i=this;return e.dom.Sizzle(k,i.get(j)||i.get(i.settings.root_element)||i.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(c.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return e.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":b?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
                          "+j;m.removeChild(m.firstChild)}catch(l){m=i.create("div");m.innerHTML="
                          "+j;g(m.childNodes,function(o,n){if(n){m.appendChild(o)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){g(s.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:q(s.styleSheet);break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,T=0,F=1,j=2,E=true,S=false,V="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L});function x(){return e.createDocumentFragment()}function q(W,t){C(E,W,t)}function s(W,t){C(S,W,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[V]}else{O[h]=O[Q];O[V]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(Z,t){var ac=O[h],X=O[V],ab=O[Q],W=O[A],aa=t.startContainer,ae=t.startOffset,Y=t.endContainer,ad=t.endOffset;if(Z===0){return H(ac,X,aa,ae)}if(Z===1){return H(ab,W,aa,ae)}if(Z===2){return H(ab,W,Y,ad)}if(Z===3){return H(ac,X,Y,ad)}}function p(){l(j)}function I(){return l(T)}function d(){return l(F)}function D(Z){var W=this[h],t=this[V],Y,X;if((W.nodeType===3||W.nodeType===4)&&W.nodeValue){if(!t){W.parentNode.insertBefore(Z,W)}else{if(t>=W.nodeValue.length){c.insertAfter(Z,W)}else{Y=W.splitText(t);W.parentNode.insertBefore(Z,Y)}}}else{if(W.childNodes.length>0){X=W.childNodes[t]}if(X){W.insertBefore(Z,X)}else{W.appendChild(Z)}}}function N(W){var t=O.extractContents();O.insertNode(W);W.appendChild(t);O.selectNode(W)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[V],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,W){var X;if(t.nodeType==3){return t}if(W<0){return t}X=t.firstChild;while(X&&W>0){--W;X=X.nextSibling}if(X){return X}return t}function m(){return(O[h]==O[Q]&&O[V]==O[A])}function H(Y,aa,W,Z){var ab,X,t,ac,ae,ad;if(Y==W){if(aa==Z){return 0}if(aa0){O.collapse(W)}}else{O.collapse(W)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ac){var ab,Y=0,ae=0,W,aa,X,Z,t,ad;if(O[h]==O[Q]){return f(ac)}for(ab=O[Q],W=ab.parentNode;W;ab=W,W=W.parentNode){if(W==O[h]){return r(ab,ac)}++Y}for(ab=O[h],W=ab.parentNode;W;ab=W,W=W.parentNode){if(W==O[Q]){return U(ab,ac)}++ae}aa=ae-Y;X=O[h];while(aa>0){X=X.parentNode;aa--}Z=O[Q];while(aa<0){Z=Z.parentNode;aa++}for(t=X.parentNode,ad=Z.parentNode;t!=ad;t=t.parentNode,ad=ad.parentNode){X=t;Z=ad}return o(X,Z,ac)}function f(ab){var ad,ae,t,X,Y,ac,Z,W,aa;if(ab!=j){ad=x()}if(O[V]==O[A]){return ad}if(O[h].nodeType==3){ae=O[h].nodeValue;t=ae.substring(O[V],O[A]);if(ab!=F){X=O[h];W=O[V];aa=O[A]-O[V];if(W===0&&aa>=X.nodeValue.length-1){X.parentNode.removeChild(X)}else{X.deleteData(W,aa)}O.collapse(E)}if(ab==j){return}if(t.length>0){ad.appendChild(e.createTextNode(t))}return ad}X=P(O[h],O[V]);Y=O[A]-O[V];while(X&&Y>0){ac=X.nextSibling;Z=z(X,ab);if(ad){ad.appendChild(Z)}--Y;X=ac}if(ab!=F){O.collapse(E)}return ad}function r(ac,Z){var ab,aa,W,t,Y,X;if(Z!=j){ab=x()}aa=i(ac,Z);if(ab){ab.appendChild(aa)}W=n(ac);t=W-O[V];if(t<=0){if(Z!=F){O.setEndBefore(ac);O.collapse(S)}return ab}aa=ac.previousSibling;while(t>0){Y=aa.previousSibling;X=z(aa,Z);if(ab){ab.insertBefore(X,ab.firstChild)}--t;aa=Y}if(Z!=F){O.setEndBefore(ac);O.collapse(S)}return ab}function U(aa,Z){var ac,W,ab,t,Y,X;if(Z!=j){ac=x()}ab=R(aa,Z);if(ac){ac.appendChild(ab)}W=n(aa);++W;t=O[A]-W;ab=aa.nextSibling;while(ab&&t>0){Y=ab.nextSibling;X=z(ab,Z);if(ac){ac.appendChild(X)}--t;ab=Y}if(Z!=F){O.setStartAfter(aa);O.collapse(E)}return ac}function o(aa,t,ad){var X,af,Z,ab,ac,W,ae,Y;if(ad!=j){af=x()}X=R(aa,ad);if(af){af.appendChild(X)}Z=aa.parentNode;ab=n(aa);ac=n(t);++ab;W=ac-ab;ae=aa.nextSibling;while(W>0){Y=ae.nextSibling;X=z(ae,ad);if(af){af.appendChild(X)}ae=Y;--W}X=i(t,ad);if(af){af.appendChild(X)}if(ad!=F){O.setStartAfter(aa);O.collapse(E)}return af}function i(ab,ac){var X=P(O[Q],O[A]-1),ad,aa,Z,t,W,Y=X!=O[Q];if(X==ab){return M(X,Y,S,ac)}ad=X.parentNode;aa=M(ad,S,S,ac);while(ad){while(X){Z=X.previousSibling;t=M(X,Y,S,ac);if(ac!=j){aa.insertBefore(t,aa.firstChild)}Y=E;X=Z}if(ad==ab){return aa}X=ad.previousSibling;ad=ad.parentNode;W=M(ad,S,S,ac);if(ac!=j){W.appendChild(aa)}aa=W}}function R(ab,ac){var Y=P(O[h],O[V]),Z=Y!=O[h],ad,aa,X,t,W;if(Y==ab){return M(Y,Z,E,ac)}ad=Y.parentNode;aa=M(ad,S,E,ac);while(ad){while(Y){X=Y.nextSibling;t=M(Y,Z,E,ac);if(ac!=j){aa.appendChild(t)}Z=E;Y=X}if(ad==ab){return aa}Y=ad.nextSibling;ad=ad.parentNode;W=M(ad,S,E,ac);if(ac!=j){W.appendChild(aa)}aa=W}}function M(t,Z,ac,ad){var Y,X,aa,W,ab;if(Z){return z(t,ad)}if(t.nodeType==3){Y=t.nodeValue;if(ac){W=O[V];X=Y.substring(W);aa=Y.substring(0,W)}else{W=O[A];X=Y.substring(0,W);aa=Y.substring(W)}if(ad!=F){t.nodeValue=aa}if(ad==j){return}ab=c.clone(t,S);ab.nodeValue=X;return ab}if(ad==j){return}return c.clone(t,S)}function z(W,t){if(t!=j){return t==F?c.clone(W,E):W}W.parentNode.removeChild(W)}}a.Range=b})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,s,q,r=d.dom.doc,m=r.body;function j(z){var u,y,t,x,v;t=h.create("a");u=z?k:s;y=z?p:q;x=n.duplicate();if(u==r||u==r.documentElement){u=m;y=0}if(u.nodeType==3){u.parentNode.insertBefore(t,u);x.moveToElementText(t);x.moveStart("character",y);h.remove(t);n.setEndPoint(z?"StartToStart":"EndToEnd",x)}else{v=u.childNodes;if(v.length){if(y>=v.length){h.insertAfter(t,v[v.length-1])}else{u.insertBefore(t,v[y])}x.moveToElementText(t)}else{if(u.canHaveHTML){u.innerHTML="\uFEFF";t=u.firstChild;x.moveToElementText(t);x.collapse(f)}}n.setEndPoint(z?"StartToStart":"EndToEnd",x);h.remove(t)}}k=i.startContainer;p=i.startOffset;s=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==s&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var n=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i="sizcache",o=0,r=Object.prototype.toString,h=false,g=true,q=/\\/g,u=/\r\n/g,x=/\W/;[0,0].sort(function(){g=false;return 0});var d=function(C,e,F,G){F=F||[];e=e||document;var I=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!C||typeof C!=="string"){return F}var z,K,N,y,J,M,L,E,B=true,A=d.isXML(e),D=[],H=C;do{n.exec("");z=n.exec(H);if(z){H=z[3];D.push(z[1]);if(z[2]){y=z[3];break}}}while(z);if(D.length>1&&j.exec(C)){if(D.length===2&&k.relative[D[0]]){K=s(D[0]+D[1],e,G)}else{K=k.relative[D[0]]?[e]:d(D.shift(),e);while(D.length){C=D.shift();if(k.relative[C]){C+=D.shift()}K=s(C,K,G)}}}else{if(!G&&D.length>1&&e.nodeType===9&&!A&&k.match.ID.test(D[0])&&!k.match.ID.test(D[D.length-1])){J=d.find(D.shift(),e,A);e=J.expr?d.filter(J.expr,J.set)[0]:J.set[0]}if(e){J=G?{expr:D.pop(),set:l(G)}:d.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&e.parentNode?e.parentNode:e,A);K=J.expr?d.filter(J.expr,J.set):J.set;if(D.length>0){N=l(K)}else{B=false}while(D.length){M=D.pop();L=M;if(!k.relative[M]){M=""}else{L=D.pop()}if(L==null){L=e}k.relative[M](N,L,A)}}else{N=D=[]}}if(!N){N=K}if(!N){d.error(M||C)}if(r.call(N)==="[object Array]"){if(!B){F.push.apply(F,N)}else{if(e&&e.nodeType===1){for(E=0;N[E]!=null;E++){if(N[E]&&(N[E]===true||N[E].nodeType===1&&d.contains(e,N[E]))){F.push(K[E])}}}else{for(E=0;N[E]!=null;E++){if(N[E]&&N[E].nodeType===1){F.push(K[E])}}}}}else{l(N,F)}if(y){d(y,I,F,G);d.uniqueSort(F)}return F};d.uniqueSort=function(y){if(p){h=g;y.sort(p);if(h){for(var e=1;e0};d.find=function(E,e,F){var D,z,B,A,C,y;if(!E){return[]}for(z=0,B=k.order.length;z":function(D,y){var C,B=typeof y==="string",z=0,e=D.length;if(B&&!x.test(y)){y=y.toLowerCase();for(;z=0)){if(!z){e.push(C)}}else{if(z){y[B]=false}}}}return false},ID:function(e){return e[1].replace(q,"")},TAG:function(y,e){return y[1].replace(q,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){d.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var y=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(y[1]+(y[2]||1))-0;e[3]=y[3]-0}else{if(e[2]){d.error(e[0])}}e[0]=o++;return e},ATTR:function(B,y,z,e,C,D){var A=B[1]=B[1].replace(q,"");if(!D&&k.attrMap[A]){B[1]=k.attrMap[A]}B[4]=(B[4]||B[5]||"").replace(q,"");if(B[2]==="~="){B[4]=" "+B[4]+" "}return B},PSEUDO:function(B,y,z,e,C){if(B[1]==="not"){if((n.exec(B[3])||"").length>1||/^\w/.test(B[3])){B[3]=d(B[3],null,null,y)}else{var A=d.filter(B[3],y,z,true^C);if(!z){e.push.apply(e,A)}return false}}else{if(k.match.POS.test(B[0])||k.match.CHILD.test(B[0])){return true}}return B},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(z,y,e){return !!d(e[3],z).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(z){var e=z.getAttribute("type"),y=z.type;return z.nodeName.toLowerCase()==="input"&&"text"===y&&(e===y||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===y.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===y.type},button:function(y){var e=y.nodeName.toLowerCase();return e==="input"&&"button"===y.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(y,e){return e===0},last:function(z,y,e,A){return y===A.length-1},even:function(y,e){return e%2===0},odd:function(y,e){return e%2===1},lt:function(z,y,e){return ye[3]-0},nth:function(z,y,e){return e[3]-0===y},eq:function(z,y,e){return e[3]-0===y}},filter:{PSEUDO:function(z,E,D,F){var e=E[1],y=k.filters[e];if(y){return y(z,D,E,F)}else{if(e==="contains"){return(z.textContent||z.innerText||b([z])||"").indexOf(E[3])>=0}else{if(e==="not"){var A=E[3];for(var C=0,B=A.length;C=0)}}},ID:function(y,e){return y.nodeType===1&&y.getAttribute("id")===e},TAG:function(y,e){return(e==="*"&&y.nodeType===1)||!!y.nodeName&&y.nodeName.toLowerCase()===e},CLASS:function(y,e){return(" "+(y.className||y.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(C,A){var z=A[1],e=d.attr?d.attr(C,z):k.attrHandle[z]?k.attrHandle[z](C):C[z]!=null?C[z]:C.getAttribute(z),D=e+"",B=A[2],y=A[4];return e==null?B==="!=":!B&&d.attr?e!=null:B==="="?D===y:B==="*="?D.indexOf(y)>=0:B==="~="?(" "+D+" ").indexOf(y)>=0:!y?D&&e!==false:B==="!="?D!==y:B==="^="?D.indexOf(y)===0:B==="$="?D.substr(D.length-y.length)===y:B==="|="?D===y||D.substr(0,y.length+1)===y+"-":false},POS:function(B,y,z,C){var e=y[2],A=k.setFilters[e];if(A){return A(B,z,y,C)}}}};var j=k.match.POS,c=function(y,e){return"\\"+(e-0+1)};for(var f in k.match){k.match[f]=new RegExp(k.match[f].source+(/(?![^\[]*\])(?![^\(]*\))/.source));k.leftMatch[f]=new RegExp(/(^(?:.|\r|\n)*?)/.source+k.match[f].source.replace(/\\(\d+)/g,c))}k.match.globalPOS=j;var l=function(y,e){y=Array.prototype.slice.call(y,0);if(e){e.push.apply(e,y);return e}return y};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(v){l=function(B,A){var z=0,y=A||[];if(r.call(B)==="[object Array]"){Array.prototype.push.apply(y,B)}else{if(typeof B.length==="number"){for(var e=B.length;z";e.insertBefore(y,e.firstChild);if(document.getElementById(z)){k.find.ID=function(B,C,D){if(typeof C.getElementById!=="undefined"&&!D){var A=C.getElementById(B[1]);return A?A.id===B[1]||typeof A.getAttributeNode!=="undefined"&&A.getAttributeNode("id").nodeValue===B[1]?[A]:undefined:[]}};k.filter.ID=function(C,A){var B=typeof C.getAttributeNode!=="undefined"&&C.getAttributeNode("id");return C.nodeType===1&&B&&B.nodeValue===A}}e.removeChild(y);e=y=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){k.find.TAG=function(y,C){var B=C.getElementsByTagName(y[1]);if(y[1]==="*"){var A=[];for(var z=0;B[z];z++){if(B[z].nodeType===1){A.push(B[z])}}B=A}return B}}e.innerHTML="
                          ";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){k.attrHandle.href=function(y){return y.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div"),z="__sizzle__";A.innerHTML="

                          ";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(L,C,G,K){C=C||document;if(!K&&!d.isXML(C)){var J=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(L);if(J&&(C.nodeType===1||C.nodeType===9)){if(J[1]){return l(C.getElementsByTagName(L),G)}else{if(J[2]&&k.find.CLASS&&C.getElementsByClassName){return l(C.getElementsByClassName(J[2]),G)}}}if(C.nodeType===9){if(L==="body"&&C.body){return l([C.body],G)}else{if(J&&J[3]){var F=C.getElementById(J[3]);if(F&&F.parentNode){if(F.id===J[3]){return l([F],G)}}else{return l([],G)}}}try{return l(C.querySelectorAll(L),G)}catch(H){}}else{if(C.nodeType===1&&C.nodeName.toLowerCase()!=="object"){var D=C,E=C.getAttribute("id"),B=E||z,N=C.parentNode,M=/^\s*[+~]/.test(L);if(!E){C.setAttribute("id",B)}else{B=B.replace(/'/g,"\\$&")}if(M&&N){C=C.parentNode}try{if(!M||N){return l(C.querySelectorAll("[id='"+B+"'] "+L),G)}}catch(I){}finally{if(!E){D.removeAttribute("id")}}}}}return e(L,C,G,K)};for(var y in e){d[y]=e[y]}A=null})()}(function(){var e=document.documentElement,z=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(z){var B=!z.call(document.createElement("div"),"div"),y=false;try{z.call(document.documentElement,"[test!='']:sizzle")}catch(A){y=true}d.matchesSelector=function(D,F){F=F.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!d.isXML(D)){try{if(y||!k.match.PSEUDO.test(F)&&!/!=/.test(F)){var C=z.call(D,F);if(C||!B||D.document&&D.document.nodeType!==11){return C}}}catch(E){}}return d(F,null,null,[D]).length>0}}})();(function(){var e=document.createElement("div");e.innerHTML="
                          ";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}k.order.splice(1,0,"CLASS");k.find.CLASS=function(y,z,A){if(typeof z.getElementsByClassName!=="undefined"&&!A){return z.getElementsByClassName(y[1])}};e=null})();function a(y,D,C,G,E,F){for(var A=0,z=G.length;A0){B=e;break}}}e=e[y]}G[A]=B}}}if(document.documentElement.contains){d.contains=function(y,e){return y!==e&&(y.contains?y.contains(e):true)}}else{if(document.documentElement.compareDocumentPosition){d.contains=function(y,e){return !!(y.compareDocumentPosition(e)&16)}}else{d.contains=function(){return false}}}d.isXML=function(e){var y=(e?e.ownerDocument||e:0).documentElement;return y?y.nodeName!=="HTML":false};var s=function(z,e,D){var C,E=[],B="",F=e.nodeType?[e]:e;while((C=k.match.PSEUDO.exec(z))){B+=C[0];z=z.replace(k.match.PSEUDO,"")}z=k.relative[z]?z+"*":z;for(var A=0,y=F.length;A"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var h=this.getRng(),i,g,k,j;if(h.duplicate||h.item){if(h.item){return h.item(0)}k=h.duplicate();k.collapse(1);i=k.parentElement();g=j=h.parentElement();while(j=j.parentNode){if(j==i){i=g;break}}return i}else{i=h.startContainer;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[Math.min(i.childNodes.length-1,h.startOffset)]}if(i&&i.nodeType==3){return i.parentNode}return i}},getEnd:function(){var h=this,i=h.getRng(),j,g;if(i.duplicate||i.item){if(i.item){return i.item(0)}i=i.duplicate();i.collapse(0);j=i.parentElement();if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=i.endContainer;g=i.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[g>0?g-1:g]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){return{rng:y.getRng()}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(o){var s=this,m=s.dom,j,i,g,r,k,u,p,q;function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t.length-1;x>=1;x--){v=y.childNodes;if(t[x]>v.length-1){return}y=v[t[x]]}if(y.nodeType===3){z=Math.min(t[0],y.nodeValue.length)}if(y.nodeType===1){z=Math.min(t[0],y.childNodes.length)}if(A){g.setStart(y,z)}else{g.setEnd(y,z)}}return true}function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentNode;if(B=="start"){if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}k=u=A;p=q=t}else{if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}u=A;q=t}if(!x){z=v.previousSibling;y=v.nextSibling;e(d.grep(v.childNodes),function(C){if(C.nodeType==3){C.nodeValue=C.nodeValue.replace(/\uFEFF/g,"")}});while(v=m.get(o.id+"_"+B)){m.remove(v,1)}if(z&&y&&z.nodeType==y.nodeType&&z.nodeType==3&&!d.isOpera){t=z.nodeValue.length;z.appendData(y.nodeValue);m.remove(y);if(B=="start"){k=u=z;p=q=t}else{u=z;q=t}}}}}function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
                          '}return t}if(o){if(o.start){g=m.createRng();r=m.getRoot();if(s.tridentSel){return s.tridentSel.moveToBookmark(o)}if(h(true)&&h()){s.setRng(g)}}else{if(o.id){l("start");l("end");if(k){g=m.createRng();g.setStart(n(k),p);g.setEnd(n(u),q);s.setRng(g)}}else{if(o.name){s.select(m.select(o.name)[o.index])}else{if(o.rng){s.setRng(o.rng)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},destroy:function(h){var g=this;g.win=null;if(!h){d.removeUnload(g.destroy)}},_fixIESelection:function(){var h=this.dom,n=h.doc,i=n.body,k,o,g;function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r){q=null}return q}function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoints("StartToStart",o)>0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=q.create("script",{id:n,type:"text/javascript",src:a._addVer(m)});if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=l.length){q=0}}s=l[q];f.setAttrib(g,"tabindex","-1");f.setAttrib(s.id,"tabindex","0");f.get(s.id).focus();if(e.actOnFocus){e.onAction(s.id)}if(r){a.cancel(r)}};o=function(y){var u=37,t=39,x=38,z=40,q=27,s=14,r=13,v=32;switch(y.keyCode){case u:if(i){p.moveFocus(-1)}break;case t:if(i){p.moveFocus(1)}break;case x:if(n){p.moveFocus(-1)}break;case z:if(n){p.moveFocus(1)}break;case q:if(e.onCancel){e.onCancel();a.cancel(y)}break;case s:case r:case v:if(e.onAction){e.onAction(g);a.cancel(y)}break}};c(l,function(s,q){var r;if(!s.id){s.id=f.uniqueId("_mce_item_")}if(k){f.bind(s.id,"blur",h);r="-1"}else{r=(q===0?"0":"-1")}f.setAttrib(s.id,"tabindex",r);f.bind(f.get(s.id),"focus",j)});if(l[0]){g=l[0].id}f.setAttrib(m,"tabindex","-1");f.bind(f.get(m),"focus",d);f.bind(f.get(m),"keydown",o)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+c}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keyup",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(l){var k;b.remove(h.id,"change",i);j=false;k=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",k)});if(e.isWebKit&&(l.keyCode==37||l.keyCode==39)){return b.prevent(l)}if(l.keyCode==13||l.keyCode==32){g(l);return b.cancel(l)}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
                          ');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
                          ");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){return;var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}x=d({theme:"simple",language:"en"},x);v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/../../extra/strings.php?elanguage="+q.language+"ðeme="+q.theme)}if(q.theme&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,F=this,G=F.settings,C,y,B=F.getElement(),p,m,D,v,A,E,x,r=[];k.add(F);G.aria_label=G.aria_label||l.getAttrib(B,"aria-label",F.getLang("aria.rich_text_area"));if(G.theme){G.theme=G.theme.replace(/-/,"");p=h.get(G.theme);F.theme=new p();if(F.theme.init){F.theme.init(F,h.urls[G.theme]||k.documentBaseURL.replace(/\/$/,""))}}function z(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){z(u)});n=new t(F,o);F.plugins[s]=n;if(n.init){n.init(F,o);r.push(s)}}}i(g(G.plugins.replace(/\-/g,"")),z);if(G.popup_css!==false){if(G.popup_css){G.popup_css=F.documentBaseURI.toAbsolute(G.popup_css)}else{G.popup_css=F.baseURI.toAbsolute("themes/"+G.theme+"/skins/"+G.skin+"/dialog.css")}}if(G.popup_css_add){G.popup_css+=","+F.documentBaseURI.toAbsolute(G.popup_css_add)}F.controlManager=new k.ControlManager(F);F.onExecCommand.add(function(n,o){if(!/^(FontName|FontSize)$/.test(o)){F.nodeChanged()}});F.onBeforeRenderUI.dispatch(F,F.controlManager);if(G.render_ui&&F.theme){C=G.width||B.style.width||B.offsetWidth;y=G.height||B.style.height||B.offsetHeight;F.orgDisplay=B.style.display;E=/^[0-9\.]+(|px)$/i;if(E.test(""+C)){C=Math.max(parseInt(C,10)+(p.deltaWidth||0),100)}if(E.test(""+y)){y=Math.max(parseInt(y)+(p.deltaHeight||0),G.theme_advanced_resizing_min_height||100)}p=F.theme.renderUI({targetNode:B,width:C,height:y,deltaWidth:G.delta_width,deltaHeight:G.delta_height});F.editorContainer=p.editorContainer}if(G.content_css){i(g(G.content_css),function(n){F.contentCSS.push(F.documentBaseURI.toAbsolute(n))})}if(G.content_editable){B=q=p=null;return F.initContentBody()}if(document.domain&&location.hostname!=document.domain){k.relaxedDomain=document.domain}l.setStyles(p.sizeContainer||p.editorContainer,{width:C,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y<(G.theme_advanced_resizing_min_height||100)){y=G.theme_advanced_resizing_min_height||100}F.iframeHTML=G.doctype+'';if(G.document_base_url!=k.documentBaseURL){F.iframeHTML+=''}if(G.ie7_compat){F.iframeHTML+=''}else{F.iframeHTML+=''}F.iframeHTML+='';for(x=0;x'}F.contentCSS=[];v=G.body_id||"tinymce";if(v.indexOf("=")!=-1){v=F.getParam("body_id","","hash");v=v[F.id]||v}A=G.body_class||"";if(A.indexOf("=")!=-1){A=F.getParam("body_class","","hash");A=A[F.id]||""}F.iframeHTML+='
                          ";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){D='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+F.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:F.id+"_ifr",src:D||'javascript:""',frameBorder:"0",allowTransparency:"true",title:G.aria_label,style:{width:"100%",height:y,display:"block"}});F.contentAreaContainer=p.iframeContainer;l.get(p.editorContainer).style.display=F.orgDisplay;l.get(F.id).style.display="none";l.setAttrib(F.id,"aria-hidden",true);if(!k.relaxedDomain||!D){F.initContentBody()}B=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(s,t){var u=s.length,x,z=n.dom,y,v;while(u--){x=s[u];y=x.attr(t);v="data-mce-"+t;if(!x.attributes.map[v]){if(t==="style"){x.attr(v,z.serializeStyle(z.parseStyle(y),x.name))}else{x.attr(v,n.convertURL(y,t,x.name))}}}});n.parser.addNodeFilter("script",function(s,t){var u=s.length,v;while(u--){v=s[u];v.attr("type","mce-"+(v.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(s,t){var u=s.length,v;while(u--){v=s[u];v.type=8;v.name="#comment";v.value="[CDATA["+v.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,u){var v=t.length,x,s=n.schema.getNonEmptyElements();while(v--){x=t[v];if(x.isEmpty(s)){x.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.serializer.onPreProcess.add(function(s,t){return n.onPreProcess.dispatch(n,t,s)});n.serializer.onPostProcess.add(function(s,t){return n.onPostProcess.dispatch(n,t,s)});n.onPreInit.dispatch(n);if(!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(s,t){i(p.protect,function(u){t.content=t.content.replace(u,function(v){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
                          [\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});i(n.contentCSS,function(s){n.dom.loadCSS(s)});if(p.auto_focus){setTimeout(function(){var s=k.get(p.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};n.normalize();p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
                          "}else{r='
                          '}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}o.selection.normalize();return p.content},getContent:function(n){var m=this,o;n=n||{};n.format=n.format||"html";n.get=true;n.getInner=true;if(!n.no_events){m.onBeforeGetContent.dispatch(m,n)}if(n.format=="raw"){o=m.getBody().innerHTML}else{o=m.serializer.serialize(m.getBody(),n)}n.content=k.trim(o);if(!n.no_events){m.onGetContent.dispatch(m,n)}return n.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":r=p.getAttrib(s,"name");m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,n=m.getContainer();if(!m.removed){m.removed=1;m.hide();if(!m.settings.content_editable){j.clear(m.getWin());j.clear(m.getDoc())}j.clear(m.getBody());j.clear(m.formElement);j.unbind(n);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(n)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){Event.cancel(g)}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var c=this,f,g=c.settings,j=c.dom,k;k={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function e(i,l){var m=i.type;if(c.removed){return}if(c.onEvent.dispatch(c,i,l)!==false){c[k[i.fakeType||i.type]].dispatch(c,i,l)}}function h(i){c.focus(true)}b(k,function(l,m){var i=g.content_editable?c.getBody():c.getDoc();switch(m){case"contextmenu":j.bind(i,m,e);break;case"paste":j.bind(c.getBody(),m,e);break;case"submit":case"reset":j.bind(c.getElement().form||a.DOM.getParent(c.id,"form"),m,e);break;default:j.bind(i,m,e)}});j.bind(g.content_editable?c.getBody():(a.isGecko?c.getDoc():c.getWin()),"focus",function(i){c.focus(true)});if(g.content_editable&&a.isOpera){j.bind(c.getBody(),"click",h);j.bind(c.getBody(),"keydown",h)}c.onMouseUp.add(c.nodeChanged);c.onKeyUp.add(function(i,m){var l=m.keyCode;if((l>=33&&l<=36)||(l>=37&&l<=40)||l==13||l==45||l==46||l==8||(a.isMac&&(l==91||l==93))||m.ctrlKey){c.nodeChanged()}});c.onReset.add(function(){c.setContent(c.startContent,{format:"raw"})});function d(l,i){if(l.altKey||l.ctrlKey||l.metaKey){b(c.shortcuts,function(m){var n=a.isMac?l.metaKey:l.ctrlKey;if(m.ctrl!=n||m.alt!=l.altKey||m.shift!=l.shiftKey){return}if(l.keyCode==m.keyCode||(l.charCode&&l.charCode==m.charCode)){l.preventDefault();if(i){m.func.call(m.scope)}return true}})}}c.onKeyUp.add(function(i,l){d(l)});c.onKeyPress.add(function(i,l){d(l)});c.onKeyDown.add(function(i,l){d(l,true)});if(a.isOpera){c.onClick.add(function(i,l){l.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getDoc(),b.isGecko?"blur":"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}if(p){c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(i){var h,g=this,f=g.editor;d(f.plugins,function(j){if(j.createControl){h=j.createControl(i,g);if(h){return false}}});switch(i){case"|":case"separator":return g.createSeparator()}if(!h&&f.buttons&&(h=f.buttons[i])){return g.createButton(i,h)}return g.add(h)},createDropMenu:function(f,n,h){var m=this,i=m.editor,j,g,k,l;n=e({"class":"mceDropDown",constrain:i.settings.constrain_menus},n);n["class"]=n["class"]+" "+i.getParam("skin")+"Skin";if(k=i.getParam("skin_variant")){n["class"]+=" "+i.getParam("skin")+"Skin"+k.substring(0,1).toUpperCase()+k.substring(1)}n["class"]+=i.settings.directionality=="rtl"?" mceRtl":"";f=m.prefix+f;l=h||m._cls.dropmenu||c.ui.DropMenu;j=m.controls[f]=new l(f,n);j.onAddItem.add(function(r,q){var p=q.settings;p.title=i.getLang(p.title,p.title);if(!p.onclick){p.onclick=function(o){if(p.cmd){i.execCommand(p.cmd,p.ui||false,p.value)}}}});i.onRemove.add(function(){j.destroy()});if(c.isIE){j.onShowMenu.add(function(){i.focus();g=i.selection.getBookmark(1)});j.onHideMenu.add(function(){if(g){i.selection.moveToBookmark(g);g=0}})}return m.add(j)},createListBox:function(f,n,h){var l=this,j=l.editor,i,k,m;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,scope:n.scope,control_manager:l},n);f=l.prefix+f;function g(o){return o.settings.use_accessible_selects&&!c.isGecko}if(j.settings.use_native_selects||g(j)){k=new c.ui.NativeListBox(f,n)}else{m=h||l._cls.listbox||c.ui.ListBox;k=new m(f,n,j)}l.controls[f]=k;if(c.isWebKit){k.onPostRender.add(function(p,o){a.add(o,"mousedown",function(){j.bookmark=j.selection.getBookmark(1)});a.add(o,"focus",function(){j.selection.moveToBookmark(j.bookmark);j.bookmark=null})})}if(k.hideMenu){j.onMouseDown.add(k.hideMenu,k)}return l.add(k)},createButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.label=g.translate(i.label);i.scope=i.scope||g;if(!i.onclick&&!i.menu_button){i.onclick=function(){g.execCommand(i.cmd,i.ui||false,i.value)}}i=e({title:i.title,"class":"mce_"+m,unavailable_prefix:g.getLang("unavailable",""),scope:i.scope,control_manager:h},i);m=h.prefix+m;if(i.menu_button){f=l||h._cls.menubutton||c.ui.MenuButton;k=new f(m,i,g);g.onMouseDown.add(k.hideMenu,k)}else{f=h._cls.button||c.ui.Button;k=new f(m,i,g)}return h.add(k)},createMenuButton:function(h,f,g){f=f||{};f.menu_button=1;return this.createButton(h,f,g)},createSplitButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.scope=i.scope||g;if(!i.onclick){i.onclick=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}if(!i.onselect){i.onselect=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}i=e({title:i.title,"class":"mce_"+m,scope:i.scope,control_manager:h},i);m=h.prefix+m;f=l||h._cls.splitbutton||c.ui.SplitButton;k=h.add(new f(m,i,g));g.onMouseDown.add(k.hideMenu,k);return k},createColorSplitButton:function(f,n,h){var l=this,j=l.editor,i,k,m,g;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onclick){n.onclick=function(o){if(c.isIE){g=j.selection.getBookmark(1)}j.execCommand(n.cmd,n.ui||false,o||n.value)}}if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,menu_class:j.getParam("skin")+"Skin",scope:n.scope,more_colors_title:j.getLang("more_colors")},n);f=l.prefix+f;m=h||l._cls.colorsplitbutton||c.ui.ColorSplitButton;k=new m(f,n,j);j.onMouseDown.add(k.hideMenu,k);j.onRemove.add(function(){k.destroy()});if(c.isIE){k.onShowMenu.add(function(){j.focus();g=j.selection.getBookmark(1)});k.onHideMenu.add(function(){if(g){j.selection.moveToBookmark(g);g=0}})}return l.add(k)},createToolbar:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||g._cls.toolbar||c.ui.Toolbar;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createToolbarGroup:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||this._cls.toolbarGroup||c.ui.ToolbarGroup;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createSeparator:function(g){var f=g||this._cls.separator||c.ui.Separator;return new f()},setControlType:function(g,f){return this._cls[g.toLowerCase()]=f},destroy:function(){d(this.controls,function(f){f.destroy()});this.controls=null}})})(tinymce);(function(d){var a=d.util.Dispatcher,e=d.each,c=d.isIE,b=d.isOpera;d.create("tinymce.WindowManager",{WindowManager:function(f){var g=this;g.editor=f;g.onOpen=new a(g);g.onClose=new a(g);g.params={};g.features={}},open:function(z,h){var v=this,k="",n,m,i=v.editor.settings.dialog_type=="modal",q,o,j,g=d.DOM.getViewPort(),r;z=z||{};h=h||{};o=b?g.w:screen.width;j=b?g.h:screen.height;z.name=z.name||"mc_"+new Date().getTime();z.width=parseInt(z.width||320);z.height=parseInt(z.height||240);z.resizable=true;z.left=z.left||parseInt(o/2)-(z.width/2);z.top=z.top||parseInt(j/2)-(z.height/2);h.inline=false;h.mce_width=z.width;h.mce_height=z.height;h.mce_auto_focus=z.auto_focus;if(i){if(c){z.center=true;z.help=false;z.dialogWidth=z.width+"px";z.dialogHeight=z.height+"px";z.scroll=z.scrollbars||false}}e(z,function(p,f){if(d.is(p,"boolean")){p=p?"yes":"no"}if(!/^(name|url)$/.test(f)){if(c&&i){k+=(k?";":"")+f+":"+p}else{k+=(k?",":"")+f+"="+p}}});v.features=z;v.params=h;v.onOpen.dispatch(v,z,h);r=z.url||z.file;r=d._addVer(r);try{if(c&&i){q=1;window.showModalDialog(r,window,k)}else{q=window.open(r,z.name,k)}}catch(l){}if(!q){alert(v.editor.getLang("popup_blocked"))}},close:function(f){f.close();this.onClose.dispatch(this)},createInstance:function(i,h,g,m,l,k){var j=d.resolve(i);return new j(h,g,m,l,k)},confirm:function(h,f,i,g){g=g||window;f.call(i||this,g.confirm(this._decode(this.editor.getLang(h,h))))},alert:function(h,f,j,g){var i=this;g=g||window;g.alert(i._decode(i.editor.getLang(h,h)));if(f){f.call(j||i)}},resizeBy:function(f,g,h){h.resizeBy(f,g)},_decode:function(f){return d.DOM.decode(f).replace(/\\n/g,"\n")}})}(tinymce));(function(a){a.Formatter=function(Y){var O={},R=a.each,c=Y.dom,r=Y.selection,t=a.dom.TreeWalker,M=new a.dom.RangeUtils(c),d=Y.schema.isValidChild,H=c.isBlock,m=Y.settings.forced_root_block,s=c.nodeIndex,G=a.isGecko?"\u200B":"\uFEFF",e=/^(src|href|style)$/,V=false,C=true,D,x=c.getContentEditable;function A(Z){return Z instanceof Array}function n(aa,Z){return c.getParents(aa,Z,c.getRoot())}function b(Z){return Z.nodeType===1&&Z.id==="_mce_caret"}function j(){l({alignleft:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"},defaultBlock:"div"},{selector:"img,table",collapsed:false,styles:{"float":"left"}}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"},defaultBlock:"div"},{selector:"img",collapsed:false,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:false,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"},defaultBlock:"div"},{selector:"img,table",collapsed:false,styles:{"float":"right"}}],alignfull:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"justify"},defaultBlock:"div"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:true},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:true},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:false},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:false},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},link:{inline:"a",selector:"a",remove:"all",split:true,deep:true,onmatch:function(Z){return true},onformat:function(ab,Z,aa){R(aa,function(ad,ac){c.setAttrib(ab,ac,ad)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:true,expand:false,block_expand:true,deep:true},{selector:"span",attributes:["style","class"],remove:"empty",split:true,expand:false,deep:true},{selector:"*",attributes:["style","class"],split:false,expand:false,deep:true}]});R("p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp".split(/\s/),function(Z){l(Z,{block:Z,remove:"all"})});l(Y.settings.formats)}function U(){Y.addShortcut("ctrl+b","bold_desc","Bold");Y.addShortcut("ctrl+i","italic_desc","Italic");Y.addShortcut("ctrl+u","underline_desc","Underline");for(var Z=1;Z<=6;Z++){Y.addShortcut("ctrl+"+Z,"",["FormatBlock",false,"h"+Z])}Y.addShortcut("ctrl+7","",["FormatBlock",false,"p"]);Y.addShortcut("ctrl+8","",["FormatBlock",false,"div"]);Y.addShortcut("ctrl+9","",["FormatBlock",false,"address"])}function T(Z){return Z?O[Z]:O}function l(Z,aa){if(Z){if(typeof(Z)!=="string"){R(Z,function(ac,ab){l(ab,ac)})}else{aa=aa.length?aa:[aa];R(aa,function(ab){if(ab.deep===D){ab.deep=!ab.selector}if(ab.split===D){ab.split=!ab.selector||ab.inline}if(ab.remove===D&&ab.selector&&!ab.inline){ab.remove="none"}if(ab.selector&&ab.inline){ab.mixed=true;ab.block_expand=true}if(typeof(ab.classes)==="string"){ab.classes=ab.classes.split(/\s+/)}});O[Z]=aa}}}var i=function(aa){var Z;Y.dom.getParent(aa,function(ab){Z=Y.dom.getStyle(ab,"text-decoration");return Z&&Z!=="none"});return Z};var K=function(Z){var aa;if(Z.nodeType===1&&Z.parentNode&&Z.parentNode.nodeType===1){aa=i(Z.parentNode);if(Y.dom.getStyle(Z,"color")&&aa){Y.dom.setStyle(Z,"text-decoration",aa)}else{if(Y.dom.getStyle(Z,"textdecoration")===aa){Y.dom.setStyle(Z,"text-decoration",null)}}}};function W(ac,aj,ae){var af=T(ac),ak=af[0],ai,aa,ah,ag=r.isCollapsed();function Z(ao,an){an=an||ak;if(ao){if(an.onformat){an.onformat(ao,an,aj,ae)}R(an.styles,function(aq,ap){c.setStyle(ao,ap,q(aq,aj))});R(an.attributes,function(aq,ap){c.setAttrib(ao,ap,q(aq,aj))});R(an.classes,function(ap){ap=q(ap,aj);if(!c.hasClass(ao,ap)){c.addClass(ao,ap)}})}}function ad(){function ap(aw,au){var av=new t(au);for(ae=av.current();ae;ae=av.prev()){if(ae.childNodes.length>1||ae==aw||ae.tagName=="BR"){return ae}}}var ao=Y.selection.getRng();var at=ao.startContainer;var an=ao.endContainer;if(at!=an&&ao.endOffset===0){var ar=ap(at,an);var aq=ar.nodeType==3?ar.length:ar.childNodes.length;ao.setEnd(ar,aq)}return ao}function ab(aq,aw,au,at,ao){var an=[],ap=-1,av,ay=-1,ar=-1,ax;R(aq.childNodes,function(aA,az){if(aA.nodeName==="UL"||aA.nodeName==="OL"){ap=az;av=aA;return false}});R(aq.childNodes,function(aA,az){if(aA.nodeName==="SPAN"&&c.getAttrib(aA,"data-mce-type")=="bookmark"){if(aA.id==aw.id+"_start"){ay=az}else{if(aA.id==aw.id+"_end"){ar=az}}}});if(ap<=0||(ayap)){R(a.grep(aq.childNodes),ao);return 0}else{ax=c.clone(au,V);R(a.grep(aq.childNodes),function(aA,az){if((ayap&&az>ap)){an.push(aA);aA.parentNode.removeChild(aA)}});if(ayap){aq.insertBefore(ax,av.nextSibling)}}at.push(ax);R(an,function(az){ax.appendChild(az)});return ax}}function al(ao,aq,au){var an=[],at,ap,ar=true;at=ak.inline||ak.block;ap=c.create(at);Z(ap);M.walk(ao,function(av){var aw;function ax(ay){var aD,aB,az,aA,aC;aC=ar;aD=ay.nodeName.toLowerCase();aB=ay.parentNode.nodeName.toLowerCase();if(ay.nodeType===1&&x(ay)){aC=ar;ar=x(ay)==="true";aA=true}if(g(aD,"br")){aw=0;if(ak.block){c.remove(ay)}return}if(ak.wrapper&&y(ay,ac,aj)){aw=0;return}if(ar&&!aA&&ak.block&&!ak.wrapper&&I(aD)){ay=c.rename(ay,at);Z(ay);an.push(ay);aw=0;return}if(ak.selector){R(af,function(aE){if("collapsed" in aE&&aE.collapsed!==ag){return}if(c.is(ay,aE.selector)&&!b(ay)){Z(ay,aE);az=true}});if(!ak.inline||az){aw=0;return}}if(ar&&!aA&&d(at,aD)&&d(aB,at)&&!(!au&&ay.nodeType===3&&ay.nodeValue.length===1&&ay.nodeValue.charCodeAt(0)===65279)&&!b(ay)){if(!aw){aw=c.clone(ap,V);ay.parentNode.insertBefore(aw,ay);an.push(aw)}aw.appendChild(ay)}else{if(aD=="li"&&aq){aw=ab(ay,aq,ap,an,ax)}else{aw=0;R(a.grep(ay.childNodes),ax);if(aA){ar=aC}aw=0}}}R(av,ax)});if(ak.wrap_links===false){R(an,function(av){function aw(aA){var az,ay,ax;if(aA.nodeName==="A"){ay=c.clone(ap,V);an.push(ay);ax=a.grep(aA.childNodes);for(az=0;az1||!H(ax))&&av===0){c.remove(ax,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&av===1){ax=aw(ax)}R(af,function(az){R(c.select(az.inline,ax),function(aB){var aA;if(az.wrap_links===false){aA=aB.parentNode;do{if(aA.nodeName==="A"){return}}while(aA=aA.parentNode)}X(az,aj,aB,az.exact?aB:null)})});if(y(ax.parentNode,ac,aj)){c.remove(ax,1);ax=0;return C}if(ak.merge_with_parents){c.getParent(ax.parentNode,function(az){if(y(az,ac,aj)){c.remove(ax,1);ax=0;return C}})}if(ax&&ak.merge_siblings!==false){ax=u(E(ax),ax);ax=u(ax,E(ax,C))}}})}if(ak){if(ae){if(ae.nodeType){aa=c.createRng();aa.setStartBefore(ae);aa.setEndAfter(ae);al(p(aa,af),null,true)}else{al(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var am=Y.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(am,c.isBlock)){W(af[0].defaultBlock)}Y.selection.setRng(ad());ai=r.getBookmark();al(p(r.getRng(C),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(am,K,"childNodes");K(am)}r.moveToBookmark(ai);P(r.getRng(C));Y.nodeChanged()}else{S("apply",ac,aj)}}}}function B(ab,ak,ad){var ae=T(ab),am=ae[0],ai,ah,aa,aj=true;function ac(at){var ar,aq,ap,ao,av,au;if(at.nodeType===1&&x(at)){av=aj;aj=x(at)==="true";au=true}ar=a.grep(at.childNodes);if(aj&&!au){for(aq=0,ap=ae.length;aq=0;aa--){Z=af[aa].selector;if(!Z){return C}for(ae=ab.length-1;ae>=0;ae--){if(c.is(ab[ae],Z)){return C}}}}return V}a.extend(this,{get:T,register:l,apply:W,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z});j();U();function h(Z,aa){if(g(Z,aa.inline)){return C}if(g(Z,aa.block)){return C}if(aa.selector){return c.is(Z,aa.selector)}}function g(aa,Z){aa=aa||"";Z=Z||"";aa=""+(aa.nodeName||aa);Z=""+(Z.nodeName||Z);return aa.toLowerCase()==Z.toLowerCase()}function N(aa,Z){var ab=c.getStyle(aa,Z);if(Z=="color"||Z=="backgroundColor"){ab=c.toHex(ab)}if(Z=="fontWeight"&&ab==700){ab="bold"}return""+ab}function q(Z,aa){if(typeof(Z)!="string"){Z=Z(aa)}else{if(aa){Z=Z.replace(/%(\w+)/g,function(ac,ab){return aa[ab]||ac})}}return Z}function f(Z){return Z&&Z.nodeType===3&&/^([\t \r\n]+|)$/.test(Z.nodeValue)}function Q(ab,aa,Z){var ac=c.create(aa,Z);ab.parentNode.insertBefore(ac,ab);ac.appendChild(ab);return ac}function p(Z,ak,ac){var an,al,af,aj,ab=Z.startContainer,ag=Z.startOffset,ap=Z.endContainer,ai=Z.endOffset;function am(ax){var ar,av,aw,au,at,aq;ar=av=ax?ab:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();if(ar.nodeType==3&&!f(ar)){if(ax?ag>0:aial?al:ag];if(ab.nodeType==3){ag=0}}if(ap.nodeType==1&&ap.hasChildNodes()){al=ap.childNodes.length-1;ap=ap.childNodes[ai>al?al:ai-1];if(ap.nodeType==3){ai=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ah(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ac){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&af.node.nodeType===3&&af.node.nodeValue.charAt(af.offset-1)===" "){if(af.offset>1){ap=af.node;ap.splitText(af.offset-1)}}}}if(ak[0].inline||ak[0].block_expand){if(!ak[0].inline||(ab.nodeType!=3||ag===0)){ab=am(true)}if(!ak[0].inline||(ap.nodeType!=3||ai===ap.nodeValue.length)){ap=am()}}if(ak[0].selector&&ak[0].expand!==V&&!ak[0].inline){ab=ad(ab,"previousSibling");ap=ad(ap,"nextSibling")}if(ak[0].block||ak[0].selector){ab=aa(ab,"previousSibling");ap=aa(ap,"nextSibling");if(ak[0].block){if(!H(ab)){ab=am(true)}if(!H(ap)){ap=am()}}}if(ab.nodeType==1){ag=s(ab);ab=ab.parentNode}if(ap.nodeType==1){ai=s(ap)+1;ap=ap.parentNode}return{startContainer:ab,startOffset:ag,endContainer:ap,endOffset:ai}}function X(af,ae,ac,Z){var ab,aa,ad;if(!h(ac,af)){return V}if(af.remove!="all"){R(af.styles,function(ah,ag){ah=q(ah,ae);if(typeof(ag)==="number"){ag=ah;Z=0}if(!Z||g(N(Z,ag),ah)){c.setStyle(ac,ag,"")}ad=1});if(ad&&c.getAttrib(ac,"style")==""){ac.removeAttribute("style");ac.removeAttribute("data-mce-style")}R(af.attributes,function(ai,ag){var ah;ai=q(ai,ae);if(typeof(ag)==="number"){ag=ai;Z=0}if(!Z||g(c.getAttrib(Z,ag),ai)){if(ag=="class"){ai=c.getAttrib(ac,ag);if(ai){ah="";R(ai.split(/\s+/),function(aj){if(/mce\w+/.test(aj)){ah+=(ah?" ":"")+aj}});if(ah){c.setAttrib(ac,ag,ah);return}}}if(ag=="class"){ac.removeAttribute("className")}if(e.test(ag)){ac.removeAttribute("data-mce-"+ag)}ac.removeAttribute(ag)}});R(af.classes,function(ag){ag=q(ag,ae);if(!Z||c.hasClass(Z,ag)){c.removeClass(ac,ag)}});aa=c.getAttribs(ac);for(ab=0;abab?ab:ad]}if(Z.nodeType===3&&ae&&ad>=Z.nodeValue.length){Z=new t(Z,Y.getBody()).next()||Z}if(Z.nodeType===3&&!ae&&ad===0){Z=new t(Z,Y.getBody()).prev()||Z}return Z}function S(ai,Z,ag){var aj="_mce_caret",aa=Y.settings.caret_debug;function ab(am){var al=c.create("span",{id:aj,"data-mce-bogus":true,style:aa?"color:red":""});if(am){al.appendChild(Y.getDoc().createTextNode(G))}return al}function ah(am,al){while(am){if((am.nodeType===3&&am.nodeValue!==G)||am.childNodes.length>1){return false}if(al&&am.nodeType===1){al.push(am)}am=am.firstChild}return true}function ae(al){while(al){if(al.id===aj){return al}al=al.parentNode}}function ad(al){var am;if(al){am=new t(al,al);for(al=am.current();al;al=am.next()){if(al.nodeType===3){return al}}}}function ac(an,am){var ao,al;if(!an){an=ae(r.getStart());if(!an){while(an=c.get(aj)){ac(an,false)}}}else{al=r.getRng(true);if(ah(an)){if(am!==false){al.setStartBefore(an);al.setEndBefore(an)}c.remove(an)}else{ao=ad(an);if(ao.nodeValue.charAt(0)===G){ao=ao.deleteData(0,1)}c.remove(an,1)}r.setRng(al)}}function af(){var an,al,ar,aq,ao,am,ap;an=r.getRng(true);aq=an.startOffset;am=an.startContainer;ap=am.nodeValue;al=ae(r.getStart());if(al){ar=ad(al)}if(ap&&aq>0&&aq=0;ap--){an.appendChild(c.clone(au[ap],false));an=an.firstChild}an.appendChild(c.doc.createTextNode(G));an=an.firstChild;c.insertAfter(at,av);r.setCursorLocation(an,1)}}if(!self._hasCaretEvents){Y.onBeforeGetContent.addToTop(function(){var al=[],am;if(ah(ae(r.getStart()),al)){am=al.length;while(am--){c.setAttrib(al[am],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(al){Y[al].addToTop(function(){ac()})});Y.onKeyDown.addToTop(function(al,an){var am=an.keyCode;if(am==8||am==37||am==39){ac(ae(r.getStart()))}});r.onSetContent.add(function(){c.getParent(r.getStart(),function(al){if(al.id!==aj&&c.getAttrib(al,"data-mce-bogus")&&!c.isEmpty(al)){c.setAttrib(al,"data-mce-bogus",null)}})});self._hasCaretEvents=true}if(ai=="apply"){af()}else{ak()}}function P(aa){var Z=aa.startContainer,ag=aa.startOffset,ac,af,ae,ab,ad;if(Z.nodeType==3&&ag>=Z.nodeValue.length){ag=s(Z);Z=Z.parentNode;ac=true}if(Z.nodeType==1){ab=Z.childNodes;Z=ab[Math.min(ag,ab.length-1)];af=new t(Z,c.getParent(Z,c.isBlock));if(ag>ab.length-1||ac){af.next()}for(ae=af.current();ae;ae=af.next()){if(ae.nodeType==3&&!f(ae)){ad=c.create("a",null,G);ae.parentNode.insertBefore(ad,ae);aa.setStart(ae,0);r.setRng(aa);c.remove(ad);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(e){var h=e.dom,d=e.selection,c=e.settings,g=e.undoManager;function f(y){var u=d.getRng(true),C,i,x,t,o,H,n,j,l,s,E,v,z;function B(I){return I&&h.isBlock(I)&&!/^(TD|TH|CAPTION)$/.test(I.nodeName)&&!/^(fixed|absolute)/i.test(I.style.position)&&h.getContentEditable(I)!=="true"}function m(J){var O,M,I,P,N,L=J,K;I=h.createRng();if(J.hasChildNodes()){O=new a(J,J);while(M=O.current()){if(M.nodeType==3){I.setStart(M,0);I.setEnd(M,0);break}if(/^(BR|IMG)$/.test(M.nodeName)){I.setStartBefore(M);I.setEndBefore(M);break}L=M;M=O.next()}if(!M){I.setStart(L,0);I.setEnd(L,0)}}else{if(J.nodeName=="BR"){if(J.nextSibling&&h.isBlock(J.nextSibling)){if(!H||H<9){K=h.create("br");J.parentNode.insertBefore(K,J)}I.setStartBefore(J);I.setEndBefore(J)}else{I.setStartAfter(J);I.setEndAfter(J)}}else{I.setStart(J,0);I.setEnd(J,0)}}d.setRng(I);h.remove(K);N=h.getViewPort(e.getWin());P=h.getPos(J).y;if(PN.y+N.h){e.getWin().scrollTo(0,P"}return M}function p(L){var K,J,I;if(x.nodeType==3&&(L?t>0:t=x.nodeValue.length){if(!b.isIE&&!A()){J=h.create("br");u.insertNode(J);u.setStartAfter(J);u.setEndAfter(J);I=true}}J=h.create("br");u.insertNode(J);if(b.isIE&&s=="PRE"&&(!H||H<8)){J.parentNode.insertBefore(h.doc.createTextNode("\r"),J)}if(!I){u.setStartAfter(J);u.setEndAfter(J)}else{u.setStartBefore(J);u.setEndBefore(J)}d.setRng(u);g.add()}function r(I){do{if(I.nodeType===3){I.nodeValue=I.nodeValue.replace(/^[\r\n]+/,"")}I=I.firstChild}while(I)}function F(K){var I=h.getRoot(),J,L;J=K;while(J!==I&&h.getContentEditable(J)!=="false"){if(h.getContentEditable(J)==="true"){L=J}J=J.parentNode}return J!==I?L:I}if(!u.collapsed){e.execCommand("Delete");return}if(y.isDefaultPrevented()){return}x=u.startContainer;t=u.startOffset;v=c.forced_root_block;v=v?v.toUpperCase():"";H=h.doc.documentMode;if(x.nodeType==1&&x.hasChildNodes()){z=t>x.childNodes.length-1;x=x.childNodes[Math.min(t,x.childNodes.length-1)]||x;t=0}i=F(x);if(!i){return}g.beforeChange();if(!h.isBlock(i)&&i!=h.getRoot()){if(!v||y.shiftKey){G()}return}if((v&&!y.shiftKey)||(!v&&y.shiftKey)){x=k(x,t)}o=h.getParent(x,h.isBlock);l=o?h.getParent(o.parentNode,h.isBlock):null;s=o?o.nodeName.toUpperCase():"";E=l?l.nodeName.toUpperCase():"";if(s=="LI"&&h.isEmpty(o)){if(/^(UL|OL|LI)$/.test(l.parentNode.nodeName)){return false}D();return}if(s=="PRE"&&c.br_in_pre!==false){if(!y.shiftKey){G();return}}else{if((!v&&!y.shiftKey&&s!="LI")||(v&&y.shiftKey)){G();return}}v=v||"P";if(p()){if(/^(H[1-6]|PRE)$/.test(s)&&E!="HGROUP"){n=q(v)}else{n=q()}if(c.end_container_on_empty_block&&B(l)&&h.isEmpty(o)){n=h.split(l,o)}else{h.insertAfter(n,o)}}else{if(p(true)){n=o.parentNode.insertBefore(q(),o)}else{C=u.cloneRange();C.setEndAfter(o);j=C.extractContents();r(j);n=j.firstChild;h.insertAfter(j,o)}}h.setAttrib(n,"id","");m(n);g.add()}e.onKeyDown.add(function(j,i){if(i.keyCode==13){if(f(i)!==false){i.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery.js b/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery.js deleted file mode 100644 index d89e5f3de08..00000000000 --- a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_jquery.js +++ /dev/null @@ -1 +0,0 @@ -(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"@@tinymce_major_version@@",minorVersion:"@@tinymce_minor_version@@",releaseDate:"@@tinymce_release_date@@",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey}}})(tinymce);tinymce.util.Quirks=function(d){var l=tinymce.VK,r=l.BACKSPACE,s=l.DELETE,o=d.dom,z=d.selection,q=d.settings;function c(D,C){try{d.getDoc().execCommand(D,false,C)}catch(B){}}function h(){function B(E){var C,G,D,F;C=z.getRng();G=o.getParent(C.startContainer,o.isBlock);if(E){G=o.getNext(G,o.isBlock)}if(G){D=G.firstChild;while(D&&D.nodeType==3&&D.nodeValue.length===0){D=D.nextSibling}if(D&&D.nodeName==="SPAN"){F=D.cloneNode(false)}}d.getDoc().execCommand(E?"ForwardDelete":"Delete",false,null);G=o.getParent(C.startContainer,o.isBlock);tinymce.each(o.select("span.Apple-style-span,font.Apple-style-span",G),function(H){var I=z.getBookmark();if(F){o.replace(F.cloneNode(false),H,true)}else{o.remove(H,true)}z.moveToBookmark(I)})}d.onKeyDown.add(function(C,E){var D;D=E.keyCode==s;if(!E.isDefaultPrevented()&&(D||E.keyCode==r)&&!l.modifierPressed(E)){E.preventDefault();B(D)}});d.addCommand("Delete",function(){B()})}function A(){function C(E,H){var D,G,F=H?"start":"end";D=E[F+"Container"];G=E[F+"Offset"];if(D.nodeType==1&&D.hasChildNodes()){D=D.childNodes[Math.min(H?G:(G>0?G-1:0),D.childNodes.length-1)]}return D}function B(G,K){var F,J,E,H,I=K?"start":"end",D;F=G[I+"Container"];J=G[I+"Offset"];E=o.getRoot();if(F.nodeType==1){D=J>=F.childNodes.length;F=C(G,K);if(F.nodeType==3){J=K&&!D?0:F.nodeValue.length}}if(F.nodeType==3&&((K&&J>0)||(!K&&J7){return}c("RespectVisibilityInDesign",true);o.addClass(d.getBody(),"mceHideBrInPre");d.parser.addNodeFilter("pre",function(C,E){var F=C.length,H,D,I,G;while(F--){H=C[F].getAll("br");D=H.length;while(D--){I=H[D];G=I.prev;if(G&&G.type===3&&G.value.charAt(G.value-1)!="\n"){G.value+="\n"}else{I.parent.insert(new tinymce.html.Node("#text",3),I,true).value="\n"}}}});d.serializer.addNodeFilter("pre",function(C,E){var F=C.length,H,D,I,G;while(F--){H=C[F].getAll("br");D=H.length;while(D--){I=H[D];G=I.prev;if(G&&G.type==3){G.value=G.value.replace(/\r?\n$/,"")}}}})}function f(){o.bind(d.getBody(),"mouseup",function(D){var C,B=z.getNode();if(B.nodeName=="IMG"){if(C=o.getStyle(B,"width")){o.setAttrib(B,"width",C.replace(/[^0-9%]+/g,""));o.setStyle(B,"width","")}if(C=o.getStyle(B,"height")){o.setAttrib(B,"height",C.replace(/[^0-9%]+/g,""));o.setStyle(B,"height","")}}})}function p(){d.onKeyDown.add(function(H,I){var G,B,C,E,F,J,D;G=I.keyCode==s;if(!I.isDefaultPrevented()&&(G||I.keyCode==r)&&!l.modifierPressed(I)){B=z.getRng();C=B.startContainer;E=B.startOffset;D=B.collapsed;if(C.nodeType==3&&C.nodeValue.length>0&&((E===0&&!D)||(D&&E===(G?0:1)))){nonEmptyElements=H.schema.getNonEmptyElements();I.preventDefault();F=o.create("br",{id:"__tmp"});C.parentNode.insertBefore(F,C);H.getDoc().execCommand(G?"ForwardDelete":"Delete",false,null);C=z.getRng().startContainer;J=C.previousSibling;if(J&&J.nodeType==1&&!o.isBlock(J)&&o.isEmpty(J)&&!nonEmptyElements[J.nodeName.toLowerCase()]){o.remove(J)}o.remove("__tmp")}}})}function e(){d.onKeyDown.add(function(F,G){var D,C,H,B,E;if(G.isDefaultPrevented()||G.keyCode!=l.BACKSPACE){return}D=z.getRng();C=D.startContainer;H=D.startOffset;B=o.getRoot();E=C;if(!D.collapsed||H!==0){return}while(E&&E.parentNode&&E.parentNode.firstChild==E&&E.parentNode!=B){E=E.parentNode}if(E.tagName==="BLOCKQUOTE"){F.formatter.toggle("blockquote",null,E);D.setStart(C,0);D.setEnd(C,0);z.setRng(D);z.collapse(false)}})}function k(){function B(){d._refreshContentEditable();c("StyleWithCSS",false);c("enableInlineTableEditing",false);if(!q.object_resizing){c("enableObjectResizing",false)}}if(!q.readonly){d.onBeforeExecCommand.add(B);d.onMouseDown.add(B)}}function n(){function B(C,D){tinymce.each(o.select("a"),function(G){var E=G.parentNode,F=o.getRoot();if(E.lastChild===G){while(E&&!o.isBlock(E)){if(E.parentNode.lastChild!==E||E===F){return}E=E.parentNode}o.add(E,"br",{"data-mce-bogus":1})}})}d.onExecCommand.add(function(C,D){if(D==="CreateLink"){B(C)}});d.onSetContent.add(z.onSetContent.add(B))}function a(){function B(D,C){if(!D||!C.initial){d.execCommand("mceRepaint")}}d.onUndo.add(B);d.onRedo.add(B);d.onSetContent.add(B)}function j(){d.onKeyDown.add(function(B,C){if(!C.isDefaultPrevented()&&C.keyCode==8&&z.getNode().nodeName=="IMG"){C.preventDefault();B.undoManager.beforeChange();o.remove(z.getNode());B.undoManager.add()}})}u();e();A();if(tinymce.isWebKit){p();h();t();v();if(tinymce.isIDevice){i()}}if(tinymce.isIE){m();y();g();f();j()}if(tinymce.isGecko){m();b();x();k();n();a()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][C]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script style textarea");q=m("self_closing_elements","colgroup dd dt li options p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object",z);v=m("block_elements","h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot th tr td li ol ul caption blockquote center dl dt dd dir fieldset noscript menu isindex samp header footer article section hgroup aside nav figure");function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t0){P.value=l;P=P.prev}else{N=P.prev;P.remove();P=N}}}n=new b.html.SaxParser({validate:z,fix_self_closing:!z,cdata:function(l){B.append(J("#cdata",4)).value=l},text:function(O,l){var N;if(!K){O=O.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){O=O.replace(E,"")}}if(O.length!==0){N=J("#text",3);N.raw=!!l;B.append(N).value=O}},comment:function(l){B.append(J("#comment",8)).value=l},pi:function(l,N){B.append(J(l,7)).value=N;H(B)},doctype:function(N){var l;l=B.append(J("#doctype",10));l.value=N;H(B)},start:function(l,V,O){var T,Q,P,N,R,W,U,S;P=z?h.getElementRule(l):{};if(P){T=J(P.outputName||l,1);T.attributes=V;T.shortEnded=O;B.append(T);S=p[B.name];if(S&&p[T.name]&&!S[T.name]){L.push(T)}Q=d.length;while(Q--){R=d[Q].name;if(R in V.map){F=c[R];if(F){F.push(T)}else{c[R]=[T]}}}if(o[l]){H(T)}if(!O){B=T}if(!K&&s[l]){K=true}}},end:function(l){var R,O,Q,N,P;O=z?h.getElementRule(l):{};if(O){if(o[l]){if(!K){R=B.firstChild;if(R&&R.type===3){Q=R.value.replace(E,"");if(Q.length>0){R.value=Q;R=R.next}else{N=R.next;R.remove();R=N}while(R&&R.type===3){Q=R.value;N=R.next;if(Q.length===0||y.test(Q)){R.remove();R=N}R=N}}R=B.lastChild;if(R&&R.type===3){Q=R.value.replace(t,"");if(Q.length>0){R.value=Q;R=R.prev}else{N=R.prev;R.remove();R=N}while(R&&R.type===3){Q=R.value;N=R.prev;if(Q.length===0||y.test(Q)){R.remove();R=N}R=N}}}R=B.prev;if(R&&R.type===3){Q=R.value.replace(E,"");if(Q.length>0){R.value=Q}else{R.remove()}}}if(K&&s[l]){K=false}if(O.removeEmpty||O.paddEmpty){if(B.isEmpty(u)){if(O.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name){P=B.parent;B.empty().remove();B=P;return}}}}B=B.parent}}},h);I=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&L.length){if(!m.context){j(L)}else{m.invalid=true}}if(q&&I.name=="body"){G()}if(!m.invalid){for(M in i){F=e[M];A=i[M];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":b?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
                          "+j;m.removeChild(m.firstChild)}catch(l){m=i.create("div");m.innerHTML="
                          "+j;g(m.childNodes,function(o,n){if(n){m.appendChild(o)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){g(s.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:q(s.styleSheet);break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,T=0,F=1,j=2,E=true,S=false,V="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L});function x(){return e.createDocumentFragment()}function q(W,t){C(E,W,t)}function s(W,t){C(S,W,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[V]}else{O[h]=O[Q];O[V]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(Z,t){var ac=O[h],X=O[V],ab=O[Q],W=O[A],aa=t.startContainer,ae=t.startOffset,Y=t.endContainer,ad=t.endOffset;if(Z===0){return H(ac,X,aa,ae)}if(Z===1){return H(ab,W,aa,ae)}if(Z===2){return H(ab,W,Y,ad)}if(Z===3){return H(ac,X,Y,ad)}}function p(){l(j)}function I(){return l(T)}function d(){return l(F)}function D(Z){var W=this[h],t=this[V],Y,X;if((W.nodeType===3||W.nodeType===4)&&W.nodeValue){if(!t){W.parentNode.insertBefore(Z,W)}else{if(t>=W.nodeValue.length){c.insertAfter(Z,W)}else{Y=W.splitText(t);W.parentNode.insertBefore(Z,Y)}}}else{if(W.childNodes.length>0){X=W.childNodes[t]}if(X){W.insertBefore(Z,X)}else{W.appendChild(Z)}}}function N(W){var t=O.extractContents();O.insertNode(W);W.appendChild(t);O.selectNode(W)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[V],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,W){var X;if(t.nodeType==3){return t}if(W<0){return t}X=t.firstChild;while(X&&W>0){--W;X=X.nextSibling}if(X){return X}return t}function m(){return(O[h]==O[Q]&&O[V]==O[A])}function H(Y,aa,W,Z){var ab,X,t,ac,ae,ad;if(Y==W){if(aa==Z){return 0}if(aa0){O.collapse(W)}}else{O.collapse(W)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ac){var ab,Y=0,ae=0,W,aa,X,Z,t,ad;if(O[h]==O[Q]){return f(ac)}for(ab=O[Q],W=ab.parentNode;W;ab=W,W=W.parentNode){if(W==O[h]){return r(ab,ac)}++Y}for(ab=O[h],W=ab.parentNode;W;ab=W,W=W.parentNode){if(W==O[Q]){return U(ab,ac)}++ae}aa=ae-Y;X=O[h];while(aa>0){X=X.parentNode;aa--}Z=O[Q];while(aa<0){Z=Z.parentNode;aa++}for(t=X.parentNode,ad=Z.parentNode;t!=ad;t=t.parentNode,ad=ad.parentNode){X=t;Z=ad}return o(X,Z,ac)}function f(ab){var ad,ae,t,X,Y,ac,Z,W,aa;if(ab!=j){ad=x()}if(O[V]==O[A]){return ad}if(O[h].nodeType==3){ae=O[h].nodeValue;t=ae.substring(O[V],O[A]);if(ab!=F){X=O[h];W=O[V];aa=O[A]-O[V];if(W===0&&aa>=X.nodeValue.length-1){X.parentNode.removeChild(X)}else{X.deleteData(W,aa)}O.collapse(E)}if(ab==j){return}if(t.length>0){ad.appendChild(e.createTextNode(t))}return ad}X=P(O[h],O[V]);Y=O[A]-O[V];while(X&&Y>0){ac=X.nextSibling;Z=z(X,ab);if(ad){ad.appendChild(Z)}--Y;X=ac}if(ab!=F){O.collapse(E)}return ad}function r(ac,Z){var ab,aa,W,t,Y,X;if(Z!=j){ab=x()}aa=i(ac,Z);if(ab){ab.appendChild(aa)}W=n(ac);t=W-O[V];if(t<=0){if(Z!=F){O.setEndBefore(ac);O.collapse(S)}return ab}aa=ac.previousSibling;while(t>0){Y=aa.previousSibling;X=z(aa,Z);if(ab){ab.insertBefore(X,ab.firstChild)}--t;aa=Y}if(Z!=F){O.setEndBefore(ac);O.collapse(S)}return ab}function U(aa,Z){var ac,W,ab,t,Y,X;if(Z!=j){ac=x()}ab=R(aa,Z);if(ac){ac.appendChild(ab)}W=n(aa);++W;t=O[A]-W;ab=aa.nextSibling;while(ab&&t>0){Y=ab.nextSibling;X=z(ab,Z);if(ac){ac.appendChild(X)}--t;ab=Y}if(Z!=F){O.setStartAfter(aa);O.collapse(E)}return ac}function o(aa,t,ad){var X,af,Z,ab,ac,W,ae,Y;if(ad!=j){af=x()}X=R(aa,ad);if(af){af.appendChild(X)}Z=aa.parentNode;ab=n(aa);ac=n(t);++ab;W=ac-ab;ae=aa.nextSibling;while(W>0){Y=ae.nextSibling;X=z(ae,ad);if(af){af.appendChild(X)}ae=Y;--W}X=i(t,ad);if(af){af.appendChild(X)}if(ad!=F){O.setStartAfter(aa);O.collapse(E)}return af}function i(ab,ac){var X=P(O[Q],O[A]-1),ad,aa,Z,t,W,Y=X!=O[Q];if(X==ab){return M(X,Y,S,ac)}ad=X.parentNode;aa=M(ad,S,S,ac);while(ad){while(X){Z=X.previousSibling;t=M(X,Y,S,ac);if(ac!=j){aa.insertBefore(t,aa.firstChild)}Y=E;X=Z}if(ad==ab){return aa}X=ad.previousSibling;ad=ad.parentNode;W=M(ad,S,S,ac);if(ac!=j){W.appendChild(aa)}aa=W}}function R(ab,ac){var Y=P(O[h],O[V]),Z=Y!=O[h],ad,aa,X,t,W;if(Y==ab){return M(Y,Z,E,ac)}ad=Y.parentNode;aa=M(ad,S,E,ac);while(ad){while(Y){X=Y.nextSibling;t=M(Y,Z,E,ac);if(ac!=j){aa.appendChild(t)}Z=E;Y=X}if(ad==ab){return aa}Y=ad.nextSibling;ad=ad.parentNode;W=M(ad,S,E,ac);if(ac!=j){W.appendChild(aa)}aa=W}}function M(t,Z,ac,ad){var Y,X,aa,W,ab;if(Z){return z(t,ad)}if(t.nodeType==3){Y=t.nodeValue;if(ac){W=O[V];X=Y.substring(W);aa=Y.substring(0,W)}else{W=O[A];X=Y.substring(0,W);aa=Y.substring(W)}if(ad!=F){t.nodeValue=aa}if(ad==j){return}ab=c.clone(t,S);ab.nodeValue=X;return ab}if(ad==j){return}return c.clone(t,S)}function z(W,t){if(t!=j){return t==F?c.clone(W,E):W}W.parentNode.removeChild(W)}}a.Range=b})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,s,q,r=d.dom.doc,m=r.body;function j(z){var u,y,t,x,v;t=h.create("a");u=z?k:s;y=z?p:q;x=n.duplicate();if(u==r||u==r.documentElement){u=m;y=0}if(u.nodeType==3){u.parentNode.insertBefore(t,u);x.moveToElementText(t);x.moveStart("character",y);h.remove(t);n.setEndPoint(z?"StartToStart":"EndToEnd",x)}else{v=u.childNodes;if(v.length){if(y>=v.length){h.insertAfter(t,v[v.length-1])}else{u.insertBefore(t,v[y])}x.moveToElementText(t)}else{if(u.canHaveHTML){u.innerHTML="\uFEFF";t=u.firstChild;x.moveToElementText(t);x.collapse(f)}}n.setEndPoint(z?"StartToStart":"EndToEnd",x);h.remove(t)}}k=i.startContainer;p=i.startOffset;s=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==s&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(a){a.dom.Element=function(f,d){var b=this,e,c;b.settings=d=d||{};b.id=f;b.dom=e=d.dom||a.DOM;if(!a.isIE){c=e.get(b.id)}a.each(("getPos,getRect,getParent,add,setStyle,getStyle,setStyles,setAttrib,setAttribs,getAttrib,addClass,removeClass,hasClass,getOuterHTML,setOuterHTML,remove,show,hide,isHidden,setHTML,get").split(/,/),function(g){b[g]=function(){var h=[f],j;for(j=0;j"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var h=this.getRng(),i,g,k,j;if(h.duplicate||h.item){if(h.item){return h.item(0)}k=h.duplicate();k.collapse(1);i=k.parentElement();g=j=h.parentElement();while(j=j.parentNode){if(j==i){i=g;break}}return i}else{i=h.startContainer;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[Math.min(i.childNodes.length-1,h.startOffset)]}if(i&&i.nodeType==3){return i.parentNode}return i}},getEnd:function(){var h=this,i=h.getRng(),j,g;if(i.duplicate||i.item){if(i.item){return i.item(0)}i=i.duplicate();i.collapse(0);j=i.parentElement();if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=i.endContainer;g=i.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[g>0?g-1:g]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){return{rng:y.getRng()}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(o){var s=this,m=s.dom,j,i,g,r,k,u,p,q;function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t.length-1;x>=1;x--){v=y.childNodes;if(t[x]>v.length-1){return}y=v[t[x]]}if(y.nodeType===3){z=Math.min(t[0],y.nodeValue.length)}if(y.nodeType===1){z=Math.min(t[0],y.childNodes.length)}if(A){g.setStart(y,z)}else{g.setEnd(y,z)}}return true}function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentNode;if(B=="start"){if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}k=u=A;p=q=t}else{if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}u=A;q=t}if(!x){z=v.previousSibling;y=v.nextSibling;e(d.grep(v.childNodes),function(C){if(C.nodeType==3){C.nodeValue=C.nodeValue.replace(/\uFEFF/g,"")}});while(v=m.get(o.id+"_"+B)){m.remove(v,1)}if(z&&y&&z.nodeType==y.nodeType&&z.nodeType==3&&!d.isOpera){t=z.nodeValue.length;z.appendData(y.nodeValue);m.remove(y);if(B=="start"){k=u=z;p=q=t}else{u=z;q=t}}}}}function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
                          '}return t}if(o){if(o.start){g=m.createRng();r=m.getRoot();if(s.tridentSel){return s.tridentSel.moveToBookmark(o)}if(h(true)&&h()){s.setRng(g)}}else{if(o.id){l("start");l("end");if(k){g=m.createRng();g.setStart(n(k),p);g.setEnd(n(u),q);s.setRng(g)}}else{if(o.name){s.select(m.select(o.name)[o.index])}else{if(o.rng){s.setRng(o.rng)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},destroy:function(h){var g=this;g.win=null;if(!h){d.removeUnload(g.destroy)}},_fixIESelection:function(){var h=this.dom,n=h.doc,i=n.body,k,o,g;function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r){q=null}return q}function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoints("StartToStart",o)>0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=q.create("script",{id:n,type:"text/javascript",src:a._addVer(m)});if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=l.length){q=0}}s=l[q];f.setAttrib(g,"tabindex","-1");f.setAttrib(s.id,"tabindex","0");f.get(s.id).focus();if(e.actOnFocus){e.onAction(s.id)}if(r){a.cancel(r)}};o=function(y){var u=37,t=39,x=38,z=40,q=27,s=14,r=13,v=32;switch(y.keyCode){case u:if(i){p.moveFocus(-1)}break;case t:if(i){p.moveFocus(1)}break;case x:if(n){p.moveFocus(-1)}break;case z:if(n){p.moveFocus(1)}break;case q:if(e.onCancel){e.onCancel();a.cancel(y)}break;case s:case r:case v:if(e.onAction){e.onAction(g);a.cancel(y)}break}};c(l,function(s,q){var r;if(!s.id){s.id=f.uniqueId("_mce_item_")}if(k){f.bind(s.id,"blur",h);r="-1"}else{r=(q===0?"0":"-1")}f.setAttrib(s.id,"tabindex",r);f.bind(f.get(s.id),"focus",j)});if(l[0]){g=l[0].id}f.setAttrib(m,"tabindex","-1");f.bind(f.get(m),"focus",d);f.bind(f.get(m),"keydown",o)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+c}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keyup",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(l){var k;b.remove(h.id,"change",i);j=false;k=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",k)});if(e.isWebKit&&(l.keyCode==37||l.keyCode==39)){return b.prevent(l)}if(l.keyCode==13||l.keyCode==32){g(l);return b.cancel(l)}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
                          ');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
                          ");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){return;var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}x=d({theme:"simple",language:"en"},x);v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);if(j.adapter){j.adapter.patchEditor(m)}return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/../../extra/strings.php?elanguage="+q.language+"ðeme="+q.theme)}if(q.theme&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,F=this,G=F.settings,C,y,B=F.getElement(),p,m,D,v,A,E,x,r=[];k.add(F);G.aria_label=G.aria_label||l.getAttrib(B,"aria-label",F.getLang("aria.rich_text_area"));if(G.theme){G.theme=G.theme.replace(/-/,"");p=h.get(G.theme);F.theme=new p();if(F.theme.init){F.theme.init(F,h.urls[G.theme]||k.documentBaseURL.replace(/\/$/,""))}}function z(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){z(u)});n=new t(F,o);F.plugins[s]=n;if(n.init){n.init(F,o);r.push(s)}}}i(g(G.plugins.replace(/\-/g,"")),z);if(G.popup_css!==false){if(G.popup_css){G.popup_css=F.documentBaseURI.toAbsolute(G.popup_css)}else{G.popup_css=F.baseURI.toAbsolute("themes/"+G.theme+"/skins/"+G.skin+"/dialog.css")}}if(G.popup_css_add){G.popup_css+=","+F.documentBaseURI.toAbsolute(G.popup_css_add)}F.controlManager=new k.ControlManager(F);F.onExecCommand.add(function(n,o){if(!/^(FontName|FontSize)$/.test(o)){F.nodeChanged()}});F.onBeforeRenderUI.dispatch(F,F.controlManager);if(G.render_ui&&F.theme){C=G.width||B.style.width||B.offsetWidth;y=G.height||B.style.height||B.offsetHeight;F.orgDisplay=B.style.display;E=/^[0-9\.]+(|px)$/i;if(E.test(""+C)){C=Math.max(parseInt(C,10)+(p.deltaWidth||0),100)}if(E.test(""+y)){y=Math.max(parseInt(y)+(p.deltaHeight||0),G.theme_advanced_resizing_min_height||100)}p=F.theme.renderUI({targetNode:B,width:C,height:y,deltaWidth:G.delta_width,deltaHeight:G.delta_height});F.editorContainer=p.editorContainer}if(G.content_css){i(g(G.content_css),function(n){F.contentCSS.push(F.documentBaseURI.toAbsolute(n))})}if(G.content_editable){B=q=p=null;return F.initContentBody()}if(document.domain&&location.hostname!=document.domain){k.relaxedDomain=document.domain}l.setStyles(p.sizeContainer||p.editorContainer,{width:C,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y<(G.theme_advanced_resizing_min_height||100)){y=G.theme_advanced_resizing_min_height||100}F.iframeHTML=G.doctype+'';if(G.document_base_url!=k.documentBaseURL){F.iframeHTML+=''}if(G.ie7_compat){F.iframeHTML+=''}else{F.iframeHTML+=''}F.iframeHTML+='';for(x=0;x'}F.contentCSS=[];v=G.body_id||"tinymce";if(v.indexOf("=")!=-1){v=F.getParam("body_id","","hash");v=v[F.id]||v}A=G.body_class||"";if(A.indexOf("=")!=-1){A=F.getParam("body_class","","hash");A=A[F.id]||""}F.iframeHTML+='
                          ";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){D='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+F.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:F.id+"_ifr",src:D||'javascript:""',frameBorder:"0",allowTransparency:"true",title:G.aria_label,style:{width:"100%",height:y,display:"block"}});F.contentAreaContainer=p.iframeContainer;l.get(p.editorContainer).style.display=F.orgDisplay;l.get(F.id).style.display="none";l.setAttrib(F.id,"aria-hidden",true);if(!k.relaxedDomain||!D){F.initContentBody()}B=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(s,t){var u=s.length,x,z=n.dom,y,v;while(u--){x=s[u];y=x.attr(t);v="data-mce-"+t;if(!x.attributes.map[v]){if(t==="style"){x.attr(v,z.serializeStyle(z.parseStyle(y),x.name))}else{x.attr(v,n.convertURL(y,t,x.name))}}}});n.parser.addNodeFilter("script",function(s,t){var u=s.length,v;while(u--){v=s[u];v.attr("type","mce-"+(v.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(s,t){var u=s.length,v;while(u--){v=s[u];v.type=8;v.name="#comment";v.value="[CDATA["+v.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,u){var v=t.length,x,s=n.schema.getNonEmptyElements();while(v--){x=t[v];if(x.isEmpty(s)){x.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.serializer.onPreProcess.add(function(s,t){return n.onPreProcess.dispatch(n,t,s)});n.serializer.onPostProcess.add(function(s,t){return n.onPostProcess.dispatch(n,t,s)});n.onPreInit.dispatch(n);if(!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(s,t){i(p.protect,function(u){t.content=t.content.replace(u,function(v){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
                          [\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});i(n.contentCSS,function(s){n.dom.loadCSS(s)});if(p.auto_focus){setTimeout(function(){var s=k.get(p.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};n.normalize();p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
                          "}else{r='
                          '}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}o.selection.normalize();return p.content},getContent:function(n){var m=this,o;n=n||{};n.format=n.format||"html";n.get=true;n.getInner=true;if(!n.no_events){m.onBeforeGetContent.dispatch(m,n)}if(n.format=="raw"){o=m.getBody().innerHTML}else{o=m.serializer.serialize(m.getBody(),n)}n.content=k.trim(o);if(!n.no_events){m.onGetContent.dispatch(m,n)}return n.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":r=p.getAttrib(s,"name");m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,n=m.getContainer();if(!m.removed){m.removed=1;m.hide();if(!m.settings.content_editable){j.clear(m.getWin());j.clear(m.getDoc())}j.clear(m.getBody());j.clear(m.formElement);j.unbind(n);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(n)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){Event.cancel(g)}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var c=this,f,g=c.settings,j=c.dom,k;k={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function e(i,l){var m=i.type;if(c.removed){return}if(c.onEvent.dispatch(c,i,l)!==false){c[k[i.fakeType||i.type]].dispatch(c,i,l)}}function h(i){c.focus(true)}b(k,function(l,m){var i=g.content_editable?c.getBody():c.getDoc();switch(m){case"contextmenu":j.bind(i,m,e);break;case"paste":j.bind(c.getBody(),m,e);break;case"submit":case"reset":j.bind(c.getElement().form||a.DOM.getParent(c.id,"form"),m,e);break;default:j.bind(i,m,e)}});j.bind(g.content_editable?c.getBody():(a.isGecko?c.getDoc():c.getWin()),"focus",function(i){c.focus(true)});if(g.content_editable&&a.isOpera){j.bind(c.getBody(),"click",h);j.bind(c.getBody(),"keydown",h)}c.onMouseUp.add(c.nodeChanged);c.onKeyUp.add(function(i,m){var l=m.keyCode;if((l>=33&&l<=36)||(l>=37&&l<=40)||l==13||l==45||l==46||l==8||(a.isMac&&(l==91||l==93))||m.ctrlKey){c.nodeChanged()}});c.onReset.add(function(){c.setContent(c.startContent,{format:"raw"})});function d(l,i){if(l.altKey||l.ctrlKey||l.metaKey){b(c.shortcuts,function(m){var n=a.isMac?l.metaKey:l.ctrlKey;if(m.ctrl!=n||m.alt!=l.altKey||m.shift!=l.shiftKey){return}if(l.keyCode==m.keyCode||(l.charCode&&l.charCode==m.charCode)){l.preventDefault();if(i){m.func.call(m.scope)}return true}})}}c.onKeyUp.add(function(i,l){d(l)});c.onKeyPress.add(function(i,l){d(l)});c.onKeyDown.add(function(i,l){d(l,true)});if(a.isOpera){c.onClick.add(function(i,l){l.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getDoc(),b.isGecko?"blur":"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}if(p){c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(i){var h,g=this,f=g.editor;d(f.plugins,function(j){if(j.createControl){h=j.createControl(i,g);if(h){return false}}});switch(i){case"|":case"separator":return g.createSeparator()}if(!h&&f.buttons&&(h=f.buttons[i])){return g.createButton(i,h)}return g.add(h)},createDropMenu:function(f,n,h){var m=this,i=m.editor,j,g,k,l;n=e({"class":"mceDropDown",constrain:i.settings.constrain_menus},n);n["class"]=n["class"]+" "+i.getParam("skin")+"Skin";if(k=i.getParam("skin_variant")){n["class"]+=" "+i.getParam("skin")+"Skin"+k.substring(0,1).toUpperCase()+k.substring(1)}n["class"]+=i.settings.directionality=="rtl"?" mceRtl":"";f=m.prefix+f;l=h||m._cls.dropmenu||c.ui.DropMenu;j=m.controls[f]=new l(f,n);j.onAddItem.add(function(r,q){var p=q.settings;p.title=i.getLang(p.title,p.title);if(!p.onclick){p.onclick=function(o){if(p.cmd){i.execCommand(p.cmd,p.ui||false,p.value)}}}});i.onRemove.add(function(){j.destroy()});if(c.isIE){j.onShowMenu.add(function(){i.focus();g=i.selection.getBookmark(1)});j.onHideMenu.add(function(){if(g){i.selection.moveToBookmark(g);g=0}})}return m.add(j)},createListBox:function(f,n,h){var l=this,j=l.editor,i,k,m;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,scope:n.scope,control_manager:l},n);f=l.prefix+f;function g(o){return o.settings.use_accessible_selects&&!c.isGecko}if(j.settings.use_native_selects||g(j)){k=new c.ui.NativeListBox(f,n)}else{m=h||l._cls.listbox||c.ui.ListBox;k=new m(f,n,j)}l.controls[f]=k;if(c.isWebKit){k.onPostRender.add(function(p,o){a.add(o,"mousedown",function(){j.bookmark=j.selection.getBookmark(1)});a.add(o,"focus",function(){j.selection.moveToBookmark(j.bookmark);j.bookmark=null})})}if(k.hideMenu){j.onMouseDown.add(k.hideMenu,k)}return l.add(k)},createButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.label=g.translate(i.label);i.scope=i.scope||g;if(!i.onclick&&!i.menu_button){i.onclick=function(){g.execCommand(i.cmd,i.ui||false,i.value)}}i=e({title:i.title,"class":"mce_"+m,unavailable_prefix:g.getLang("unavailable",""),scope:i.scope,control_manager:h},i);m=h.prefix+m;if(i.menu_button){f=l||h._cls.menubutton||c.ui.MenuButton;k=new f(m,i,g);g.onMouseDown.add(k.hideMenu,k)}else{f=h._cls.button||c.ui.Button;k=new f(m,i,g)}return h.add(k)},createMenuButton:function(h,f,g){f=f||{};f.menu_button=1;return this.createButton(h,f,g)},createSplitButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.scope=i.scope||g;if(!i.onclick){i.onclick=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}if(!i.onselect){i.onselect=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}i=e({title:i.title,"class":"mce_"+m,scope:i.scope,control_manager:h},i);m=h.prefix+m;f=l||h._cls.splitbutton||c.ui.SplitButton;k=h.add(new f(m,i,g));g.onMouseDown.add(k.hideMenu,k);return k},createColorSplitButton:function(f,n,h){var l=this,j=l.editor,i,k,m,g;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onclick){n.onclick=function(o){if(c.isIE){g=j.selection.getBookmark(1)}j.execCommand(n.cmd,n.ui||false,o||n.value)}}if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,menu_class:j.getParam("skin")+"Skin",scope:n.scope,more_colors_title:j.getLang("more_colors")},n);f=l.prefix+f;m=h||l._cls.colorsplitbutton||c.ui.ColorSplitButton;k=new m(f,n,j);j.onMouseDown.add(k.hideMenu,k);j.onRemove.add(function(){k.destroy()});if(c.isIE){k.onShowMenu.add(function(){j.focus();g=j.selection.getBookmark(1)});k.onHideMenu.add(function(){if(g){j.selection.moveToBookmark(g);g=0}})}return l.add(k)},createToolbar:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||g._cls.toolbar||c.ui.Toolbar;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createToolbarGroup:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||this._cls.toolbarGroup||c.ui.ToolbarGroup;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createSeparator:function(g){var f=g||this._cls.separator||c.ui.Separator;return new f()},setControlType:function(g,f){return this._cls[g.toLowerCase()]=f},destroy:function(){d(this.controls,function(f){f.destroy()});this.controls=null}})})(tinymce);(function(d){var a=d.util.Dispatcher,e=d.each,c=d.isIE,b=d.isOpera;d.create("tinymce.WindowManager",{WindowManager:function(f){var g=this;g.editor=f;g.onOpen=new a(g);g.onClose=new a(g);g.params={};g.features={}},open:function(z,h){var v=this,k="",n,m,i=v.editor.settings.dialog_type=="modal",q,o,j,g=d.DOM.getViewPort(),r;z=z||{};h=h||{};o=b?g.w:screen.width;j=b?g.h:screen.height;z.name=z.name||"mc_"+new Date().getTime();z.width=parseInt(z.width||320);z.height=parseInt(z.height||240);z.resizable=true;z.left=z.left||parseInt(o/2)-(z.width/2);z.top=z.top||parseInt(j/2)-(z.height/2);h.inline=false;h.mce_width=z.width;h.mce_height=z.height;h.mce_auto_focus=z.auto_focus;if(i){if(c){z.center=true;z.help=false;z.dialogWidth=z.width+"px";z.dialogHeight=z.height+"px";z.scroll=z.scrollbars||false}}e(z,function(p,f){if(d.is(p,"boolean")){p=p?"yes":"no"}if(!/^(name|url)$/.test(f)){if(c&&i){k+=(k?";":"")+f+":"+p}else{k+=(k?",":"")+f+"="+p}}});v.features=z;v.params=h;v.onOpen.dispatch(v,z,h);r=z.url||z.file;r=d._addVer(r);try{if(c&&i){q=1;window.showModalDialog(r,window,k)}else{q=window.open(r,z.name,k)}}catch(l){}if(!q){alert(v.editor.getLang("popup_blocked"))}},close:function(f){f.close();this.onClose.dispatch(this)},createInstance:function(i,h,g,m,l,k){var j=d.resolve(i);return new j(h,g,m,l,k)},confirm:function(h,f,i,g){g=g||window;f.call(i||this,g.confirm(this._decode(this.editor.getLang(h,h))))},alert:function(h,f,j,g){var i=this;g=g||window;g.alert(i._decode(i.editor.getLang(h,h)));if(f){f.call(j||i)}},resizeBy:function(f,g,h){h.resizeBy(f,g)},_decode:function(f){return d.DOM.decode(f).replace(/\\n/g,"\n")}})}(tinymce));(function(a){a.Formatter=function(Y){var O={},R=a.each,c=Y.dom,r=Y.selection,t=a.dom.TreeWalker,M=new a.dom.RangeUtils(c),d=Y.schema.isValidChild,H=c.isBlock,m=Y.settings.forced_root_block,s=c.nodeIndex,G=a.isGecko?"\u200B":"\uFEFF",e=/^(src|href|style)$/,V=false,C=true,D,x=c.getContentEditable;function A(Z){return Z instanceof Array}function n(aa,Z){return c.getParents(aa,Z,c.getRoot())}function b(Z){return Z.nodeType===1&&Z.id==="_mce_caret"}function j(){l({alignleft:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"},defaultBlock:"div"},{selector:"img,table",collapsed:false,styles:{"float":"left"}}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"},defaultBlock:"div"},{selector:"img",collapsed:false,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:false,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"},defaultBlock:"div"},{selector:"img,table",collapsed:false,styles:{"float":"right"}}],alignfull:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"justify"},defaultBlock:"div"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:true},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:true},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:false},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:false},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},link:{inline:"a",selector:"a",remove:"all",split:true,deep:true,onmatch:function(Z){return true},onformat:function(ab,Z,aa){R(aa,function(ad,ac){c.setAttrib(ab,ac,ad)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:true,expand:false,block_expand:true,deep:true},{selector:"span",attributes:["style","class"],remove:"empty",split:true,expand:false,deep:true},{selector:"*",attributes:["style","class"],split:false,expand:false,deep:true}]});R("p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp".split(/\s/),function(Z){l(Z,{block:Z,remove:"all"})});l(Y.settings.formats)}function U(){Y.addShortcut("ctrl+b","bold_desc","Bold");Y.addShortcut("ctrl+i","italic_desc","Italic");Y.addShortcut("ctrl+u","underline_desc","Underline");for(var Z=1;Z<=6;Z++){Y.addShortcut("ctrl+"+Z,"",["FormatBlock",false,"h"+Z])}Y.addShortcut("ctrl+7","",["FormatBlock",false,"p"]);Y.addShortcut("ctrl+8","",["FormatBlock",false,"div"]);Y.addShortcut("ctrl+9","",["FormatBlock",false,"address"])}function T(Z){return Z?O[Z]:O}function l(Z,aa){if(Z){if(typeof(Z)!=="string"){R(Z,function(ac,ab){l(ab,ac)})}else{aa=aa.length?aa:[aa];R(aa,function(ab){if(ab.deep===D){ab.deep=!ab.selector}if(ab.split===D){ab.split=!ab.selector||ab.inline}if(ab.remove===D&&ab.selector&&!ab.inline){ab.remove="none"}if(ab.selector&&ab.inline){ab.mixed=true;ab.block_expand=true}if(typeof(ab.classes)==="string"){ab.classes=ab.classes.split(/\s+/)}});O[Z]=aa}}}var i=function(aa){var Z;Y.dom.getParent(aa,function(ab){Z=Y.dom.getStyle(ab,"text-decoration");return Z&&Z!=="none"});return Z};var K=function(Z){var aa;if(Z.nodeType===1&&Z.parentNode&&Z.parentNode.nodeType===1){aa=i(Z.parentNode);if(Y.dom.getStyle(Z,"color")&&aa){Y.dom.setStyle(Z,"text-decoration",aa)}else{if(Y.dom.getStyle(Z,"textdecoration")===aa){Y.dom.setStyle(Z,"text-decoration",null)}}}};function W(ac,aj,ae){var af=T(ac),ak=af[0],ai,aa,ah,ag=r.isCollapsed();function Z(ao,an){an=an||ak;if(ao){if(an.onformat){an.onformat(ao,an,aj,ae)}R(an.styles,function(aq,ap){c.setStyle(ao,ap,q(aq,aj))});R(an.attributes,function(aq,ap){c.setAttrib(ao,ap,q(aq,aj))});R(an.classes,function(ap){ap=q(ap,aj);if(!c.hasClass(ao,ap)){c.addClass(ao,ap)}})}}function ad(){function ap(aw,au){var av=new t(au);for(ae=av.current();ae;ae=av.prev()){if(ae.childNodes.length>1||ae==aw||ae.tagName=="BR"){return ae}}}var ao=Y.selection.getRng();var at=ao.startContainer;var an=ao.endContainer;if(at!=an&&ao.endOffset===0){var ar=ap(at,an);var aq=ar.nodeType==3?ar.length:ar.childNodes.length;ao.setEnd(ar,aq)}return ao}function ab(aq,aw,au,at,ao){var an=[],ap=-1,av,ay=-1,ar=-1,ax;R(aq.childNodes,function(aA,az){if(aA.nodeName==="UL"||aA.nodeName==="OL"){ap=az;av=aA;return false}});R(aq.childNodes,function(aA,az){if(aA.nodeName==="SPAN"&&c.getAttrib(aA,"data-mce-type")=="bookmark"){if(aA.id==aw.id+"_start"){ay=az}else{if(aA.id==aw.id+"_end"){ar=az}}}});if(ap<=0||(ayap)){R(a.grep(aq.childNodes),ao);return 0}else{ax=c.clone(au,V);R(a.grep(aq.childNodes),function(aA,az){if((ayap&&az>ap)){an.push(aA);aA.parentNode.removeChild(aA)}});if(ayap){aq.insertBefore(ax,av.nextSibling)}}at.push(ax);R(an,function(az){ax.appendChild(az)});return ax}}function al(ao,aq,au){var an=[],at,ap,ar=true;at=ak.inline||ak.block;ap=c.create(at);Z(ap);M.walk(ao,function(av){var aw;function ax(ay){var aD,aB,az,aA,aC;aC=ar;aD=ay.nodeName.toLowerCase();aB=ay.parentNode.nodeName.toLowerCase();if(ay.nodeType===1&&x(ay)){aC=ar;ar=x(ay)==="true";aA=true}if(g(aD,"br")){aw=0;if(ak.block){c.remove(ay)}return}if(ak.wrapper&&y(ay,ac,aj)){aw=0;return}if(ar&&!aA&&ak.block&&!ak.wrapper&&I(aD)){ay=c.rename(ay,at);Z(ay);an.push(ay);aw=0;return}if(ak.selector){R(af,function(aE){if("collapsed" in aE&&aE.collapsed!==ag){return}if(c.is(ay,aE.selector)&&!b(ay)){Z(ay,aE);az=true}});if(!ak.inline||az){aw=0;return}}if(ar&&!aA&&d(at,aD)&&d(aB,at)&&!(!au&&ay.nodeType===3&&ay.nodeValue.length===1&&ay.nodeValue.charCodeAt(0)===65279)&&!b(ay)){if(!aw){aw=c.clone(ap,V);ay.parentNode.insertBefore(aw,ay);an.push(aw)}aw.appendChild(ay)}else{if(aD=="li"&&aq){aw=ab(ay,aq,ap,an,ax)}else{aw=0;R(a.grep(ay.childNodes),ax);if(aA){ar=aC}aw=0}}}R(av,ax)});if(ak.wrap_links===false){R(an,function(av){function aw(aA){var az,ay,ax;if(aA.nodeName==="A"){ay=c.clone(ap,V);an.push(ay);ax=a.grep(aA.childNodes);for(az=0;az1||!H(ax))&&av===0){c.remove(ax,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&av===1){ax=aw(ax)}R(af,function(az){R(c.select(az.inline,ax),function(aB){var aA;if(az.wrap_links===false){aA=aB.parentNode;do{if(aA.nodeName==="A"){return}}while(aA=aA.parentNode)}X(az,aj,aB,az.exact?aB:null)})});if(y(ax.parentNode,ac,aj)){c.remove(ax,1);ax=0;return C}if(ak.merge_with_parents){c.getParent(ax.parentNode,function(az){if(y(az,ac,aj)){c.remove(ax,1);ax=0;return C}})}if(ax&&ak.merge_siblings!==false){ax=u(E(ax),ax);ax=u(ax,E(ax,C))}}})}if(ak){if(ae){if(ae.nodeType){aa=c.createRng();aa.setStartBefore(ae);aa.setEndAfter(ae);al(p(aa,af),null,true)}else{al(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var am=Y.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(am,c.isBlock)){W(af[0].defaultBlock)}Y.selection.setRng(ad());ai=r.getBookmark();al(p(r.getRng(C),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(am,K,"childNodes");K(am)}r.moveToBookmark(ai);P(r.getRng(C));Y.nodeChanged()}else{S("apply",ac,aj)}}}}function B(ab,ak,ad){var ae=T(ab),am=ae[0],ai,ah,aa,aj=true;function ac(at){var ar,aq,ap,ao,av,au;if(at.nodeType===1&&x(at)){av=aj;aj=x(at)==="true";au=true}ar=a.grep(at.childNodes);if(aj&&!au){for(aq=0,ap=ae.length;aq=0;aa--){Z=af[aa].selector;if(!Z){return C}for(ae=ab.length-1;ae>=0;ae--){if(c.is(ab[ae],Z)){return C}}}}return V}a.extend(this,{get:T,register:l,apply:W,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z});j();U();function h(Z,aa){if(g(Z,aa.inline)){return C}if(g(Z,aa.block)){return C}if(aa.selector){return c.is(Z,aa.selector)}}function g(aa,Z){aa=aa||"";Z=Z||"";aa=""+(aa.nodeName||aa);Z=""+(Z.nodeName||Z);return aa.toLowerCase()==Z.toLowerCase()}function N(aa,Z){var ab=c.getStyle(aa,Z);if(Z=="color"||Z=="backgroundColor"){ab=c.toHex(ab)}if(Z=="fontWeight"&&ab==700){ab="bold"}return""+ab}function q(Z,aa){if(typeof(Z)!="string"){Z=Z(aa)}else{if(aa){Z=Z.replace(/%(\w+)/g,function(ac,ab){return aa[ab]||ac})}}return Z}function f(Z){return Z&&Z.nodeType===3&&/^([\t \r\n]+|)$/.test(Z.nodeValue)}function Q(ab,aa,Z){var ac=c.create(aa,Z);ab.parentNode.insertBefore(ac,ab);ac.appendChild(ab);return ac}function p(Z,ak,ac){var an,al,af,aj,ab=Z.startContainer,ag=Z.startOffset,ap=Z.endContainer,ai=Z.endOffset;function am(ax){var ar,av,aw,au,at,aq;ar=av=ax?ab:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();if(ar.nodeType==3&&!f(ar)){if(ax?ag>0:aial?al:ag];if(ab.nodeType==3){ag=0}}if(ap.nodeType==1&&ap.hasChildNodes()){al=ap.childNodes.length-1;ap=ap.childNodes[ai>al?al:ai-1];if(ap.nodeType==3){ai=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ah(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ac){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&af.node.nodeType===3&&af.node.nodeValue.charAt(af.offset-1)===" "){if(af.offset>1){ap=af.node;ap.splitText(af.offset-1)}}}}if(ak[0].inline||ak[0].block_expand){if(!ak[0].inline||(ab.nodeType!=3||ag===0)){ab=am(true)}if(!ak[0].inline||(ap.nodeType!=3||ai===ap.nodeValue.length)){ap=am()}}if(ak[0].selector&&ak[0].expand!==V&&!ak[0].inline){ab=ad(ab,"previousSibling");ap=ad(ap,"nextSibling")}if(ak[0].block||ak[0].selector){ab=aa(ab,"previousSibling");ap=aa(ap,"nextSibling");if(ak[0].block){if(!H(ab)){ab=am(true)}if(!H(ap)){ap=am()}}}if(ab.nodeType==1){ag=s(ab);ab=ab.parentNode}if(ap.nodeType==1){ai=s(ap)+1;ap=ap.parentNode}return{startContainer:ab,startOffset:ag,endContainer:ap,endOffset:ai}}function X(af,ae,ac,Z){var ab,aa,ad;if(!h(ac,af)){return V}if(af.remove!="all"){R(af.styles,function(ah,ag){ah=q(ah,ae);if(typeof(ag)==="number"){ag=ah;Z=0}if(!Z||g(N(Z,ag),ah)){c.setStyle(ac,ag,"")}ad=1});if(ad&&c.getAttrib(ac,"style")==""){ac.removeAttribute("style");ac.removeAttribute("data-mce-style")}R(af.attributes,function(ai,ag){var ah;ai=q(ai,ae);if(typeof(ag)==="number"){ag=ai;Z=0}if(!Z||g(c.getAttrib(Z,ag),ai)){if(ag=="class"){ai=c.getAttrib(ac,ag);if(ai){ah="";R(ai.split(/\s+/),function(aj){if(/mce\w+/.test(aj)){ah+=(ah?" ":"")+aj}});if(ah){c.setAttrib(ac,ag,ah);return}}}if(ag=="class"){ac.removeAttribute("className")}if(e.test(ag)){ac.removeAttribute("data-mce-"+ag)}ac.removeAttribute(ag)}});R(af.classes,function(ag){ag=q(ag,ae);if(!Z||c.hasClass(Z,ag)){c.removeClass(ac,ag)}});aa=c.getAttribs(ac);for(ab=0;abab?ab:ad]}if(Z.nodeType===3&&ae&&ad>=Z.nodeValue.length){Z=new t(Z,Y.getBody()).next()||Z}if(Z.nodeType===3&&!ae&&ad===0){Z=new t(Z,Y.getBody()).prev()||Z}return Z}function S(ai,Z,ag){var aj="_mce_caret",aa=Y.settings.caret_debug;function ab(am){var al=c.create("span",{id:aj,"data-mce-bogus":true,style:aa?"color:red":""});if(am){al.appendChild(Y.getDoc().createTextNode(G))}return al}function ah(am,al){while(am){if((am.nodeType===3&&am.nodeValue!==G)||am.childNodes.length>1){return false}if(al&&am.nodeType===1){al.push(am)}am=am.firstChild}return true}function ae(al){while(al){if(al.id===aj){return al}al=al.parentNode}}function ad(al){var am;if(al){am=new t(al,al);for(al=am.current();al;al=am.next()){if(al.nodeType===3){return al}}}}function ac(an,am){var ao,al;if(!an){an=ae(r.getStart());if(!an){while(an=c.get(aj)){ac(an,false)}}}else{al=r.getRng(true);if(ah(an)){if(am!==false){al.setStartBefore(an);al.setEndBefore(an)}c.remove(an)}else{ao=ad(an);if(ao.nodeValue.charAt(0)===G){ao=ao.deleteData(0,1)}c.remove(an,1)}r.setRng(al)}}function af(){var an,al,ar,aq,ao,am,ap;an=r.getRng(true);aq=an.startOffset;am=an.startContainer;ap=am.nodeValue;al=ae(r.getStart());if(al){ar=ad(al)}if(ap&&aq>0&&aq=0;ap--){an.appendChild(c.clone(au[ap],false));an=an.firstChild}an.appendChild(c.doc.createTextNode(G));an=an.firstChild;c.insertAfter(at,av);r.setCursorLocation(an,1)}}if(!self._hasCaretEvents){Y.onBeforeGetContent.addToTop(function(){var al=[],am;if(ah(ae(r.getStart()),al)){am=al.length;while(am--){c.setAttrib(al[am],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(al){Y[al].addToTop(function(){ac()})});Y.onKeyDown.addToTop(function(al,an){var am=an.keyCode;if(am==8||am==37||am==39){ac(ae(r.getStart()))}});r.onSetContent.add(function(){c.getParent(r.getStart(),function(al){if(al.id!==aj&&c.getAttrib(al,"data-mce-bogus")&&!c.isEmpty(al)){c.setAttrib(al,"data-mce-bogus",null)}})});self._hasCaretEvents=true}if(ai=="apply"){af()}else{ak()}}function P(aa){var Z=aa.startContainer,ag=aa.startOffset,ac,af,ae,ab,ad;if(Z.nodeType==3&&ag>=Z.nodeValue.length){ag=s(Z);Z=Z.parentNode;ac=true}if(Z.nodeType==1){ab=Z.childNodes;Z=ab[Math.min(ag,ab.length-1)];af=new t(Z,c.getParent(Z,c.isBlock));if(ag>ab.length-1||ac){af.next()}for(ae=af.current();ae;ae=af.next()){if(ae.nodeType==3&&!f(ae)){ad=c.create("a",null,G);ae.parentNode.insertBefore(ad,ae);aa.setStart(ae,0);r.setRng(aa);c.remove(ad);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(e){var h=e.dom,d=e.selection,c=e.settings,g=e.undoManager;function f(y){var u=d.getRng(true),C,i,x,t,o,H,n,j,l,s,E,v,z;function B(I){return I&&h.isBlock(I)&&!/^(TD|TH|CAPTION)$/.test(I.nodeName)&&!/^(fixed|absolute)/i.test(I.style.position)&&h.getContentEditable(I)!=="true"}function m(J){var O,M,I,P,N,L=J,K;I=h.createRng();if(J.hasChildNodes()){O=new a(J,J);while(M=O.current()){if(M.nodeType==3){I.setStart(M,0);I.setEnd(M,0);break}if(/^(BR|IMG)$/.test(M.nodeName)){I.setStartBefore(M);I.setEndBefore(M);break}L=M;M=O.next()}if(!M){I.setStart(L,0);I.setEnd(L,0)}}else{if(J.nodeName=="BR"){if(J.nextSibling&&h.isBlock(J.nextSibling)){if(!H||H<9){K=h.create("br");J.parentNode.insertBefore(K,J)}I.setStartBefore(J);I.setEndBefore(J)}else{I.setStartAfter(J);I.setEndAfter(J)}}else{I.setStart(J,0);I.setEnd(J,0)}}d.setRng(I);h.remove(K);N=h.getViewPort(e.getWin());P=h.getPos(J).y;if(PN.y+N.h){e.getWin().scrollTo(0,P"}return M}function p(L){var K,J,I;if(x.nodeType==3&&(L?t>0:t=x.nodeValue.length){if(!b.isIE&&!A()){J=h.create("br");u.insertNode(J);u.setStartAfter(J);u.setEndAfter(J);I=true}}J=h.create("br");u.insertNode(J);if(b.isIE&&s=="PRE"&&(!H||H<8)){J.parentNode.insertBefore(h.doc.createTextNode("\r"),J)}if(!I){u.setStartAfter(J);u.setEndAfter(J)}else{u.setStartBefore(J);u.setEndBefore(J)}d.setRng(u);g.add()}function r(I){do{if(I.nodeType===3){I.nodeValue=I.nodeValue.replace(/^[\r\n]+/,"")}I=I.firstChild}while(I)}function F(K){var I=h.getRoot(),J,L;J=K;while(J!==I&&h.getContentEditable(J)!=="false"){if(h.getContentEditable(J)==="true"){L=J}J=J.parentNode}return J!==I?L:I}if(!u.collapsed){e.execCommand("Delete");return}if(y.isDefaultPrevented()){return}x=u.startContainer;t=u.startOffset;v=c.forced_root_block;v=v?v.toUpperCase():"";H=h.doc.documentMode;if(x.nodeType==1&&x.hasChildNodes()){z=t>x.childNodes.length-1;x=x.childNodes[Math.min(t,x.childNodes.length-1)]||x;t=0}i=F(x);if(!i){return}g.beforeChange();if(!h.isBlock(i)&&i!=h.getRoot()){if(!v||y.shiftKey){G()}return}if((v&&!y.shiftKey)||(!v&&y.shiftKey)){x=k(x,t)}o=h.getParent(x,h.isBlock);l=o?h.getParent(o.parentNode,h.isBlock):null;s=o?o.nodeName.toUpperCase():"";E=l?l.nodeName.toUpperCase():"";if(s=="LI"&&h.isEmpty(o)){if(/^(UL|OL|LI)$/.test(l.parentNode.nodeName)){return false}D();return}if(s=="PRE"&&c.br_in_pre!==false){if(!y.shiftKey){G();return}}else{if((!v&&!y.shiftKey&&s!="LI")||(v&&y.shiftKey)){G();return}}v=v||"P";if(p()){if(/^(H[1-6]|PRE)$/.test(s)&&E!="HGROUP"){n=q(v)}else{n=q()}if(c.end_container_on_empty_block&&B(l)&&h.isEmpty(o)){n=h.split(l,o)}else{h.insertAfter(n,o)}}else{if(p(true)){n=o.parentNode.insertBefore(q(),o)}else{C=u.cloneRange();C.setEndAfter(o);j=C.extractContents();r(j);n=j.firstChild;h.insertAfter(j,o)}}h.setAttrib(n,"id","");m(n);g.add()}e.onKeyDown.add(function(j,i){if(i.keyCode==13){if(f(i)!==false){i.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype.js b/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype.js deleted file mode 100644 index 7c95d2a37e6..00000000000 --- a/lib/editor/tinymce/tiny_mce/3.5/tiny_mce_prototype.js +++ /dev/null @@ -1 +0,0 @@ -(function(e){var a=/^\s*|\s*$/g,b,d="B".replace(/A(.)|B/,"$1")==="$1";var c={majorVersion:"@@tinymce_major_version@@",minorVersion:"@@tinymce_minor_version@@",releaseDate:"@@tinymce_release_date@@",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=e.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(e.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m0?b:[f.scope]);if(e===false){break}}a.inDispatch=false;return e}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w\-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});c=g.base_uri;if(c){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host==="mce_host"){f.port=c.port}if(!f.host||f.host==="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var d=this,f;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:d});if((b.host!="mce_host"&&d.host!=b.host&&b.host)||d.port!=b.port||d.protocol!=b.protocol){return b.getURI()}var c=d.getURI(),e=b.getURI();if(c==e||(c.charAt(c.length-1)=="/"&&c.substr(0,c.length-1)==e)){return c}f=d.toRelPath(d.path,b.path);if(b.query){f+="?"+b.query}if(b.anchor){f+="#"+b.anchor}return f},toAbsolute:function(b,c){b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length=g.length||g[e]!=c[e]){f=e+1;break}}}if(f===1){return h}for(e=0,b=g.length-(f-1);e=0;c--){if(f[c].length===0||f[c]==="."){continue}if(f[c]===".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!==0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t,name;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(name in o){if(o.hasOwnProperty(name)){v+=typeof o[name]!="function"?(v.length>1?","+quote:quote)+name+quote+":"+serialize(o[name],quote):""}}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(b){return b.shiftKey||b.ctrlKey||b.altKey}}})(tinymce);tinymce.util.Quirks=function(d){var l=tinymce.VK,r=l.BACKSPACE,s=l.DELETE,o=d.dom,z=d.selection,q=d.settings;function c(D,C){try{d.getDoc().execCommand(D,false,C)}catch(B){}}function h(){function B(E){var C,G,D,F;C=z.getRng();G=o.getParent(C.startContainer,o.isBlock);if(E){G=o.getNext(G,o.isBlock)}if(G){D=G.firstChild;while(D&&D.nodeType==3&&D.nodeValue.length===0){D=D.nextSibling}if(D&&D.nodeName==="SPAN"){F=D.cloneNode(false)}}d.getDoc().execCommand(E?"ForwardDelete":"Delete",false,null);G=o.getParent(C.startContainer,o.isBlock);tinymce.each(o.select("span.Apple-style-span,font.Apple-style-span",G),function(H){var I=z.getBookmark();if(F){o.replace(F.cloneNode(false),H,true)}else{o.remove(H,true)}z.moveToBookmark(I)})}d.onKeyDown.add(function(C,E){var D;D=E.keyCode==s;if(!E.isDefaultPrevented()&&(D||E.keyCode==r)&&!l.modifierPressed(E)){E.preventDefault();B(D)}});d.addCommand("Delete",function(){B()})}function A(){function C(E,H){var D,G,F=H?"start":"end";D=E[F+"Container"];G=E[F+"Offset"];if(D.nodeType==1&&D.hasChildNodes()){D=D.childNodes[Math.min(H?G:(G>0?G-1:0),D.childNodes.length-1)]}return D}function B(G,K){var F,J,E,H,I=K?"start":"end",D;F=G[I+"Container"];J=G[I+"Offset"];E=o.getRoot();if(F.nodeType==1){D=J>=F.childNodes.length;F=C(G,K);if(F.nodeType==3){J=K&&!D?0:F.nodeValue.length}}if(F.nodeType==3&&((K&&J>0)||(!K&&J7){return}c("RespectVisibilityInDesign",true);o.addClass(d.getBody(),"mceHideBrInPre");d.parser.addNodeFilter("pre",function(C,E){var F=C.length,H,D,I,G;while(F--){H=C[F].getAll("br");D=H.length;while(D--){I=H[D];G=I.prev;if(G&&G.type===3&&G.value.charAt(G.value-1)!="\n"){G.value+="\n"}else{I.parent.insert(new tinymce.html.Node("#text",3),I,true).value="\n"}}}});d.serializer.addNodeFilter("pre",function(C,E){var F=C.length,H,D,I,G;while(F--){H=C[F].getAll("br");D=H.length;while(D--){I=H[D];G=I.prev;if(G&&G.type==3){G.value=G.value.replace(/\r?\n$/,"")}}}})}function f(){o.bind(d.getBody(),"mouseup",function(D){var C,B=z.getNode();if(B.nodeName=="IMG"){if(C=o.getStyle(B,"width")){o.setAttrib(B,"width",C.replace(/[^0-9%]+/g,""));o.setStyle(B,"width","")}if(C=o.getStyle(B,"height")){o.setAttrib(B,"height",C.replace(/[^0-9%]+/g,""));o.setStyle(B,"height","")}}})}function p(){d.onKeyDown.add(function(H,I){var G,B,C,E,F,J,D;G=I.keyCode==s;if(!I.isDefaultPrevented()&&(G||I.keyCode==r)&&!l.modifierPressed(I)){B=z.getRng();C=B.startContainer;E=B.startOffset;D=B.collapsed;if(C.nodeType==3&&C.nodeValue.length>0&&((E===0&&!D)||(D&&E===(G?0:1)))){nonEmptyElements=H.schema.getNonEmptyElements();I.preventDefault();F=o.create("br",{id:"__tmp"});C.parentNode.insertBefore(F,C);H.getDoc().execCommand(G?"ForwardDelete":"Delete",false,null);C=z.getRng().startContainer;J=C.previousSibling;if(J&&J.nodeType==1&&!o.isBlock(J)&&o.isEmpty(J)&&!nonEmptyElements[J.nodeName.toLowerCase()]){o.remove(J)}o.remove("__tmp")}}})}function e(){d.onKeyDown.add(function(F,G){var D,C,H,B,E;if(G.isDefaultPrevented()||G.keyCode!=l.BACKSPACE){return}D=z.getRng();C=D.startContainer;H=D.startOffset;B=o.getRoot();E=C;if(!D.collapsed||H!==0){return}while(E&&E.parentNode&&E.parentNode.firstChild==E&&E.parentNode!=B){E=E.parentNode}if(E.tagName==="BLOCKQUOTE"){F.formatter.toggle("blockquote",null,E);D.setStart(C,0);D.setEnd(C,0);z.setRng(D);z.collapse(false)}})}function k(){function B(){d._refreshContentEditable();c("StyleWithCSS",false);c("enableInlineTableEditing",false);if(!q.object_resizing){c("enableObjectResizing",false)}}if(!q.readonly){d.onBeforeExecCommand.add(B);d.onMouseDown.add(B)}}function n(){function B(C,D){tinymce.each(o.select("a"),function(G){var E=G.parentNode,F=o.getRoot();if(E.lastChild===G){while(E&&!o.isBlock(E)){if(E.parentNode.lastChild!==E||E===F){return}E=E.parentNode}o.add(E,"br",{"data-mce-bogus":1})}})}d.onExecCommand.add(function(C,D){if(D==="CreateLink"){B(C)}});d.onSetContent.add(z.onSetContent.add(B))}function a(){function B(D,C){if(!D||!C.initial){d.execCommand("mceRepaint")}}d.onUndo.add(B);d.onRedo.add(B);d.onSetContent.add(B)}function j(){d.onKeyDown.add(function(B,C){if(!C.isDefaultPrevented()&&C.keyCode==8&&z.getNode().nodeName=="IMG"){C.preventDefault();B.undoManager.beforeChange();o.remove(z.getNode());B.undoManager.add()}})}u();e();A();if(tinymce.isWebKit){p();h();t();v();if(tinymce.isIDevice){i()}}if(tinymce.isIE){m();y();g();f();j()}if(tinymce.isGecko){m();b();x();k();n();a()}};(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':""","'":"'","<":"<",">":">","&":"&"};d={"<":"<",">":">","&":"&",""":'"',"'":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(s){var z={},q,n,x,r,v=d.url_converter,y=d.url_converter_scope||this;function p(D,G){var F,C,B,E;F=z[D+"-top"+G];if(!F){return}C=z[D+"-right"+G];if(F!=C){return}B=z[D+"-bottom"+G];if(C!=B){return}E=z[D+"-left"+G];if(B!=E){return}z[D+G]=E;delete z[D+"-top"+G];delete z[D+"-right"+G];delete z[D+"-bottom"+G];delete z[D+"-left"+G]}function u(C){var D=z[C],B;if(!D||D.indexOf(" ")<0){return}D=D.split(" ");B=D.length;while(B--){if(D[B]!==D[0]){return false}}z[C]=D[0];return true}function A(D,C,B,E){if(!u(C)){return}if(!u(B)){return}if(!u(E)){return}z[D]=z[C]+" "+z[B]+" "+z[E];delete z[C];delete z[B];delete z[E]}function t(B){r=true;return a[B]}function i(C,B){if(r){C=C.replace(/\uFEFF[0-9]/g,function(D){return a[D]})}if(!B){C=C.replace(/\\([\'\";:])/g,"$1")}return C}function o(C,B,F,E,G,D){G=G||D;if(G){G=i(G);return"'"+G.replace(/\'/g,"\\'")+"'"}B=i(B||F||E);if(v){B=v.call(y,B,"style")}return"url('"+B.replace(/\'/g,"\\'")+"')"}if(s){s=s.replace(/\\[\"\';:\uFEFF]/g,t).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(B){return B.replace(/[;:]/g,t)});while(q=b.exec(s)){n=q[1].replace(l,"").toLowerCase();x=q[2].replace(l,"");if(n&&x.length>0){if(n==="font-weight"&&x==="700"){x="bold"}else{if(n==="color"||n==="background-color"){x=x.toLowerCase()}}x=x.replace(k,c);x=x.replace(h,o);z[n]=r?i(x,true):x}b.lastIndex=q.index+q[0].length}p("border","");p("border","-width");p("border","-color");p("border","-style");p("padding","");p("margin","");A("border","border-width","border-style","border-color");if(z.border==="medium none"){delete z.border}}return z},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(f){var a={},e=f.makeMap,g=f.each;function d(j,i){return j.split(i||",")}function h(m,l){var j,k={};function i(n){return n.replace(/[A-Z]+/g,function(o){return i(m[o])})}for(j in m){if(m.hasOwnProperty(j)){m[j]=i(m[j])}}i(l).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(q,o,n,p){n=d(n,"|");k[o]={attributes:e(n),attributesOrder:n,children:e(p,"|",{"#comment":{}})}});return k}function b(){var i=a.html5;if(!i){i=a.html5=h({A:"id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title",B:"#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video",C:"#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video"},"html[A|manifest][body|head]head[A][base|command|link|meta|noscript|script|style|title]title[A][#]base[A|href|target][]link[A|href|rel|media|type|sizes][]meta[A|http-equiv|name|content|charset][]style[A|type|media|scoped][#]script[A|charset|type|src|defer|async][#]noscript[A][C]body[A][C]section[A][C]nav[A][C]article[A][C]aside[A][C]h1[A][B]h2[A][B]h3[A][B]h4[A][B]h5[A][B]h6[A][B]hgroup[A][h1|h2|h3|h4|h5|h6]header[A][C]footer[A][C]address[A][C]p[A][B]br[A][]pre[A][B]dialog[A][dd|dt]blockquote[A|cite][C]ol[A|start|reversed][li]ul[A][li]li[A|value][C]dl[A][dd|dt]dt[A][B]dd[A][C]a[A|href|target|ping|rel|media|type][C]em[A][B]strong[A][B]small[A][B]cite[A][B]q[A|cite][B]dfn[A][B]abbr[A][B]code[A][B]var[A][B]samp[A][B]kbd[A][B]sub[A][B]sup[A][B]i[A][B]b[A][B]mark[A][B]progress[A|value|max][B]meter[A|value|min|max|low|high|optimum][B]time[A|datetime][B]ruby[A][B|rt|rp]rt[A][B]rp[A][B]bdo[A][B]span[A][B]ins[A|cite|datetime][B]del[A|cite|datetime][B]figure[A][C|legend|figcaption]figcaption[A][C]img[A|alt|src|height|width|usemap|ismap][]iframe[A|name|src|height|width|sandbox|seamless][]embed[A|src|height|width|type][]object[A|data|type|height|width|usemap|name|form|classid][param]param[A|name|value][]details[A|open][C|legend]command[A|type|label|icon|disabled|checked|radiogroup][]menu[A|type|label][C|li]legend[A][C|B]div[A][C]source[A|src|type|media][]audio[A|src|autobuffer|autoplay|loop|controls][source]video[A|src|autobuffer|autoplay|loop|controls|width|height|poster][source]hr[A][]form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]fieldset[A|disabled|form|name][C|legend]label[A|form|for][B]input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]datalist[A][B|option]optgroup[A|disabled|label][option]option[A|disabled|selected|label|value][]textarea[A|autofocus|disabled|form|maxlength|name|placeholder|readonly|required|rows|cols|wrap][]keygen[A|autofocus|challenge|disabled|form|keytype|name][]output[A|for|form|name][B]canvas[A|width|height][]map[A|name][B|C]area[A|shape|coords|href|alt|target|media|rel|ping|type][]mathml[A][]svg[A][]table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]caption[A][C]colgroup[A|span][col]col[A|span][]thead[A][tr]tfoot[A][tr]tbody[A][tr]tr[A][th|td]th[A|headers|rowspan|colspan|scope][B]td[A|headers|rowspan|colspan][C]")}return i}function c(){var i=a.html4;if(!i){i=a.html4=h({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]")}return i}f.html.Schema=function(A){var u=this,s={},k={},j=[],D,y;var o,q,z,r,v,n,p={};function m(F,E,H){var G=A[F];if(!G){G=a[F];if(!G){G=e(E," ",e(E.toUpperCase()," "));G=f.extend(G,H);a[F]=G}}else{G=e(G,",",e(G.toUpperCase()," "))}return G}A=A||{};y=A.schema=="html5"?b():c();if(A.verify_html===false){A.valid_elements="*[*]"}if(A.valid_styles){D={};g(A.valid_styles,function(F,E){D[E]=f.explode(F)})}o=m("whitespace_elements","pre script style textarea");q=m("self_closing_elements","colgroup dd dt li options p td tfoot th thead tr");z=m("short_ended_elements","area base basefont br col frame hr img input isindex link meta param embed source");r=m("boolean_attributes","checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls");n=m("non_empty_elements","td th iframe video audio object",z);v=m("block_elements","h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot th tr td li ol ul caption blockquote center dl dt dd dir fieldset noscript menu isindex samp header footer article section hgroup aside nav figure");function i(E){return new RegExp("^"+E.replace(/([?+*])/g,".$1")+"$")}function C(L){var K,G,Z,V,aa,F,I,U,X,Q,Y,ac,O,J,W,E,S,H,ab,ad,P,T,N=/^([#+\-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,R=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,M=/[*?+]/;if(L){L=d(L);if(s["@"]){S=s["@"].attributes;H=s["@"].attributesOrder}for(K=0,G=L.length;K=0){for(U=A.length-1;U>=V;U--){T=A[U];if(T.valid){n.end(T.name)}}A.length=V}}function p(U,T,Y,X,W){var Z,V;T=T.toLowerCase();Y=T in H?T:j(Y||X||W||"");if(v&&!z&&T.indexOf("data-")!==0){Z=P[T];if(!Z&&F){V=F.length;while(V--){Z=F[V];if(Z.pattern.test(T)){break}}if(V===-1){Z=null}}if(!Z){return}if(Z.validValues&&!(Y in Z.validValues)){return}}N.map[T]=Y;N.push({name:T,value:Y})}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*|\\/|\\s+)>))","g");D=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;K={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};M=e.getShortEndedElements();J=e.getSelfClosingElements();H=e.getBoolAttrs();v=c.validate;s=c.remove_internals;y=c.fix_self_closing;q=a.isIE;o=/^:/;while(g=l.exec(E)){if(G0&&A[A.length-1].name===I){u(I)}if(!v||(m=e.getElementRule(I))){k=true;if(v){P=m.attributes;F=m.attributePatterns}if(R=g[8]){z=R.indexOf("data-mce-type")!==-1;if(z&&s){k=false}N=[];N.map={};R.replace(D,p)}else{N=[];N.map={}}if(v&&!z){S=m.attributesRequired;L=m.attributesDefault;f=m.attributesForced;if(f){Q=f.length;while(Q--){t=f[Q];r=t.name;h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}if(L){Q=L.length;while(Q--){t=L[Q];r=t.name;if(!(r in N.map)){h=t.value;if(h==="{$uid}"){h="mce_"+x++}N.map[r]=h;N.push({name:r,value:h})}}}if(S){Q=S.length;while(Q--){if(S[Q] in N.map){break}}if(Q===-1){k=false}}if(N.map["data-mce-bogus"]){k=false}}if(k){n.start(I,N,O)}}else{k=false}if(B=K[I]){B.lastIndex=G=g.index+g[0].length;if(g=B.exec(E)){if(k){C=E.substr(G,g.index-G)}G=g.index+g[0].length}else{C=E.substr(G);G=E.length}if(k&&C.length>0){n.text(C,true)}if(k){n.end(I)}l.lastIndex=G;continue}if(!O){if(!R||R.indexOf("/")!=R.length-1){A.push({name:I,valid:k})}else{if(k){n.end(I)}}}}else{if(I=g[1]){n.comment(I)}else{if(I=g[2]){n.cdata(I)}else{if(I=g[3]){n.doctype(I)}else{if(I=g[4]){n.pi(I,g[5])}}}}}}G=g.index+g[0].length}if(G=0;Q--){I=A[Q];if(I.valid){n.end(I.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t0){P.value=l;P=P.prev}else{N=P.prev;P.remove();P=N}}}n=new b.html.SaxParser({validate:z,fix_self_closing:!z,cdata:function(l){B.append(J("#cdata",4)).value=l},text:function(O,l){var N;if(!K){O=O.replace(k," ");if(B.lastChild&&o[B.lastChild.name]){O=O.replace(E,"")}}if(O.length!==0){N=J("#text",3);N.raw=!!l;B.append(N).value=O}},comment:function(l){B.append(J("#comment",8)).value=l},pi:function(l,N){B.append(J(l,7)).value=N;H(B)},doctype:function(N){var l;l=B.append(J("#doctype",10));l.value=N;H(B)},start:function(l,V,O){var T,Q,P,N,R,W,U,S;P=z?h.getElementRule(l):{};if(P){T=J(P.outputName||l,1);T.attributes=V;T.shortEnded=O;B.append(T);S=p[B.name];if(S&&p[T.name]&&!S[T.name]){L.push(T)}Q=d.length;while(Q--){R=d[Q].name;if(R in V.map){F=c[R];if(F){F.push(T)}else{c[R]=[T]}}}if(o[l]){H(T)}if(!O){B=T}if(!K&&s[l]){K=true}}},end:function(l){var R,O,Q,N,P;O=z?h.getElementRule(l):{};if(O){if(o[l]){if(!K){R=B.firstChild;if(R&&R.type===3){Q=R.value.replace(E,"");if(Q.length>0){R.value=Q;R=R.next}else{N=R.next;R.remove();R=N}while(R&&R.type===3){Q=R.value;N=R.next;if(Q.length===0||y.test(Q)){R.remove();R=N}R=N}}R=B.lastChild;if(R&&R.type===3){Q=R.value.replace(t,"");if(Q.length>0){R.value=Q;R=R.prev}else{N=R.prev;R.remove();R=N}while(R&&R.type===3){Q=R.value;N=R.prev;if(Q.length===0||y.test(Q)){R.remove();R=N}R=N}}}R=B.prev;if(R&&R.type===3){Q=R.value.replace(E,"");if(Q.length>0){R.value=Q}else{R.remove()}}}if(K&&s[l]){K=false}if(O.removeEmpty||O.paddEmpty){if(B.isEmpty(u)){if(O.paddEmpty){B.empty().append(new a("#text","3")).value="\u00a0"}else{if(!B.attributes.map.name){P=B.parent;B.empty().remove();B=P;return}}}}B=B.parent}}},h);I=B=new a(m.context||g.root_name,11);n.parse(v);if(z&&L.length){if(!m.context){j(L)}else{m.invalid=true}}if(q&&I.name=="body"){G()}if(!m.invalid){for(M in i){F=e[M];A=i[M];x=A.length;while(x--){if(!A[x].parent){A.splice(x,1)}}for(D=0,C=F.length;D0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("")},comment:function(h){c.push("")},pi:function(h,i){if(i){c.push("")}else{c.push("")}if(a){c.push("\n")}},doctype:function(h){c.push("",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n=8;k.boxModel=!e.isIE||o.compatMode=="CSS1Compat"||k.stdMode;k.hasOuterHTML="outerHTML" in o.createElement("a");k.settings=l=e.extend({keep_values:false,hex_colors:1},l);k.schema=l.schema;k.styles=new e.html.Styles({url_converter:l.url_converter,url_converter_scope:l.url_converter_scope},l.schema);if(e.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(m){k.cssFlicker=true}}k.fixDoc(o);k.events=l.ownEvents?new e.dom.EventUtils(l.proxy):e.dom.Event;e.addUnload(k.destroy,k);n=l.schema?l.schema.getBlockElements():{};k.isBlock=function(q){var p=q.nodeType;if(p){return !!(p===1&&n[q.nodeName])}return !!n[q]}},fixDoc:function(k){var j=this.settings,i;if(b&&j.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(l){k.createElement(l)});for(i in j.schema.getCustomElements()){k.createElement(i)}}},clone:function(k,i){var j=this,m,l;if(!b||k.nodeType!==1||i){return k.cloneNode(i)}l=j.doc;if(!i){m=l.createElement(k.nodeName);g(j.getAttribs(k),function(n){j.setAttrib(m,n.nodeName,j.getAttrib(k,n.nodeName))});return m}return m.firstChild},getRoot:function(){var i=this,j=i.settings;return(j&&i.get(j.root_element))||i.doc.body},getViewPort:function(j){var k,i;j=!j?this.win:j;k=j.document;i=this.boxModel?k.documentElement:k.body;return{x:j.pageXOffset||i.scrollLeft,y:j.pageYOffset||i.scrollTop,w:j.innerWidth||i.clientWidth,h:j.innerHeight||i.clientHeight}},getRect:function(l){var k,i=this,j;l=i.get(l);k=i.getPos(l);j=i.getSize(l);return{x:k.x,y:k.y,w:j.w,h:j.h}},getSize:function(l){var j=this,i,k;l=j.get(l);i=j.getStyle(l,"width");k=j.getStyle(l,"height");if(i.indexOf("px")===-1){i=0}if(k.indexOf("px")===-1){k=0}return{w:parseInt(i,10)||l.offsetWidth||l.clientWidth,h:parseInt(k,10)||l.offsetHeight||l.clientHeight}},getParent:function(k,j,i){return this.getParents(k,j,i,false)},getParents:function(s,m,k,q){var j=this,i,l=j.settings,p=[];s=j.get(s);q=q===undefined;if(l.strict_root){k=k||j.getRoot()}if(d(m,"string")){i=m;if(m==="*"){m=function(o){return o.nodeType==1}}else{m=function(o){return j.is(o,i)}}}while(s){if(s==k||!s.nodeType||s.nodeType===9){break}if(!m||m(s)){if(q){p.push(s)}else{return s}}s=s.parentNode}return q?p:null},get:function(i){var j;if(i&&this.doc&&typeof(i)=="string"){j=i;i=this.doc.getElementById(i);if(i&&i.id!==j){return this.doc.getElementsByName(j)[1]}}return i},getNext:function(j,i){return this._findSib(j,i,"nextSibling")},getPrev:function(j,i){return this._findSib(j,i,"previousSibling")},select:function(k,j){var i=this;return e.dom.Sizzle(k,i.get(j)||i.get(i.settings.root_element)||i.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(c.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return e.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(l,o,i,k,m){var j=this;return this.run(l,function(r){var q,n;q=d(o,"string")?j.doc.createElement(o):o;j.setAttribs(q,i);if(k){if(k.nodeType){q.appendChild(k)}else{j.setHTML(q,k)}}return !m?r.appendChild(q):q})},create:function(k,i,j){return this.add(this.doc.createElement(k),k,i,j,1)},createHTML:function(q,i,m){var p="",l=this,j;p+="<"+q;for(j in i){if(i.hasOwnProperty(j)){p+=" "+j+'="'+l.encode(i[j])+'"'}}if(typeof(m)!="undefined"){return p+">"+m+""}return p+" />"},remove:function(i,j){return this.run(i,function(l){var m,k=l.parentNode;if(!k){return null}if(j){while(m=l.firstChild){if(!e.isIE||m.nodeType!==3||m.nodeValue){k.insertBefore(m,l)}else{l.removeChild(m)}}}return k.removeChild(l)})},setStyle:function(l,i,j){var k=this;return k.run(l,function(o){var n,m;n=o.style;i=i.replace(/-(\D)/g,function(q,p){return p.toUpperCase()});if(k.pixelStyles.test(i)&&(e.is(j,"number")||/^[\-0-9\.]+$/.test(j))){j+="px"}switch(i){case"opacity":if(b){n.filter=j===""?"":"alpha(opacity="+(j*100)+")";if(!l.currentStyle||!l.currentStyle.hasLayout){n.display="inline-block"}}n[i]=n["-moz-opacity"]=n["-khtml-opacity"]=j||"";break;case"float":b?n.styleFloat=j:n.cssFloat=j;break;default:n[i]=j||""}if(k.settings.update_styles){k.setAttrib(o,"data-mce-style")}})},getStyle:function(l,i,k){l=this.get(l);if(!l){return}if(this.doc.defaultView&&k){i=i.replace(/[A-Z]/g,function(m){return"-"+m});try{return this.doc.defaultView.getComputedStyle(l,null).getPropertyValue(i)}catch(j){return null}}i=i.replace(/-(\D)/g,function(n,m){return m.toUpperCase()});if(i=="float"){i=b?"styleFloat":"cssFloat"}if(l.currentStyle&&k){return l.currentStyle[i]}return l.style?l.style[i]:undefined},setStyles:function(l,m){var j=this,k=j.settings,i;i=k.update_styles;k.update_styles=0;g(m,function(o,p){j.setStyle(l,p,o)});k.update_styles=i;if(k.update_styles){j.setAttrib(l,k.cssText)}},removeAllAttribs:function(i){return this.run(i,function(l){var k,j=l.attributes;for(k=j.length-1;k>=0;k--){l.removeAttributeNode(j.item(k))}})},setAttrib:function(k,l,i){var j=this;if(!k||!l){return}if(j.settings.strict){l=l.toLowerCase()}return this.run(k,function(p){var o=j.settings;var m=p.getAttribute(l);if(i!==null){switch(l){case"style":if(!d(i,"string")){g(i,function(q,r){j.setStyle(p,r,q)});return}if(o.keep_values){if(i&&!j._isRes(i)){p.setAttribute("data-mce-style",i,2)}else{p.removeAttribute("data-mce-style",2)}}p.style.cssText=i;break;case"class":p.className=i||"";break;case"src":case"href":if(o.keep_values){if(o.url_converter){i=o.url_converter.call(o.url_converter_scope||j,i,l,p)}j.setAttrib(p,"data-mce-"+l,i,2)}break;case"shape":p.setAttribute("data-mce-style",i);break}}if(d(i)&&i!==null&&i.length!==0){p.setAttribute(l,""+i,2)}else{p.removeAttribute(l,2)}if(tinyMCE.activeEditor&&m!=i){var n=tinyMCE.activeEditor;n.onSetAttrib.dispatch(n,p,l,i)}})},setAttribs:function(j,k){var i=this;return this.run(j,function(l){g(k,function(m,o){i.setAttrib(l,o,m)})})},getAttrib:function(m,o,k){var i,j=this,l;m=j.get(m);if(!m||m.nodeType!==1){return k===l?false:k}if(!d(k)){k=""}if(/^(src|href|style|coords|shape)$/.test(o)){i=m.getAttribute("data-mce-"+o);if(i){return i}}if(b&&j.props[o]){i=m[j.props[o]];i=i&&i.nodeValue?i.nodeValue:i}if(!i){i=m.getAttribute(o,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(o)){if(m[j.props[o]]===true&&i===""){return o}return i?o:""}if(m.nodeName==="FORM"&&m.getAttributeNode(o)){return m.getAttributeNode(o).nodeValue}if(o==="style"){i=i||m.style.cssText;if(i){i=j.serializeStyle(j.parseStyle(i),m.nodeName);if(j.settings.keep_values&&!j._isRes(i)){m.setAttribute("data-mce-style",i)}}}if(f&&o==="class"&&i){i=i.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(o){case"rowspan":case"colspan":if(i===1){i=""}break;case"size":if(i==="+0"||i===20||i===0){i=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(i===0){i=""}break;case"hspace":if(i===-1){i=""}break;case"maxlength":case"tabindex":if(i===32768||i===2147483647||i==="32768"){i=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(i===65535){return o}return k;case"shape":i=i.toLowerCase();break;default:if(o.indexOf("on")===0&&i){i=e._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+i)}}}return(i!==l&&i!==null&&i!=="")?""+i:k},getPos:function(q,l){var j=this,i=0,p=0,m,o=j.doc,k;q=j.get(q);l=l||o.body;if(q){if(q.getBoundingClientRect){q=q.getBoundingClientRect();m=j.boxModel?o.documentElement:o.body;i=q.left+(o.documentElement.scrollLeft||o.body.scrollLeft)-m.clientTop;p=q.top+(o.documentElement.scrollTop||o.body.scrollTop)-m.clientLeft;return{x:i,y:p}}k=q;while(k&&k!=l&&k.nodeType){i+=k.offsetLeft||0;p+=k.offsetTop||0;k=k.offsetParent}k=q.parentNode;while(k&&k!=l&&k.nodeType){i-=k.scrollLeft||0;p-=k.scrollTop||0;k=k.parentNode}}return{x:i,y:p}},parseStyle:function(i){return this.styles.parse(i)},serializeStyle:function(j,i){return this.styles.serialize(j,i)},loadCSS:function(i){var k=this,l=k.doc,j;if(!i){i=""}j=l.getElementsByTagName("head")[0];g(i.split(","),function(m){var n;if(k.files[m]){return}k.files[m]=true;n=k.create("link",{rel:"stylesheet",href:e._addVer(m)});if(b&&l.documentMode&&l.recalc){n.onload=function(){if(l.recalc){l.recalc()}n.onload=null}}j.appendChild(n)})},addClass:function(i,j){return this.run(i,function(k){var l;if(!j){return 0}if(this.hasClass(k,j)){return k.className}l=this.removeClass(k,j);return k.className=(l!=""?(l+" "):"")+j})},removeClass:function(k,l){var i=this,j;return i.run(k,function(n){var m;if(i.hasClass(n,l)){if(!j){j=new RegExp("(^|\\s+)"+l+"(\\s+|$)","g")}m=n.className.replace(j," ");m=e.trim(m!=" "?m:"");n.className=m;if(!m){n.removeAttribute("class");n.removeAttribute("className")}return m}return n.className})},hasClass:function(j,i){j=this.get(j);if(!j||!i){return false}return(" "+j.className+" ").indexOf(" "+i+" ")!==-1},show:function(i){return this.setStyle(i,"display","block")},hide:function(i){return this.setStyle(i,"display","none")},isHidden:function(i){i=this.get(i);return !i||i.style.display=="none"||this.getStyle(i,"display")=="none"},uniqueId:function(i){return(!i?"mce_":i)+(this.counter++)},setHTML:function(k,j){var i=this;return i.run(k,function(m){if(b){while(m.firstChild){m.removeChild(m.firstChild)}try{m.innerHTML="
                          "+j;m.removeChild(m.firstChild)}catch(l){m=i.create("div");m.innerHTML="
                          "+j;g(m.childNodes,function(o,n){if(n){m.appendChild(o)}})}}else{m.innerHTML=j}return j})},getOuterHTML:function(k){var j,i=this;k=i.get(k);if(!k){return null}if(k.nodeType===1&&i.hasOuterHTML){return k.outerHTML}j=(k.ownerDocument||i.doc).createElement("body");j.appendChild(k.cloneNode(true));return j.innerHTML},setOuterHTML:function(l,j,m){var i=this;function k(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){i.insertAfter(s.cloneNode(true),p);s=s.previousSibling}i.remove(p)}return this.run(l,function(o){o=i.get(o);if(o.nodeType==1){m=m||o.ownerDocument||i.doc;if(b){try{if(b&&o.nodeType==1){o.outerHTML=j}else{k(o,j,m)}}catch(n){k(o,j,m)}}else{k(o,j,m)}}})},decode:h.decode,encode:h.encodeAllRaw,insertAfter:function(i,j){j=this.get(j);return this.run(i,function(l){var k,m;k=j.parentNode;m=j.nextSibling;if(m){k.insertBefore(l,m)}else{k.appendChild(l)}return l})},replace:function(m,l,i){var j=this;if(d(l,"array")){m=m.cloneNode(true)}return j.run(l,function(k){if(i){g(e.grep(k.childNodes),function(n){m.appendChild(n)})}return k.parentNode.replaceChild(m,k)})},rename:function(l,i){var k=this,j;if(l.nodeName!=i.toUpperCase()){j=k.create(i);g(k.getAttribs(l),function(m){k.setAttrib(j,m.nodeName,k.getAttrib(l,m.nodeName))});k.replace(j,l,1)}return j||l},findCommonAncestor:function(k,i){var l=k,j;while(l){j=i;while(j&&l!=j){j=j.parentNode}if(l==j){break}l=l.parentNode}if(!l&&k.ownerDocument){return k.ownerDocument.documentElement}return l},toHex:function(i){var k=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(i);function j(l){l=parseInt(l,10).toString(16);return l.length>1?l:"0"+l}if(k){i="#"+j(k[1])+j(k[2])+j(k[3]);return i}return i},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(i){g(i.imports,function(s){q(s)});g(i.cssRules||i.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){g(s.selectorText.split(","),function(r){r=r.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(r)||!/\.[\w\-]+$/.test(r)){return}l=r;r=e._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",r);if(p&&!(r=p(r,l))){return}if(!o[r]){j.push({"class":r});o[r]=1}})}break;case 3:q(s.styleSheet);break}})}try{g(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(l,k,j){var i=this,m;if(i.doc&&typeof(l)==="string"){l=i.get(l)}if(!l){return false}j=j||this;if(!l.nodeType&&(l.length||l.length===0)){m=[];g(l,function(o,n){if(o){if(typeof(o)=="string"){o=i.doc.getElementById(o)}m.push(k.call(j,o,n))}});return m}return k.call(j,l)},getAttribs:function(j){var i;j=this.get(j);if(!j){return[]}if(b){i=[];if(j.nodeName=="OBJECT"){return j.attributes}if(j.nodeName==="OPTION"&&this.getAttrib(j,"selected")){i.push({specified:1,nodeName:"selected"})}j.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(k){i.push({specified:1,nodeName:k})});return i}return j.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p=0;m=m.firstChild;if(m){j=new e.dom.TreeWalker(m,m.parentNode);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){if(l==="br"){p++;continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if(q==8){return false}if((q===3&&!a.test(m.nodeValue))){return false}}while(m=j.next())}return p<=1},destroy:function(j){var i=this;i.win=i.doc=i.root=i.events=i.frag=null;if(!j){e.removeUnload(i.destroy)}},createRng:function(){var i=this.doc;return i.createRange?i.createRange():new e.dom.Range(this)},nodeIndex:function(m,n){var i=0,k,l,j;if(m){for(k=m.nodeType,m=m.previousSibling,l=m;m;m=m.previousSibling){j=m.nodeType;if(n&&j==3){if(j==k||!m.nodeValue.length){continue}}i++;k=j}}return i},split:function(m,l,p){var q=this,i=q.createRng(),n,k,o;function j(v){var t,s=v.childNodes,u=v.nodeType;function x(A){var z=A.previousSibling&&A.previousSibling.nodeName=="SPAN";var y=A.nextSibling&&A.nextSibling.nodeName=="SPAN";return z&&y}if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=s.length-1;t>=0;t--){j(s[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){var r=e.trim(v.nodeValue).length;if(!q.isBlock(v.parentNode)||r>0||r===0&&x(v)){return}}else{if(u==1){s=v.childNodes;if(s.length==1&&s[0]&&s[0].nodeType==1&&s[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(s[0],v)}if(s.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}q.remove(v)}return v}if(m&&l){i.setStart(m.parentNode,q.nodeIndex(m));i.setEnd(l.parentNode,q.nodeIndex(l));n=i.extractContents();i=q.createRng();i.setStart(l.parentNode,q.nodeIndex(l)+1);i.setEnd(m.parentNode,q.nodeIndex(m)+1);k=i.extractContents();o=m.parentNode;o.insertBefore(j(n),m);if(p){o.replaceChild(p,l)}else{o.insertBefore(l,m)}o.insertBefore(j(k),m);q.remove(m);return p||l}},bind:function(l,i,k,j){return this.events.add(l,i,k,j||this)},unbind:function(k,i,j){return this.events.remove(k,i,j)},fire:function(k,j,i){return this.events.fire(k,j,i)},getContentEditable:function(j){var i;if(j.nodeType!=1){return null}i=j.getAttribute("data-mce-contenteditable");if(i&&i!=="inherit"){return i}return j.contentEditable!=="inherit"?j.contentEditable:null},_findSib:function(l,i,j){var k=this,m=i;if(l){if(d(m,"string")){m=function(n){return k.is(n,i)}}for(l=l[j];l;l=l[j]){if(m(l)){return l}}}return null},_isRes:function(i){return/^(top|left|bottom|right|width|height)/i.test(i)||/;\s*(top|left|bottom|right|width|height)/i.test(i)}});e.DOM=new e.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var O=this,e=c.doc,T=0,F=1,j=2,E=true,S=false,V="startOffset",h="startContainer",Q="endContainer",A="endOffset",k=tinymce.extend,n=c.nodeIndex;k(O,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:E,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:J,setEndBefore:K,setEndAfter:u,collapse:B,selectNode:y,selectNodeContents:G,compareBoundaryPoints:v,deleteContents:p,extractContents:I,cloneContents:d,insertNode:D,surroundContents:N,cloneRange:L});function x(){return e.createDocumentFragment()}function q(W,t){C(E,W,t)}function s(W,t){C(S,W,t)}function g(t){q(t.parentNode,n(t))}function J(t){q(t.parentNode,n(t)+1)}function K(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function B(t){if(t){O[Q]=O[h];O[A]=O[V]}else{O[h]=O[Q];O[V]=O[A]}O.collapsed=E}function y(t){g(t);u(t)}function G(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(Z,t){var ac=O[h],X=O[V],ab=O[Q],W=O[A],aa=t.startContainer,ae=t.startOffset,Y=t.endContainer,ad=t.endOffset;if(Z===0){return H(ac,X,aa,ae)}if(Z===1){return H(ab,W,aa,ae)}if(Z===2){return H(ab,W,Y,ad)}if(Z===3){return H(ac,X,Y,ad)}}function p(){l(j)}function I(){return l(T)}function d(){return l(F)}function D(Z){var W=this[h],t=this[V],Y,X;if((W.nodeType===3||W.nodeType===4)&&W.nodeValue){if(!t){W.parentNode.insertBefore(Z,W)}else{if(t>=W.nodeValue.length){c.insertAfter(Z,W)}else{Y=W.splitText(t);W.parentNode.insertBefore(Z,Y)}}}else{if(W.childNodes.length>0){X=W.childNodes[t]}if(X){W.insertBefore(Z,X)}else{W.appendChild(Z)}}}function N(W){var t=O.extractContents();O.insertNode(W);W.appendChild(t);O.selectNode(W)}function L(){return k(new b(c),{startContainer:O[h],startOffset:O[V],endContainer:O[Q],endOffset:O[A],collapsed:O.collapsed,commonAncestorContainer:O.commonAncestorContainer})}function P(t,W){var X;if(t.nodeType==3){return t}if(W<0){return t}X=t.firstChild;while(X&&W>0){--W;X=X.nextSibling}if(X){return X}return t}function m(){return(O[h]==O[Q]&&O[V]==O[A])}function H(Y,aa,W,Z){var ab,X,t,ac,ae,ad;if(Y==W){if(aa==Z){return 0}if(aa0){O.collapse(W)}}else{O.collapse(W)}O.collapsed=m();O.commonAncestorContainer=c.findCommonAncestor(O[h],O[Q])}function l(ac){var ab,Y=0,ae=0,W,aa,X,Z,t,ad;if(O[h]==O[Q]){return f(ac)}for(ab=O[Q],W=ab.parentNode;W;ab=W,W=W.parentNode){if(W==O[h]){return r(ab,ac)}++Y}for(ab=O[h],W=ab.parentNode;W;ab=W,W=W.parentNode){if(W==O[Q]){return U(ab,ac)}++ae}aa=ae-Y;X=O[h];while(aa>0){X=X.parentNode;aa--}Z=O[Q];while(aa<0){Z=Z.parentNode;aa++}for(t=X.parentNode,ad=Z.parentNode;t!=ad;t=t.parentNode,ad=ad.parentNode){X=t;Z=ad}return o(X,Z,ac)}function f(ab){var ad,ae,t,X,Y,ac,Z,W,aa;if(ab!=j){ad=x()}if(O[V]==O[A]){return ad}if(O[h].nodeType==3){ae=O[h].nodeValue;t=ae.substring(O[V],O[A]);if(ab!=F){X=O[h];W=O[V];aa=O[A]-O[V];if(W===0&&aa>=X.nodeValue.length-1){X.parentNode.removeChild(X)}else{X.deleteData(W,aa)}O.collapse(E)}if(ab==j){return}if(t.length>0){ad.appendChild(e.createTextNode(t))}return ad}X=P(O[h],O[V]);Y=O[A]-O[V];while(X&&Y>0){ac=X.nextSibling;Z=z(X,ab);if(ad){ad.appendChild(Z)}--Y;X=ac}if(ab!=F){O.collapse(E)}return ad}function r(ac,Z){var ab,aa,W,t,Y,X;if(Z!=j){ab=x()}aa=i(ac,Z);if(ab){ab.appendChild(aa)}W=n(ac);t=W-O[V];if(t<=0){if(Z!=F){O.setEndBefore(ac);O.collapse(S)}return ab}aa=ac.previousSibling;while(t>0){Y=aa.previousSibling;X=z(aa,Z);if(ab){ab.insertBefore(X,ab.firstChild)}--t;aa=Y}if(Z!=F){O.setEndBefore(ac);O.collapse(S)}return ab}function U(aa,Z){var ac,W,ab,t,Y,X;if(Z!=j){ac=x()}ab=R(aa,Z);if(ac){ac.appendChild(ab)}W=n(aa);++W;t=O[A]-W;ab=aa.nextSibling;while(ab&&t>0){Y=ab.nextSibling;X=z(ab,Z);if(ac){ac.appendChild(X)}--t;ab=Y}if(Z!=F){O.setStartAfter(aa);O.collapse(E)}return ac}function o(aa,t,ad){var X,af,Z,ab,ac,W,ae,Y;if(ad!=j){af=x()}X=R(aa,ad);if(af){af.appendChild(X)}Z=aa.parentNode;ab=n(aa);ac=n(t);++ab;W=ac-ab;ae=aa.nextSibling;while(W>0){Y=ae.nextSibling;X=z(ae,ad);if(af){af.appendChild(X)}ae=Y;--W}X=i(t,ad);if(af){af.appendChild(X)}if(ad!=F){O.setStartAfter(aa);O.collapse(E)}return af}function i(ab,ac){var X=P(O[Q],O[A]-1),ad,aa,Z,t,W,Y=X!=O[Q];if(X==ab){return M(X,Y,S,ac)}ad=X.parentNode;aa=M(ad,S,S,ac);while(ad){while(X){Z=X.previousSibling;t=M(X,Y,S,ac);if(ac!=j){aa.insertBefore(t,aa.firstChild)}Y=E;X=Z}if(ad==ab){return aa}X=ad.previousSibling;ad=ad.parentNode;W=M(ad,S,S,ac);if(ac!=j){W.appendChild(aa)}aa=W}}function R(ab,ac){var Y=P(O[h],O[V]),Z=Y!=O[h],ad,aa,X,t,W;if(Y==ab){return M(Y,Z,E,ac)}ad=Y.parentNode;aa=M(ad,S,E,ac);while(ad){while(Y){X=Y.nextSibling;t=M(Y,Z,E,ac);if(ac!=j){aa.appendChild(t)}Z=E;Y=X}if(ad==ab){return aa}Y=ad.nextSibling;ad=ad.parentNode;W=M(ad,S,E,ac);if(ac!=j){W.appendChild(aa)}aa=W}}function M(t,Z,ac,ad){var Y,X,aa,W,ab;if(Z){return z(t,ad)}if(t.nodeType==3){Y=t.nodeValue;if(ac){W=O[V];X=Y.substring(W);aa=Y.substring(0,W)}else{W=O[A];X=Y.substring(0,W);aa=Y.substring(W)}if(ad!=F){t.nodeValue=aa}if(ad==j){return}ab=c.clone(t,S);ab.nodeValue=X;return ab}if(ad==j){return}return c.clone(t,S)}function z(W,t){if(t!=j){return t==F?c.clone(W,E):W}W.parentNode.removeChild(W)}}a.Range=b})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",1)===0||s!=k.parentElement()){break}o++}}else{k.collapse(true);o=0;while(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)!==0){if(k.move("character",-1)===0||s!=k.parentElement()){break}o++}}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p&&t.nodeType!==9){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,s,q,r=d.dom.doc,m=r.body;function j(z){var u,y,t,x,v;t=h.create("a");u=z?k:s;y=z?p:q;x=n.duplicate();if(u==r||u==r.documentElement){u=m;y=0}if(u.nodeType==3){u.parentNode.insertBefore(t,u);x.moveToElementText(t);x.moveStart("character",y);h.remove(t);n.setEndPoint(z?"StartToStart":"EndToEnd",x)}else{v=u.childNodes;if(v.length){if(y>=v.length){h.insertAfter(t,v[v.length-1])}else{u.insertBefore(t,v[y])}x.moveToElementText(t)}else{if(u.canHaveHTML){u.innerHTML="\uFEFF";t=u.firstChild;x.moveToElementText(t);x.collapse(f)}}n.setEndPoint(z?"StartToStart":"EndToEnd",x);h.remove(t)}}k=i.startContainer;p=i.startOffset;s=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==s&&k.nodeType==1){if(p==q&&!k.hasChildNodes()){if(k.canHaveHTML){k.innerHTML="\uFEFF\uFEFF";n.moveToElementText(k.lastChild);n.select();h.doc.selection.clear();k.innerHTML="";return}else{p=h.nodeIndex(k);k=k.parentNode}}if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var n=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,i="sizcache",o=0,r=Object.prototype.toString,h=false,g=true,q=/\\/g,u=/\r\n/g,x=/\W/;[0,0].sort(function(){g=false;return 0});var d=function(C,e,F,G){F=F||[];e=e||document;var I=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!C||typeof C!=="string"){return F}var z,K,N,y,J,M,L,E,B=true,A=d.isXML(e),D=[],H=C;do{n.exec("");z=n.exec(H);if(z){H=z[3];D.push(z[1]);if(z[2]){y=z[3];break}}}while(z);if(D.length>1&&j.exec(C)){if(D.length===2&&k.relative[D[0]]){K=s(D[0]+D[1],e,G)}else{K=k.relative[D[0]]?[e]:d(D.shift(),e);while(D.length){C=D.shift();if(k.relative[C]){C+=D.shift()}K=s(C,K,G)}}}else{if(!G&&D.length>1&&e.nodeType===9&&!A&&k.match.ID.test(D[0])&&!k.match.ID.test(D[D.length-1])){J=d.find(D.shift(),e,A);e=J.expr?d.filter(J.expr,J.set)[0]:J.set[0]}if(e){J=G?{expr:D.pop(),set:l(G)}:d.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&e.parentNode?e.parentNode:e,A);K=J.expr?d.filter(J.expr,J.set):J.set;if(D.length>0){N=l(K)}else{B=false}while(D.length){M=D.pop();L=M;if(!k.relative[M]){M=""}else{L=D.pop()}if(L==null){L=e}k.relative[M](N,L,A)}}else{N=D=[]}}if(!N){N=K}if(!N){d.error(M||C)}if(r.call(N)==="[object Array]"){if(!B){F.push.apply(F,N)}else{if(e&&e.nodeType===1){for(E=0;N[E]!=null;E++){if(N[E]&&(N[E]===true||N[E].nodeType===1&&d.contains(e,N[E]))){F.push(K[E])}}}else{for(E=0;N[E]!=null;E++){if(N[E]&&N[E].nodeType===1){F.push(K[E])}}}}}else{l(N,F)}if(y){d(y,I,F,G);d.uniqueSort(F)}return F};d.uniqueSort=function(y){if(p){h=g;y.sort(p);if(h){for(var e=1;e0};d.find=function(E,e,F){var D,z,B,A,C,y;if(!E){return[]}for(z=0,B=k.order.length;z":function(D,y){var C,B=typeof y==="string",z=0,e=D.length;if(B&&!x.test(y)){y=y.toLowerCase();for(;z=0)){if(!z){e.push(C)}}else{if(z){y[B]=false}}}}return false},ID:function(e){return e[1].replace(q,"")},TAG:function(y,e){return y[1].replace(q,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){d.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var y=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(y[1]+(y[2]||1))-0;e[3]=y[3]-0}else{if(e[2]){d.error(e[0])}}e[0]=o++;return e},ATTR:function(B,y,z,e,C,D){var A=B[1]=B[1].replace(q,"");if(!D&&k.attrMap[A]){B[1]=k.attrMap[A]}B[4]=(B[4]||B[5]||"").replace(q,"");if(B[2]==="~="){B[4]=" "+B[4]+" "}return B},PSEUDO:function(B,y,z,e,C){if(B[1]==="not"){if((n.exec(B[3])||"").length>1||/^\w/.test(B[3])){B[3]=d(B[3],null,null,y)}else{var A=d.filter(B[3],y,z,true^C);if(!z){e.push.apply(e,A)}return false}}else{if(k.match.POS.test(B[0])||k.match.CHILD.test(B[0])){return true}}return B},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(z,y,e){return !!d(e[3],z).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(z){var e=z.getAttribute("type"),y=z.type;return z.nodeName.toLowerCase()==="input"&&"text"===y&&(e===y||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===y.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(y){var e=y.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===y.type},button:function(y){var e=y.nodeName.toLowerCase();return e==="input"&&"button"===y.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(y,e){return e===0},last:function(z,y,e,A){return y===A.length-1},even:function(y,e){return e%2===0},odd:function(y,e){return e%2===1},lt:function(z,y,e){return ye[3]-0},nth:function(z,y,e){return e[3]-0===y},eq:function(z,y,e){return e[3]-0===y}},filter:{PSEUDO:function(z,E,D,F){var e=E[1],y=k.filters[e];if(y){return y(z,D,E,F)}else{if(e==="contains"){return(z.textContent||z.innerText||b([z])||"").indexOf(E[3])>=0}else{if(e==="not"){var A=E[3];for(var C=0,B=A.length;C=0)}}},ID:function(y,e){return y.nodeType===1&&y.getAttribute("id")===e},TAG:function(y,e){return(e==="*"&&y.nodeType===1)||!!y.nodeName&&y.nodeName.toLowerCase()===e},CLASS:function(y,e){return(" "+(y.className||y.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(C,A){var z=A[1],e=d.attr?d.attr(C,z):k.attrHandle[z]?k.attrHandle[z](C):C[z]!=null?C[z]:C.getAttribute(z),D=e+"",B=A[2],y=A[4];return e==null?B==="!=":!B&&d.attr?e!=null:B==="="?D===y:B==="*="?D.indexOf(y)>=0:B==="~="?(" "+D+" ").indexOf(y)>=0:!y?D&&e!==false:B==="!="?D!==y:B==="^="?D.indexOf(y)===0:B==="$="?D.substr(D.length-y.length)===y:B==="|="?D===y||D.substr(0,y.length+1)===y+"-":false},POS:function(B,y,z,C){var e=y[2],A=k.setFilters[e];if(A){return A(B,z,y,C)}}}};var j=k.match.POS,c=function(y,e){return"\\"+(e-0+1)};for(var f in k.match){k.match[f]=new RegExp(k.match[f].source+(/(?![^\[]*\])(?![^\(]*\))/.source));k.leftMatch[f]=new RegExp(/(^(?:.|\r|\n)*?)/.source+k.match[f].source.replace(/\\(\d+)/g,c))}k.match.globalPOS=j;var l=function(y,e){y=Array.prototype.slice.call(y,0);if(e){e.push.apply(e,y);return e}return y};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(v){l=function(B,A){var z=0,y=A||[];if(r.call(B)==="[object Array]"){Array.prototype.push.apply(y,B)}else{if(typeof B.length==="number"){for(var e=B.length;z";e.insertBefore(y,e.firstChild);if(document.getElementById(z)){k.find.ID=function(B,C,D){if(typeof C.getElementById!=="undefined"&&!D){var A=C.getElementById(B[1]);return A?A.id===B[1]||typeof A.getAttributeNode!=="undefined"&&A.getAttributeNode("id").nodeValue===B[1]?[A]:undefined:[]}};k.filter.ID=function(C,A){var B=typeof C.getAttributeNode!=="undefined"&&C.getAttributeNode("id");return C.nodeType===1&&B&&B.nodeValue===A}}e.removeChild(y);e=y=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){k.find.TAG=function(y,C){var B=C.getElementsByTagName(y[1]);if(y[1]==="*"){var A=[];for(var z=0;B[z];z++){if(B[z].nodeType===1){A.push(B[z])}}B=A}return B}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){k.attrHandle.href=function(y){return y.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div"),z="__sizzle__";A.innerHTML="

                          ";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(L,C,G,K){C=C||document;if(!K&&!d.isXML(C)){var J=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(L);if(J&&(C.nodeType===1||C.nodeType===9)){if(J[1]){return l(C.getElementsByTagName(L),G)}else{if(J[2]&&k.find.CLASS&&C.getElementsByClassName){return l(C.getElementsByClassName(J[2]),G)}}}if(C.nodeType===9){if(L==="body"&&C.body){return l([C.body],G)}else{if(J&&J[3]){var F=C.getElementById(J[3]);if(F&&F.parentNode){if(F.id===J[3]){return l([F],G)}}else{return l([],G)}}}try{return l(C.querySelectorAll(L),G)}catch(H){}}else{if(C.nodeType===1&&C.nodeName.toLowerCase()!=="object"){var D=C,E=C.getAttribute("id"),B=E||z,N=C.parentNode,M=/^\s*[+~]/.test(L);if(!E){C.setAttribute("id",B)}else{B=B.replace(/'/g,"\\$&")}if(M&&N){C=C.parentNode}try{if(!M||N){return l(C.querySelectorAll("[id='"+B+"'] "+L),G)}}catch(I){}finally{if(!E){D.removeAttribute("id")}}}}}return e(L,C,G,K)};for(var y in e){d[y]=e[y]}A=null})()}(function(){var e=document.documentElement,z=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(z){var B=!z.call(document.createElement("div"),"div"),y=false;try{z.call(document.documentElement,"[test!='']:sizzle")}catch(A){y=true}d.matchesSelector=function(D,F){F=F.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!d.isXML(D)){try{if(y||!k.match.PSEUDO.test(F)&&!/!=/.test(F)){var C=z.call(D,F);if(C||!B||D.document&&D.document.nodeType!==11){return C}}}catch(E){}}return d(F,null,null,[D]).length>0}}})();(function(){var e=document.createElement("div");e.innerHTML="
                          ";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}k.order.splice(1,0,"CLASS");k.find.CLASS=function(y,z,A){if(typeof z.getElementsByClassName!=="undefined"&&!A){return z.getElementsByClassName(y[1])}};e=null})();function a(y,D,C,G,E,F){for(var A=0,z=G.length;A0){B=e;break}}}e=e[y]}G[A]=B}}}if(document.documentElement.contains){d.contains=function(y,e){return y!==e&&(y.contains?y.contains(e):true)}}else{if(document.documentElement.compareDocumentPosition){d.contains=function(y,e){return !!(y.compareDocumentPosition(e)&16)}}else{d.contains=function(){return false}}}d.isXML=function(e){var y=(e?e.ownerDocument||e:0).documentElement;return y?y.nodeName!=="HTML":false};var s=function(z,e,D){var C,E=[],B="",F=e.nodeType?[e]:e;while((C=k.match.PSEUDO.exec(z))){B+=C[0];z=z.replace(k.match.PSEUDO,"")}z=k.relative[z]?z+"*":z;for(var A=0,y=F.length;A"+(i.item?i.item(0).outerHTML:i.htmlText);m.removeChild(m.firstChild)}else{m.innerHTML=i.toString()}}if(/^\s/.test(m.innerHTML)){j=" "}if(/\s+$/.test(m.innerHTML)){l=" "}h.getInner=true;h.content=g.isCollapsed()?"":j+g.serializer.serialize(m,h)+l;g.onGetContent.dispatch(g,h);return h.content},setContent:function(h,j){var o=this,g=o.getRng(),k,l=o.win.document,n,m;j=j||{format:"html"};j.set=true;h=j.content=h;if(!j.no_events){o.onBeforeSetContent.dispatch(o,j)}h=j.content;if(g.insertNode){h+='_';if(g.startContainer==l&&g.endContainer==l){l.body.innerHTML=h}else{g.deleteContents();if(l.body.childNodes.length===0){l.body.innerHTML=h}else{if(g.createContextualFragment){g.insertNode(g.createContextualFragment(h))}else{n=l.createDocumentFragment();m=l.createElement("div");n.appendChild(m);m.outerHTML=h;g.insertNode(n)}}}k=o.dom.get("__caret");g=l.createRange();g.setStartBefore(k);g.setEndBefore(k);o.setRng(g);o.dom.remove("__caret");try{o.setRng(g)}catch(i){}}else{if(g.item){l.execCommand("Delete",false,null);g=o.getRng()}if(/^\s+/.test(h)){g.pasteHTML('_'+h);o.dom.remove("__mce_tmp")}else{g.pasteHTML(h)}}if(!j.no_events){o.onSetContent.dispatch(o,j)}},getStart:function(){var h=this.getRng(),i,g,k,j;if(h.duplicate||h.item){if(h.item){return h.item(0)}k=h.duplicate();k.collapse(1);i=k.parentElement();g=j=h.parentElement();while(j=j.parentNode){if(j==i){i=g;break}}return i}else{i=h.startContainer;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[Math.min(i.childNodes.length-1,h.startOffset)]}if(i&&i.nodeType==3){return i.parentNode}return i}},getEnd:function(){var h=this,i=h.getRng(),j,g;if(i.duplicate||i.item){if(i.item){return i.item(0)}i=i.duplicate();i.collapse(0);j=i.parentElement();if(j&&j.nodeName=="BODY"){return j.lastChild||j}return j}else{j=i.endContainer;g=i.endOffset;if(j.nodeType==1&&j.hasChildNodes()){j=j.childNodes[g>0?g-1:g]}if(j&&j.nodeType==3){return j.parentNode}return j}},getBookmark:function(s,v){var y=this,n=y.dom,h,k,j,o,i,p,q,m="\uFEFF",x;function g(z,A){var t=0;e(n.select(z),function(C,B){if(C==A){t=B}});return t}function u(t){function z(E){var A,D,C,B=E?"start":"end";A=t[B+"Container"];D=t[B+"Offset"];if(A.nodeType==1&&A.nodeName=="TR"){C=A.childNodes;A=C[Math.min(E?D:D-1,C.length-1)];if(A){D=E?0:A.childNodes.length;t["set"+(E?"Start":"End")](A,D)}}}z(true);z();return t}function l(){var z=y.getRng(true),t=n.getRoot(),A={};function B(E,J){var D=E[J?"startContainer":"endContainer"],I=E[J?"startOffset":"endOffset"],C=[],F,H,G=0;if(D.nodeType==3){if(v){for(F=D.previousSibling;F&&F.nodeType==3;F=F.previousSibling){I+=F.nodeValue.length}}C.push(I)}else{H=D.childNodes;if(I>=H.length&&H.length){G=1;I=Math.max(0,H.length-1)}C.push(y.dom.nodeIndex(H[I],v)+G)}for(;D&&D!=t;D=D.parentNode){C.push(y.dom.nodeIndex(D,v))}return C}A.start=B(z,true);if(!y.isCollapsed()){A.end=B(z)}return A}if(s==2){if(y.tridentSel){return y.tridentSel.getBookmark(s)}return l()}if(s){return{rng:y.getRng()}}h=y.getRng();j=n.uniqueId();o=tinyMCE.activeEditor.selection.isCollapsed();x="overflow:hidden;line-height:0px";if(h.duplicate||h.item){if(!h.item){k=h.duplicate();try{h.collapse();h.pasteHTML(''+m+"");if(!o){k.collapse(false);h.moveToElementText(k.parentElement());if(h.compareEndPoints("StartToEnd",k)===0){k.move("character",-1)}k.pasteHTML(''+m+"")}}catch(r){return null}}else{p=h.item(0);i=p.nodeName;return{name:i,index:g(i,p)}}}else{p=y.getNode();i=p.nodeName;if(i=="IMG"){return{name:i,index:g(i,p)}}k=u(h.cloneRange());if(!o){k.collapse(false);k.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_end",style:x},m))}h=u(h);h.collapse(true);h.insertNode(n.create("span",{"data-mce-type":"bookmark",id:j+"_start",style:x},m))}y.moveToBookmark({id:j,keep:1});return{id:j}},moveToBookmark:function(o){var s=this,m=s.dom,j,i,g,r,k,u,p,q;function h(A){var t=o[A?"start":"end"],x,y,z,v;if(t){z=t[0];for(y=r,x=t.length-1;x>=1;x--){v=y.childNodes;if(t[x]>v.length-1){return}y=v[t[x]]}if(y.nodeType===3){z=Math.min(t[0],y.nodeValue.length)}if(y.nodeType===1){z=Math.min(t[0],y.childNodes.length)}if(A){g.setStart(y,z)}else{g.setEnd(y,z)}}return true}function l(B){var v=m.get(o.id+"_"+B),A,t,y,z,x=o.keep;if(v){A=v.parentNode;if(B=="start"){if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}k=u=A;p=q=t}else{if(!x){t=m.nodeIndex(v)}else{A=v.firstChild;t=1}u=A;q=t}if(!x){z=v.previousSibling;y=v.nextSibling;e(d.grep(v.childNodes),function(C){if(C.nodeType==3){C.nodeValue=C.nodeValue.replace(/\uFEFF/g,"")}});while(v=m.get(o.id+"_"+B)){m.remove(v,1)}if(z&&y&&z.nodeType==y.nodeType&&z.nodeType==3&&!d.isOpera){t=z.nodeValue.length;z.appendData(y.nodeValue);m.remove(y);if(B=="start"){k=u=z;p=q=t}else{u=z;q=t}}}}}function n(t){if(m.isBlock(t)&&!t.innerHTML&&!b){t.innerHTML='
                          '}return t}if(o){if(o.start){g=m.createRng();r=m.getRoot();if(s.tridentSel){return s.tridentSel.moveToBookmark(o)}if(h(true)&&h()){s.setRng(g)}}else{if(o.id){l("start");l("end");if(k){g=m.createRng();g.setStart(n(k),p);g.setEnd(n(u),q);s.setRng(g)}}else{if(o.name){s.select(m.select(o.name)[o.index])}else{if(o.rng){s.setRng(o.rng)}}}}}},select:function(l,k){var j=this,m=j.dom,h=m.createRng(),g;function i(n,p){var o=new a(n,n);do{if(n.nodeType==3&&d.trim(n.nodeValue).length!==0){if(p){h.setStart(n,0)}else{h.setEnd(n,n.nodeValue.length)}return}if(n.nodeName=="BR"){if(p){h.setStartBefore(n)}else{h.setEndBefore(n)}return}}while(n=(p?o.next():o.prev()))}if(l){g=m.nodeIndex(l);h.setStart(l.parentNode,g);h.setEnd(l.parentNode,g+1);if(k){i(l,1);i(l)}j.setRng(h)}return l},isCollapsed:function(){var g=this,i=g.getRng(),h=g.getSel();if(!i||i.item){return false}if(i.compareEndPoints){return i.compareEndPoints("StartToEnd",i)===0}return !h||i.collapsed},collapse:function(g){var i=this,h=i.getRng(),j;if(h.item){j=h.item(0);h=i.win.document.body.createTextRange();h.moveToElementText(j)}h.collapse(!!g);i.setRng(h)},getSel:function(){var h=this,g=this.win;return g.getSelection?g.getSelection():g.document.selection},getRng:function(m){var h=this,j,g,l,k=h.win.document;if(m&&h.tridentSel){return h.tridentSel.getRangeAt(0)}try{if(j=h.getSel()){g=j.rangeCount>0?j.getRangeAt(0):(j.createRange?j.createRange():k.createRange())}}catch(i){}if(d.isIE&&g&&g.setStart&&k.selection.createRange().item){l=k.selection.createRange().item(0);g=k.createRange();g.setStartBefore(l);g.setEndAfter(l)}if(!g){g=k.createRange?k.createRange():k.body.createTextRange()}if(g.setStart&&g.startContainer.nodeType===9&&g.collapsed){l=h.dom.getRoot();g.setStart(l,0);g.setEnd(l,0)}if(h.selectedRange&&h.explicitRange){if(g.compareBoundaryPoints(g.START_TO_START,h.selectedRange)===0&&g.compareBoundaryPoints(g.END_TO_END,h.selectedRange)===0){g=h.explicitRange}else{h.selectedRange=null;h.explicitRange=null}}return g},setRng:function(k,g){var j,i=this;if(!i.tridentSel){j=i.getSel();if(j){i.explicitRange=k;try{j.removeAllRanges()}catch(h){}j.addRange(k);if(g===false&&j.extend){j.collapse(k.endContainer,k.endOffset);j.extend(k.startContainer,k.startOffset)}i.selectedRange=j.rangeCount>0?j.getRangeAt(0):null}}else{if(k.cloneRange){try{i.tridentSel.addRange(k);return}catch(h){}}try{k.select()}catch(h){}}},setNode:function(h){var g=this;g.setContent(g.dom.getOuterHTML(h));return h},getNode:function(){var i=this,h=i.getRng(),j=i.getSel(),m,l=h.startContainer,g=h.endContainer;function k(q,o){var p=q;while(q&&q.nodeType===3&&q.length===0){q=o?q.nextSibling:q.previousSibling}return q||p}if(!h){return i.dom.getRoot()}if(h.setStart){m=h.commonAncestorContainer;if(!h.collapsed){if(h.startContainer==h.endContainer){if(h.endOffset-h.startOffset<2){if(h.startContainer.hasChildNodes()){m=h.startContainer.childNodes[h.startOffset]}}}if(l.nodeType===3&&g.nodeType===3){if(l.length===h.startOffset){l=k(l.nextSibling,true)}else{l=l.parentNode}if(h.endOffset===0){g=k(g.previousSibling,false)}else{g=g.parentNode}if(l&&l===g){return l}}}if(m&&m.nodeType==3){return m.parentNode}return m}return h.item?h.item(0):h.parentElement()},getSelectedBlocks:function(p,h){var o=this,k=o.dom,m,l,i,j=[];m=k.getParent(p||o.getStart(),k.isBlock);l=k.getParent(h||o.getEnd(),k.isBlock);if(m){j.push(m)}if(m&&l&&m!=l){i=m;var g=new a(m,k.getRoot());while((i=g.next())&&i!=l){if(k.isBlock(i)){j.push(i)}}}if(l&&m!=l){j.push(l)}return j},isForward:function(){var i=this.dom,g=this.getSel(),j,h;if(!g||g.anchorNode==null||g.focusNode==null){return true}j=i.createRng();j.setStart(g.anchorNode,g.anchorOffset);j.collapse(true);h=i.createRng();h.setStart(g.focusNode,g.focusOffset);h.collapse(true);return j.compareBoundaryPoints(j.START_TO_START,h)<=0},normalize:function(){var h=this,g,m,l,j,i;function k(p){var o,r,n,s=h.dom,u=s.getRoot(),q,t,v;function y(z,A){var B=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(z=B[A?"prev":"next"]()){if(z.nodeName==="BR"){return true}}}function x(B,z){var C,A;z=z||o;C=new a(z,s.getParent(z.parentNode,s.isBlock)||u);while(q=C[B?"prev":"next"]()){if(q.nodeType===3&&q.nodeValue.length>0){o=q;r=B?q.nodeValue.length:0;m=true;return}if(s.isBlock(q)||t[q.nodeName.toLowerCase()]){return}A=q}if(l&&A){o=A;m=true;r=0}}o=g[(p?"start":"end")+"Container"];r=g[(p?"start":"end")+"Offset"];t=s.schema.getNonEmptyElements();if(o.nodeType===9){o=s.getRoot();r=0}if(o===u){if(p){q=o.childNodes[r>0?r-1:0];if(q){v=q.nodeName.toLowerCase();if(t[q.nodeName]||q.nodeName=="TABLE"){return}}}if(o.hasChildNodes()){o=o.childNodes[Math.min(!p&&r>0?r-1:r,o.childNodes.length-1)];r=0;if(o.hasChildNodes()&&!/TABLE/.test(o.nodeName)){q=o;n=new a(o,u);do{if(q.nodeType===3&&q.nodeValue.length>0){r=p?0:q.nodeValue.length;o=q;m=true;break}if(t[q.nodeName.toLowerCase()]){r=s.nodeIndex(q);o=q.parentNode;if(q.nodeName=="IMG"&&!p){r++}m=true;break}}while(q=(p?n.next():n.prev()))}}}if(l){if(o.nodeType===3&&r===0){x(true)}if(o.nodeType===1){q=o.childNodes[r];if(q&&q.nodeName==="BR"&&!y(q)&&!y(q,true)){x(true,o.childNodes[r])}}}if(p&&!l&&o.nodeType===3&&r===o.nodeValue.length){x(false)}if(m){g["set"+(p?"Start":"End")](o,r)}}if(d.isIE){return}g=h.getRng();l=g.collapsed;k(true);if(!l){k()}if(m){if(l){g.collapse(true)}h.setRng(g,h.isForward())}},destroy:function(h){var g=this;g.win=null;if(!h){d.removeUnload(g.destroy)}},_fixIESelection:function(){var h=this.dom,n=h.doc,i=n.body,k,o,g;function j(p,s){var q=i.createTextRange();try{q.moveToPoint(p,s)}catch(r){q=null}return q}function m(q){var p;if(q.button){p=j(q.x,q.y);if(p){if(p.compareEndPoints("StartToStart",o)>0){p.setEndPoint("StartToStart",o)}else{p.setEndPoint("EndToEnd",o)}p.select()}}else{l()}}function l(){var p=n.selection.createRange();if(o&&!p.item&&p.compareEndPoints("StartToEnd",p)===0){o.select()}h.unbind(n,"mouseup",l);h.unbind(n,"mousemove",m);o=k=0}n.documentElement.unselectable=true;h.bind(n,["mousedown","contextmenu"],function(p){if(p.target.nodeName==="HTML"){if(k){l()}g=n.documentElement;if(g.scrollHeight>g.clientHeight){return}k=1;o=j(p.x,p.y);if(o){h.bind(n,"mouseup",l);h.bind(n,"mousemove",m);h.win.focus();o.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";e.remove_trailing_brs="remove_trailing_brs" in e?e.remove_trailing_brs:true;h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/(?:^|\s)mce(Item\w+|Selected)(?!\S)/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addAttributeFilter("data-mce-expando",function(j,l,k){var m=j.length;while(m--){j[m].attr(l,null)}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/()/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(()?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// "}}else{if(o.length>0){n.firstChild.value=""}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(a.trim(m.getInner?o.innerHTML:i.getOuterHTML(o)),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF|\u200B/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],e={},d=[],g=0,f;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=q.create("script",{id:n,type:"text/javascript",src:a._addVer(m)});if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==f){j.push(m);l[m]=c}if(q){if(!e[m]){e[m]=[]}e[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(e[r],function(s){s.func.call(s.scope)});e[r]=f}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,s){var i=d.startContainer,l=d.startOffset,t=d.endContainer,m=d.endOffset,j,g,o,h,r,q,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(u){s([u])});return}function f(u){var v;v=u[0];if(v.nodeType===3&&v===i&&l>=v.nodeValue.length){u.splice(0,1)}v=u[u.length-1];if(m===0&&u.length>0&&v===t&&v.nodeType===3){u.splice(u.length-1,1)}return u}function p(x,v,u){var y=[];for(;x&&x!=u;x=x[v]){y.push(x)}return y}function n(v,u){do{if(v.parentNode==u){return v}v=v.parentNode}while(v)}function k(x,v,y){var u=y?"nextSibling":"previousSibling";for(h=x,r=h.parentNode;h&&h!=v;h=r){r=h.parentNode;q=p(h==x?h:h[u],u);if(q.length){if(!y){q.reverse()}s(f(q))}}}if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[l]}if(t.nodeType==1&&t.hasChildNodes()){t=t.childNodes[Math.min(m-1,t.childNodes.length-1)]}if(i==t){return s(f([i]))}j=c.findCommonAncestor(i,t);for(h=i;h;h=h.parentNode){if(h===t){return k(i,j,true)}if(h===j){break}}for(h=t;h;h=h.parentNode){if(h===i){return k(t,j)}if(h===j){break}}g=n(i,j)||i;o=n(t,j)||t;k(i,g,true);q=p(g==i?g:g.nextSibling,"nextSibling",o==t?o.nextSibling:o);if(q.length){s(f(q))}k(t,o)};this.split=function(e){var h=e.startContainer,d=e.startOffset,i=e.endContainer,g=e.endOffset;function f(j,k){return j.splitText(k)}if(h==i&&h.nodeType==3){if(d>0&&dd){g=g-d;h=i=f(i,g).previousSibling;g=i.nodeValue.length;d=0}else{g=0}}}else{if(h.nodeType==3&&d>0&&d0&&g=l.length){q=0}}s=l[q];f.setAttrib(g,"tabindex","-1");f.setAttrib(s.id,"tabindex","0");f.get(s.id).focus();if(e.actOnFocus){e.onAction(s.id)}if(r){a.cancel(r)}};o=function(y){var u=37,t=39,x=38,z=40,q=27,s=14,r=13,v=32;switch(y.keyCode){case u:if(i){p.moveFocus(-1)}break;case t:if(i){p.moveFocus(1)}break;case x:if(n){p.moveFocus(-1)}break;case z:if(n){p.moveFocus(1)}break;case q:if(e.onCancel){e.onCancel();a.cancel(y)}break;case s:case r:case v:if(e.onAction){e.onAction(g);a.cancel(y)}break}};c(l,function(s,q){var r;if(!s.id){s.id=f.uniqueId("_mce_item_")}if(k){f.bind(s.id,"blur",h);r="-1"}else{r=(q===0?"0":"-1")}f.setAttrib(s.id,"tabindex",r);f.bind(f.get(s.id),"focus",j)});if(l[0]){g=l[0].id}f.setAttrib(m,"tabindex","-1");f.bind(f.get(m),"focus",d);f.bind(f.get(m),"keydown",o)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.offsetWidth,j.max_width):g.offsetWidth;k=j.max_height?Math.min(g.offsetHeight,j.max_height):g.offsetHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeightv){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return false}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.get("menu_"+g.id);h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){if(typeof h.settings.style=="function"){h.settings.style=h.settings.style()}c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+=''+a.encode(e.title)+''+c}else{d+=''+(c?''+c+"":"")}d+='";d+="";return d},postRender:function(){var d=this,e=d.settings,c;if(b.isIE&&d.editor){b.dom.Event.add(d.id,"mousedown",function(f){var g=d.editor.selection.getNode().nodeName;c=g==="IMG"?d.editor.selection.getBookmark():null})}b.dom.Event.add(d.id,"click",function(f){if(!d.isDisabled()){if(b.isIE&&d.editor&&c!==null){d.editor.selection.moveToBookmark(c)}return e.onclick.call(e.scope,f)}});b.dom.Event.add(d.id,"keyup",function(f){if(!d.isDisabled()&&f.keyCode==b.VK.SPACEBAR){return e.onclick.call(e.scope,f)}})}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(j,i,g){var h=this;h.parent(j,i,g);h.items=[];h.onChange=new a(h);h.onPostRender=new a(h);h.onAdd=new a(h);h.onRenderMenu=new e.util.Dispatcher(this);h.classPrefix="mceListBox";h.marked={}},select:function(h){var g=this,j,i;g.marked={};if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){var i=this,j,k,h;i.marked={};if(g!=i.selectedIndex){j=d.get(i.id+"_text");h=d.get(i.id+"_voiceDesc");k=i.items[g];if(k){i.selectedValue=k.value;i.selectedIndex=g;d.setHTML(j,d.encode(k.title));d.setHTML(h,i.settings.title+" - "+k.title);d.removeClass(j,"mceTitle");d.setAttrib(i.id,"aria-valuenow",k.title)}else{d.setHTML(j,d.encode(i.settings.title));d.setHTML(h,d.encode(i.settings.title));d.addClass(j,"mceTitle");i.selectedValue=i.selectedIndex=null;d.setAttrib(i.id,"aria-valuenow",i.settings.title)}j=0}},mark:function(g){this.marked[g]=true},add:function(j,g,i){var h=this;i=i||{};i=e.extend(i,{title:j,value:g});h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var j="",g=this,i=g.settings,k=g.classPrefix;j='';j+="";j+="";j+="";return j},showMenu:function(){var h=this,j,i=d.get(this.id),g;if(h.isDisabled()||h.items.length===0){return}if(h.menu&&h.menu.isMenuVisible){return h.hideMenu()}if(!h.isMenuRendered){h.renderMenu();h.isMenuRendered=true}j=d.getPos(i);g=h.menu;g.settings.offset_x=j.x;g.settings.offset_y=j.y;g.settings.keyboard_focus=!e.isOpera;f(h.items,function(k){if(g.items[k.id]){g.items[k.id].setSelected(0)}});f(h.items,function(k){if(g.items[k.id]&&h.marked[k.value]){g.items[k.id].setSelected(1)}if(k.value===h.selectedValue){g.items[k.id].setSelected(1)}});g.showMenu(0,i.clientHeight);b.add(d.doc,"mousedown",h.hideMenu,h);d.addClass(h.id,h.classPrefix+"Selected")},hideMenu:function(h){var g=this;if(g.menu&&g.menu.isMenuVisible){d.removeClass(g.id,g.classPrefix+"Selected");if(h&&h.type=="mousedown"&&(h.target.id==g.id+"_text"||h.target.id==g.id+"_open")){return}if(!h||!d.getParent(h.target,".mceMenu")){d.removeClass(g.id,g.classPrefix+"Selected");b.remove(d.doc,"mousedown",g.hideMenu,g);g.menu.hideMenu()}}},renderMenu:function(){var h=this,g;g=h.settings.control_manager.createDropMenu(h.id+"_menu",{menu_line:1,"class":h.classPrefix+"Menu mceNoIcons",max_width:250,max_height:150});g.onHideMenu.add(function(){h.hideMenu();h.focus()});g.add({title:h.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}});f(h.items,function(i){if(i.value===c){g.add({title:i.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(h.settings.onselect("")!==false){h.select("")}}})}else{i.id=d.uniqueId();i.role="option";i.onclick=function(){if(h.settings.onselect(i.value)!==false){h.select(i.value)}};g.add(i)}});h.onRenderMenu.dispatch(h,g);h.menu=g},postRender:function(){var g=this,h=g.classPrefix;b.add(g.id,"click",g.showMenu,g);b.add(g.id,"keydown",function(i){if(i.keyCode==32){g.showMenu(i);b.cancel(i)}});b.add(g.id,"focus",function(){if(!g._focused){g.keyDownHandler=b.add(g.id,"keydown",function(i){if(i.keyCode==40){g.showMenu();b.cancel(i)}});g.keyPressHandler=b.add(g.id,"keypress",function(j){var i;if(j.keyCode==13){i=g.selectedValue;g.selectedValue=null;b.cancel(j);g.settings.onselect(i)}})}g._focused=1});b.add(g.id,"blur",function(){b.remove(g.id,"keydown",g.keyDownHandler);b.remove(g.id,"keypress",g.keyPressHandler);g._focused=0});if(e.isIE6||!d.boxModel){b.add(g.id,"mouseover",function(){if(!d.hasClass(g.id,h+"Disabled")){d.addClass(g.id,h+"Hover")}});b.add(g.id,"mouseout",function(){if(!d.hasClass(g.id,h+"Disabled")){d.removeClass(g.id,h+"Hover")}})}g.onPostRender.dispatch(g,d.get(g.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(e){var d=e.DOM,b=e.dom.Event,f=e.each,a=e.util.Dispatcher,c;e.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(h,g){this.parent(h,g);this.classPrefix="mceNativeListBox"},setDisabled:function(g){d.get(this.id).disabled=g;this.setAriaProperty("disabled",g)},isDisabled:function(){return d.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==c){return g.selectByIndex(-1)}if(h&&typeof(h)=="function"){i=h}else{i=function(k){return k==h}}if(h!=g.selectedValue){f(g.items,function(l,k){if(i(l.value)){j=1;g.selectByIndex(k);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(g){d.get(this.id).selectedIndex=g+1;this.selectedValue=this.items[g]?this.items[g].value:null},add:function(k,h,g){var j,i=this;g=g||{};g.value=h;if(i.isRendered()){d.add(d.get(this.id),"option",g,k)}j={title:k,value:h,attribs:g};i.items.push(j);i.onAdd.dispatch(i,j)},getLength:function(){return this.items.length},renderHTML:function(){var i,g=this;i=d.createHTML("option",{value:""},"-- "+g.settings.title+" --");f(g.items,function(h){i+=d.createHTML("option",{value:h.value},h.title)});i=d.createHTML("select",{id:g.id,"class":"mceNativeListBox","aria-labelledby":g.id+"_aria"},i);i+=d.createHTML("span",{id:g.id+"_aria",style:"display: none"},g.settings.title);return i},postRender:function(){var h=this,i,j=true;h.rendered=true;function g(l){var k=h.items[l.target.selectedIndex-1];if(k&&(k=k.value)){h.onChange.dispatch(h,k);if(h.settings.onselect){h.settings.onselect(k)}}}b.add(h.id,"change",g);b.add(h.id,"keydown",function(l){var k;b.remove(h.id,"change",i);j=false;k=b.add(h.id,"blur",function(){if(j){return}j=true;b.add(h.id,"change",g);b.remove(h.id,"blur",k)});if(e.isWebKit&&(l.keyCode==37||l.keyCode==39)){return b.prevent(l)}if(l.keyCode==13||l.keyCode==32){g(l);return b.cancel(l)}});h.onPostRender.dispatch(h,d.get(h.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.firstChild.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+=""+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'');i+=""+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"";i+="";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.firstChild.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(m){m=m.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");var i={href:"javascript:;",style:{backgroundColor:"#"+m},title:p.editor.getLang("colors."+m,m),"data-mce-color":"#"+m};if(!d.isIE){i.role="option"}g=c.add(g,"a",i);if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+m;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return false});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('
                          ');i.push("");i.push('");j(e,function(h){i.push(h.renderHTML())});i.push("");i.push("
                          ");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,""))}}if(c.stdMode){f+=''+k.renderHTML()+""}else{f+=""+k.renderHTML()+""}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,""))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,""));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},""+f+"")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){return;var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!==0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(x){var v=this,o,n=j.ScriptLoader,u,l=[],r;function q(t){var s=t.id;if(!s){s=t.name;if(s&&!k.get(s)){s=t.name}else{s=k.uniqueId()}t.setAttribute("id",s)}return s}function m(z,A,t){var y=z[A];if(!y){return}if(j.is(y,"string")){t=y.replace(/\.\w+$/,"");t=t?j.resolve(t):0;y=j.resolve(y)}return y.apply(t||this,Array.prototype.slice.call(arguments,2))}function p(t,s){return s.constructor===RegExp?s.test(t.className):k.hasClass(t,s)}x=d({theme:"simple",language:"en"},x);v.settings=x;i.bind(window,"ready",function(){var s,t;m(x,"onpageload");switch(x.mode){case"exact":s=x.elements||"";if(s.length>0){g(e(s),function(y){if(k.get(y)){r=new j.Editor(y,x);l.push(r);r.render(1)}else{g(document.forms,function(z){g(z.elements,function(A){if(A.name===y){y="mce_editor_"+c++;k.setAttrib(A,"id",y);r=new j.Editor(y,x);l.push(r);r.render(1)}})})}})}break;case"textareas":case"specific_textareas":g(k.select("textarea"),function(y){if(x.editor_deselector&&p(y,x.editor_deselector)){return}if(!x.editor_selector||p(y,x.editor_selector)){r=new j.Editor(q(y),x);l.push(r);r.render(1)}});break;default:if(x.types){g(x.types,function(y){g(k.select(y.selector),function(A){var z=new j.Editor(q(A),j.extend({},x,y));l.push(z);z.render(1)})})}else{if(x.selector){g(k.select(x.selector),function(z){var y=new j.Editor(q(z),x);l.push(y);y.render(1)})}}}if(x.oninit){s=t=0;g(l,function(y){t++;if(!y.initialized){y.onInit.add(function(){s++;if(s==t){m(x,"oninit")}})}else{s++}if(s==t){m(x,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l':"",visual:n,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",apply_source_formatting:n,directionality:"ltr",forced_root_block:"p",hidden_input:n,padd_empty_editor:n,render_ui:n,indentation:"30px",fix_table_elements:n,inline_styles:n,convert_fonts_to_spans:n,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure",validate:n,entity_encoding:"named",url_converter:m.convertURL,url_converter_scope:m,ie7_compat:n},o);m.id=m.editorId=p;m.isNotDirty=false;m.plugins={};m.documentBaseURI=new k.util.URI(o.document_base_url||k.documentBaseURL,{base_uri:tinyMCE.baseURI});m.baseURI=k.baseURI;m.contentCSS=[];m.setupEvents();m.execCommands={};m.queryStateCommands={};m.queryValueCommands={};m.execCallback("setup",m)},render:function(o){var p=this,q=p.settings,r=p.id,m=k.ScriptLoader;if(!j.domLoaded){j.add(window,"ready",function(){p.render()});return}tinyMCE.settings=q;if(!p.getElement()){return}if(k.isIDevice&&!k.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(p.getElement().nodeName)&&q.hidden_input&&l.getParent(r,"form")){l.insertAfter(l.create("input",{type:"hidden",name:r}),r)}if(k.WindowManager){p.windowManager=new k.WindowManager(p)}if(q.encoding=="xml"){p.onGetContent.add(function(s,t){if(t.save){t.content=l.encode(t.content)}})}if(q.add_form_submit_trigger){p.onSubmit.addToTop(function(){if(p.initialized){p.save();p.isNotDirty=1}})}if(q.add_unload_trigger){p._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(p.initialized&&!p.destroyed&&!p.isHidden()){p.save({format:"raw",no_events:true})}})}k.addUnload(p.destroy,p);if(q.submit_patch){p.onBeforeRenderUI.add(function(){var s=p.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){p.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){k.triggerSave();p.isNotDirty=1;return p.formElement._mceOldSubmit(p.formElement)}}s=null})}function n(){if(q.language&&q.language_load!==false){m.add(k.baseURL+"/../../extra/strings.php?elanguage="+q.language+"ðeme="+q.theme)}if(q.theme&&q.theme.charAt(0)!="-"&&!h.urls[q.theme]){h.load(q.theme,"themes/"+q.theme+"/editor_template"+k.suffix+".js")}i(g(q.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(v){var u={prefix:"plugins/",resource:v,suffix:"/editor_plugin"+k.suffix+".js"};v=c.createUrl(u,v);c.load(v.resource,v)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+k.suffix+".js"})}}});m.loadQueue(function(){if(!p.removed){p.init()}})}n()},init:function(){var q,F=this,G=F.settings,C,y,B=F.getElement(),p,m,D,v,A,E,x,r=[];k.add(F);G.aria_label=G.aria_label||l.getAttrib(B,"aria-label",F.getLang("aria.rich_text_area"));if(G.theme){G.theme=G.theme.replace(/-/,"");p=h.get(G.theme);F.theme=new p();if(F.theme.init){F.theme.init(F,h.urls[G.theme]||k.documentBaseURL.replace(/\/$/,""))}}function z(s){var t=c.get(s),o=c.urls[s]||k.documentBaseURL.replace(/\/$/,""),n;if(t&&k.inArray(r,s)===-1){i(c.dependencies(s),function(u){z(u)});n=new t(F,o);F.plugins[s]=n;if(n.init){n.init(F,o);r.push(s)}}}i(g(G.plugins.replace(/\-/g,"")),z);if(G.popup_css!==false){if(G.popup_css){G.popup_css=F.documentBaseURI.toAbsolute(G.popup_css)}else{G.popup_css=F.baseURI.toAbsolute("themes/"+G.theme+"/skins/"+G.skin+"/dialog.css")}}if(G.popup_css_add){G.popup_css+=","+F.documentBaseURI.toAbsolute(G.popup_css_add)}F.controlManager=new k.ControlManager(F);F.onExecCommand.add(function(n,o){if(!/^(FontName|FontSize)$/.test(o)){F.nodeChanged()}});F.onBeforeRenderUI.dispatch(F,F.controlManager);if(G.render_ui&&F.theme){C=G.width||B.style.width||B.offsetWidth;y=G.height||B.style.height||B.offsetHeight;F.orgDisplay=B.style.display;E=/^[0-9\.]+(|px)$/i;if(E.test(""+C)){C=Math.max(parseInt(C,10)+(p.deltaWidth||0),100)}if(E.test(""+y)){y=Math.max(parseInt(y)+(p.deltaHeight||0),G.theme_advanced_resizing_min_height||100)}p=F.theme.renderUI({targetNode:B,width:C,height:y,deltaWidth:G.delta_width,deltaHeight:G.delta_height});F.editorContainer=p.editorContainer}if(G.content_css){i(g(G.content_css),function(n){F.contentCSS.push(F.documentBaseURI.toAbsolute(n))})}if(G.content_editable){B=q=p=null;return F.initContentBody()}if(document.domain&&location.hostname!=document.domain){k.relaxedDomain=document.domain}l.setStyles(p.sizeContainer||p.editorContainer,{width:C,height:y});y=(p.iframeHeight||y)+(typeof(y)=="number"?(p.deltaHeight||0):"");if(y<(G.theme_advanced_resizing_min_height||100)){y=G.theme_advanced_resizing_min_height||100}F.iframeHTML=G.doctype+'';if(G.document_base_url!=k.documentBaseURL){F.iframeHTML+=''}if(G.ie7_compat){F.iframeHTML+=''}else{F.iframeHTML+=''}F.iframeHTML+='';for(x=0;x'}F.contentCSS=[];v=G.body_id||"tinymce";if(v.indexOf("=")!=-1){v=F.getParam("body_id","","hash");v=v[F.id]||v}A=G.body_class||"";if(A.indexOf("=")!=-1){A=F.getParam("body_class","","hash");A=A[F.id]||""}F.iframeHTML+='
                          ";if(k.relaxedDomain&&(b||(k.isOpera&&parseFloat(opera.version())<11))){D='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+F.id+'");document.write(ed.iframeHTML);document.close();ed.initContentBody();})()'}q=l.add(p.iframeContainer,"iframe",{id:F.id+"_ifr",src:D||'javascript:""',frameBorder:"0",allowTransparency:"true",title:G.aria_label,style:{width:"100%",height:y,display:"block"}});F.contentAreaContainer=p.iframeContainer;l.get(p.editorContainer).style.display=F.orgDisplay;l.get(F.id).style.display="none";l.setAttrib(F.id,"aria-hidden",true);if(!k.relaxedDomain||!D){F.initContentBody()}B=q=p=null},initContentBody:function(){var n=this,p=n.settings,q=l.get(n.id),r=n.getDoc(),o,m;if((!b||!k.relaxedDomain)&&!p.content_editable){r.open();r.write(n.iframeHTML);r.close();if(k.relaxedDomain){r.domain=k.relaxedDomain}}if(p.content_editable){l.addClass(q,"mceContentBody");n.contentDocument=r=p.content_document||document;n.contentWindow=p.content_window||window;n.bodyElement=q;p.content_document=p.content_window=null}m=n.getBody();m.disabled=true;if(!p.readonly){m.contentEditable=n.getParam("content_editable_state",true)}m.disabled=false;n.schema=new k.html.Schema(p);n.dom=new k.dom.DOMUtils(r,{keep_values:true,url_converter:n.convertURL,url_converter_scope:n,hex_colors:p.force_hex_style_colors,class_filter:p.class_filter,update_styles:true,root_element:p.content_editable?n.id:null,schema:n.schema});n.parser=new k.html.DomParser(p,n.schema);n.parser.addAttributeFilter("src,href,style",function(s,t){var u=s.length,x,z=n.dom,y,v;while(u--){x=s[u];y=x.attr(t);v="data-mce-"+t;if(!x.attributes.map[v]){if(t==="style"){x.attr(v,z.serializeStyle(z.parseStyle(y),x.name))}else{x.attr(v,n.convertURL(y,t,x.name))}}}});n.parser.addNodeFilter("script",function(s,t){var u=s.length,v;while(u--){v=s[u];v.attr("type","mce-"+(v.attr("type")||"text/javascript"))}});n.parser.addNodeFilter("#cdata",function(s,t){var u=s.length,v;while(u--){v=s[u];v.type=8;v.name="#comment";v.value="[CDATA["+v.value+"]]"}});n.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,u){var v=t.length,x,s=n.schema.getNonEmptyElements();while(v--){x=t[v];if(x.isEmpty(s)){x.empty().append(new k.html.Node("br",1)).shortEnded=true}}});n.serializer=new k.dom.Serializer(p,n.dom,n.schema);n.selection=new k.dom.Selection(n.dom,n.getWin(),n.serializer);n.formatter=new k.Formatter(n);n.undoManager=new k.UndoManager(n);n.forceBlocks=new k.ForceBlocks(n);n.enterKey=new k.EnterKey(n);n.editorCommands=new k.EditorCommands(n);n.serializer.onPreProcess.add(function(s,t){return n.onPreProcess.dispatch(n,t,s)});n.serializer.onPostProcess.add(function(s,t){return n.onPostProcess.dispatch(n,t,s)});n.onPreInit.dispatch(n);if(!p.gecko_spellcheck){r.body.spellcheck=false}if(!p.readonly){n.bindNativeEvents()}n.controlManager.onPostRender.dispatch(n,n.controlManager);n.onPostRender.dispatch(n);n.quirks=k.util.Quirks(n);if(p.directionality){m.dir=p.directionality}if(p.nowrap){m.style.whiteSpace="nowrap"}if(p.protect){n.onBeforeSetContent.add(function(s,t){i(p.protect,function(u){t.content=t.content.replace(u,function(v){return""})})})}n.onSetContent.add(function(){n.addVisual(n.getBody())});if(p.padd_empty_editor){n.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(]*>( | |\s|\u00a0|)<\/p>[\r\n]*|
                          [\r\n]*)$/,"")})}n.load({initial:true,format:"html"});n.startContent=n.getContent({format:"raw"});n.initialized=true;n.onInit.dispatch(n);n.execCallback("setupcontent_callback",n.id,m,r);n.execCallback("init_instance_callback",n);n.focus(true);n.nodeChanged({initial:true});i(n.contentCSS,function(s){n.dom.loadCSS(s)});if(p.auto_focus){setTimeout(function(){var s=k.get(p.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}q=r=m=null},focus:function(p){var o,u=this,t=u.selection,q=u.settings.content_editable,n,r,s=u.getDoc(),m;if(!p){n=t.getRng();if(n.item){r=n.item(0)}u._refreshContentEditable();if(!q){u.getWin().focus()}if(k.isGecko||q){m=u.getBody();if(m.setActive){m.setActive()}else{m.focus()}if(q){t.normalize()}}if(r&&r.ownerDocument==s){n=s.body.createControlRange();n.addElement(r);n.select()}}if(k.activeEditor!=u){if((o=k.activeEditor)!=null){o.onDeactivate.dispatch(o,u)}u.onActivate.dispatch(u,o)}k._setActive(u)},execCallback:function(q){var m=this,p=m.settings[q],o;if(!p){return}if(m.callbackLookup&&(o=m.callbackLookup[q])){p=o.func;o=o.scope}if(d(p,"string")){o=p.replace(/\.\w+$/,"");o=o?k.resolve(o):0;p=k.resolve(p);m.callbackLookup=m.callbackLookup||{};m.callbackLookup[q]={func:p,scope:o}}return p.apply(o||m,Array.prototype.slice.call(arguments,1))},translate:function(m){var o=this.settings.language||"en",n=k.i18n;if(!m){return""}return n[o+"."+m]||m.replace(/\{\#([^\}]+)\}/g,function(q,p){return n[o+"."+p]||"{#"+p+"}"})},getLang:function(o,m){return k.i18n[(this.settings.language||"en")+"."+o]||(d(m)?m:"{#"+o+"}")},getParam:function(t,q,m){var r=k.trim,p=d(this.settings[t])?this.settings[t]:q,s;if(m==="hash"){s={};if(d(p,"string")){i(p.indexOf("=")>0?p.split(/[;,](?![^=;,]*(?:[;,]|$))/):p.split(","),function(n){n=n.split("=");if(n.length>1){s[r(n[0])]=r(n[1])}else{s[r(n[0])]=r(n)}})}else{s=p}return s}return p},nodeChanged:function(q){var m=this,n=m.selection,p;if(m.initialized){q=q||{};n.normalize();p=n.getStart()||m.getBody();p=b&&p.ownerDocument!=m.getDoc()?m.getBody():p;q.parents=[];m.dom.getParent(p,function(o){if(o.nodeName=="BODY"){return true}q.parents.push(o)});m.onNodeChange.dispatch(m,q?q.controlManager||m.controlManager:m.controlManager,p,n.isCollapsed(),q)}},addButton:function(n,o){var m=this;m.buttons=m.buttons||{};m.buttons[n]=o},addCommand:function(m,o,n){this.execCommands[m]={func:o,scope:n||this}},addQueryStateHandler:function(m,o,n){this.queryStateCommands[m]={func:o,scope:n||this}},addQueryValueHandler:function(m,o,n){this.queryValueCommands[m]={func:o,scope:n||this}},addShortcut:function(o,q,m,p){var n=this,r;if(n.settings.custom_shortcuts===false){return false}n.shortcuts=n.shortcuts||{};if(d(m,"string")){r=m;m=function(){n.execCommand(r,false,null)}}if(d(m,"object")){r=m;m=function(){n.execCommand(r[0],r[1],r[2])}}i(g(o),function(s){var t={func:m,scope:p||this,desc:n.translate(q),alt:false,ctrl:false,shift:false};i(g(s,"+"),function(u){switch(u){case"alt":case"ctrl":case"shift":t[u]=true;break;default:t.charCode=u.charCodeAt(0);t.keyCode=u.toUpperCase().charCodeAt(0)}});n.shortcuts[(t.ctrl?"ctrl":"")+","+(t.alt?"alt":"")+","+(t.shift?"shift":"")+","+t.keyCode]=t});return true},execCommand:function(u,r,x,m){var p=this,q=0,v,n;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(u)&&(!m||!m.skip_focus)){p.focus()}m=f({},m);p.onBeforeExecCommand.dispatch(p,u,r,x,m);if(m.terminate){return false}if(p.execCallback("execcommand_callback",p.id,p.selection.getNode(),u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(v=p.execCommands[u]){n=v.func.call(v.scope,r,x);if(n!==true){p.onExecCommand.dispatch(p,u,r,x,m);return n}}i(p.plugins,function(o){if(o.execCommand&&o.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);q=1;return false}});if(q){return true}if(p.theme&&p.theme.execCommand&&p.theme.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}if(p.editorCommands.execCommand(u,r,x)){p.onExecCommand.dispatch(p,u,r,x,m);return true}p.getDoc().execCommand(u,r,x);p.onExecCommand.dispatch(p,u,r,x,m)},queryCommandState:function(q){var n=this,r,p;if(n._isHidden()){return}if(r=n.queryStateCommands[q]){p=r.func.call(r.scope);if(p!==true){return p}}r=n.editorCommands.queryCommandState(q);if(r!==-1){return r}try{return this.getDoc().queryCommandState(q)}catch(m){}},queryCommandValue:function(r){var n=this,q,p;if(n._isHidden()){return}if(q=n.queryValueCommands[r]){p=q.func.call(q.scope);if(p!==true){return p}}q=n.editorCommands.queryCommandValue(r);if(d(q)){return q}try{return this.getDoc().queryCommandValue(r)}catch(m){}},show:function(){var m=this;l.show(m.getContainer());l.hide(m.id);m.load()},hide:function(){var m=this,n=m.getDoc();if(b&&n){n.execCommand("SelectAll")}m.save();l.hide(m.getContainer());l.setStyle(m.id,"display",m.orgDisplay)},isHidden:function(){return !l.isHidden(this.id)},setProgressState:function(m,n,p){this.onSetProgressState.dispatch(this,m,n,p);return m},load:function(q){var m=this,p=m.getElement(),n;if(p){q=q||{};q.load=true;n=m.setContent(d(p.value)?p.value:p.innerHTML,q);q.element=p;if(!q.no_events){m.onLoadContent.dispatch(m,q)}q.element=p=null;return n}},save:function(r){var m=this,q=m.getElement(),n,p;if(!q||!m.initialized){return}r=r||{};r.save=true;r.element=q;n=r.content=m.getContent(r);if(!r.no_events){m.onSaveContent.dispatch(m,r)}n=r.content;if(!/TEXTAREA|INPUT/i.test(q.nodeName)){q.innerHTML=n;if(p=l.getParent(m.id,"form")){i(p.elements,function(o){if(o.name==m.id){o.value=n;return false}})}}else{q.value=n}r.element=q=null;return n},setContent:function(r,p){var o=this,n,m=o.getBody(),q;p=p||{};p.format=p.format||"html";p.set=true;p.content=r;if(!p.no_events){o.onBeforeSetContent.dispatch(o,p)}r=p.content;if(!k.isIE&&(r.length===0||/^\s+$/.test(r))){q=o.settings.forced_root_block;if(q){r="<"+q+'>
                          "}else{r='
                          '}m.innerHTML=r;o.selection.select(m,true);o.selection.collapse(true);return}if(p.format!=="raw"){r=new k.html.Serializer({},o.schema).serialize(o.parser.parse(r))}p.content=k.trim(r);o.dom.setHTML(m,p.content);if(!p.no_events){o.onSetContent.dispatch(o,p)}o.selection.normalize();return p.content},getContent:function(n){var m=this,o;n=n||{};n.format=n.format||"html";n.get=true;n.getInner=true;if(!n.no_events){m.onBeforeGetContent.dispatch(m,n)}if(n.format=="raw"){o=m.getBody().innerHTML}else{o=m.serializer.serialize(m.getBody(),n)}n.content=k.trim(o);if(!n.no_events){m.onGetContent.dispatch(m,n)}return n.content},isDirty:function(){var m=this;return k.trim(m.startContent)!=k.trim(m.getContent({format:"raw",no_events:1}))&&!m.isNotDirty},getContainer:function(){var m=this;if(!m.container){m.container=l.get(m.editorContainer||m.id+"_parent")}return m.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return l.get(this.settings.content_element||this.id)},getWin:function(){var m=this,n;if(!m.contentWindow){n=l.get(m.id+"_ifr");if(n){m.contentWindow=n.contentWindow}}return m.contentWindow},getDoc:function(){var m=this,n;if(!m.contentDocument){n=m.getWin();if(n){m.contentDocument=n.document}}return m.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(o,n,q){var m=this,p=m.settings;if(p.urlconverter_callback){return m.execCallback("urlconverter_callback",o,q,true,n)}if(!p.convert_urls||(q&&q.nodeName=="LINK")||o.indexOf("file:")===0){return o}if(p.relative_urls){return m.documentBaseURI.toRelative(o)}o=m.documentBaseURI.toAbsolute(o,p.remove_script_host);return o},addVisual:function(q){var n=this,o=n.settings,p=n.dom,m;q=q||n.getBody();if(!d(n.hasVisual)){n.hasVisual=o.visual}i(p.select("table,a",q),function(s){var r;switch(s.nodeName){case"TABLE":m=o.visual_table_class||"mceItemTable";r=p.getAttrib(s,"border");if(!r||r=="0"){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return;case"A":r=p.getAttrib(s,"name");m="mceItemAnchor";if(r){if(n.hasVisual){p.addClass(s,m)}else{p.removeClass(s,m)}}return}});n.onVisualAid.dispatch(n,q,n.hasVisual)},remove:function(){var m=this,n=m.getContainer();if(!m.removed){m.removed=1;m.hide();if(!m.settings.content_editable){j.clear(m.getWin());j.clear(m.getDoc())}j.clear(m.getBody());j.clear(m.formElement);j.unbind(n);m.execCallback("remove_instance_callback",m);m.onRemove.dispatch(m);m.onExecCommand.listeners=[];k.remove(m);l.remove(n)}},destroy:function(n){var m=this;if(m.destroyed){return}if(a){j.unbind(m.getDoc());j.unbind(m.getWin());j.unbind(m.getBody())}if(!n){k.removeUnload(m.destroy);tinyMCE.onBeforeUnload.remove(m._beforeUnload);if(m.theme&&m.theme.destroy){m.theme.destroy()}m.controlManager.destroy();m.selection.destroy();m.dom.destroy()}if(m.formElement){m.formElement.submit=m.formElement._mceOldSubmit;m.formElement._mceOldSubmit=null}m.contentAreaContainer=m.formElement=m.container=m.settings.content_element=m.bodyElement=m.contentDocument=m.contentWindow=null;if(m.selection){m.selection=m.selection.win=m.selection.dom=m.selection.dom.doc=null}m.destroyed=1},_refreshContentEditable:function(){var n=this,m,o;if(n._isHidden()){m=n.getBody();o=m.parentNode;o.removeChild(m);o.appendChild(m);m.focus()}},_isHidden:function(){var m;if(!a){return 0}m=this.selection.getSel();return(!m||!m.rangeCount||m.rangeCount===0)}})})(tinymce);(function(a){var b=a.each;a.Editor.prototype.setupEvents=function(){var c=this,d=c.settings;b(["onPreInit","onBeforeRenderUI","onPostRender","onLoad","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState","onSetAttrib"],function(e){c[e]=new a.util.Dispatcher(c)});if(d.cleanup_callback){c.onBeforeSetContent.add(function(e,f){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)});c.onPreProcess.add(function(e,f){if(f.set){e.execCallback("cleanup_callback","insert_to_editor_dom",f.node,f)}if(f.get){e.execCallback("cleanup_callback","get_from_editor_dom",f.node,f)}});c.onPostProcess.add(function(e,f){if(f.set){f.content=e.execCallback("cleanup_callback","insert_to_editor",f.content,f)}if(f.get){f.content=e.execCallback("cleanup_callback","get_from_editor",f.content,f)}})}if(d.save_callback){c.onGetContent.add(function(e,f){if(f.save){f.content=e.execCallback("save_callback",e.id,f.content,e.getBody())}})}if(d.handle_event_callback){c.onEvent.add(function(f,g,h){if(c.execCallback("handle_event_callback",g,f,h)===false){Event.cancel(g)}})}if(d.handle_node_change_callback){c.onNodeChange.add(function(f,e,g){f.execCallback("handle_node_change_callback",f.id,g,-1,-1,true,f.selection.isCollapsed())})}if(d.save_callback){c.onSaveContent.add(function(e,g){var f=e.execCallback("save_callback",e.id,g.content,e.getBody());if(f){g.content=f}})}if(d.onchange_callback){c.onChange.add(function(f,e){f.execCallback("onchange_callback",f,e)})}};a.Editor.prototype.bindNativeEvents=function(){var c=this,f,g=c.settings,j=c.dom,k;k={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function e(i,l){var m=i.type;if(c.removed){return}if(c.onEvent.dispatch(c,i,l)!==false){c[k[i.fakeType||i.type]].dispatch(c,i,l)}}function h(i){c.focus(true)}b(k,function(l,m){var i=g.content_editable?c.getBody():c.getDoc();switch(m){case"contextmenu":j.bind(i,m,e);break;case"paste":j.bind(c.getBody(),m,e);break;case"submit":case"reset":j.bind(c.getElement().form||a.DOM.getParent(c.id,"form"),m,e);break;default:j.bind(i,m,e)}});j.bind(g.content_editable?c.getBody():(a.isGecko?c.getDoc():c.getWin()),"focus",function(i){c.focus(true)});if(g.content_editable&&a.isOpera){j.bind(c.getBody(),"click",h);j.bind(c.getBody(),"keydown",h)}c.onMouseUp.add(c.nodeChanged);c.onKeyUp.add(function(i,m){var l=m.keyCode;if((l>=33&&l<=36)||(l>=37&&l<=40)||l==13||l==45||l==46||l==8||(a.isMac&&(l==91||l==93))||m.ctrlKey){c.nodeChanged()}});c.onReset.add(function(){c.setContent(c.startContent,{format:"raw"})});function d(l,i){if(l.altKey||l.ctrlKey||l.metaKey){b(c.shortcuts,function(m){var n=a.isMac?l.metaKey:l.ctrlKey;if(m.ctrl!=n||m.alt!=l.altKey||m.shift!=l.shiftKey){return}if(l.keyCode==m.keyCode||(l.charCode&&l.charCode==m.charCode)){l.preventDefault();if(i){m.func.call(m.scope)}return true}})}}c.onKeyUp.add(function(i,l){d(l)});c.onKeyPress.add(function(i,l){d(l)});c.onKeyDown.add(function(i,l){d(l,true)});if(a.isOpera){c.onClick.add(function(i,l){l.preventDefault()})}}})(tinymce);(function(d){var e=d.each,b,a=true,c=false;d.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return c}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return c}function u(v,x){x=x||"exec";e(v,function(z,y){e(y.toLowerCase().split(","),function(A){j[x][A]=z})})}d.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===b){x=c}if(v===b){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:b)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(d.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(c)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);e("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=d.explode(k.font_size_style_values);v=d.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return c}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new d.html.Serializer({},n.schema);v='\uFEFF';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(//i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.yL.x+L.w||C.x")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(z){var x="align"+z.substring(7);var v=p.isCollapsed()?[m.getParent(p.getNode(),m.isBlock)]:p.getSelectedBlocks();var y=d.map(v,function(A){return !!q.matchNode(A,x)});return d.inArray(y,a)!==-1},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(h){var l,i=0,e=[],g,k,j,f;function c(){return b.trim(h.getContent({format:"raw",no_events:1}).replace(/]+data-mce-bogus[^>]+>[\u200B\uFEFF]+<\/span>/g,""))}function d(){l.typing=false;l.add()}k=new a(l);j=new a(l);f=new a(l);k.add(function(m,n){if(m.hasUndo()){return h.onChange.dispatch(h,n,m)}});j.add(function(m,n){return h.onUndo.dispatch(h,n,m)});f.add(function(m,n){return h.onRedo.dispatch(h,n,m)});h.onInit.add(function(){l.add()});h.onBeforeExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.beforeChange()}});h.onExecCommand.add(function(m,p,o,q,n){if(p!="Undo"&&p!="Redo"&&p!="mceRepaint"&&(!n||!n.skip_undo)){l.add()}});h.onSaveContent.add(d);h.dom.bind(h.dom.getRoot(),"dragend",d);h.dom.bind(h.getDoc(),b.isGecko?"blur":"focusout",function(m){if(!h.removed&&l.typing){d()}});h.onKeyUp.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45||n==13||o.ctrlKey){d()}});h.onKeyDown.add(function(m,o){var n=o.keyCode;if((n>=33&&n<=36)||(n>=37&&n<=40)||n==45){if(l.typing){d()}return}if((n<16||n>20)&&n!=224&&n!=91&&!l.typing){l.beforeChange();l.typing=true;l.add()}});h.onMouseDown.add(function(m,n){if(l.typing){d()}});h.addShortcut("ctrl+z","undo_desc","Undo");h.addShortcut("ctrl+y","redo_desc","Redo");l={data:e,typing:false,onAdd:k,onUndo:j,onRedo:f,beforeChange:function(){g=h.selection.getBookmark(2,true)},add:function(p){var m,n=h.settings,o;p=p||{};p.content=c();o=e[i];if(o&&o.content==p.content){return null}if(e[i]){e[i].beforeBookmark=g}if(n.custom_undo_redo_levels){if(e.length>n.custom_undo_redo_levels){for(m=0;m0){n=e[--i];h.setContent(n.content,{format:"raw"});h.selection.moveToBookmark(n.beforeBookmark);l.onUndo.dispatch(l,n)}return n},redo:function(){var m;if(i0||this.typing},hasRedo:function(){return i0){g.moveEnd("character",q)}g.select()}catch(n){}}if(p){c.nodeChanged()}}if(b.forced_root_block){c.onKeyUp.add(f);c.onNodeChange.add(f)}};(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(i){var h,g=this,f=g.editor;d(f.plugins,function(j){if(j.createControl){h=j.createControl(i,g);if(h){return false}}});switch(i){case"|":case"separator":return g.createSeparator()}if(!h&&f.buttons&&(h=f.buttons[i])){return g.createButton(i,h)}return g.add(h)},createDropMenu:function(f,n,h){var m=this,i=m.editor,j,g,k,l;n=e({"class":"mceDropDown",constrain:i.settings.constrain_menus},n);n["class"]=n["class"]+" "+i.getParam("skin")+"Skin";if(k=i.getParam("skin_variant")){n["class"]+=" "+i.getParam("skin")+"Skin"+k.substring(0,1).toUpperCase()+k.substring(1)}n["class"]+=i.settings.directionality=="rtl"?" mceRtl":"";f=m.prefix+f;l=h||m._cls.dropmenu||c.ui.DropMenu;j=m.controls[f]=new l(f,n);j.onAddItem.add(function(r,q){var p=q.settings;p.title=i.getLang(p.title,p.title);if(!p.onclick){p.onclick=function(o){if(p.cmd){i.execCommand(p.cmd,p.ui||false,p.value)}}}});i.onRemove.add(function(){j.destroy()});if(c.isIE){j.onShowMenu.add(function(){i.focus();g=i.selection.getBookmark(1)});j.onHideMenu.add(function(){if(g){i.selection.moveToBookmark(g);g=0}})}return m.add(j)},createListBox:function(f,n,h){var l=this,j=l.editor,i,k,m;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,scope:n.scope,control_manager:l},n);f=l.prefix+f;function g(o){return o.settings.use_accessible_selects&&!c.isGecko}if(j.settings.use_native_selects||g(j)){k=new c.ui.NativeListBox(f,n)}else{m=h||l._cls.listbox||c.ui.ListBox;k=new m(f,n,j)}l.controls[f]=k;if(c.isWebKit){k.onPostRender.add(function(p,o){a.add(o,"mousedown",function(){j.bookmark=j.selection.getBookmark(1)});a.add(o,"focus",function(){j.selection.moveToBookmark(j.bookmark);j.bookmark=null})})}if(k.hideMenu){j.onMouseDown.add(k.hideMenu,k)}return l.add(k)},createButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.label=g.translate(i.label);i.scope=i.scope||g;if(!i.onclick&&!i.menu_button){i.onclick=function(){g.execCommand(i.cmd,i.ui||false,i.value)}}i=e({title:i.title,"class":"mce_"+m,unavailable_prefix:g.getLang("unavailable",""),scope:i.scope,control_manager:h},i);m=h.prefix+m;if(i.menu_button){f=l||h._cls.menubutton||c.ui.MenuButton;k=new f(m,i,g);g.onMouseDown.add(k.hideMenu,k)}else{f=h._cls.button||c.ui.Button;k=new f(m,i,g)}return h.add(k)},createMenuButton:function(h,f,g){f=f||{};f.menu_button=1;return this.createButton(h,f,g)},createSplitButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.scope=i.scope||g;if(!i.onclick){i.onclick=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}if(!i.onselect){i.onselect=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}i=e({title:i.title,"class":"mce_"+m,scope:i.scope,control_manager:h},i);m=h.prefix+m;f=l||h._cls.splitbutton||c.ui.SplitButton;k=h.add(new f(m,i,g));g.onMouseDown.add(k.hideMenu,k);return k},createColorSplitButton:function(f,n,h){var l=this,j=l.editor,i,k,m,g;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onclick){n.onclick=function(o){if(c.isIE){g=j.selection.getBookmark(1)}j.execCommand(n.cmd,n.ui||false,o||n.value)}}if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,menu_class:j.getParam("skin")+"Skin",scope:n.scope,more_colors_title:j.getLang("more_colors")},n);f=l.prefix+f;m=h||l._cls.colorsplitbutton||c.ui.ColorSplitButton;k=new m(f,n,j);j.onMouseDown.add(k.hideMenu,k);j.onRemove.add(function(){k.destroy()});if(c.isIE){k.onShowMenu.add(function(){j.focus();g=j.selection.getBookmark(1)});k.onHideMenu.add(function(){if(g){j.selection.moveToBookmark(g);g=0}})}return l.add(k)},createToolbar:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||g._cls.toolbar||c.ui.Toolbar;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createToolbarGroup:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||this._cls.toolbarGroup||c.ui.ToolbarGroup;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createSeparator:function(g){var f=g||this._cls.separator||c.ui.Separator;return new f()},setControlType:function(g,f){return this._cls[g.toLowerCase()]=f},destroy:function(){d(this.controls,function(f){f.destroy()});this.controls=null}})})(tinymce);(function(d){var a=d.util.Dispatcher,e=d.each,c=d.isIE,b=d.isOpera;d.create("tinymce.WindowManager",{WindowManager:function(f){var g=this;g.editor=f;g.onOpen=new a(g);g.onClose=new a(g);g.params={};g.features={}},open:function(z,h){var v=this,k="",n,m,i=v.editor.settings.dialog_type=="modal",q,o,j,g=d.DOM.getViewPort(),r;z=z||{};h=h||{};o=b?g.w:screen.width;j=b?g.h:screen.height;z.name=z.name||"mc_"+new Date().getTime();z.width=parseInt(z.width||320);z.height=parseInt(z.height||240);z.resizable=true;z.left=z.left||parseInt(o/2)-(z.width/2);z.top=z.top||parseInt(j/2)-(z.height/2);h.inline=false;h.mce_width=z.width;h.mce_height=z.height;h.mce_auto_focus=z.auto_focus;if(i){if(c){z.center=true;z.help=false;z.dialogWidth=z.width+"px";z.dialogHeight=z.height+"px";z.scroll=z.scrollbars||false}}e(z,function(p,f){if(d.is(p,"boolean")){p=p?"yes":"no"}if(!/^(name|url)$/.test(f)){if(c&&i){k+=(k?";":"")+f+":"+p}else{k+=(k?",":"")+f+"="+p}}});v.features=z;v.params=h;v.onOpen.dispatch(v,z,h);r=z.url||z.file;r=d._addVer(r);try{if(c&&i){q=1;window.showModalDialog(r,window,k)}else{q=window.open(r,z.name,k)}}catch(l){}if(!q){alert(v.editor.getLang("popup_blocked"))}},close:function(f){f.close();this.onClose.dispatch(this)},createInstance:function(i,h,g,m,l,k){var j=d.resolve(i);return new j(h,g,m,l,k)},confirm:function(h,f,i,g){g=g||window;f.call(i||this,g.confirm(this._decode(this.editor.getLang(h,h))))},alert:function(h,f,j,g){var i=this;g=g||window;g.alert(i._decode(i.editor.getLang(h,h)));if(f){f.call(j||i)}},resizeBy:function(f,g,h){h.resizeBy(f,g)},_decode:function(f){return d.DOM.decode(f).replace(/\\n/g,"\n")}})}(tinymce));(function(a){a.Formatter=function(Y){var O={},R=a.each,c=Y.dom,r=Y.selection,t=a.dom.TreeWalker,M=new a.dom.RangeUtils(c),d=Y.schema.isValidChild,H=c.isBlock,m=Y.settings.forced_root_block,s=c.nodeIndex,G=a.isGecko?"\u200B":"\uFEFF",e=/^(src|href|style)$/,V=false,C=true,D,x=c.getContentEditable;function A(Z){return Z instanceof Array}function n(aa,Z){return c.getParents(aa,Z,c.getRoot())}function b(Z){return Z.nodeType===1&&Z.id==="_mce_caret"}function j(){l({alignleft:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"},defaultBlock:"div"},{selector:"img,table",collapsed:false,styles:{"float":"left"}}],aligncenter:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"},defaultBlock:"div"},{selector:"img",collapsed:false,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:false,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"},defaultBlock:"div"},{selector:"img,table",collapsed:false,styles:{"float":"right"}}],alignfull:[{selector:"figure,p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"justify"},defaultBlock:"div"}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:true},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:true},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:false},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:false},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},link:{inline:"a",selector:"a",remove:"all",split:true,deep:true,onmatch:function(Z){return true},onformat:function(ab,Z,aa){R(aa,function(ad,ac){c.setAttrib(ab,ac,ad)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:true,expand:false,block_expand:true,deep:true},{selector:"span",attributes:["style","class"],remove:"empty",split:true,expand:false,deep:true},{selector:"*",attributes:["style","class"],split:false,expand:false,deep:true}]});R("p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp".split(/\s/),function(Z){l(Z,{block:Z,remove:"all"})});l(Y.settings.formats)}function U(){Y.addShortcut("ctrl+b","bold_desc","Bold");Y.addShortcut("ctrl+i","italic_desc","Italic");Y.addShortcut("ctrl+u","underline_desc","Underline");for(var Z=1;Z<=6;Z++){Y.addShortcut("ctrl+"+Z,"",["FormatBlock",false,"h"+Z])}Y.addShortcut("ctrl+7","",["FormatBlock",false,"p"]);Y.addShortcut("ctrl+8","",["FormatBlock",false,"div"]);Y.addShortcut("ctrl+9","",["FormatBlock",false,"address"])}function T(Z){return Z?O[Z]:O}function l(Z,aa){if(Z){if(typeof(Z)!=="string"){R(Z,function(ac,ab){l(ab,ac)})}else{aa=aa.length?aa:[aa];R(aa,function(ab){if(ab.deep===D){ab.deep=!ab.selector}if(ab.split===D){ab.split=!ab.selector||ab.inline}if(ab.remove===D&&ab.selector&&!ab.inline){ab.remove="none"}if(ab.selector&&ab.inline){ab.mixed=true;ab.block_expand=true}if(typeof(ab.classes)==="string"){ab.classes=ab.classes.split(/\s+/)}});O[Z]=aa}}}var i=function(aa){var Z;Y.dom.getParent(aa,function(ab){Z=Y.dom.getStyle(ab,"text-decoration");return Z&&Z!=="none"});return Z};var K=function(Z){var aa;if(Z.nodeType===1&&Z.parentNode&&Z.parentNode.nodeType===1){aa=i(Z.parentNode);if(Y.dom.getStyle(Z,"color")&&aa){Y.dom.setStyle(Z,"text-decoration",aa)}else{if(Y.dom.getStyle(Z,"textdecoration")===aa){Y.dom.setStyle(Z,"text-decoration",null)}}}};function W(ac,aj,ae){var af=T(ac),ak=af[0],ai,aa,ah,ag=r.isCollapsed();function Z(ao,an){an=an||ak;if(ao){if(an.onformat){an.onformat(ao,an,aj,ae)}R(an.styles,function(aq,ap){c.setStyle(ao,ap,q(aq,aj))});R(an.attributes,function(aq,ap){c.setAttrib(ao,ap,q(aq,aj))});R(an.classes,function(ap){ap=q(ap,aj);if(!c.hasClass(ao,ap)){c.addClass(ao,ap)}})}}function ad(){function ap(aw,au){var av=new t(au);for(ae=av.current();ae;ae=av.prev()){if(ae.childNodes.length>1||ae==aw||ae.tagName=="BR"){return ae}}}var ao=Y.selection.getRng();var at=ao.startContainer;var an=ao.endContainer;if(at!=an&&ao.endOffset===0){var ar=ap(at,an);var aq=ar.nodeType==3?ar.length:ar.childNodes.length;ao.setEnd(ar,aq)}return ao}function ab(aq,aw,au,at,ao){var an=[],ap=-1,av,ay=-1,ar=-1,ax;R(aq.childNodes,function(aA,az){if(aA.nodeName==="UL"||aA.nodeName==="OL"){ap=az;av=aA;return false}});R(aq.childNodes,function(aA,az){if(aA.nodeName==="SPAN"&&c.getAttrib(aA,"data-mce-type")=="bookmark"){if(aA.id==aw.id+"_start"){ay=az}else{if(aA.id==aw.id+"_end"){ar=az}}}});if(ap<=0||(ayap)){R(a.grep(aq.childNodes),ao);return 0}else{ax=c.clone(au,V);R(a.grep(aq.childNodes),function(aA,az){if((ayap&&az>ap)){an.push(aA);aA.parentNode.removeChild(aA)}});if(ayap){aq.insertBefore(ax,av.nextSibling)}}at.push(ax);R(an,function(az){ax.appendChild(az)});return ax}}function al(ao,aq,au){var an=[],at,ap,ar=true;at=ak.inline||ak.block;ap=c.create(at);Z(ap);M.walk(ao,function(av){var aw;function ax(ay){var aD,aB,az,aA,aC;aC=ar;aD=ay.nodeName.toLowerCase();aB=ay.parentNode.nodeName.toLowerCase();if(ay.nodeType===1&&x(ay)){aC=ar;ar=x(ay)==="true";aA=true}if(g(aD,"br")){aw=0;if(ak.block){c.remove(ay)}return}if(ak.wrapper&&y(ay,ac,aj)){aw=0;return}if(ar&&!aA&&ak.block&&!ak.wrapper&&I(aD)){ay=c.rename(ay,at);Z(ay);an.push(ay);aw=0;return}if(ak.selector){R(af,function(aE){if("collapsed" in aE&&aE.collapsed!==ag){return}if(c.is(ay,aE.selector)&&!b(ay)){Z(ay,aE);az=true}});if(!ak.inline||az){aw=0;return}}if(ar&&!aA&&d(at,aD)&&d(aB,at)&&!(!au&&ay.nodeType===3&&ay.nodeValue.length===1&&ay.nodeValue.charCodeAt(0)===65279)&&!b(ay)){if(!aw){aw=c.clone(ap,V);ay.parentNode.insertBefore(aw,ay);an.push(aw)}aw.appendChild(ay)}else{if(aD=="li"&&aq){aw=ab(ay,aq,ap,an,ax)}else{aw=0;R(a.grep(ay.childNodes),ax);if(aA){ar=aC}aw=0}}}R(av,ax)});if(ak.wrap_links===false){R(an,function(av){function aw(aA){var az,ay,ax;if(aA.nodeName==="A"){ay=c.clone(ap,V);an.push(ay);ax=a.grep(aA.childNodes);for(az=0;az1||!H(ax))&&av===0){c.remove(ax,1);return}if(ak.inline||ak.wrapper){if(!ak.exact&&av===1){ax=aw(ax)}R(af,function(az){R(c.select(az.inline,ax),function(aB){var aA;if(az.wrap_links===false){aA=aB.parentNode;do{if(aA.nodeName==="A"){return}}while(aA=aA.parentNode)}X(az,aj,aB,az.exact?aB:null)})});if(y(ax.parentNode,ac,aj)){c.remove(ax,1);ax=0;return C}if(ak.merge_with_parents){c.getParent(ax.parentNode,function(az){if(y(az,ac,aj)){c.remove(ax,1);ax=0;return C}})}if(ax&&ak.merge_siblings!==false){ax=u(E(ax),ax);ax=u(ax,E(ax,C))}}})}if(ak){if(ae){if(ae.nodeType){aa=c.createRng();aa.setStartBefore(ae);aa.setEndAfter(ae);al(p(aa,af),null,true)}else{al(ae,null,true)}}else{if(!ag||!ak.inline||c.select("td.mceSelected,th.mceSelected").length){var am=Y.selection.getNode();if(!m&&af[0].defaultBlock&&!c.getParent(am,c.isBlock)){W(af[0].defaultBlock)}Y.selection.setRng(ad());ai=r.getBookmark();al(p(r.getRng(C),af),ai);if(ak.styles&&(ak.styles.color||ak.styles.textDecoration)){a.walk(am,K,"childNodes");K(am)}r.moveToBookmark(ai);P(r.getRng(C));Y.nodeChanged()}else{S("apply",ac,aj)}}}}function B(ab,ak,ad){var ae=T(ab),am=ae[0],ai,ah,aa,aj=true;function ac(at){var ar,aq,ap,ao,av,au;if(at.nodeType===1&&x(at)){av=aj;aj=x(at)==="true";au=true}ar=a.grep(at.childNodes);if(aj&&!au){for(aq=0,ap=ae.length;aq=0;aa--){Z=af[aa].selector;if(!Z){return C}for(ae=ab.length-1;ae>=0;ae--){if(c.is(ab[ae],Z)){return C}}}}return V}a.extend(this,{get:T,register:l,apply:W,remove:B,toggle:F,match:k,matchAll:v,matchNode:y,canApply:z});j();U();function h(Z,aa){if(g(Z,aa.inline)){return C}if(g(Z,aa.block)){return C}if(aa.selector){return c.is(Z,aa.selector)}}function g(aa,Z){aa=aa||"";Z=Z||"";aa=""+(aa.nodeName||aa);Z=""+(Z.nodeName||Z);return aa.toLowerCase()==Z.toLowerCase()}function N(aa,Z){var ab=c.getStyle(aa,Z);if(Z=="color"||Z=="backgroundColor"){ab=c.toHex(ab)}if(Z=="fontWeight"&&ab==700){ab="bold"}return""+ab}function q(Z,aa){if(typeof(Z)!="string"){Z=Z(aa)}else{if(aa){Z=Z.replace(/%(\w+)/g,function(ac,ab){return aa[ab]||ac})}}return Z}function f(Z){return Z&&Z.nodeType===3&&/^([\t \r\n]+|)$/.test(Z.nodeValue)}function Q(ab,aa,Z){var ac=c.create(aa,Z);ab.parentNode.insertBefore(ac,ab);ac.appendChild(ab);return ac}function p(Z,ak,ac){var an,al,af,aj,ab=Z.startContainer,ag=Z.startOffset,ap=Z.endContainer,ai=Z.endOffset;function am(ax){var ar,av,aw,au,at,aq;ar=av=ax?ab:ap;at=ax?"previousSibling":"nextSibling";aq=c.getRoot();if(ar.nodeType==3&&!f(ar)){if(ax?ag>0:aial?al:ag];if(ab.nodeType==3){ag=0}}if(ap.nodeType==1&&ap.hasChildNodes()){al=ap.childNodes.length-1;ap=ap.childNodes[ai>al?al:ai-1];if(ap.nodeType==3){ai=ap.nodeValue.length}}function ao(ar){var aq=ar;while(aq){if(aq.nodeType===1&&x(aq)){return x(aq)==="false"?aq:ar}aq=aq.parentNode}return ar}function ah(ar,aw,ay){var av,at,ax,aq;function au(aA,aC){var aD,az,aB=aA.nodeValue;if(typeof(aC)=="undefined"){aC=ay?aB.length:0}if(ay){aD=aB.lastIndexOf(" ",aC);az=aB.lastIndexOf("\u00a0",aC);aD=aD>az?aD:az;if(aD!==-1&&!ac){aD++}}else{aD=aB.indexOf(" ",aC);az=aB.indexOf("\u00a0",aC);aD=aD!==-1&&(az===-1||aD0&&af.node.nodeType===3&&af.node.nodeValue.charAt(af.offset-1)===" "){if(af.offset>1){ap=af.node;ap.splitText(af.offset-1)}}}}if(ak[0].inline||ak[0].block_expand){if(!ak[0].inline||(ab.nodeType!=3||ag===0)){ab=am(true)}if(!ak[0].inline||(ap.nodeType!=3||ai===ap.nodeValue.length)){ap=am()}}if(ak[0].selector&&ak[0].expand!==V&&!ak[0].inline){ab=ad(ab,"previousSibling");ap=ad(ap,"nextSibling")}if(ak[0].block||ak[0].selector){ab=aa(ab,"previousSibling");ap=aa(ap,"nextSibling");if(ak[0].block){if(!H(ab)){ab=am(true)}if(!H(ap)){ap=am()}}}if(ab.nodeType==1){ag=s(ab);ab=ab.parentNode}if(ap.nodeType==1){ai=s(ap)+1;ap=ap.parentNode}return{startContainer:ab,startOffset:ag,endContainer:ap,endOffset:ai}}function X(af,ae,ac,Z){var ab,aa,ad;if(!h(ac,af)){return V}if(af.remove!="all"){R(af.styles,function(ah,ag){ah=q(ah,ae);if(typeof(ag)==="number"){ag=ah;Z=0}if(!Z||g(N(Z,ag),ah)){c.setStyle(ac,ag,"")}ad=1});if(ad&&c.getAttrib(ac,"style")==""){ac.removeAttribute("style");ac.removeAttribute("data-mce-style")}R(af.attributes,function(ai,ag){var ah;ai=q(ai,ae);if(typeof(ag)==="number"){ag=ai;Z=0}if(!Z||g(c.getAttrib(Z,ag),ai)){if(ag=="class"){ai=c.getAttrib(ac,ag);if(ai){ah="";R(ai.split(/\s+/),function(aj){if(/mce\w+/.test(aj)){ah+=(ah?" ":"")+aj}});if(ah){c.setAttrib(ac,ag,ah);return}}}if(ag=="class"){ac.removeAttribute("className")}if(e.test(ag)){ac.removeAttribute("data-mce-"+ag)}ac.removeAttribute(ag)}});R(af.classes,function(ag){ag=q(ag,ae);if(!Z||c.hasClass(Z,ag)){c.removeClass(ac,ag)}});aa=c.getAttribs(ac);for(ab=0;abab?ab:ad]}if(Z.nodeType===3&&ae&&ad>=Z.nodeValue.length){Z=new t(Z,Y.getBody()).next()||Z}if(Z.nodeType===3&&!ae&&ad===0){Z=new t(Z,Y.getBody()).prev()||Z}return Z}function S(ai,Z,ag){var aj="_mce_caret",aa=Y.settings.caret_debug;function ab(am){var al=c.create("span",{id:aj,"data-mce-bogus":true,style:aa?"color:red":""});if(am){al.appendChild(Y.getDoc().createTextNode(G))}return al}function ah(am,al){while(am){if((am.nodeType===3&&am.nodeValue!==G)||am.childNodes.length>1){return false}if(al&&am.nodeType===1){al.push(am)}am=am.firstChild}return true}function ae(al){while(al){if(al.id===aj){return al}al=al.parentNode}}function ad(al){var am;if(al){am=new t(al,al);for(al=am.current();al;al=am.next()){if(al.nodeType===3){return al}}}}function ac(an,am){var ao,al;if(!an){an=ae(r.getStart());if(!an){while(an=c.get(aj)){ac(an,false)}}}else{al=r.getRng(true);if(ah(an)){if(am!==false){al.setStartBefore(an);al.setEndBefore(an)}c.remove(an)}else{ao=ad(an);if(ao.nodeValue.charAt(0)===G){ao=ao.deleteData(0,1)}c.remove(an,1)}r.setRng(al)}}function af(){var an,al,ar,aq,ao,am,ap;an=r.getRng(true);aq=an.startOffset;am=an.startContainer;ap=am.nodeValue;al=ae(r.getStart());if(al){ar=ad(al)}if(ap&&aq>0&&aq=0;ap--){an.appendChild(c.clone(au[ap],false));an=an.firstChild}an.appendChild(c.doc.createTextNode(G));an=an.firstChild;c.insertAfter(at,av);r.setCursorLocation(an,1)}}if(!self._hasCaretEvents){Y.onBeforeGetContent.addToTop(function(){var al=[],am;if(ah(ae(r.getStart()),al)){am=al.length;while(am--){c.setAttrib(al[am],"data-mce-bogus","1")}}});a.each("onMouseUp onKeyUp".split(" "),function(al){Y[al].addToTop(function(){ac()})});Y.onKeyDown.addToTop(function(al,an){var am=an.keyCode;if(am==8||am==37||am==39){ac(ae(r.getStart()))}});r.onSetContent.add(function(){c.getParent(r.getStart(),function(al){if(al.id!==aj&&c.getAttrib(al,"data-mce-bogus")&&!c.isEmpty(al)){c.setAttrib(al,"data-mce-bogus",null)}})});self._hasCaretEvents=true}if(ai=="apply"){af()}else{ak()}}function P(aa){var Z=aa.startContainer,ag=aa.startOffset,ac,af,ae,ab,ad;if(Z.nodeType==3&&ag>=Z.nodeValue.length){ag=s(Z);Z=Z.parentNode;ac=true}if(Z.nodeType==1){ab=Z.childNodes;Z=ab[Math.min(ag,ab.length-1)];af=new t(Z,c.getParent(Z,c.isBlock));if(ag>ab.length-1||ac){af.next()}for(ae=af.current();ae;ae=af.next()){if(ae.nodeType==3&&!f(ae)){ad=c.create("a",null,G);ae.parentNode.insertBefore(ad,ae);aa.setStart(ae,0);r.setRng(aa);c.remove(ad);return}}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}if(c.inline_styles){h=e.explode(c.font_size_legacy_values);d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size,10)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}});(function(b){var a=b.dom.TreeWalker;b.EnterKey=function(e){var h=e.dom,d=e.selection,c=e.settings,g=e.undoManager;function f(y){var u=d.getRng(true),C,i,x,t,o,H,n,j,l,s,E,v,z;function B(I){return I&&h.isBlock(I)&&!/^(TD|TH|CAPTION)$/.test(I.nodeName)&&!/^(fixed|absolute)/i.test(I.style.position)&&h.getContentEditable(I)!=="true"}function m(J){var O,M,I,P,N,L=J,K;I=h.createRng();if(J.hasChildNodes()){O=new a(J,J);while(M=O.current()){if(M.nodeType==3){I.setStart(M,0);I.setEnd(M,0);break}if(/^(BR|IMG)$/.test(M.nodeName)){I.setStartBefore(M);I.setEndBefore(M);break}L=M;M=O.next()}if(!M){I.setStart(L,0);I.setEnd(L,0)}}else{if(J.nodeName=="BR"){if(J.nextSibling&&h.isBlock(J.nextSibling)){if(!H||H<9){K=h.create("br");J.parentNode.insertBefore(K,J)}I.setStartBefore(J);I.setEndBefore(J)}else{I.setStartAfter(J);I.setEndAfter(J)}}else{I.setStart(J,0);I.setEnd(J,0)}}d.setRng(I);h.remove(K);N=h.getViewPort(e.getWin());P=h.getPos(J).y;if(PN.y+N.h){e.getWin().scrollTo(0,P"}return M}function p(L){var K,J,I;if(x.nodeType==3&&(L?t>0:t=x.nodeValue.length){if(!b.isIE&&!A()){J=h.create("br");u.insertNode(J);u.setStartAfter(J);u.setEndAfter(J);I=true}}J=h.create("br");u.insertNode(J);if(b.isIE&&s=="PRE"&&(!H||H<8)){J.parentNode.insertBefore(h.doc.createTextNode("\r"),J)}if(!I){u.setStartAfter(J);u.setEndAfter(J)}else{u.setStartBefore(J);u.setEndBefore(J)}d.setRng(u);g.add()}function r(I){do{if(I.nodeType===3){I.nodeValue=I.nodeValue.replace(/^[\r\n]+/,"")}I=I.firstChild}while(I)}function F(K){var I=h.getRoot(),J,L;J=K;while(J!==I&&h.getContentEditable(J)!=="false"){if(h.getContentEditable(J)==="true"){L=J}J=J.parentNode}return J!==I?L:I}if(!u.collapsed){e.execCommand("Delete");return}if(y.isDefaultPrevented()){return}x=u.startContainer;t=u.startOffset;v=c.forced_root_block;v=v?v.toUpperCase():"";H=h.doc.documentMode;if(x.nodeType==1&&x.hasChildNodes()){z=t>x.childNodes.length-1;x=x.childNodes[Math.min(t,x.childNodes.length-1)]||x;t=0}i=F(x);if(!i){return}g.beforeChange();if(!h.isBlock(i)&&i!=h.getRoot()){if(!v||y.shiftKey){G()}return}if((v&&!y.shiftKey)||(!v&&y.shiftKey)){x=k(x,t)}o=h.getParent(x,h.isBlock);l=o?h.getParent(o.parentNode,h.isBlock):null;s=o?o.nodeName.toUpperCase():"";E=l?l.nodeName.toUpperCase():"";if(s=="LI"&&h.isEmpty(o)){if(/^(UL|OL|LI)$/.test(l.parentNode.nodeName)){return false}D();return}if(s=="PRE"&&c.br_in_pre!==false){if(!y.shiftKey){G();return}}else{if((!v&&!y.shiftKey&&s!="LI")||(v&&y.shiftKey)){G();return}}v=v||"P";if(p()){if(/^(H[1-6]|PRE)$/.test(s)&&E!="HGROUP"){n=q(v)}else{n=q()}if(c.end_container_on_empty_block&&B(l)&&h.isEmpty(o)){n=h.split(l,o)}else{h.insertAfter(n,o)}}else{if(p(true)){n=o.parentNode.insertBefore(q(),o)}else{C=u.cloneRange();C.setEndAfter(o);j=C.extractContents();r(j);n=j.firstChild;h.insertAfter(j,o)}}h.setAttrib(n,"id","");m(n);g.add()}e.onKeyDown.add(function(j,i){if(i.keyCode==13){if(f(i)!==false){i.preventDefault()}}})}})(tinymce); \ No newline at end of file diff --git a/lib/editor/tinymce/version.php b/lib/editor/tinymce/version.php index 416fd95336c..c6c843ad686 100644 --- a/lib/editor/tinymce/version.php +++ b/lib/editor/tinymce/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012050800; // The current plugin version (Date: YYYYMMDDXX) +$plugin->version = 2012052400; // The current plugin version (Date: YYYYMMDDXX) $plugin->requires = 2011112900; // Requires this Moodle version $plugin->component = 'editor_tinymce'; // Full name of the plugin (used for diagnostics) -$plugin->release = '3.5.0'; +$plugin->release = '3.5.1.1'; diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml index e322747d541..d122746e2b5 100644 --- a/lib/thirdpartylibs.xml +++ b/lib/thirdpartylibs.xml @@ -32,7 +32,7 @@ editor/tinymce/tiny_mce TinyMCE LGPL - 3.5 + 3.5.1.1 2.1+ From ac29403e398d724f30b0f34b0bcfc09da2278a08 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Wed, 23 May 2012 13:19:10 +0800 Subject: [PATCH 367/455] MDL-33172 - filestorage: Add unit test for breaking oracle functions --- lib/filestorage/tests/file_storage_test.php | 190 ++++++++++++++++++++ lib/tests/filelib_test.php | 1 + 2 files changed, 191 insertions(+) diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index 24529f5f7fe..d571bebba61 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir . '/filelib.php'); +require_once($CFG->dirroot . '/repository/lib.php'); class filestoragelib_testcase extends advanced_testcase { @@ -207,4 +208,193 @@ class filestoragelib_testcase extends advanced_testcase { // still readable? $this->assertEquals($content, $importedfile->get_content()); } + + /** + * TODO: the tests following this line were added to demonstrate specific Oracle problems in + * MDL-33172. They need to be improved to properly evalulate the results of the tests. This is + * tracked in MDL-33326. + */ + private function setup_three_private_files() { + global $USER, $DB; + + $this->resetAfterTest(true); + + $generator = $this->getDataGenerator(); + $user = $generator->create_user(); + $usercontext = context_user::instance($user->id); + $USER = $DB->get_record('user', array('id'=>$user->id)); + // create a user private file + $file1 = new stdClass; + $file1->contextid = $usercontext->id; + $file1->component = 'user'; + $file1->filearea = 'private'; + $file1->itemid = 0; + $file1->filepath = '/'; + $file1->filename = '1.txt'; + $file1->source = 'test'; + + $fs = get_file_storage(); + $userfile1 = $fs->create_file_from_string($file1, 'file1 content'); + $file2 = clone($file1); + $file2->filename = '2.txt'; + $userfile2 = $fs->create_file_from_string($file2, 'file2 content'); + + $file3 = clone($file1); + $file3->filename = '3.txt'; + $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2); + + $user->ctxid = $usercontext->id; + + return $user; + } + + + public function test_get_area_files() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + // Get area files with default options. + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. + $this->assertEquals(4, count($areafiles)); + + // Get area files without a folder. + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false); + // Should be the two files without folder. + $this->assertEquals(3, count($areafiles)); + + // Get area files ordered by id (was breaking on oracle). + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false); + // Should be the two files without folder. + $this->assertEquals(3, count($areafiles)); + + // Test with an itemid with no files + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false); + // Should none + $this->assertEquals(0, count($areafiles)); + } + + public function test_get_area_tree() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + // Get area files with default options. + $areafiles = $fs->get_area_tree($user->ctxid, 'user', 'private', 0); + $areafiles = $fs->get_area_tree($user->ctxid, 'user', 'private', 666); + //TODO: verify result!! MDL-33326 + } + + public function test_get_file_by_id() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + + // Test get_file_by_id. + $filebyid = reset($areafiles); + $shouldbesame = $fs->get_file_by_id($filebyid->get_id()); + $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash()); + } + + public function test_get_file_by_hash() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Test get_file_by_hash + $filebyhash = reset($areafiles); + $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash()); + $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id()); + } + + public function test_get_references_by_storedfile() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + //Test get_file_by_hash + + $testfile = reset($areafiles); + $references = $fs->get_references_by_storedfile($testfile); + //TODO: verify result!! MDL-33326 + } + + public function test_get_external_files() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + $repos = repository::get_instances(array('type'=>'user')); + $userrepository = reset($repos); + $this->assertInstanceOf('repository', $userrepository); + + // this should break on oracle + $fs->get_external_files($userrepository->id, 'id'); + //TODO: verify result!! MDL-33326 + } + + public function test_get_directory_files() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + // This should also break on oracle. + $fs->create_directory($user->ctxid, 'user', 'private', 0, '/'); + //TODO: verify result!! MDL-33326 + + // Don't recurse with dirs + $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id'); + //TODO: verify result!! MDL-33326 + + // Don't recurse without dirs + $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id'); + //TODO: verify result!! MDL-33326 + + // Recurse with dirs + $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id'); + //TODO: verify result!! MDL-33326 + // Recurse without dirs + $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id'); + //TODO: verify result!! MDL-33326 + } + + public function test_search_references() { + $fs = get_file_storage(); + $references = $fs->search_references('testsearch'); + //TODO: verify result!! MDL-33326 + } + + public function test_search_references_count() { + $fs = get_file_storage(); + $references = $fs->search_references_count('testsearch'); + //TODO: verify result!! MDL-33326 + } + + public function test_delete_area_files() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + // Get area files with default options. + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. + $this->assertEquals(4, count($areafiles)); + $fs->delete_area_files($user->ctxid, 'user', 'private'); + + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. + $this->assertEquals(0, count($areafiles)); + } + + public function test_delete_area_files_select() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + // Get area files with default options. + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. + $this->assertEquals(4, count($areafiles)); + $fs->delete_area_files_select($user->ctxid, 'user', 'private', '!= :notitemid', array('notitemid'=>9999)); + + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. + $this->assertEquals(0, count($areafiles)); + } } diff --git a/lib/tests/filelib_test.php b/lib/tests/filelib_test.php index 36207ade16c..53bc3178fe0 100644 --- a/lib/tests/filelib_test.php +++ b/lib/tests/filelib_test.php @@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir . '/filelib.php'); +require_once($CFG->dirroot . '/repository/lib.php'); class filelib_testcase extends advanced_testcase { public function test_format_postdata_for_curlcall() { From 3447100cdb2c0f5170ea0ca15940cd4996af4e28 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Thu, 24 May 2012 01:35:13 -0400 Subject: [PATCH 368/455] MDL-33172 - filestorage: Fix oracle incompatibilites Fixes the following problems: * When we select from two tables with the same named fields (id) and ask to sort by that field, Oracle doesn't know which table to sort frm unless that field is named in the SELECT. Here we do that by explicitly naming the fields. This keeps compatibility with before the reference table was added. * Text comparisong without sql_compare_text --- lib/filestorage/file_storage.php | 64 +++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index ab71c424218..47f87df956c 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -272,7 +272,7 @@ class file_storage { public function get_file_by_id($fileid) { global $DB; - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -293,7 +293,7 @@ class file_storage { public function get_file_by_hash($pathnamehash) { global $DB; - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -370,7 +370,7 @@ class file_storage { */ public function get_external_files($repositoryid, $sort = 'sortorder, itemid, filepath, filename') { global $DB; - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -407,7 +407,7 @@ class file_storage { $itemidsql = ''; } - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -504,7 +504,7 @@ class file_storage { $dirs = $includedirs ? "" : "AND filename <> '.'"; $length = textlib::strlen($filepath); - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -534,7 +534,7 @@ class file_storage { $length = textlib::strlen($filepath); if ($includedirs) { - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -553,7 +553,7 @@ class file_storage { } } - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -772,7 +772,7 @@ class file_storage { unset($filerecord['contenthash']); unset($filerecord['pathnamehash']); - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id @@ -1669,11 +1669,12 @@ class file_storage { */ public function search_references($str) { global $DB; - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id - WHERE r.reference = ? AND (f.component <> ? OR f.filearea <> ?)"; + WHERE ".$DB->sql_compare_text('r.reference').' = '.$DB->sql_compare_text('?')." + AND (f.component <> ? OR f.filearea <> ?)"; $rs = $DB->get_recordset_sql($sql, array($str, 'user', 'draft')); $files = array(); @@ -1699,7 +1700,8 @@ class file_storage { FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id - WHERE r.reference = ? AND (f.component <> ? OR f.filearea <> ?)"; + WHERE ".$DB->sql_compare_text('r.reference').' = '.$DB->sql_compare_text('?')." + AND (f.component <> ? OR f.filearea <> ?)"; $count = $DB->count_records_sql($sql, array($str, 'user', 'draft')); return $count; @@ -1726,11 +1728,12 @@ class file_storage { $reference = self::pack_reference($params); - $sql = "SELECT f.*, r.repositoryid, r.reference + $sql = "SELECT ".self::instance_sql_fields('f', 'r')." FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id - WHERE r.reference = ? AND (f.component <> ? OR f.filearea <> ?)"; + WHERE ".$DB->sql_compare_text('r.reference').' = '.$DB->sql_compare_text('?')." + AND (f.component <> ? OR f.filearea <> ?)"; $rs = $DB->get_recordset_sql($sql, array($reference, 'user', 'draft')); $files = array(); @@ -1769,7 +1772,8 @@ class file_storage { FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id - WHERE r.reference = ? AND (f.component <> ? OR f.filearea <> ?)"; + WHERE ".$DB->sql_compare_text('r.reference').' = '.$DB->sql_compare_text('?')." + AND (f.component <> ? OR f.filearea <> ?)"; $count = $DB->count_records_sql($sql, array($reference, 'user', 'draft')); return $count; @@ -1875,5 +1879,37 @@ class file_storage { mtrace('done.'); } } + + /** + * Get the sql formated fields for a file instance to be created from a + * {files} and {files_refernece} join. + * + * @param string $filesprefix the table prefix for the {files} table + * @param string $filesreferenceprefix the table prefix for the {files_reference} table + * @return string the sql to go after a SELECT + */ + private static function instance_sql_fields($filesprefix, $filesreferenceprefix) { + // Note, these fieldnames MUST NOT overlap between the two tables, + // else problems like MDL-33172 occur. + $filefields = array('contenthash', 'pathnamehash', 'contextid', 'component', 'filearea', + 'itemid', 'filepath', 'filename', 'userid', 'filesize', 'mimetype', 'status', 'source', + 'author', 'license', 'timecreated', 'timemodified', 'sortorder', 'referencefileid', + 'referencelastsync', 'referencelifetime'); + + $referencefields = array('repositoryid', 'reference'); + + // id is specifically named to prevent overlaping between the two tables. + $fields = array(); + $fields[] = $filesprefix.'.id AS id'; + foreach ($filefields as $field) { + $fields[] = "{$filesprefix}.{$field}"; + } + + foreach ($referencefields as $field) { + $fields[] = "{$filesreferenceprefix}.{$field}"; + } + + return implode(', ', $fields); + } } From 6347a6216d919316ae8f71b29a6c02983d662250 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Fri, 25 May 2012 11:37:07 +1200 Subject: [PATCH 369/455] MDL-33172: Fixed whitespace --- lib/filestorage/file_storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index 47f87df956c..edac5a52517 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -1733,7 +1733,7 @@ class file_storage { LEFT JOIN {files_reference} r ON f.referencefileid = r.id WHERE ".$DB->sql_compare_text('r.reference').' = '.$DB->sql_compare_text('?')." - AND (f.component <> ? OR f.filearea <> ?)"; + AND (f.component <> ? OR f.filearea <> ?)"; $rs = $DB->get_recordset_sql($sql, array($reference, 'user', 'draft')); $files = array(); From c291e996c8ab156e79d4833ec78384a6ed6fdc21 Mon Sep 17 00:00:00 2001 From: AMOS bot Date: Fri, 25 May 2012 00:31:16 +0000 Subject: [PATCH 370/455] Automatically generated installer lang files --- install/lang/pt_br/install.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/install/lang/pt_br/install.php b/install/lang/pt_br/install.php index 15b6f3de0a0..fa8b9b95b99 100644 --- a/install/lang/pt_br/install.php +++ b/install/lang/pt_br/install.php @@ -34,6 +34,7 @@ $string['admindirname'] = 'Diretório admin'; $string['availablelangs'] = 'Lista de idiomas disponíveis'; $string['chooselanguagehead'] = 'Escolha um idioma'; $string['chooselanguagesub'] = 'Por favor, escolha o idioma para a instalação.Este idioma também será utilizado como idioma padrão do site, embora você possa mudar mais tarde.'; +$string['clialreadyconfigured'] = 'Arquivo config.php já existente. Por favor use admin/cli/install_database.php se você quer instalar este site'; $string['clialreadyinstalled'] = 'O arquivo config.php já existe, por favor use admin/cli/upgrade.php, se você quiser atualizar o seu site.'; $string['cliinstallheader'] = 'Programa de instalação por linha de comando do Moodle {$a}'; $string['databasehost'] = 'Host da base de dados'; @@ -82,7 +83,7 @@ $string['phpversionhelp'] = '

                          Moodle requer a versão 4.3.0 de PHP ou posterio

                          Atualize a versão do PHP!

                          (atenção, a versão 5.0.x tem muitos problemas - use a versão 5.1.0 ou a 4.4)'; $string['welcomep10'] = '{$a->installername} ({$a->installerversion})'; -$string['welcomep20'] = 'Se você chegou nesta página, o pacote {$a->packname} {$a->packversion} foi instalado. Parabéns!'; +$string['welcomep20'] = 'Você está vendo esa página pois instalou com sucesso o pacote{$a->packname} {$a->packversion}. Parabéns!'; $string['welcomep30'] = 'Esta versão do {$a->installername} inclui as aplicações para a criação de um ambiente em que Moodle possa operar:'; $string['welcomep40'] = 'O pacote inclui também o Moodle {$a->moodlerelease} ({$a->moodleversion}).'; $string['welcomep50'] = 'O uso das aplicações incluídas neste pacote é regulamentado pelas respectivas licenças. O instalador completo {$a->installername} é open source e é distribuído com uma licença GPL.'; From 4c88645920fab4e76fd265174843b4c1bcf022c5 Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Thu, 24 May 2012 16:05:30 +0800 Subject: [PATCH 371/455] MDL-33173 Filepicker: renamed private files edit page to main page --- blocks/private_files/block_private_files.php | 2 +- lib/navigationlib.php | 2 +- user/files.php | 36 +++++++--- user/{filesedit_form.php => files_form.php} | 2 +- user/filesedit.php | 74 -------------------- 5 files changed, 31 insertions(+), 85 deletions(-) rename user/{filesedit_form.php => files_form.php} (97%) delete mode 100644 user/filesedit.php diff --git a/blocks/private_files/block_private_files.php b/blocks/private_files/block_private_files.php index 594f27600f5..bf4cc89c10b 100644 --- a/blocks/private_files/block_private_files.php +++ b/blocks/private_files/block_private_files.php @@ -62,7 +62,7 @@ class block_private_files extends block_base { $renderer = $this->page->get_renderer('block_private_files'); $this->content->text = $renderer->private_files_tree(); if (has_capability('moodle/user:manageownfiles', $this->context)) { - $this->content->text .= $OUTPUT->single_button(new moodle_url('/user/filesedit.php', array('returnurl'=>$PAGE->url->out())), get_string('myfilesmanage'), 'get'); + $this->content->text .= $OUTPUT->single_button(new moodle_url('/user/files.php', array('returnurl'=>$PAGE->url->out())), get_string('myfilesmanage'), 'get'); } $this->content->footer = ''; diff --git a/lib/navigationlib.php b/lib/navigationlib.php index 059e3a4738a..d24b735436d 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -2324,7 +2324,7 @@ class global_navigation extends navigation_node { $context = get_context_instance(CONTEXT_USER, $USER->id); if ($iscurrentuser && has_capability('moodle/user:manageownfiles', $context)) { - $url = new moodle_url('/user/filesedit.php'); + $url = new moodle_url('/user/files.php'); $usernode->add(get_string('myfiles'), $url, self::TYPE_SETTING); } diff --git a/user/files.php b/user/files.php index 4bc2ba618ff..a5a49b9a124 100644 --- a/user/files.php +++ b/user/files.php @@ -16,22 +16,33 @@ // along with Moodle. If not, see . /** - * View private user files + * Manage files in folder in private area. * - * @package moodlecore + * @package moodle * @copyright 2010 Petr Skoda (http://skodak.org) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require('../config.php'); +require_once("$CFG->dirroot/user/files_form.php"); +require_once("$CFG->dirroot/repository/lib.php"); require_login(); if (isguestuser()) { die(); } +$returnurl = optional_param('returnurl', '', PARAM_URL); +$returnbutton = true; + +if (empty($returnurl)) { + $returnbutton = false; + $returnurl = new moodle_url('/user/files.php'); +} + $context = get_context_instance(CONTEXT_USER, $USER->id); require_capability('moodle/user:manageownfiles', $context); + $title = get_string('myfiles'); $struser = get_string('user'); @@ -42,13 +53,22 @@ $PAGE->set_heading($title); $PAGE->set_pagelayout('mydashboard'); $PAGE->set_pagetype('user-files'); +$data = new stdClass(); +$data->returnurl = $returnurl; +$options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*'); +file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0); + +$mform = new user_files_form(null, array('data'=>$data, 'options'=>$options, 'cancelbutton'=>$returnbutton)); + +if ($mform->is_cancelled()) { + redirect($returnurl); +} else if ($formdata = $mform->get_data()) { + $formdata = file_postupdate_standard_filemanager($formdata, 'files', $options, $context, 'user', 'private', 0); + redirect($returnurl); +} + echo $OUTPUT->header(); echo $OUTPUT->box_start('generalbox'); - -$renderer = $PAGE->get_renderer('core', 'user'); -echo $renderer->user_files_tree(); - -echo $OUTPUT->single_button(new moodle_url('/user/filesedit.php'), get_string('myfilesmanage'), 'get'); - +$mform->display(); echo $OUTPUT->box_end(); echo $OUTPUT->footer(); diff --git a/user/filesedit_form.php b/user/files_form.php similarity index 97% rename from user/filesedit_form.php rename to user/files_form.php index 13cc0418c3e..535105607c2 100644 --- a/user/filesedit_form.php +++ b/user/files_form.php @@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/formslib.php"); -class user_filesedit_form extends moodleform { +class user_files_form extends moodleform { function definition() { $mform = $this->_form; diff --git a/user/filesedit.php b/user/filesedit.php deleted file mode 100644 index 22c61235f6b..00000000000 --- a/user/filesedit.php +++ /dev/null @@ -1,74 +0,0 @@ -. - -/** - * Manage files in folder in private area. - * - * @package moodle - * @copyright 2010 Petr Skoda (http://skodak.org) - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -require('../config.php'); -require_once("$CFG->dirroot/user/filesedit_form.php"); -require_once("$CFG->dirroot/repository/lib.php"); - -require_login(); -if (isguestuser()) { - die(); -} - -$returnurl = optional_param('returnurl', '', PARAM_URL); -$returnbutton = true; - -if (empty($returnurl)) { - $returnbutton = false; - $returnurl = new moodle_url('/user/filesedit.php'); -} - -$context = get_context_instance(CONTEXT_USER, $USER->id); -require_capability('moodle/user:manageownfiles', $context); - -$title = get_string('myfiles'); -$struser = get_string('user'); - -$PAGE->set_url('/user/filesedit.php'); -$PAGE->set_context($context); -$PAGE->set_title($title); -$PAGE->set_heading($title); -$PAGE->set_pagelayout('mydashboard'); -$PAGE->set_pagetype('user-files'); - -$data = new stdClass(); -$data->returnurl = $returnurl; -$options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*'); -file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0); - -$mform = new user_filesedit_form(null, array('data'=>$data, 'options'=>$options, 'cancelbutton'=>$returnbutton)); - -if ($mform->is_cancelled()) { - redirect($returnurl); -} else if ($formdata = $mform->get_data()) { - $formdata = file_postupdate_standard_filemanager($formdata, 'files', $options, $context, 'user', 'private', 0); - redirect($returnurl); -} - -echo $OUTPUT->header(); -echo $OUTPUT->box_start('generalbox'); -$mform->display(); -echo $OUTPUT->box_end(); -echo $OUTPUT->footer(); From f5a68663db0125ba954067ffbd7aa1a9c3407737 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 25 May 2012 10:03:33 +0800 Subject: [PATCH 372/455] MDL-33173 files: correct @package name --- user/files.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user/files.php b/user/files.php index a5a49b9a124..5da4d8d4744 100644 --- a/user/files.php +++ b/user/files.php @@ -18,7 +18,7 @@ /** * Manage files in folder in private area. * - * @package moodle + * @package core_files * @copyright 2010 Petr Skoda (http://skodak.org) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 2528e8e52f043e2704c77088ea9dc6fb1bae91aa Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 25 May 2012 10:09:09 +0800 Subject: [PATCH 373/455] MDL-33139 mod_forum: fix minor whitespace problem --- mod/forum/post.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/forum/post.php b/mod/forum/post.php index a57633f29a2..7e864e51845 100644 --- a/mod/forum/post.php +++ b/mod/forum/post.php @@ -647,7 +647,7 @@ if ($fromform = $mform_post->get_data()) { if (!empty($message)) { // if we're printing stuff about the file upload $timemessage = 4; } - + if ($realpost->userid == $USER->id) { $message .= '
                          '.get_string("postupdated", "forum"); } else { From 5e963820a593312ecd9629b4b47adfdb9efec742 Mon Sep 17 00:00:00 2001 From: Vadim Dvorovenko Date: Wed, 16 May 2012 18:03:09 +0700 Subject: [PATCH 374/455] MDL-29836 webservices: use individual string To allow accurate transalation --- admin/settings/plugins.php | 2 +- lang/en/webservice.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index 96d045535fa..638aa4009b7 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -370,7 +370,7 @@ if ($hassiteconfig) { // to set the page layout on all admin pages. // $wsdoclink = $OUTPUT->doc_link('How_to_get_a_security_key'); $url = new moodle_url(get_docs_url('How_to_get_a_security_key')); - $wsdoclink = html_writer::tag('a', new lang_string('supplyinfo'),array('href'=>$url)); + $wsdoclink = html_writer::tag('a', new lang_string('supplyinfo', 'webservice'), array('href'=>$url)); $temp->add(new admin_setting_configcheckbox('enablewsdocumentation', new lang_string('enablewsdocumentation', 'admin'), new lang_string('configenablewsdocumentation', 'admin', $wsdoclink), false)); $ADMIN->add('webservicesettings', $temp); diff --git a/lang/en/webservice.php b/lang/en/webservice.php index 58a10cb89b3..2b72efe56a5 100644 --- a/lang/en/webservice.php +++ b/lang/en/webservice.php @@ -170,6 +170,7 @@ $string['serviceusersmatching'] = 'Authorised users matching'; $string['serviceuserssettings'] = 'Change settings for the authorised users'; $string['simpleauthlog'] = 'Simple authentication login'; $string['step'] = 'Step'; +$string['supplyinfo'] = 'More details'; $string['testauserwithtestclientdescription'] = 'Simulate external access to the service using the web service test client. Before doing so, login as a user with the moodle/webservice:createtoken capability and obtain the security key (token) via My profile settings. You will use this token in the test client. In the test client, also choose an enabled protocol with the token authentication. WARNING: The functions that you test WILL BE EXECUTED for this user, so be careful what you choose to test!'; $string['testclient'] = 'Web service test client'; $string['testclientdescription'] = '* The web service test client executes the functions for REAL. Do not test functions that you don\'t know.
                          * All existing web service functions are not yet implemented into the test client.
                          * In order to check that a user cannot access some functions, you can test some functions that you didn\'t allow.
                          * To see clearer error messages set the debugging to {$a->mode} into {$a->atag}
                          * Access the {$a->amfatag}.'; From 488656491d9de95a068006f0acfa35afbac8902e Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 25 May 2012 10:36:43 +0800 Subject: [PATCH 375/455] MDL-29836 webservice: version bump to pickup new string --- version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.php b/version.php index c684104095c..b9bf9429178 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052200.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052200.01; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From c46da759172ef873662f7debaa098e37c95efac9 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 25 May 2012 11:08:14 +0800 Subject: [PATCH 376/455] MDL-28557 - calendar: fix trivial whitespace issue --- calendar/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calendar/lib.php b/calendar/lib.php index 8307c09bd03..184449a06ba 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -1393,7 +1393,7 @@ function calendar_set_filters(array $courseeventsfrom, $ignorefilters = false) { $group = true; } else if ($isloggedin) { $groupids = array(); - + // We already have the courses to examine in $courses // For each course... foreach ($courseeventsfrom as $courseid => $course) { From 0479a2873e516fc199c87004a299acce4c2dbf2e Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Fri, 25 May 2012 11:25:57 +0800 Subject: [PATCH 377/455] MDL-33324 Filepicker : removed redundant parantheses. --- repository/lib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/repository/lib.php b/repository/lib.php index d97b7521207..1bcfa7a7ad3 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1775,9 +1775,9 @@ abstract class repository { $defaultfoldericon = $OUTPUT->pix_url(file_folder_icon(24))->out(false); // prepare $listing['path'] or $listing->path - if (is_array($listing) && isset($listing['path']) && is_array(($listing['path']))) { + if (is_array($listing) && isset($listing['path']) && is_array((listing['path'])) { $path = &$listing['path']; - } else if (is_object($listing) && isset($listing->path) && is_array(($listing->path))) { + } else if (is_object($listing) && isset($listing->path) && is_array($listing->path)) { $path = &$listing->path; } if (isset($path)) { @@ -1792,10 +1792,10 @@ abstract class repository { } // prepare $listing['list'] or $listing->list - if (is_array($listing) && isset($listing['list']) && is_array(($listing['list']))) { + if (is_array($listing) && isset($listing['list']) && is_array($listing['list'])) { $listing['list'] = array_values($listing['list']); // convert to array $files = &$listing['list']; - } else if (is_object($listing) && isset($listing->list) && is_array(($listing->list))) { + } else if (is_object($listing) && isset($listing->list) && is_array($listing->list)) { $listing->list = array_values($listing->list); // convert to array $files = &$listing->list; } else { From 09cb95f8618b2cb65e422a9f9f8e637de4fcac4b Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Fri, 25 May 2012 11:44:04 +0800 Subject: [PATCH 378/455] MDL-33324 Filepicker : fixed syntax. --- repository/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repository/lib.php b/repository/lib.php index 1bcfa7a7ad3..3abca8d9a75 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -1775,7 +1775,7 @@ abstract class repository { $defaultfoldericon = $OUTPUT->pix_url(file_folder_icon(24))->out(false); // prepare $listing['path'] or $listing->path - if (is_array($listing) && isset($listing['path']) && is_array((listing['path'])) { + if (is_array($listing) && isset($listing['path']) && is_array($listing['path'])) { $path = &$listing['path']; } else if (is_object($listing) && isset($listing->path) && is_array($listing->path)) { $path = &$listing->path; From 4631e39533ba154546a84f5a81fe56d89dc658f0 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 25 May 2012 18:07:10 +0800 Subject: [PATCH 379/455] on-demand release 2.3dev --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index b9bf9429178..f9992a16395 100644 --- a/version.php +++ b/version.php @@ -30,11 +30,11 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052200.01; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052500.00; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes -$release = '2.3dev (Build: 20120522)'; // Human-friendly version name +$release = '2.3dev (Build: 20120525)'; // Human-friendly version name $branch = '23'; // this version's branch $maturity = MATURITY_ALPHA; // this version's maturity level From 9f3015ecf828a543eb2745b0ba632c4b236f6cbe Mon Sep 17 00:00:00 2001 From: Ruslan Kabalin Date: Thu, 24 May 2012 11:20:57 +0100 Subject: [PATCH 380/455] MDL-32824: Make dragdrop work correctly with section titles/links Initially, the default section title was swapped within the course format javascript functions. Though some section titles may be custom and does not require swapping, in addition they may have links to single section view. This introduces some callback functions for define what needs to be done in sections libs and js files. --- course/format/renderer.php | 25 ++++++++++++++-------- course/format/topics/format.js | 27 ++++++++++++++++++++---- course/format/topics/lib.php | 21 +++++++++++++++++++ course/format/weeks/format.js | 32 +++++++++++++++++++++-------- course/format/weeks/lib.php | 21 +++++++++++++++++++ course/rest.php | 9 ++++++++ course/yui/coursebase/coursebase.js | 15 ++++++++++++++ course/yui/dragdrop/dragdrop.js | 18 +++++++++++++--- 8 files changed, 145 insertions(+), 23 deletions(-) diff --git a/course/format/renderer.php b/course/format/renderer.php index d969e8bc7c7..986cad95151 100644 --- a/course/format/renderer.php +++ b/course/format/renderer.php @@ -56,6 +56,21 @@ abstract class format_section_renderer_base extends plugin_renderer_base { */ abstract protected function page_title(); + /** + * Generate the section title + * + * @param stdClass $section The course_section entry from DB + * @param stdClass $course The course entry from DB + * @return string HTML to output. + */ + public function section_title($section, $course) { + $title = get_section_name($course, $section); + if ($section->section != 0 && $course->coursedisplay == COURSE_DISPLAY_MULTIPAGE) { + $title = html_writer::link(course_get_url($course, $section->section), $title); + } + return $title; + } + /** * Generate the content to displayed on the right part of a section * before course modules are included @@ -106,7 +121,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base { * * @param stdClass $section The course_section entry from DB * @param stdClass $course The course entry from DB - * @param bool $onsectionpage true if being printed on a section page + * @param bool $onsectionpage true if being printed on a single-section page * @return string HTML to output. */ protected function section_header($section, $course, $onsectionpage) { @@ -115,7 +130,6 @@ abstract class format_section_renderer_base extends plugin_renderer_base { $o = ''; $currenttext = ''; $sectionstyle = ''; - $linktitle = false; if ($section->section != 0) { // Only in the non-general sections. @@ -124,7 +138,6 @@ abstract class format_section_renderer_base extends plugin_renderer_base { } else if ($course->marker == $section->section) { $sectionstyle = ' current'; } - $linktitle = ($course->coursedisplay == COURSE_DISPLAY_MULTIPAGE); } $o.= html_writer::start_tag('li', array('id' => 'section-'.$section->section, @@ -138,11 +151,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base { $o.= html_writer::start_tag('div', array('class' => 'content')); if (!$onsectionpage) { - $title = get_section_name($course, $section); - if ($linktitle) { - $title = html_writer::link(course_get_url($course, $section->section), $title); - } - $o.= $this->output->heading($title, 3, 'sectionname'); + $o.= $this->output->heading($this->section_title($section, $course), 3, 'sectionname'); } $o.= html_writer::start_tag('div', array('class' => 'summary')); diff --git a/course/format/topics/format.js b/course/format/topics/format.js index 218492df6d6..71e87972308 100644 --- a/course/format/topics/format.js +++ b/course/format/topics/format.js @@ -1,4 +1,4 @@ -// Javascript functions for course format +// Javascript functions for Topics course format M.course = M.course || {}; @@ -36,13 +36,32 @@ M.course.format.get_config = function() { M.course.format.swap_sections = function(Y, node1, node2) { var CSS = { COURSECONTENT : 'course-content', - LEFT : 'left', SECTIONADDMENUS : 'section_add_menus' }; var sectionlist = Y.Node.all('.'+CSS.COURSECONTENT+' '+M.course.format.get_section_selector(Y)); - // Swap left block - sectionlist.item(node1).one('.'+CSS.LEFT).swap(sectionlist.item(node2).one('.'+CSS.LEFT)); // Swap menus sectionlist.item(node1).one('.'+CSS.SECTIONADDMENUS).swap(sectionlist.item(node2).one('.'+CSS.SECTIONADDMENUS)); } + +/** + * Process sections after ajax response + * + * @param {YUI} Y YUI3 instance + * @param {array} response ajax response + * @param {string} sectionfrom first affected section + * @param {string} sectionto last affected section + * @return void + */ +M.course.format.process_sections = function(Y, sectionlist, response, sectionfrom, sectionto) { + var CSS = { + SECTIONNAME : 'sectionname' + }; + + if (response.action == 'move') { + // update titles in all affected sections + for (var i = sectionfrom; i <= sectionto; i++) { + sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]); + } + } +} diff --git a/course/format/topics/lib.php b/course/format/topics/lib.php index 710abaf318e..e8632fcab8b 100644 --- a/course/format/topics/lib.php +++ b/course/format/topics/lib.php @@ -80,3 +80,24 @@ function callback_topics_ajax_support() { $ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0); return $ajaxsupport; } + +/** + * Callback function to do some action after section move + * + * @param stdClass $course The course entry from DB + * @return array This will be passed in ajax respose. + */ +function callback_topics_ajax_section_move($course) { + global $COURSE, $PAGE; + + $titles = array(); + rebuild_course_cache($course->id); + $modinfo = get_fast_modinfo($COURSE); + $renderer = $PAGE->get_renderer('format_topics'); + if ($renderer && ($sections = $modinfo->get_section_info_all())) { + foreach ($sections as $number => $section) { + $titles[$number] = $renderer->section_title($section, $course); + } + } + return array('sectiontitles' => $titles, 'action' => 'move'); +} diff --git a/course/format/weeks/format.js b/course/format/weeks/format.js index 28aed42aa42..28ec82a2b4f 100644 --- a/course/format/weeks/format.js +++ b/course/format/weeks/format.js @@ -1,4 +1,4 @@ -// Javascript functions for course format +// Javascript functions for Weeks course format M.course = M.course || {}; @@ -36,16 +36,32 @@ M.course.format.get_config = function() { M.course.format.swap_sections = function(Y, node1, node2) { var CSS = { COURSECONTENT : 'course-content', - LEFT : 'left', - SECTIONADDMENUS : 'section_add_menus', - WEEKDATES: 'weekdates' + SECTIONADDMENUS : 'section_add_menus' }; var sectionlist = Y.Node.all('.'+CSS.COURSECONTENT+' '+M.course.format.get_section_selector(Y)); - // Swap left block - sectionlist.item(node1).one('.'+CSS.LEFT).swap(sectionlist.item(node2).one('.'+CSS.LEFT)); // Swap menus sectionlist.item(node1).one('.'+CSS.SECTIONADDMENUS).swap(sectionlist.item(node2).one('.'+CSS.SECTIONADDMENUS)); - // Swap week dates - sectionlist.item(node1).one('.'+CSS.WEEKDATES).swap(sectionlist.item(node2).one('.'+CSS.WEEKDATES)); +} + +/** + * Process sections after ajax response + * + * @param {YUI} Y YUI3 instance + * @param {array} response ajax response + * @param {string} sectionfrom first affected section + * @param {string} sectionto last affected section + * @return void + */ +M.course.format.process_sections = function(Y, sectionlist, response, sectionfrom, sectionto) { + var CSS = { + SECTIONNAME : 'sectionname' + }; + + if (response.action == 'move') { + // update titles in all affected sections + for (var i = sectionfrom; i <= sectionto; i++) { + sectionlist.item(i).one('.'+CSS.SECTIONNAME).setContent(response.sectiontitles[i]); + } + } } diff --git a/course/format/weeks/lib.php b/course/format/weeks/lib.php index 9201c9e2d6f..6619622383b 100644 --- a/course/format/weeks/lib.php +++ b/course/format/weeks/lib.php @@ -102,3 +102,24 @@ function callback_weeks_ajax_support() { $ajaxsupport->testedbrowsers = array('MSIE' => 6.0, 'Gecko' => 20061111, 'Safari' => 531, 'Chrome' => 6.0); return $ajaxsupport; } + +/** + * Callback function to do some action after section move + * + * @param stdClass $course The course entry from DB + * @return array This will be passed in ajax respose. + */ +function callback_weeks_ajax_section_move($course) { + global $COURSE, $PAGE; + + $titles = array(); + rebuild_course_cache($course->id); + $modinfo = get_fast_modinfo($COURSE); + $renderer = $PAGE->get_renderer('format_weeks'); + if ($renderer && ($sections = $modinfo->get_section_info_all())) { + foreach ($sections as $number => $section) { + $titles[$number] = $renderer->section_title($section, $course); + } + } + return array('sectiontitles' => $titles, 'action' => 'move'); +} diff --git a/course/rest.php b/course/rest.php index 5152563ad92..6efd228db65 100644 --- a/course/rest.php +++ b/course/rest.php @@ -89,6 +89,15 @@ switch($requestmethod) { case 'move': move_section_to($course, $id, $value); + // See if format wants to do something about it + $libfile = $CFG->dirroot.'/course/format/'.$course->format.'/lib.php'; + $functionname = 'callback_'.$course->format.'_ajax_section_move'; + if (!function_exists($functionname) && file_exists($libfile)) { + require_once $libfile; + } + if (function_exists($functionname)) { + echo json_encode($functionname($course)); + } break; } rebuild_course_cache($course->id); diff --git a/course/yui/coursebase/coursebase.js b/course/yui/coursebase/coursebase.js index 3dbbf0bf0a8..b02c36263c0 100644 --- a/course/yui/coursebase/coursebase.js +++ b/course/yui/coursebase/coursebase.js @@ -68,6 +68,21 @@ YUI.add('moodle-course-coursebase', function(Y) { return null; } + /** + * Process sections after ajax response (should be defined in format.js) + * If some response is expected, we pass it over to format, as it knows better + * hot to process it. + * + * @param {YUI} Y YUI3 instance + * @param {NodeList} list of sections + * @param {array} response ajax response + * @param {string} sectionfrom first affected section + * @param {string} sectionto last affected section + * @return void + */ + M.course.format.process_sections = M.course.format.process_sections || function(Y, sectionlist, response, sectionfrom, sectionto) { + return null; + } /** * Get sections config for this format, for examples see function definition diff --git a/course/yui/dragdrop/dragdrop.js b/course/yui/dragdrop/dragdrop.js index 012355ece9f..b054ef68578 100644 --- a/course/yui/dragdrop/dragdrop.js +++ b/course/yui/dragdrop/dragdrop.js @@ -172,9 +172,16 @@ YUI.add('moodle-course-dragdrop', function(Y) { lightbox.show(); }, success: function(tid, response) { - window.setTimeout(function(e) { - lightbox.hide(); - }, 250); + // Update section titles, we can't simply swap them as + // they might have custom title + try { + var responsetext = Y.JSON.parse(response.responseText); + if (responsetext.error) { + new M.core.ajaxException(responsetext); + } + M.course.format.process_sections(Y, sectionlist, responsetext, loopstart, loopend); + } catch (e) {} + // Classic bubble sort algorithm is applied to the section // nodes between original drag node location and the new one. do { @@ -193,6 +200,11 @@ YUI.add('moodle-course-dragdrop', function(Y) { } loopend = loopend - 1; } while (swapped); + + // Finally, hide the lightbox + window.setTimeout(function(e) { + lightbox.hide(); + }, 250); }, failure: function(tid, response) { this.ajax_failure(response); From a252a148352564c8203fe18f984f19965010a303 Mon Sep 17 00:00:00 2001 From: Ruslan Kabalin Date: Tue, 22 May 2012 17:07:22 +0100 Subject: [PATCH 381/455] MDL-33192: Prevent global DDM conflicting with others drag-drop instances. --- lib/yui/dragdrop/dragdrop.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/yui/dragdrop/dragdrop.js b/lib/yui/dragdrop/dragdrop.js index 930f60042f3..d1135f3db3b 100644 --- a/lib/yui/dragdrop/dragdrop.js +++ b/lib/yui/dragdrop/dragdrop.js @@ -66,14 +66,23 @@ YUI.add('moodle-core-dragdrop', function(Y) { return new M.core.exception(e); }, + in_group: function(target) { + var ret = false; + Y.each(this.groups, function(v, k) { + if (target._groups[v]) { + ret = true; + } + }, this); + return ret; + }, /* * Drag-dropping related functions */ global_drag_start : function(e) { // Get our drag object var drag = e.target; - // Check that drop object belong to correct group - if (!drag.target.inGroup(this.groups)) { + // Check that drag object belongs to correct group + if (!this.in_group(drag)) { return; } // Set some general styles here @@ -89,8 +98,8 @@ YUI.add('moodle-core-dragdrop', function(Y) { global_drag_end : function(e) { var drag = e.target; - // Check that drop object belong to correct group - if (!drag.target.inGroup(this.groups)) { + // Check that drag object belongs to correct group + if (!this.in_group(drag)) { return; } //Put our general styles back @@ -103,8 +112,8 @@ YUI.add('moodle-core-dragdrop', function(Y) { global_drag_drag : function(e) { var drag = e.target; - // Check that drop object belong to correct group - if (!drag.target.inGroup(this.groups)) { + // Check that drag object belongs to correct group + if (!this.in_group(drag)) { return; } //Get the last y point From 9e302b63b9fc4b3db2ecd5b49f1fd92d05d7c809 Mon Sep 17 00:00:00 2001 From: Helen Foster Date: Sun, 27 May 2012 17:28:43 +0200 Subject: [PATCH 382/455] MDL-33120 book: Amend module strings Al the changes are fixes but numberingoptions_help that is one change of string key too, hence we instruct AMOS to move it. AMOS BEGIN MOV [numberingoptions_help,mod_book],[numberingoptions_desc,mod_book] AMOS END --- mod/book/lang/en/book.php | 55 ++++--------------- .../lang/en/booktool_exportimscp.php | 2 +- .../lang/en/booktool_importhtml.php | 12 ++-- 3 files changed, 17 insertions(+), 52 deletions(-) diff --git a/mod/book/lang/en/book.php b/mod/book/lang/en/book.php index f737bda401f..5d29b71943c 100644 --- a/mod/book/lang/en/book.php +++ b/mod/book/lang/en/book.php @@ -38,74 +38,39 @@ $string['pluginname'] = 'Book'; $string['pluginadministration'] = 'Book administration'; $string['toc'] = 'Table of contents'; -$string['faq'] = 'Book FAQ'; -$string['faq_help'] = ' -*Why only two levels?* - -Two levels are generally enough for all books, three levels would lead to poorly structured documents. Book module is designed for -creation of short multipage study materials. It is usually better to use PDF format for longer documents. The easiest way to create PDFs are -virtual printers (see -PDFCreator, -PDFFactory, -Adobe Acrobat, -etc.). - -*Can students edit books?* - -Only teachers can create and edit books. There are no plans to implement student editing for books, but somebody may create something -similar for students (Portfolio?). The main reason is to keep Book module as simple as possible. - -*How do I search the books?* - -At present there is only one way, use browser\'s search capability in print page. Global searching is now possible only in Moodle forums. -It would be nice to have global searching for all resources including books, any volunteers? - -*My titles do not fit on one line.* - -Either rephrase your titles or ask your site admin to change TOC -width. It is defined globally for all books in module configuration -page.'; - $string['customtitles'] = 'Custom titles'; -$string['customtitles_help'] = 'Chapter titles are displayed automatically only in TOC.'; +$string['customtitles_help'] = 'Normally the chapter title is displayed in the table of contents (TOC) AND as a heading above the content. +If the custom titles checkbox is ticked, the chapter title is NOT displayed as a heading above the content. A different title (perhaps longer than the chapter title) may be entered as part of the content.'; $string['chapters'] = 'Chapters'; $string['editingchapter'] = 'Editing chapter'; $string['chaptertitle'] = 'Chapter title'; $string['content'] = 'Content'; $string['subchapter'] = 'Subchapter'; - -$string['numbering'] = 'Chapter numbering'; -$string['numbering_help'] = '* None - chapter and subchapter titles are not formatted at all, use if you want to define special numbering styles. For example letters: in chapter title type "A First Chapter", "A.1 Some Subchapter",... -* Numbers - chapters and subchapters are numbered (1, 1.1, 1.2, 2, ...) -* Bullets - subchapters are indented and displayed with bullets -* Indented - subchapters are indented'; - +$string['numbering'] = 'Chapter formatting'; +$string['numbering_help'] = '* None - Chapter and subchapter titles have no formatting +* Numbers - Chapters and subchapter titles are numbered 1, 1.1, 1.2, 2, ... +* Bullets - Subchapters are indented and displayed with bullets in the table of contents +* Indented - Subchapters are indented in the table of contents'; $string['numbering0'] = 'None'; $string['numbering1'] = 'Numbers'; $string['numbering2'] = 'Bullets'; $string['numbering3'] = 'Indented'; -$string['numberingoptions'] = 'Available numbering options'; -$string['numberingoptions_help'] = 'Select numbering options that should be available when creating new books.'; - +$string['numberingoptions'] = 'Available options for chapter formatting'; +$string['numberingoptions_desc'] = 'Options for displaying chapters and subchapters in the table of contents'; $string['chapterscount'] = 'Chapters'; - $string['addafter'] = 'Add new chapter'; $string['confchapterdelete'] = 'Do you really want to delete this chapter?'; $string['confchapterdeleteall'] = 'Do you really want to delete this chapter and all its subchapters?'; - $string['top'] = 'top'; - $string['navprev'] = 'Previous'; $string['navnext'] = 'Next'; $string['navexit'] = 'Exit book'; - $string['book:addinstance'] = 'Add a new book'; $string['book:read'] = 'Read book'; $string['book:edit'] = 'Edit book chapters'; $string['book:viewhiddenchapters'] = 'View hidden book chapters'; - -$string['errorchapter'] = 'Error reading book chapter.'; +$string['errorchapter'] = 'Error reading chapter of book.'; $string['page-mod-book-x'] = 'Any book module page'; diff --git a/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php b/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php index 2273e55db7d..5b6a50504cb 100644 --- a/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php +++ b/mod/book/tool/exportimscp/lang/en/booktool_exportimscp.php @@ -26,5 +26,5 @@ defined('MOODLE_INTERNAL') || die; $string['exportimscp:export'] = 'Export book as IMS content package'; $string['generateimscp'] = 'Generate IMS CP'; -$string['nochapters'] = 'No book chapters found, can not export to IMS CP.'; +$string['nochapters'] = 'No book chapters found, so unable to export to IMS CP.'; $string['pluginname'] = 'Book IMS CP export'; diff --git a/mod/book/tool/importhtml/lang/en/booktool_importhtml.php b/mod/book/tool/importhtml/lang/en/booktool_importhtml.php index c5640092b80..bbd811dc1ab 100644 --- a/mod/book/tool/importhtml/lang/en/booktool_importhtml.php +++ b/mod/book/tool/importhtml/lang/en/booktool_importhtml.php @@ -25,16 +25,16 @@ defined('MOODLE_INTERNAL') || die; $string['doimport'] = 'Import'; -$string['errornochapters'] = 'Can not find chapters in selected file'; -$string['import'] = 'Import from HTML'; +$string['errornochapters'] = 'Cannot find chapters in selected file'; +$string['import'] = 'Import chapter'; $string['importhtml:import'] = 'Import chapters'; $string['importing'] = 'Importing'; $string['importingchapters'] = 'Importing chapters into book'; -$string['pluginname'] = 'Book HTML import'; +$string['pluginname'] = 'Book chapter import'; $string['relinking'] = 'Relinking'; $string['type'] = 'Type'; $string['typeonefile'] = 'One HTML file with headings as chapters'; $string['typezipfiles'] = 'Each HTML file represents one chapter'; -$string['typezipdirs'] = 'Each directory represents one chapter'; -$string['ziparchive'] = 'Zip archive'; -$string['ziparchive_help'] = 'Select a ZIP archive that contains HTML files and other media. File or directory names ending with "_sub" indicate subchapters. You can use copy and paste in text editor for simple HML files without embedded media.'; \ No newline at end of file +$string['typezipdirs'] = 'Each folder represents one chapter'; +$string['ziparchive'] = 'Zip file'; +$string['ziparchive_help'] = 'Select a zip file containing HTML files and optional multimedia files and folders. To upload subchapters, add "_sub" to the end of HTML file or folder names.'; From a60d964abce516ad92200d938ef9c01f098cfa26 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Sun, 27 May 2012 17:40:50 +0200 Subject: [PATCH 383/455] MDL-33120 book: changes in code based on amended strings - Replace numberingoptions_help by numberingoptions_desc. - Delete the faq code and related styles. - Bump version to force lang/style refresh. --- mod/book/locallib.php | 6 ------ mod/book/settings.php | 4 ++-- mod/book/styles.css | 4 ---- mod/book/version.php | 2 +- 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/mod/book/locallib.php b/mod/book/locallib.php index 96f9f456aad..238913d6588 100644 --- a/mod/book/locallib.php +++ b/mod/book/locallib.php @@ -194,12 +194,6 @@ function book_add_fake_block($chapters, $chapter, $book, $cm, $edit) { $toc = book_get_toc($chapters, $chapter, $book, $cm, $edit, 0); - if ($edit) { - $toc .= '
                          '; - $toc .= $OUTPUT->help_icon('faq', 'mod_book', get_string('faq', 'mod_book')); - $toc .= '
                          '; - } - $bc = new block_contents(); $bc->title = get_string('toc', 'mod_book'); $bc->attributes['class'] = 'block'; diff --git a/mod/book/settings.php b/mod/book/settings.php index 810ad3c76f4..38f87bb8fd5 100644 --- a/mod/book/settings.php +++ b/mod/book/settings.php @@ -35,7 +35,7 @@ if ($ADMIN->fulltree) { $options = book_get_numbering_types(); $settings->add(new admin_setting_configmultiselect('book/numberingoptions', - get_string('numberingoptions', 'mod_book'), get_string('numberingoptions_help', 'mod_book'), + get_string('numberingoptions', 'mod_book'), get_string('numberingoptions_desc', 'mod_book'), array_keys($options), $options)); @@ -46,4 +46,4 @@ if ($ADMIN->fulltree) { $settings->add(new admin_setting_configselect('book/numbering', get_string('numbering', 'mod_book'), '', BOOK_NUM_NUMBERS, $options)); -} \ No newline at end of file +} diff --git a/mod/book/styles.css b/mod/book/styles.css index d09189d15bf..6ddaf09cf06 100644 --- a/mod/book/styles.css +++ b/mod/book/styles.css @@ -29,10 +29,6 @@ /* == Fake toc block == */ -.mod_book .book_faq { - font-size: 0.7em; -} - /* toc style NONE */ .mod_book .book_toc_none { font-size: 0.8em; diff --git a/mod/book/version.php b/mod/book/version.php index fe07130751e..fbce66e5fdd 100644 --- a/mod/book/version.php +++ b/mod/book/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die; $module->component = 'mod_book'; // Full name of the plugin (used for diagnostics) -$module->version = 2012052100; // The current module version (Date: YYYYMMDDXX) +$module->version = 2012052700; // The current module version (Date: YYYYMMDDXX) $module->requires = 2012051900; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) From d2e3a1b4f9c1f568a23d972402f4c5747b5f73cb Mon Sep 17 00:00:00 2001 From: Dan Marsden Date: Mon, 19 Mar 2012 14:50:59 +1300 Subject: [PATCH 384/455] MDL-27368 Clean up invalid course completion records keep oldest timestamps from all records --- lib/db/upgrade.php | 37 +++++++++++++++++++++++++++++++++++++ version.php | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index c74c7248216..d2d71489e95 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -648,5 +648,42 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2012052100.00); } + if ($oldversion < 2012052500.01) { // fix invalid course_completion_records MDL-27368 + //first get all instances of duplicate records + $sql = 'SELECT userid, course FROM {course_completions} WHERE (deleted IS NULL OR deleted <> 1) GROUP BY userid, course HAVING (count(id) > 1)'; + $duplicates = $DB->get_recordset_sql($sql, array()); + + foreach ($duplicates as $duplicate) { + $pointer = 0; + //now get all the records for this user/course + $sql = 'userid = ? AND course = ? AND (deleted IS NULL OR deleted <> 1)'; + $completions = $DB->get_records_select('course_completions', $sql, + array($duplicate->userid, $duplicate->course), 'timecompleted DESC, timestarted DESC'); + $needsupdate = false; + $origcompletion = null; + foreach ($completions as $completion) { + $pointer++; + if ($pointer === 1) { //keep 1st record but delete all others. + $origcompletion = $completion; + } else { + //we need to keep the "oldest" of all these fields as the valid completion record. + $fieldstocheck = array('timecompleted', 'timestarted', 'timeenrolled'); + foreach ($fieldstocheck as $f) { + if ($origcompletion->$f > $completion->$f) { + $origcompletion->$f = $completion->$f; + $needsupdate = true; + } + } + $DB->delete_records('course_completions', array('id'=>$completion->id)); + } + } + if ($needsupdate) { + $DB->update_record('course_completions', $origcompletion); + } + } + + // Main savepoint reached + upgrade_main_savepoint(true, 2012052500.01); + } return true; } diff --git a/version.php b/version.php index f9992a16395..9a4c454f1f9 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052500.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052500.01; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From 9a2c4dbd0041893caa832f102e5ad9ef5264c201 Mon Sep 17 00:00:00 2001 From: Andreas Grabs Date: Fri, 15 Jul 2011 02:03:21 +0200 Subject: [PATCH 385/455] MDL-27675 - Feedback module abuses data_submitted --- mod/feedback/complete.php | 8 +++----- mod/feedback/complete_guest.php | 10 ++++------ mod/feedback/item/captcha/lib.php | 4 ++++ mod/feedback/item/feedback_item_class.php | 12 ++++++++++-- mod/feedback/item/info/lib.php | 4 ++++ mod/feedback/item/label/lib.php | 3 +++ mod/feedback/item/multichoice/lib.php | 8 ++++++++ mod/feedback/item/multichoicerated/lib.php | 3 +++ mod/feedback/item/numeric/lib.php | 4 ++++ mod/feedback/item/textarea/lib.php | 4 ++++ mod/feedback/item/textfield/lib.php | 4 ++++ mod/feedback/lib.php | 11 +++++++++++ 12 files changed, 62 insertions(+), 13 deletions(-) diff --git a/mod/feedback/complete.php b/mod/feedback/complete.php index 7fee6412d83..e4c202c50d9 100644 --- a/mod/feedback/complete.php +++ b/mod/feedback/complete.php @@ -507,11 +507,8 @@ if ($feedback_can_submit) { //get the value $frmvaluename = $feedbackitem->typ . '_'. $feedbackitem->id; if (isset($savereturn)) { - if (isset($formdata->{$frmvaluename})) { - $value = $formdata->{$frmvaluename}; - } else { - $value = null; - } + $value = isset($formdata->{$frmvaluename}) ? $formdata->{$frmvaluename} : null; + $value = feedback_clean_input_value($feedbackitem, $value); } else { if (isset($feedbackcompletedtmp->id)) { $value = feedback_get_item_value($feedbackcompletedtmp->id, @@ -530,6 +527,7 @@ if ($feedback_can_submit) { feedback_print_item_complete($feedbackitem, $value, $highlightrequired); echo $OUTPUT->box_end(); } + echo $OUTPUT->box_end(); $lastbreakposition = $feedbackitem->position; //last item-pos (item or pagebreak) diff --git a/mod/feedback/complete_guest.php b/mod/feedback/complete_guest.php index 25747a99082..37930a3948e 100644 --- a/mod/feedback/complete_guest.php +++ b/mod/feedback/complete_guest.php @@ -441,13 +441,10 @@ if ($feedback_can_submit) { echo $OUTPUT->box_start('feedback_item_box_'.$align.$dependstyle); $value = ''; //get the value - $frmvaluename = $feedbackitem->typ.'_'.$feedbackitem->id; + $frmvaluename = $feedbackitem->typ . '_'. $feedbackitem->id; if (isset($savereturn)) { - if (isset($formdata->{$frmvaluename})) { - $value = $formdata->{$frmvaluename}; - } else { - $value = null; - } + $value = isset($formdata->{$frmvaluename}) ? $formdata->{$frmvaluename} : null; + $value = feedback_clean_input_value($feedbackitem, $value); } else { if (isset($feedbackcompletedtmp->id)) { $value = feedback_get_item_value($feedbackcompletedtmp->id, @@ -466,6 +463,7 @@ if ($feedback_can_submit) { feedback_print_item_complete($feedbackitem, $value, $highlightrequired); echo $OUTPUT->box_end(); } + echo $OUTPUT->box_end(); $lastbreakposition = $feedbackitem->position; //last item-pos (item or pagebreak) diff --git a/mod/feedback/item/captcha/lib.php b/mod/feedback/item/captcha/lib.php index 126d51e3417..42d4a559b19 100644 --- a/mod/feedback/item/captcha/lib.php +++ b/mod/feedback/item/captcha/lib.php @@ -326,4 +326,8 @@ class feedback_item_captcha extends feedback_item_base { public function can_switch_require() { return false; } + + function clean_input_value($value) { + return clean_param($value, PARAM_RAW); + } } diff --git a/mod/feedback/item/feedback_item_class.php b/mod/feedback/item/feedback_item_class.php index 981aefd58ea..fa4d5754e55 100644 --- a/mod/feedback/item/feedback_item_class.php +++ b/mod/feedback/item/feedback_item_class.php @@ -128,6 +128,14 @@ abstract class feedback_item_base { */ abstract public function print_item_show_value($item, $value = ''); + /** + * cleans the userinput while submitting the form + * + * @param mixed $value + * @return mixed + */ + abstract function clean_input_value($value); + } //a dummy class to realize pagebreaks @@ -175,7 +183,7 @@ class feedback_item_pagebreak extends feedback_item_base { } public function can_switch_require() { } + public function clean_input_value($value) { + } } - - diff --git a/mod/feedback/item/info/lib.php b/mod/feedback/item/info/lib.php index 299fef24b04..16709740be1 100644 --- a/mod/feedback/item/info/lib.php +++ b/mod/feedback/item/info/lib.php @@ -388,4 +388,8 @@ class feedback_item_info extends feedback_item_base { public function can_switch_require() { return false; } + + function clean_input_value($value) { + return clean_param($value, PARAM_INT); + } } diff --git a/mod/feedback/item/label/lib.php b/mod/feedback/item/label/lib.php index 25c62a9f55d..934734bf556 100644 --- a/mod/feedback/item/label/lib.php +++ b/mod/feedback/item/label/lib.php @@ -270,4 +270,7 @@ class feedback_item_label extends feedback_item_base { } public function get_analysed($item, $groupid = false, $courseid = false) { } + public function clean_input_value($value) { + return ''; + } } diff --git a/mod/feedback/item/multichoice/lib.php b/mod/feedback/item/multichoice/lib.php index cfba141be16..47447678301 100644 --- a/mod/feedback/item/multichoice/lib.php +++ b/mod/feedback/item/multichoice/lib.php @@ -826,4 +826,12 @@ class feedback_item_multichoice extends feedback_item_base { public function value_is_array() { return true; } + + function can_switch_require() { + return true; + } + + function clean_input_value($value) { + return clean_param_array($value, PARAM_INT); + } } diff --git a/mod/feedback/item/multichoicerated/lib.php b/mod/feedback/item/multichoicerated/lib.php index 031f7b89540..c0a74b5e9c0 100644 --- a/mod/feedback/item/multichoicerated/lib.php +++ b/mod/feedback/item/multichoicerated/lib.php @@ -678,4 +678,7 @@ class feedback_item_multichoicerated extends feedback_item_base { return true; } + function clean_input_value($value) { + return clean_param($value, PARAM_INT); + } } diff --git a/mod/feedback/item/numeric/lib.php b/mod/feedback/item/numeric/lib.php index 23694137d8f..fc19d733939 100644 --- a/mod/feedback/item/numeric/lib.php +++ b/mod/feedback/item/numeric/lib.php @@ -534,4 +534,8 @@ class feedback_item_numeric extends feedback_item_base { public function can_switch_require() { return true; } + + function clean_input_value($value) { + return clean_param($value, PARAM_FLOAT); + } } diff --git a/mod/feedback/item/textarea/lib.php b/mod/feedback/item/textarea/lib.php index 54df5e6e47e..d96a4021599 100644 --- a/mod/feedback/item/textarea/lib.php +++ b/mod/feedback/item/textarea/lib.php @@ -333,4 +333,8 @@ class feedback_item_textarea extends feedback_item_base { public function can_switch_require() { return true; } + + function clean_input_value($value) { + return clean_param($value, PARAM_CLEANHTML); + } } diff --git a/mod/feedback/item/textfield/lib.php b/mod/feedback/item/textfield/lib.php index 4051ffb97c0..7258806db99 100644 --- a/mod/feedback/item/textfield/lib.php +++ b/mod/feedback/item/textfield/lib.php @@ -320,4 +320,8 @@ class feedback_item_textfield extends feedback_item_base { public function can_switch_require() { return true; } + + function clean_input_value($value) { + return clean_param($value, PARAM_CLEANHTML); + } } diff --git a/mod/feedback/lib.php b/mod/feedback/lib.php index 3c9809b9f08..5807e8cb110 100644 --- a/mod/feedback/lib.php +++ b/mod/feedback/lib.php @@ -2058,6 +2058,17 @@ function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid //functions to handle the values //////////////////////////////////////////////// +/** + * cleans the userinput while submitting the form. + * + * @param mixed $value + * @return mixed + */ +function feedback_clean_input_value($item, $value) { + $itemobj = feedback_get_item_class($item->typ); + return $itemobj->clean_input_value($value); +} + /** * this saves the values of an completed. * if the param $tmp is set true so the values are saved temporary in table feedback_valuetmp. From 1cb73662b22a4516ab432ea2719bbbdd3f2610c0 Mon Sep 17 00:00:00 2001 From: "eLeDia GmbH (Andreas Grabs)" Date: Wed, 9 May 2012 16:52:26 +0200 Subject: [PATCH 386/455] MDL-27675 - Feedback module abuses data_submitted --- mod/feedback/complete_guest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/feedback/complete_guest.php b/mod/feedback/complete_guest.php index 37930a3948e..b472c09e023 100644 --- a/mod/feedback/complete_guest.php +++ b/mod/feedback/complete_guest.php @@ -72,7 +72,7 @@ if (isset($formdata->sesskey) AND !isset($formdata->gonextpage) AND !isset($formdata->gopreviouspage)) { - $gopage = $formdata->lastpage; + $gopage = (int) $formdata->lastpage; } if (isset($formdata->savevalues)) { $savevalues = true; From fde4c6091177259c6b0b11fcc5ed79760b5e354c Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Mon, 28 May 2012 02:44:24 +0200 Subject: [PATCH 387/455] MDL-33364 automated backup: return and log each course result correctly --- backup/util/helper/backup_cron_helper.class.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backup/util/helper/backup_cron_helper.class.php b/backup/util/helper/backup_cron_helper.class.php index d25c7945634..94a7a873189 100644 --- a/backup/util/helper/backup_cron_helper.class.php +++ b/backup/util/helper/backup_cron_helper.class.php @@ -315,6 +315,7 @@ abstract class backup_cron_automated_helper { */ public static function launch_automated_backup($course, $starttime, $userid) { + $outcome = true; $config = get_config('backup'); $bc = new backup_controller(backup::TYPE_1COURSE, $course->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_AUTOMATED, $userid); @@ -347,7 +348,7 @@ abstract class backup_cron_automated_helper { $bc->set_status(backup::STATUS_AWAITING); - $outcome = $bc->execute_plan(); + $bc->execute_plan(); $results = $bc->get_results(); $file = $results['backup_destination']; $dir = $config->backup_auto_destination; @@ -363,16 +364,17 @@ abstract class backup_cron_automated_helper { } } - $outcome = true; - } catch (backup_exception $e) { - $bc->log('backup_auto_failed_on_course', backup::LOG_WARNING, $course->shortname); + } catch (moodle_exception $e) { + $bc->log('backup_auto_failed_on_course', backup::LOG_ERROR, $course->shortname); // Log error header. + $bc->log('Exception: ' . $e->errorcode, backup::LOG_ERROR, $e->a, 1); // Log original exception problem. + $bc->log('Debug: ' . $e->debuginfo, backup::LOG_DEBUG, null, 1); // Log original debug information. $outcome = false; } $bc->destroy(); unset($bc); - return true; + return $outcome; } /** From 4ad85bd857a5233c2938d98d825bac9b0a66e275 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Sat, 26 May 2012 12:15:17 +0800 Subject: [PATCH 388/455] MDL-33359 - mtrace: dont output to STDOUT in unit tests This allows us to use phpunit output buffering functions --- lib/moodlelib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 8b0379b9551..23ee2f5630c 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -9642,7 +9642,7 @@ function address_in_subnet($addr, $subnetstr) { */ function mtrace($string, $eol="\n", $sleep=0) { - if (defined('STDOUT')) { + if (defined('STDOUT') and !PHPUNIT_TEST) { fwrite(STDOUT, $string.$eol); } else { echo $string . $eol; From 064cac786602be109863db4a2ac15c3162655254 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Mon, 28 May 2012 13:38:36 +1200 Subject: [PATCH 389/455] MDL-27675 mod_feedback: Tidy up of phpdocs and scope within feedback mod --- mod/feedback/item/captcha/lib.php | 7 ++++++- mod/feedback/item/feedback_item_class.php | 6 +++--- mod/feedback/item/info/lib.php | 7 ++++++- mod/feedback/item/label/lib.php | 5 +++++ mod/feedback/item/multichoice/lib.php | 11 ++++++----- mod/feedback/item/multichoicerated/lib.php | 7 ++++++- mod/feedback/item/numeric/lib.php | 9 +++++++-- mod/feedback/item/textarea/lib.php | 7 ++++++- mod/feedback/item/textfield/lib.php | 7 ++++++- mod/feedback/lib.php | 3 ++- 10 files changed, 53 insertions(+), 16 deletions(-) diff --git a/mod/feedback/item/captcha/lib.php b/mod/feedback/item/captcha/lib.php index 42d4a559b19..19fa17b7835 100644 --- a/mod/feedback/item/captcha/lib.php +++ b/mod/feedback/item/captcha/lib.php @@ -327,7 +327,12 @@ class feedback_item_captcha extends feedback_item_base { return false; } - function clean_input_value($value) { + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param($value, PARAM_RAW); } } diff --git a/mod/feedback/item/feedback_item_class.php b/mod/feedback/item/feedback_item_class.php index fa4d5754e55..57f1d6d8180 100644 --- a/mod/feedback/item/feedback_item_class.php +++ b/mod/feedback/item/feedback_item_class.php @@ -128,13 +128,13 @@ abstract class feedback_item_base { */ abstract public function print_item_show_value($item, $value = ''); - /** + /** * cleans the userinput while submitting the form * * @param mixed $value * @return mixed */ - abstract function clean_input_value($value); + abstract public function clean_input_value($value); } @@ -186,4 +186,4 @@ class feedback_item_pagebreak extends feedback_item_base { public function clean_input_value($value) { } -} +} \ No newline at end of file diff --git a/mod/feedback/item/info/lib.php b/mod/feedback/item/info/lib.php index 16709740be1..b58123fc12b 100644 --- a/mod/feedback/item/info/lib.php +++ b/mod/feedback/item/info/lib.php @@ -389,7 +389,12 @@ class feedback_item_info extends feedback_item_base { return false; } - function clean_input_value($value) { + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param($value, PARAM_INT); } } diff --git a/mod/feedback/item/label/lib.php b/mod/feedback/item/label/lib.php index 934734bf556..bd88d391eae 100644 --- a/mod/feedback/item/label/lib.php +++ b/mod/feedback/item/label/lib.php @@ -270,6 +270,11 @@ class feedback_item_label extends feedback_item_base { } public function get_analysed($item, $groupid = false, $courseid = false) { } + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ public function clean_input_value($value) { return ''; } diff --git a/mod/feedback/item/multichoice/lib.php b/mod/feedback/item/multichoice/lib.php index 47447678301..d48abbeca62 100644 --- a/mod/feedback/item/multichoice/lib.php +++ b/mod/feedback/item/multichoice/lib.php @@ -827,11 +827,12 @@ class feedback_item_multichoice extends feedback_item_base { return true; } - function can_switch_require() { - return true; - } - - function clean_input_value($value) { + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param_array($value, PARAM_INT); } } diff --git a/mod/feedback/item/multichoicerated/lib.php b/mod/feedback/item/multichoicerated/lib.php index c0a74b5e9c0..47ecedb630f 100644 --- a/mod/feedback/item/multichoicerated/lib.php +++ b/mod/feedback/item/multichoicerated/lib.php @@ -678,7 +678,12 @@ class feedback_item_multichoicerated extends feedback_item_base { return true; } - function clean_input_value($value) { + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param($value, PARAM_INT); } } diff --git a/mod/feedback/item/numeric/lib.php b/mod/feedback/item/numeric/lib.php index fc19d733939..eb2b7206231 100644 --- a/mod/feedback/item/numeric/lib.php +++ b/mod/feedback/item/numeric/lib.php @@ -534,8 +534,13 @@ class feedback_item_numeric extends feedback_item_base { public function can_switch_require() { return true; } - - function clean_input_value($value) { + + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param($value, PARAM_FLOAT); } } diff --git a/mod/feedback/item/textarea/lib.php b/mod/feedback/item/textarea/lib.php index d96a4021599..8ed937075de 100644 --- a/mod/feedback/item/textarea/lib.php +++ b/mod/feedback/item/textarea/lib.php @@ -334,7 +334,12 @@ class feedback_item_textarea extends feedback_item_base { return true; } - function clean_input_value($value) { + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param($value, PARAM_CLEANHTML); } } diff --git a/mod/feedback/item/textfield/lib.php b/mod/feedback/item/textfield/lib.php index 7258806db99..c9a4dc67b6a 100644 --- a/mod/feedback/item/textfield/lib.php +++ b/mod/feedback/item/textfield/lib.php @@ -321,7 +321,12 @@ class feedback_item_textfield extends feedback_item_base { return true; } - function clean_input_value($value) { + /** + * Cleans the value coming from the user for a field of this type. + * @param mixed $value + * @return mixed + */ + public function clean_input_value($value) { return clean_param($value, PARAM_CLEANHTML); } } diff --git a/mod/feedback/lib.php b/mod/feedback/lib.php index 5807e8cb110..e007c4e3d87 100644 --- a/mod/feedback/lib.php +++ b/mod/feedback/lib.php @@ -2058,9 +2058,10 @@ function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid //functions to handle the values //////////////////////////////////////////////// -/** +/** * cleans the userinput while submitting the form. * + * @param stdClass $item The feedback item record from the database that the value needs to be cleaned against. * @param mixed $value * @return mixed */ From 33fcc04082c3c89f0b99b4f821bf3548f870307c Mon Sep 17 00:00:00 2001 From: Rajesh Taneja Date: Fri, 25 May 2012 16:19:08 +0800 Subject: [PATCH 390/455] MDL-33347 course: section move is visible without ajax --- course/lib.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/course/lib.php b/course/lib.php index 8e073737607..648f87e86af 100644 --- a/course/lib.php +++ b/course/lib.php @@ -2995,6 +2995,8 @@ function move_section($course, $section, $move) { } $n++; } + // After moving section, rebuild course cache. + rebuild_course_cache($course->id, true); return true; } From 424a19b106003a55d1fbe857a2c66a3ba6450fd3 Mon Sep 17 00:00:00 2001 From: Aaron Barnes Date: Mon, 28 May 2012 15:14:28 +1200 Subject: [PATCH 391/455] MDL-28949 course completion: Database structure fixes --- lib/db/install.xml | 11 ++++--- lib/db/upgrade.php | 70 +++++++++++++++++++++++++++++++++++++++++++ lib/upgradelib.php | 75 ++++++++++++++++++++++++++++++++++++++++++++++ version.php | 2 +- 4 files changed, 153 insertions(+), 5 deletions(-) diff --git a/lib/db/install.xml b/lib/db/install.xml index 0463430e996..d4b707752f3 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -149,7 +149,8 @@ - + + @@ -190,7 +191,8 @@ - + +
                          @@ -226,7 +228,8 @@ - + +
                          @@ -2867,4 +2870,4 @@
                          - \ No newline at end of file + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index c74c7248216..a2f0052f7fd 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -648,5 +648,75 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2012052100.00); } + + /** + * Major clean up of course completion tables + */ + if ($oldversion < 2012052500.02) { + + // Clean up all instances of duplicate records + // Add indexes to prevent new duplicates + upgrade_course_completion_remove_duplicates( + 'course_completions', + array('userid', 'course'), + array('timecompleted', 'timestarted', 'timeenrolled') + ); + + // Define index useridcourse (unique) to be added to course_completions + $table = new xmldb_table('course_completions'); + $index = new xmldb_index('useridcourse', XMLDB_INDEX_UNIQUE, array('userid', 'course')); + + + // Conditionally launch add index useridcourse + if (!$dbman->index_exists($table, $index)) { + $dbman->add_index($table, $index); + } + + // Main savepoint reached + upgrade_main_savepoint(true, 2012052500.02); + } + + if ($oldversion < 2012052500.03) { + + upgrade_course_completion_remove_duplicates( + 'course_completion_crit_compl', + array('userid', 'course', 'criteriaid'), + array('timecompleted') + ); + + + // Define index useridcoursecriteraid (unique) to be added to course_completion_crit_compl + $table = new xmldb_table('course_completion_crit_compl'); + $index = new xmldb_index('useridcoursecriteraid', XMLDB_INDEX_UNIQUE, array('userid', 'course', 'criteriaid')); + + // Conditionally launch add index useridcoursecriteraid + if (!$dbman->index_exists($table, $index)) { + $dbman->add_index($table, $index); + } + + // Main savepoint reached + upgrade_main_savepoint(true, 2012052500.03); + } + + if ($oldversion < 2012052500.04) { + + upgrade_course_completion_remove_duplicates( + 'course_completion_aggr_methd', + array('course', 'criteriatype') + ); + + // Define index coursecriteratype (unique) to be added to course_completion_aggr_methd + $table = new xmldb_table('course_completion_aggr_methd'); + $index = new xmldb_index('coursecriteriatype', XMLDB_INDEX_UNIQUE, array('course', 'criteriatype')); + + // Conditionally launch add index coursecriteratype + if (!$dbman->index_exists($table, $index)) { + $dbman->add_index($table, $index); + } + + // Main savepoint reached + upgrade_main_savepoint(true, 2012052500.04); + } + return true; } diff --git a/lib/upgradelib.php b/lib/upgradelib.php index 6e6e0298b75..ff87f9a2cf0 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -1764,3 +1764,78 @@ function admin_mnet_method_profile(Zend_Server_Reflection_Function_Abstract $fun } return $profile; } + + +/** + * This function finds duplicate records (based on combinations of fields that should be unique) + * and then progamatically generated a "most correct" version of the data, update and removing + * records as appropriate + * + * Thanks to Dan Marsden for help + * + * @param string $table Table name + * @param array $uniques Array of field names that should be unique + * @param array $feildstocheck Array of fields to generate "correct" data from (optional) + * @return void + */ +function upgrade_course_completion_remove_duplicates($table, $uniques, $fieldstocheck = array()) { + global $DB; + + // Find duplicates + $sql_cols = implode(', ', $uniques); + + $sql = "SELECT {$sql_cols} FROM {{$table}} GROUP BY {$sql_cols} HAVING (count(id) > 1)"; + $duplicates = $DB->get_recordset_sql($sql, array()); + + // Loop through duplicates + foreach ($duplicates as $duplicate) { + $pointer = 0; + + // Generate SQL for finding records with these duplicate uniques + $sql_select = implode(' = ? AND ', $uniques).' = ?'; /// builds "fieldname = ? AND fieldname = ?" + $uniq_values = array(); + foreach ($uniques as $u) { + $uniq_values[] = $duplicate->$u; + } + + $sql_order = implode(' DESC, ', $uniques).' DESC'; // builds "fieldname DESC, fieldname DESC" + + // Get records with these duplicate uniques + $records = $DB->get_records_select( + $table, + $sql_select, + $uniq_values, + $sql_order + ); + + // Loop through and build a "correct" record, deleting the others + $needsupdate = false; + $origrecord = null; + foreach ($records as $record) { + $pointer++; + if ($pointer === 1) { // keep 1st record but delete all others. + $origrecord = $record; + } else { + // If we have fields to check, update original record + if ($fieldstocheck) { + // we need to keep the "oldest" of all these fields as the valid completion record. + // but we want to ignore null values + foreach ($fieldstocheck as $f) { + if ($record->$f && (($origrecord->$f > $record->$f) || !$origrecord->$f)) { + $origrecord->$f = $record->$f; + $needsupdate = true; + } + } + } + $DB->delete_records($table, array('id' => $record->id)); + } + } + if ($needsupdate || isset($origrecord->reaggregate)) { + // If this table has a reaggregate field, update to force recheck on next cron cron + if (isset($origrecord->reaggregate)) { + $origrecord->reaggregate = time(); + } + $DB->update_record($table, $origrecord); + } + } +} diff --git a/version.php b/version.php index 9a4c454f1f9..6dc6b76293f 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052500.01; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052500.04; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From 287451dcd45f46a1507e866b56311c17fbca9f23 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 28 May 2012 12:37:50 +0800 Subject: [PATCH 392/455] Revert "MDL-29173 grade: altered the definiton of round() in /lib/evalmath/evalmath.class.php" Breaking unit tests. This reverts commit 4be0947bbe63f32f38aa1698d4bbb9068d7a9dc9. --- lib/evalmath/evalmath.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/evalmath/evalmath.class.php b/lib/evalmath/evalmath.class.php index 894de5d05e2..aa5539fe186 100644 --- a/lib/evalmath/evalmath.class.php +++ b/lib/evalmath/evalmath.class.php @@ -107,13 +107,13 @@ class EvalMath { 'sin','sinh','arcsin','asin','arcsinh','asinh', 'cos','cosh','arccos','acos','arccosh','acosh', 'tan','tanh','arctan','atan','arctanh','atanh', - 'sqrt','abs','ln','log','exp','floor','ceil'); + 'sqrt','abs','ln','log','exp','floor','ceil','round'); var $fc = array( // calc functions emulation 'average'=>array(-1), 'max'=>array(-1), 'min'=>array(-1), 'mod'=>array(2), 'pi'=>array(0), 'power'=>array(2), 'round'=>array(1, 2), 'sum'=>array(-1), 'rand_int'=>array(2), - 'rand_float'=>array(0), 'round'=>array(2)); + 'rand_float'=>array(0)); var $allowimplicitmultiplication; From 8d5745fa9291996e0548207e1150e44382874973 Mon Sep 17 00:00:00 2001 From: Rossiani Wijaya Date: Mon, 28 May 2012 11:58:37 +0800 Subject: [PATCH 393/455] MDL-32766: course view section log: fixed typo for course_sections table Conflicts: version.php --- lib/db/log.php | 2 +- version.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/db/log.php b/lib/db/log.php index 16d1f433c3b..f0475f62870 100644 --- a/lib/db/log.php +++ b/lib/db/log.php @@ -38,7 +38,7 @@ global $DB; // TODO: this is a hack, we should really do something with the SQL $logs = array( array('module'=>'course', 'action'=>'user report', 'mtable'=>'user', 'field'=>$DB->sql_concat('firstname', "' '" , 'lastname')), array('module'=>'course', 'action'=>'view', 'mtable'=>'course', 'field'=>'fullname'), - array('module'=>'course', 'action'=>'view section', 'mtable'=>'course_section', 'field'=>'COALESCE(name, section)'), + array('module'=>'course', 'action'=>'view section', 'mtable'=>'course_sections', 'field'=>'COALESCE(name, section)'), array('module'=>'course', 'action'=>'update', 'mtable'=>'course', 'field'=>'fullname'), array('module'=>'course', 'action'=>'enrol', 'mtable'=>'course', 'field'=>'fullname'), // there should be some way to store user id of the enrolled user! array('module'=>'course', 'action'=>'unenrol', 'mtable'=>'course', 'field'=>'fullname'), // there should be some way to store user id of the enrolled user! diff --git a/version.php b/version.php index 9a4c454f1f9..7eb259adf65 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052500.01; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052500.02; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From c67b08828c7cfe87873d4ae014ecf71acd27e5c9 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Mon, 28 May 2012 16:52:53 +1200 Subject: [PATCH 394/455] MDL-18763 Fixed up typo in comments of new pic size --- lib/filelib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filelib.php b/lib/filelib.php index 48f8c3632a7..302ee9b0e19 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3628,7 +3628,7 @@ function file_pluginfile($relativepath, $forcedownload, $preview = null) { if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'.png')) { if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'.jpg')) { if ($filename === 'f3') { - // f3 400x400px was introduced in 2.3, there might be only the smaller version. + // f3 512x512px was introduced in 2.3, there might be only the smaller version. if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', 'f1.png')) { $file = $fs->get_file($context->id, 'user', 'icon', 0, '/', 'f1.jpg'); } From 7ea78d9f284f0673d7e3bdf1ef8f6809c6fa86bf Mon Sep 17 00:00:00 2001 From: Andrew Robert Nicols Date: Tue, 27 Mar 2012 11:57:46 +0100 Subject: [PATCH 395/455] MDL-32199 Ensure that forum RSS feeds don't leak posts and discussions --- mod/forum/rsslib.php | 53 ++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/mod/forum/rsslib.php b/mod/forum/rsslib.php index f1444afd957..68d5dec99fe 100644 --- a/mod/forum/rsslib.php +++ b/mod/forum/rsslib.php @@ -31,7 +31,7 @@ * @return string the full path to the cached RSS feed directory. Null if there is a problem. */ function forum_rss_get_feed($context, $args) { - global $CFG, $DB; + global $CFG, $DB, $USER; $status = true; @@ -59,7 +59,7 @@ function forum_rss_get_feed($context, $args) { $sql = forum_rss_get_sql($forum, $cm); //hash the sql to get the cache file name - $filename = rss_get_file_name($forum, $sql); + $filename = rss_get_file_name($forum, $sql . $USER->id); $cachedfilepath = rss_get_file_full_name('mod_forum', $filename); //Is the cache out of date? @@ -290,8 +290,10 @@ function forum_rss_get_group_sql($cm, $groupmode, $currentgroup, $modcontext=nul * * @Todo MDL-31129 implement post attachment handling */ -function forum_rss_feed_contents($forum, $sql, $context) { - global $CFG, $DB; + +function forum_rss_feed_contents($forum, $sql) { + global $CFG, $DB, $USER; + $status = true; @@ -305,29 +307,52 @@ function forum_rss_feed_contents($forum, $sql, $context) { $isdiscussion = false; } + if (!$cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course)) { + print_error('invalidcoursemodule'); + } + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + $formatoptions = new stdClass(); $items = array(); foreach ($recs as $rec) { $item = new stdClass(); $user = new stdClass(); - if ($isdiscussion && !empty($rec->discussionname)) { - $item->title = format_string($rec->discussionname); - } else if (!empty($rec->postsubject)) { - $item->title = format_string($rec->postsubject); + + if ($isdiscussion && !forum_user_can_see_discussion($forum, $rec->discussionid, $context)) { + // This is a discussion which the user can't has no permission to view + $item->title = get_string('forumsubjecthidden', 'forum'); + $item->description = get_string('forumbodyhidden', 'forum'); + $item->author = get_string('forumauthorhidden', 'forum'); + } else if (!$isdiscussion && !forum_user_can_see_post($forum, $rec->discussionid, $rec->postid, $USER, $cm)) { + // This is a post which the user can't has no permission to view + $item->title = get_string('forumsubjecthidden', 'forum'); + $item->description = get_string('forumbodyhidden', 'forum'); + $item->author = get_string('forumauthorhidden', 'forum'); } else { - //we should have an item title by now but if we dont somehow then substitute something somewhat meaningful - $item->title = format_string($forum->name.' '.userdate($rec->postcreated,get_string('strftimedatetimeshort', 'langconfig'))); + // The user must have permission to view + if ($isdiscussion && !empty($rec->discussionname)) { + $item->title = format_string($rec->discussionname); + } else if (!empty($rec->postsubject)) { + $item->title = format_string($rec->postsubject); + } else { + //we should have an item title by now but if we dont somehow then substitute something somewhat meaningful + $item->title = format_string($forum->name.' '.userdate($rec->postcreated,get_string('strftimedatetimeshort', 'langconfig'))); + } + $user->firstname = $rec->userfirstname; + $user->lastname = $rec->userlastname; + $item->author = fullname($user); + + $formatoptions->trusted = $rec->posttrust; + $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course); } - $user->firstname = $rec->userfirstname; - $user->lastname = $rec->userlastname; - $item->author = fullname($user); - $item->pubdate = $rec->postcreated; + if ($isdiscussion) { $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid; } else { $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid."&parent=".$rec->postid; } + $formatoptions->trusted = $rec->posttrust; $message = file_rewrite_pluginfile_urls($rec->postmessage, 'pluginfile.php', $context->id, 'mod_forum', 'post', $rec->postid); From 17ec4bf045df1a21a2e490951945dee06cfff432 Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Mon, 14 May 2012 11:47:20 +0800 Subject: [PATCH 396/455] Alteration to the code to hide the body of the post / discussion --- mod/forum/rsslib.php | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/mod/forum/rsslib.php b/mod/forum/rsslib.php index 68d5dec99fe..86bf31b7e92 100644 --- a/mod/forum/rsslib.php +++ b/mod/forum/rsslib.php @@ -43,7 +43,7 @@ function forum_rss_get_feed($context, $args) { $forumid = clean_param($args[3], PARAM_INT); $cm = get_coursemodule_from_instance('forum', $forumid, 0, false, MUST_EXIST); - $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); + $modcontext = context_module::instance($cm->id); //context id from db should match the submitted one if ($context->id != $modcontext->id || !has_capability('mod/forum:viewdiscussion', $modcontext)) { @@ -58,8 +58,14 @@ function forum_rss_get_feed($context, $args) { //the sql that will retreive the data for the feed and be hashed to get the cache filename $sql = forum_rss_get_sql($forum, $cm); - //hash the sql to get the cache file name - $filename = rss_get_file_name($forum, $sql . $USER->id); + // Hash the sql to get the cache file name. + // If the forum is Q and A then we need to cache the files per user. This can + // have a large impact on performance, so we want to only do it on this type of forum. + if ($forum->type == 'qanda') { + $filename = rss_get_file_name($forum, $sql . $USER->id); + } else { + $filename = rss_get_file_name($forum, $sql); + } $cachedfilepath = rss_get_file_full_name('mod_forum', $filename); //Is the cache out of date? @@ -151,7 +157,7 @@ function forum_rss_feed_discussions_sql($forum, $cm, $newsince=0) { $now = round(time(), -2); $params = array($cm->instance); - $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); + $modcontext = context_module::instance($cm->id); if (!empty($CFG->forum_enabletimedposts)) { /// Users must fulfill timed posts if (!has_capability('mod/forum:viewhiddentimedposts', $modcontext)) { @@ -205,7 +211,7 @@ function forum_rss_feed_discussions_sql($forum, $cm, $newsince=0) { * @return string the SQL query to be used to get the Post details from the forum table of the database */ function forum_rss_feed_posts_sql($forum, $cm, $newsince=0) { - $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id); + $modcontext = context_module::instance($cm->id); //get group enforcement SQL $groupmode = groups_get_activity_groupmode($cm); @@ -310,7 +316,7 @@ function forum_rss_feed_contents($forum, $sql) { if (!$cm = get_coursemodule_from_instance('forum', $forum->id, $forum->course)) { print_error('invalidcoursemodule'); } - $context = get_context_instance(CONTEXT_MODULE, $cm->id); + $context = context_module::instance($cm->id); $formatoptions = new stdClass(); $items = array(); @@ -319,14 +325,14 @@ function forum_rss_feed_contents($forum, $sql) { $user = new stdClass(); if ($isdiscussion && !forum_user_can_see_discussion($forum, $rec->discussionid, $context)) { - // This is a discussion which the user can't has no permission to view + // This is a discussion which the user has no permission to view $item->title = get_string('forumsubjecthidden', 'forum'); - $item->description = get_string('forumbodyhidden', 'forum'); + $message = get_string('forumbodyhidden', 'forum'); $item->author = get_string('forumauthorhidden', 'forum'); } else if (!$isdiscussion && !forum_user_can_see_post($forum, $rec->discussionid, $rec->postid, $USER, $cm)) { - // This is a post which the user can't has no permission to view + // This is a post which the user has no permission to view $item->title = get_string('forumsubjecthidden', 'forum'); - $item->description = get_string('forumbodyhidden', 'forum'); + $message = get_string('forumbodyhidden', 'forum'); $item->author = get_string('forumauthorhidden', 'forum'); } else { // The user must have permission to view @@ -341,9 +347,9 @@ function forum_rss_feed_contents($forum, $sql) { $user->firstname = $rec->userfirstname; $user->lastname = $rec->userlastname; $item->author = fullname($user); - + $message = file_rewrite_pluginfile_urls($rec->postmessage, 'pluginfile.php', $context->id, + 'mod_forum', 'post', $rec->postid); $formatoptions->trusted = $rec->posttrust; - $item->description = format_text($rec->postmessage,$rec->postformat,$formatoptions,$forum->course); } if ($isdiscussion) { @@ -352,10 +358,7 @@ function forum_rss_feed_contents($forum, $sql) { $item->link = $CFG->wwwroot."/mod/forum/discuss.php?d=".$rec->discussionid."&parent=".$rec->postid; } - $formatoptions->trusted = $rec->posttrust; - $message = file_rewrite_pluginfile_urls($rec->postmessage, 'pluginfile.php', $context->id, - 'mod_forum', 'post', $rec->postid); $item->description = format_text($message, $rec->postformat, $formatoptions, $forum->course); //TODO: MDL-31129 implement post attachment handling @@ -367,6 +370,7 @@ function forum_rss_feed_contents($forum, $sql) { $item->attachments = array(); } }*/ + $item->pubdate = $rec->postcreated; $items[] = $item; } From 6adb5f13638f316550e6b6a0734a8626e2073dfb Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 28 May 2012 13:52:32 +0800 Subject: [PATCH 397/455] MDL-33356 fixed a regression after function form_filemanager_redner() was deleted --- question/type/essay/renderer.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/question/type/essay/renderer.php b/question/type/essay/renderer.php index afb52f86fca..288954f9ec6 100644 --- a/question/type/essay/renderer.php +++ b/question/type/essay/renderer.php @@ -113,7 +113,9 @@ class qtype_essay_renderer extends qtype_renderer { $pickeroptions->itemid = $qa->prepare_response_files_draft_itemid( 'attachments', $options->context->id); - return form_filemanager_render($pickeroptions) . html_writer::empty_tag( + $fm = new form_filemanager($pickeroptions); + $filesrenderer = $this->page->get_renderer('core', 'files'); + return $filesrenderer->render($fm). html_writer::empty_tag( 'input', array('type' => 'hidden', 'name' => $qa->get_qt_field_name('attachments'), 'value' => $pickeroptions->itemid)); } From 54495fe41d6647db8d18e9d36c5c5b7f7239874b Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 28 May 2012 14:43:30 +0800 Subject: [PATCH 398/455] MDL-33375 course: set anchor after changing sections So scrolling isn't required --- course/changenumsections.php | 4 +++- course/format/renderer.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/course/changenumsections.php b/course/changenumsections.php index f2af45a8409..3354f1c38b9 100644 --- a/course/changenumsections.php +++ b/course/changenumsections.php @@ -53,5 +53,7 @@ if ($course->numsections >= 0) { $DB->update_record('course', $course); } +$url = course_get_url($course); +$url->set_anchor('changenumsections'); // Redirect to where we were.. -redirect(course_get_url($course)); +redirect($url); diff --git a/course/format/renderer.php b/course/format/renderer.php index fb59c386a52..dc98d435d3f 100644 --- a/course/format/renderer.php +++ b/course/format/renderer.php @@ -624,7 +624,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base { echo $this->end_section_list(); - echo html_writer::start_tag('div', array('class' => 'mdl-right')); + echo html_writer::start_tag('div', array('id' => 'changenumsections', 'class' => 'mdl-right')); // Increase number of sections. $straddsection = get_string('increasesections', 'moodle'); From 4c2fcbfc85490848269bec3361ece4b1f6d58a82 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 28 May 2012 15:19:41 +0800 Subject: [PATCH 399/455] MDL-33338 recognising the mimetype for uploaded files - when file is uploaded in php, the tmpname does not have initial extension and mimetype recognition by extension fails - another issue is that import form for questions fails with fatal error when it should just say that field is required --- lib/filestorage/file_storage.php | 14 +++++++++----- question/import_form.php | 5 +++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index edac5a52517..5fac72679af 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -1028,7 +1028,7 @@ class file_storage { $newrecord->timecreated = $filerecord->timecreated; $newrecord->timemodified = $filerecord->timemodified; - $newrecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($pathname) : $filerecord->mimetype; + $newrecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($pathname, $filerecord->filename) : $filerecord->mimetype; $newrecord->userid = empty($filerecord->userid) ? null : $filerecord->userid; $newrecord->source = empty($filerecord->source) ? null : $filerecord->source; $newrecord->author = empty($filerecord->author) ? null : $filerecord->author; @@ -1154,7 +1154,7 @@ class file_storage { list($newrecord->contenthash, $newrecord->filesize, $newfile) = $this->add_string_to_pool($content); $filepathname = $this->path_from_hash($newrecord->contenthash) . '/' . $newrecord->contenthash; // get mimetype by magic bytes - $newrecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($filepathname) : $filerecord->mimetype; + $newrecord->mimetype = empty($filerecord->mimetype) ? $this->mimetype($filepathname, $filerecord->filename) : $filerecord->mimetype; $newrecord->pathnamehash = $this->get_pathname_hash($newrecord->contextid, $newrecord->component, $newrecord->filearea, $newrecord->itemid, $newrecord->filepath, $newrecord->filename); @@ -1801,11 +1801,15 @@ class file_storage { * If file has a known extension, we return the mimetype based on extension. * Otherwise (when possible) we try to get the mimetype from file contents. * - * @param string $pathname + * @param string $pathname full path to the file + * @param string $filename correct file name with extension, if omitted will be taken from $path * @return string */ - public static function mimetype($pathname) { - $type = mimeinfo('type', $pathname); + public static function mimetype($pathname, $filename = null) { + if (empty($filename)) { + $filename = $pathname; + } + $type = mimeinfo('type', $filename); if ($type === 'document/unknown' && class_exists('finfo') && file_exists($pathname)) { $finfo = new finfo(FILEINFO_MIME_TYPE); $type = mimeinfo_from_type('type', $finfo->file($pathname)); diff --git a/question/import_form.php b/question/import_form.php index 719317d9822..4a1a1272242 100644 --- a/question/import_form.php +++ b/question/import_form.php @@ -122,6 +122,11 @@ class question_import_form extends moodleform { return $errors; } + if (empty($data['format'])) { + $errors['format'] = get_string('required'); + return $errors; + } + $formatfile = 'format/' . $data['format'] . '/format.php'; if (!is_readable($formatfile)) { throw new moodle_exception('formatnotfound', 'question', '', $data['format']); From 17b60e9d9886ef8fb695283dde88e0ae6c5aacbe Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sun, 20 May 2012 13:19:27 +0200 Subject: [PATCH 400/455] MDL-33089 detect more problems when initialising PHPUnit test environment --- lib/setup.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/setup.php b/lib/setup.php index 1a635f3ec15..23cf9e189df 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -478,8 +478,21 @@ setup_DB(); if (PHPUNIT_TEST and !PHPUNIT_UTIL) { // make sure tests do not run in parallel phpunit_util::acquire_test_lock(); - // reset DB tables - phpunit_util::reset_database(); + $dbhash = null; + try { + if ($dbhash = $DB->get_field('config', 'value', array('name'=>'phpunittest'))) { + // reset DB tables + phpunit_util::reset_database(); + } + } catch (Exception $e) { + if ($dbhash) { + // we ned to reinit if reset fails + $DB->set_field('config', 'value', 'na', array('name'=>'phpunittest')); + } else { + throw $e; + } + } + unset($dbhash); } // Disable errors for now - needed for installation when debug enabled in config.php From b7c5627f5bc0cd4eca70ad674bb2e8fd0bc8bdbc Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Fri, 25 May 2012 10:21:12 +0200 Subject: [PATCH 401/455] MDL-33089 flag test database as soon as possible in PHPUnit init --- lib/installlib.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/installlib.php b/lib/installlib.php index e652a8c6267..7da6ed6a1f7 100644 --- a/lib/installlib.php +++ b/lib/installlib.php @@ -455,6 +455,11 @@ function install_cli_database(array $options, $interactive) { set_config('release', $release); set_config('branch', $branch); + if (PHPUNIT_TEST) { + // mark as test database as soon as possible + set_config('phpunittest', 'na'); + } + // install all plugins types, local, etc. upgrade_noncore(true); From 716b50dc2c373e781686d5325a1308ca1f9804f5 Mon Sep 17 00:00:00 2001 From: Petr Skoda Date: Sat, 19 May 2012 21:24:21 +0200 Subject: [PATCH 402/455] MDL-33001 improve error handling in mysql engine conversion tool and add listing of engines --- admin/cli/mysql_engine.php | 75 ++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/admin/cli/mysql_engine.php b/admin/cli/mysql_engine.php index 3b51f413446..6bc3642a1d4 100644 --- a/admin/cli/mysql_engine.php +++ b/admin/cli/mysql_engine.php @@ -34,8 +34,8 @@ if ($DB->get_dbfamily() !== 'mysql') { } // now get cli options -list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false), - array('h'=>'help', 'l'=>'list')); +list($options, $unrecognized) = cli_get_params(array('help'=>false, 'list'=>false, 'engine'=>false, 'available'=>false), + array('h'=>'help', 'l'=>'list', 'a'=>'available')); if ($unrecognized) { $unrecognized = implode("\n ", $unrecognized); @@ -52,6 +52,7 @@ and does not support transactions. Options: --engine=ENGINE Convert MySQL tables to different engine -l, --list Show table information +-a, --available Show list of available engines -h, --help Print out this help Example: @@ -59,7 +60,11 @@ Example: "; if (!empty($options['engine'])) { + $engines = mysql_get_engines(); $engine = clean_param($options['engine'], PARAM_ALPHA); + if (!isset($engines[strtoupper($engine)])) { + cli_error("Error: engine '$engine' is not available on this server!"); + } echo "Converting tables to '$engine' for $CFG->wwwroot:\n"; $prefix = $DB->get_prefix(); @@ -68,9 +73,11 @@ if (!empty($options['engine'])) { $rs = $DB->get_recordset_sql($sql); $converted = 0; $skipped = 0; + $errors = 0; foreach ($rs as $table) { - if ($table->engine === $engine) { - echo str_pad($table->name, 40). " - NO CONVERSION NEEDED\n"; + if (strtoupper($table->engine) === strtoupper($engine)) { + $newengine = mysql_get_table_engine($table->name); + echo str_pad($table->name, 40). " - NO CONVERSION NEEDED ($newengine)\n"; $skipped++; continue; } @@ -78,16 +85,22 @@ if (!empty($options['engine'])) { try { $DB->change_database_structure("ALTER TABLE {$table->name} ENGINE = $engine"); + $newengine = mysql_get_table_engine($table->name); + if (strtoupper($newengine) !== strtoupper($engine)) { + echo "ERROR ($newengine)\n"; + $errors++; + continue; + } + echo "DONE ($newengine)\n"; + $converted++; } catch (moodle_exception $e) { echo $e->getMessage()."\n"; - $skipped++; + $errors++; continue; } - echo "DONE\n"; - $converted++; } $rs->close(); - echo "Converted: $converted, skipped: $skipped\n"; + echo "Converted: $converted, skipped: $skipped, errors: $errors\n"; exit(0); // success } else if (!empty($options['list'])) { @@ -115,7 +128,53 @@ if (!empty($options['engine'])) { } exit(0); // success +} else if (!empty($options['available'])) { + echo "List of available MySQL engines for $CFG->wwwroot:\n"; + $engines = mysql_get_engines(); + foreach ($engines as $engine) { + echo " $engine\n"; + } + die; + } else { echo $help; die; } + + + +// ========== Some functions ============== + +function mysql_get_engines() { + global $DB; + + $sql = "SHOW Engines"; + $rs = $DB->get_recordset_sql($sql); + $engines = array(); + foreach ($rs as $engine) { + if (strtoupper($engine->support) !== 'YES' and strtoupper($engine->support) !== 'DEFAULT') { + continue; + } + $engines[strtoupper($engine->engine)] = $engine->engine; + if (strtoupper($engine->support) === 'DEFAULT') { + $engines[strtoupper($engine->engine)] .= ' (default)'; + } + } + $rs->close(); + + return $engines; +} + +function mysql_get_table_engine($tablename) { + global $DB; + + $engine = null; + $sql = "SHOW TABLE STATUS WHERE Name = '$tablename'"; // no special chars expected here + $rs = $DB->get_recordset_sql($sql); + if ($rs->valid()) { + $record = $rs->current(); + $engine = $record->engine; + } + $rs->close(); + return $engine; +} From f92b65e5a601c1badda7847d228e5a8cd53b61cf Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 28 May 2012 16:27:22 +0800 Subject: [PATCH 403/455] MDL-33377 Do not allow to link to course files since reference is preferable --- repository/coursefiles/lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repository/coursefiles/lib.php b/repository/coursefiles/lib.php index 2f1e8fe9a3e..16353b83818 100644 --- a/repository/coursefiles/lib.php +++ b/repository/coursefiles/lib.php @@ -186,7 +186,7 @@ class repository_coursefiles extends repository { } public function supported_returntypes() { - return (FILE_INTERNAL | FILE_EXTERNAL | FILE_REFERENCE); + return (FILE_INTERNAL | FILE_REFERENCE); } public static function get_type_option_names() { From 6bea694b6cbc3c53dd5cfce1f0ad15e1b120a550 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 28 May 2012 16:57:41 +0800 Subject: [PATCH 404/455] Revert "MDL-33212 Course page: Eye icon should override other conditions" This reverts commit 5d0d373733a42d1b5b25716c8d11087debd62942. --- course/lib.php | 2 +- lib/conditionlib.php | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/course/lib.php b/course/lib.php index a5566d6a6bc..648f87e86af 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1728,7 +1728,7 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false, // see the activity itself, or for staff) if (!$mod->uservisible) { echo '
                          '.$mod->availableinfo.'
                          '; - } else if ($canviewhidden && !empty($CFG->enableavailability) && $mod->visible) { + } else if ($canviewhidden && !empty($CFG->enableavailability)) { $ci = new condition_info($mod); $fullinfo = $ci->get_full_information(); if($fullinfo) { diff --git a/lib/conditionlib.php b/lib/conditionlib.php index 5e2207f186c..9bcd4bbe5d2 100644 --- a/lib/conditionlib.php +++ b/lib/conditionlib.php @@ -846,16 +846,6 @@ abstract class condition_info_base { } } - // If the item is marked as 'not visible' then we don't change the available - // flag (visible/available are treated distinctly), but we remove any - // availability info. If the item is hidden with the eye icon, it doesn't - // make sense to show 'Available from ' or similar, because even - // when that date arrives it will still not be available unless somebody - // toggles the eye icon. - if (!$this->item->visible) { - $information = ''; - } - $information = trim($information); return $available; } From 2da7fbc0c291d91b01e182d55b55a4fa5f26b544 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Mon, 28 May 2012 10:59:22 +0200 Subject: [PATCH 405/455] MDL-33382 CLI install and upgrade scripts display hint on --allow-unstable in non-interactive mode --- admin/cli/install.php | 3 ++- admin/cli/upgrade.php | 3 ++- lang/en/admin.php | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/admin/cli/install.php b/admin/cli/install.php index dc65e318d14..2cd66f7646e 100644 --- a/admin/cli/install.php +++ b/admin/cli/install.php @@ -425,7 +425,8 @@ if (isset($maturity)) { exit(1); } } else { - cli_error(get_string('maturitycorewarning', 'admin')); + cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel)); + cli_error(get_string('maturityallowunstable', 'admin')); } } } diff --git a/admin/cli/upgrade.php b/admin/cli/upgrade.php index 33e66cc3a4f..e552d4e1b31 100644 --- a/admin/cli/upgrade.php +++ b/admin/cli/upgrade.php @@ -132,7 +132,8 @@ if (isset($maturity)) { echo get_string('morehelp') . ': ' . get_docs_url('admin/versions') . PHP_EOL; cli_separator(); } else { - cli_error(get_string('maturitycorewarning', 'admin', $maturitylevel)); + cli_problem(get_string('maturitycorewarning', 'admin', $maturitylevel)); + cli_error(get_string('maturityallowunstable', 'admin')); } } } diff --git a/lang/en/admin.php b/lang/en/admin.php index 2ac7b1e2a6b..82581fe53d0 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -636,6 +636,7 @@ $string['maturity50'] = 'Alpha'; $string['maturity100'] = 'Beta'; $string['maturity150'] = 'Release candidate'; $string['maturity200'] = 'Stable version'; +$string['maturityallowunstable'] = 'Hint: You may want to run this script with --allow-unstable option'; $string['maturitycoreinfo'] = 'Your site is currently running unstable "{$a}" development code.'; $string['maturitycorewarning'] = 'The version of Moodle that you are about to install or upgrade to contains unstable "{$a}" development code that is not suitable for use on most production From 140669a9ddaf1e088ff8ef8efd25e8a2a793190d Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 28 May 2012 17:05:25 +0800 Subject: [PATCH 406/455] MDL-33026 set default author and license in drag-n-drop upload --- lib/form/dndupload.js | 4 ++++ lib/form/filemanager.js | 1 + lib/form/filepicker.js | 1 + 3 files changed, 6 insertions(+) diff --git a/lib/form/dndupload.js b/lib/form/dndupload.js index bf7316a794a..2e1514c9c3f 100644 --- a/lib/form/dndupload.js +++ b/lib/form/dndupload.js @@ -91,6 +91,7 @@ M.form_dndupload.init = function(Y, options) { this.maxfiles = options.maxfiles; this.maxbytes = options.maxbytes; this.itemid = options.itemid; + this.author = options.author; this.container = this.Y.one('#'+options.containerid); if (options.filemanager) { @@ -452,6 +453,9 @@ M.form_dndupload.init = function(Y, options) { formdata.append('sesskey', M.cfg.sesskey); formdata.append('repo_id', this.repositoryid); formdata.append('itemid', this.itemid); + if (this.author) { + formdata.append('author', this.author); + } if (this.filemanager) { // Filepickers do not have folders formdata.append('savepath', this.filemanager.currentpath); } diff --git a/lib/form/filemanager.js b/lib/form/filemanager.js index 592dc1c876a..6627c2a9d21 100644 --- a/lib/form/filemanager.js +++ b/lib/form/filemanager.js @@ -963,6 +963,7 @@ M.form_filemanager.init = function(Y, options) { filemanager: manager, acceptedtypes: options.accepted_types, clientid: options.client_id, + author: options.author, maxfiles: options.maxfiles, maxbytes: options.maxbytes, itemid: options.itemid, diff --git a/lib/form/filepicker.js b/lib/form/filepicker.js index 4b5de337f64..e372a23c086 100644 --- a/lib/form/filepicker.js +++ b/lib/form/filepicker.js @@ -47,6 +47,7 @@ M.form_filepicker.init = function(Y, options) { var dndoptions = { clientid: options.client_id, acceptedtypes: options.accepted_types, + author: options.author, maxfiles: -1, maxbytes: options.maxbytes, itemid: options.itemid, From f5b32abe577e4a90a92623b876802973a804a463 Mon Sep 17 00:00:00 2001 From: Ruslan Kabalin Date: Wed, 16 May 2012 15:41:55 +0100 Subject: [PATCH 407/455] MDL-33045: Assign: Make get_module_name() return something --- mod/assign/locallib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index ff3731971e5..099db4eb297 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -118,10 +118,10 @@ class assign { private $returnparams = array(); /** @var string modulename prevents excessive calls to get_string */ - private static $modulename = ''; + private static $modulename = null; /** @var string modulenameplural prevents excessive calls to get_string */ - private static $modulenameplural = ''; + private static $modulenameplural = null; /** * Constructor for the base assign class From 599f7a279c7f078941ede3c448f574a92be40efc Mon Sep 17 00:00:00 2001 From: Ruslan Kabalin Date: Wed, 16 May 2012 15:43:45 +0100 Subject: [PATCH 408/455] MDL-33045: Assign: remove references to old assignment in URLs --- mod/assign/locallib.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index 099db4eb297..2211bb86876 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -2368,8 +2368,8 @@ class assign { global $CFG; $posthtml = '

                          '. ''.format_string($course->shortname, true, array('context' => $context->get_course_context())).' ->'. - ''.$modulename.' ->'. - ''.format_string($assignmentname, true, array('context' => $context)).'

                          '; + ''.$modulename.' ->'. + ''.format_string($assignmentname, true, array('context' => $context)).'

                          '; $posthtml .= '
                          '; $posthtml .= '

                          '.get_string($messagetype . 'html', 'assign', $info).'

                          '; $posthtml .= '

                          '; From 77a439336fef2663846224f98bb9411d20d0f7a1 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Mon, 28 May 2012 12:19:05 +0200 Subject: [PATCH 409/455] MDL-33378 file thumbnail falls back to the default mimetype icon If for some reason the thumbnail generation fails, the default core mimetype icon for the given file is sent to the browser. --- lib/filelib.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/filelib.php b/lib/filelib.php index aa46e625863..75521fe6fce 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -2287,14 +2287,22 @@ function send_stored_file($stored_file, $lifetime=86400 , $filter=0, $forcedownl if (!empty($options['preview'])) { // replace the file with its preview $fs = get_file_storage(); - $stored_file = $fs->get_file_preview($stored_file, $options['preview']); - if (!$stored_file) { - // unable to create a preview of the file - send_header_404(); - die(); + $preview_file = $fs->get_file_preview($stored_file, $options['preview']); + if (!$preview_file) { + // unable to create a preview of the file, send its default mime icon instead + if ($options['preview'] === 'tinyicon') { + $size = 24; + } else if ($options['preview'] === 'thumb') { + $size = 90; + } else { + $size = 256; + } + $fileicon = file_file_icon($stored_file, $size); + send_file($CFG->dirroot.'/pix/'.$fileicon.'.png', basename($fileicon).'.png'); } else { // preview images have fixed cache lifetime and they ignore forced download // (they are generated by GD and therefore they are considered reasonably safe). + $stored_file = $preview_file; $lifetime = DAYSECS; $filter = 0; $forcedownload = false; From 540f89d7d4bdc76ca4f64f0709a3dc706222a3e5 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Wed, 23 May 2012 13:46:51 +0100 Subject: [PATCH 410/455] MDL-33212 Course page: Eye icon should override other conditions --- course/lib.php | 2 +- lib/conditionlib.php | 16 ++++++++++++++-- lib/tests/conditionlib_test.php | 14 ++++++++++---- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/course/lib.php b/course/lib.php index 8e073737607..cdc74a1e29e 100644 --- a/course/lib.php +++ b/course/lib.php @@ -1728,7 +1728,7 @@ function print_section($course, $section, $mods, $modnamesused, $absolute=false, // see the activity itself, or for staff) if (!$mod->uservisible) { echo '
                          '.$mod->availableinfo.'
                          '; - } else if ($canviewhidden && !empty($CFG->enableavailability)) { + } else if ($canviewhidden && !empty($CFG->enableavailability) && $mod->visible) { $ci = new condition_info($mod); $fullinfo = $ci->get_full_information(); if($fullinfo) { diff --git a/lib/conditionlib.php b/lib/conditionlib.php index 9bcd4bbe5d2..0d8b3cbfde7 100644 --- a/lib/conditionlib.php +++ b/lib/conditionlib.php @@ -69,7 +69,8 @@ class condition_info extends condition_info_base { * @param object $cm Moodle course-module object. May have extra fields * ->conditionsgrade, ->conditionscompletion which should come from * get_fast_modinfo. Should have ->availablefrom, ->availableuntil, - * and ->showavailability, ->course; but the only required thing is ->id. + * and ->showavailability, ->course, ->visible; but the only required + * thing is ->id. * @param int $expectingmissing Used to control whether or not a developer * debugging message (performance warning) will be displayed if some of * the above data is missing and needs to be retrieved; a @@ -426,7 +427,8 @@ abstract class condition_info_base { * @return array Array of field names */ protected function get_main_table_fields() { - return array('id', 'course', 'availablefrom', 'availableuntil', 'showavailability'); + return array('id', 'course', 'visible', + 'availablefrom', 'availableuntil', 'showavailability'); } /** @@ -846,6 +848,16 @@ abstract class condition_info_base { } } + // If the item is marked as 'not visible' then we don't change the available + // flag (visible/available are treated distinctly), but we remove any + // availability info. If the item is hidden with the eye icon, it doesn't + // make sense to show 'Available from ' or similar, because even + // when that date arrives it will still not be available unless somebody + // toggles the eye icon. + if (!$this->item->visible) { + $information = ''; + } + $information = trim($information); return $available; } diff --git a/lib/tests/conditionlib_test.php b/lib/tests/conditionlib_test.php index f35c916e66b..2315916241d 100644 --- a/lib/tests/conditionlib_test.php +++ b/lib/tests/conditionlib_test.php @@ -70,7 +70,8 @@ class conditionlib_testcase extends advanced_testcase { $this->assertEquals( (object)array('id'=>$id,'showavailability'=>1, 'availablefrom'=>17,'availableuntil'=>398,'course'=>64, - 'conditionsgrade'=>array(), 'conditionscompletion'=>array()), + 'conditionsgrade'=>array(), 'conditionscompletion'=>array(), + 'visible' => 1), $test->get_full_course_module()); // just the course_modules stuff; check it doesn't request that from db @@ -78,11 +79,13 @@ class conditionlib_testcase extends advanced_testcase { $cm->availablefrom=2; $cm->availableuntil=74; $cm->course=38; + $cm->visible = 1; $test=new condition_info($cm,CONDITION_MISSING_EXTRATABLE); $this->assertEquals( (object)array('id'=>$id,'showavailability'=>0, 'availablefrom'=>2,'availableuntil'=>74,'course'=>38, - 'conditionsgrade'=>array(), 'conditionscompletion'=>array()), + 'conditionsgrade' => array(), 'conditionscompletion' => array(), + 'visible' => 1), $test->get_full_course_module()); // Now let's add some actual grade/completion conditions @@ -136,7 +139,8 @@ class conditionlib_testcase extends advanced_testcase { $this->assertEquals( (object)array('id' => $id, 'showavailability' => 1, 'groupingid' => 13, 'availablefrom' => 17, 'availableuntil' => 398, 'course' => 64, - 'conditionsgrade' => array(), 'conditionscompletion' => array()), + 'conditionsgrade' => array(), 'conditionscompletion' => array(), + 'visible' => 1), $test->get_full_section()); // Just the course_sections stuff; check it doesn't request that from db @@ -146,11 +150,13 @@ class conditionlib_testcase extends advanced_testcase { $section->availableuntil = 74; $section->course = 38; $section->groupingid = 99; + $section->visible = 1; $test = new condition_info_section($section, CONDITION_MISSING_EXTRATABLE); $this->assertEquals( (object)array('id' => $id, 'showavailability' => 0, 'groupingid' => 99, 'availablefrom' => 2, 'availableuntil' => 74, 'course' => 38, - 'conditionsgrade' => array(), 'conditionscompletion' => array()), + 'conditionsgrade' => array(), 'conditionscompletion' => array(), + 'visible' => 1), $test->get_full_section()); // Now let's add some actual grade/completion conditions From e6f55285852d7dd7dd669578934c5d5b0f7e6557 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Tue, 29 May 2012 08:50:45 +1200 Subject: [PATCH 411/455] MDL-28949 upgrade: Split course completion upgrade into smaller chunks --- lib/db/upgrade.php | 42 ++++++++++++++++++++++++++++-------------- lib/upgradelib.php | 6 +++--- version.php | 2 +- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index f50502386b5..ba53f99374e 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -686,42 +686,49 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2012052500.03); } - /** - * Major clean up of course completion tables - */ if ($oldversion < 2012052900.00) { - - // Clean up all instances of duplicate records - // Add indexes to prevent new duplicates + // Clean up all duplicate records in the course_completions table in preparation + // for adding a new index there. upgrade_course_completion_remove_duplicates( 'course_completions', array('userid', 'course'), array('timecompleted', 'timestarted', 'timeenrolled') ); + // Main savepoint reached + upgrade_main_savepoint(true, 2012052900.00); + } + + if ($oldversion < 2012052900.01) { + // Add indexes to prevent new duplicates in the course_completions table. // Define index useridcourse (unique) to be added to course_completions $table = new xmldb_table('course_completions'); $index = new xmldb_index('useridcourse', XMLDB_INDEX_UNIQUE, array('userid', 'course')); - // Conditionally launch add index useridcourse if (!$dbman->index_exists($table, $index)) { $dbman->add_index($table, $index); } // Main savepoint reached - upgrade_main_savepoint(true, 2012052900.00); + upgrade_main_savepoint(true, 2012052900.01); } - if ($oldversion < 2012052900.01) { - + if ($oldversion < 2012052900.02) { + // Clean up all duplicate records in the course_completion_crit_compl table in preparation + // for adding a new index there. upgrade_course_completion_remove_duplicates( 'course_completion_crit_compl', array('userid', 'course', 'criteriaid'), array('timecompleted') ); + // Main savepoint reached + upgrade_main_savepoint(true, 2012052900.02); + } + if ($oldversion < 2012052900.03) { + // Add indexes to prevent new duplicates in the course_completion_crit_compl table. // Define index useridcoursecriteraid (unique) to be added to course_completion_crit_compl $table = new xmldb_table('course_completion_crit_compl'); $index = new xmldb_index('useridcoursecriteraid', XMLDB_INDEX_UNIQUE, array('userid', 'course', 'criteriaid')); @@ -732,16 +739,23 @@ function xmldb_main_upgrade($oldversion) { } // Main savepoint reached - upgrade_main_savepoint(true, 2012052900.01); + upgrade_main_savepoint(true, 2012052900.03); } - if ($oldversion < 2012052900.02) { - + if ($oldversion < 2012052900.04) { + // Clean up all duplicate records in the course_completion_aggr_methd table in preparation + // for adding a new index there. upgrade_course_completion_remove_duplicates( 'course_completion_aggr_methd', array('course', 'criteriatype') ); + // Main savepoint reached + upgrade_main_savepoint(true, 2012052900.04); + } + + if ($oldversion < 2012052900.05) { + // Add indexes to prevent new duplicates in the course_completion_aggr_methd table. // Define index coursecriteratype (unique) to be added to course_completion_aggr_methd $table = new xmldb_table('course_completion_aggr_methd'); $index = new xmldb_index('coursecriteriatype', XMLDB_INDEX_UNIQUE, array('course', 'criteriatype')); @@ -752,7 +766,7 @@ function xmldb_main_upgrade($oldversion) { } // Main savepoint reached - upgrade_main_savepoint(true, 2012052900.02); + upgrade_main_savepoint(true, 2012052900.05); } return true; diff --git a/lib/upgradelib.php b/lib/upgradelib.php index ff87f9a2cf0..aa6ee8f6c3f 100644 --- a/lib/upgradelib.php +++ b/lib/upgradelib.php @@ -1775,7 +1775,7 @@ function admin_mnet_method_profile(Zend_Server_Reflection_Function_Abstract $fun * * @param string $table Table name * @param array $uniques Array of field names that should be unique - * @param array $feildstocheck Array of fields to generate "correct" data from (optional) + * @param array $fieldstocheck Array of fields to generate "correct" data from (optional) * @return void */ function upgrade_course_completion_remove_duplicates($table, $uniques, $fieldstocheck = array()) { @@ -1792,7 +1792,7 @@ function upgrade_course_completion_remove_duplicates($table, $uniques, $fieldsto $pointer = 0; // Generate SQL for finding records with these duplicate uniques - $sql_select = implode(' = ? AND ', $uniques).' = ?'; /// builds "fieldname = ? AND fieldname = ?" + $sql_select = implode(' = ? AND ', $uniques).' = ?'; // builds "fieldname = ? AND fieldname = ?" $uniq_values = array(); foreach ($uniques as $u) { $uniq_values[] = $duplicate->$u; @@ -1831,7 +1831,7 @@ function upgrade_course_completion_remove_duplicates($table, $uniques, $fieldsto } } if ($needsupdate || isset($origrecord->reaggregate)) { - // If this table has a reaggregate field, update to force recheck on next cron cron + // If this table has a reaggregate field, update to force recheck on next cron run if (isset($origrecord->reaggregate)) { $origrecord->reaggregate = time(); } diff --git a/version.php b/version.php index c7e462d74fe..dd7484cfbb0 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052900.02; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012052900.05; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes From 9b27ffa042d5a84d64283ea4a2e3bb8012f92c44 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Sun, 13 May 2012 15:33:02 +0800 Subject: [PATCH 412/455] MDL-29857 - portfolio: Fix E_STRICT errors --- lib/portfolio/forms.php | 6 +++--- portfolio/add.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/portfolio/forms.php b/lib/portfolio/forms.php index ba408f78486..7b7c66908ed 100644 --- a/lib/portfolio/forms.php +++ b/lib/portfolio/forms.php @@ -107,7 +107,7 @@ final class portfolio_export_form extends moodleform { * @param stdClass $data portfolio information from form data * @return array */ - public function validation($data) { + public function validation($data, $files) { $errors = array(); @@ -228,7 +228,7 @@ final class portfolio_admin_form extends moodleform { * @param stdObject $data form data * @return array */ - public function validation($data) { + public function validation($data, $files) { global $DB; $errors = array(); @@ -296,7 +296,7 @@ final class portfolio_user_form extends moodleform { * * @param stdClass $data form data */ - public function validation($data) { + public function validation($data, $files) { $errors = $this->instance->user_config_validation($data); diff --git a/portfolio/add.php b/portfolio/add.php index b3c3982df0a..b5a1c4a4e25 100644 --- a/portfolio/add.php +++ b/portfolio/add.php @@ -221,7 +221,8 @@ if (!$exporter->get('instance')) { throw new portfolio_export_exception($exporter, 'noavailableplugins', 'portfolio'); } else if (count($options) == 1) { // no point displaying a form, just redirect. - $instance = array_shift(array_keys($options)); + $optionskeys = array_keys($options); + $instance = array_shift($optionskeys); redirect($CFG->wwwroot . '/portfolio/add.php?id= ' . $exporter->get('id') . '&instance=' . $instance . '&sesskey=' . sesskey()); } // be very selective about not including this unless we really need to From f40f6c14b1d57eff6ddb0c8569c3ef5a03bf5893 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Sun, 13 May 2012 12:57:41 +0800 Subject: [PATCH 413/455] MDL-32221 - googledocs: Add support for all file types. Now google supports 'file' as well as converted formats. --- lib/googleapi.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/googleapi.php b/lib/googleapi.php index a079ffb5d2f..51292947113 100644 --- a/lib/googleapi.php +++ b/lib/googleapi.php @@ -319,6 +319,10 @@ class google_docs { $title = (string)$gdoc->title; $source = (string)$gdoc->content[0]->attributes()->src; break; + case 'file': + $title = (string)$gdoc->title; + $source = (string)$gdoc->content[0]->attributes()->src; + break; } if(!empty($source)){ From 9f4789b8427baab411d420d7600e3818ea30d2b0 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Tue, 29 May 2012 16:38:47 +1200 Subject: [PATCH 414/455] MDL-33399 files: Fixed up handling of empty sort in File API methods. The following three methods of file_storage have been patched: * get_external_files * get_area_files * get_directory_files --- lib/filestorage/file_storage.php | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index edac5a52517..8a72ca684dc 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -366,7 +366,7 @@ class file_storage { * Returns all files belonging to given repository * * @param int $repositoryid - * @param string $sort + * @param string $sort A fragment of SQL to use for sorting */ public function get_external_files($repositoryid, $sort = 'sortorder, itemid, filepath, filename') { global $DB; @@ -374,8 +374,10 @@ class file_storage { FROM {files} f LEFT JOIN {files_reference} r ON f.referencefileid = r.id - WHERE r.repositoryid = ? - ORDER BY $sort"; + WHERE r.repositoryid = ?"; + if (!empty($sort)) { + $sql .= " ORDER BY {$sort}"; + } $result = array(); $filerecords = $DB->get_records_sql($sql, array($repositoryid)); @@ -392,11 +394,11 @@ class file_storage { * @param string $component component * @param string $filearea file area * @param int $itemid item ID or all files if not specified - * @param string $sort sort fields + * @param string $sort A fragment of SQL to use for sorting * @param bool $includedirs whether or not include directories * @return array of stored_files indexed by pathanmehash */ - public function get_area_files($contextid, $component, $filearea, $itemid = false, $sort="sortorder, itemid, filepath, filename", $includedirs = true) { + public function get_area_files($contextid, $component, $filearea, $itemid = false, $sort = "sortorder, itemid, filepath, filename", $includedirs = true) { global $DB; $conditions = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea); @@ -414,8 +416,10 @@ class file_storage { WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea - $itemidsql - ORDER BY $sort"; + $itemidsql"; + if (!empty($sort)) { + $sql .= " ORDER BY {$sort}"; + } $result = array(); $filerecords = $DB->get_records_sql($sql, $conditions); @@ -489,7 +493,7 @@ class file_storage { * @param int $filepath directory path * @param bool $recursive include all subdirectories * @param bool $includedirs include files and directories - * @param string $sort sort fields + * @param string $sort A fragment of SQL to use for sorting * @return array of stored_files indexed by pathanmehash */ public function get_directory_files($contextid, $component, $filearea, $itemid, $filepath, $recursive = false, $includedirs = true, $sort = "filepath, filename") { @@ -499,6 +503,8 @@ class file_storage { return array(); } + $orderby = (!empty($sort)) ? " ORDER BY {$sort}" : ''; + if ($recursive) { $dirs = $includedirs ? "" : "AND filename <> '.'"; @@ -512,7 +518,7 @@ class file_storage { AND ".$DB->sql_substr("f.filepath", 1, $length)." = :filepath AND f.id <> :dirid $dirs - ORDER BY $sort"; + $orderby"; $params = array('contextid'=>$contextid, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'filepath'=>$filepath, 'dirid'=>$directory->get_id()); $files = array(); @@ -542,7 +548,7 @@ class file_storage { AND f.itemid = :itemid AND f.filename = '.' AND ".$DB->sql_substr("f.filepath", 1, $length)." = :filepath AND f.id <> :dirid - ORDER BY $sort"; + $orderby"; $reqlevel = substr_count($filepath, '/') + 1; $filerecords = $DB->get_records_sql($sql, $params); foreach ($filerecords as $filerecord) { @@ -559,7 +565,7 @@ class file_storage { ON f.referencefileid = r.id WHERE f.contextid = :contextid AND f.component = :component AND f.filearea = :filearea AND f.itemid = :itemid AND f.filepath = :filepath AND f.filename <> '.' - ORDER BY $sort"; + $orderby"; $filerecords = $DB->get_records_sql($sql, $params); foreach ($filerecords as $filerecord) { From 849b9a6af7f8e50aed6e813c51b1230120dd3032 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Tue, 29 May 2012 16:44:28 +1200 Subject: [PATCH 415/455] MDL-33399 mixed: Fixed up calls to get_area_files that used empty sorts --- lib/filebrowser/file_info_stored.php | 2 +- lib/portfolio/exporter.php | 2 +- mod/scorm/datamodels/aicclib.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/filebrowser/file_info_stored.php b/lib/filebrowser/file_info_stored.php index a5a37a3d908..2f3ea57211a 100644 --- a/lib/filebrowser/file_info_stored.php +++ b/lib/filebrowser/file_info_stored.php @@ -505,7 +505,7 @@ class file_info_stored extends file_info { if ($this->is_directory()) { $filepath = $this->lf->get_filepath(); $fs = get_file_storage(); - $storedfiles = $fs->get_area_files($this->context->id, $this->get_component(), $this->lf->get_filearea(), $this->lf->get_itemid(), ""); + $storedfiles = $fs->get_area_files($this->context->id, $this->get_component(), $this->lf->get_filearea(), $this->lf->get_itemid()); foreach ($storedfiles as $file) { if (strpos($file->get_filepath(), $filepath) === 0) { $file->delete(); diff --git a/lib/portfolio/exporter.php b/lib/portfolio/exporter.php index 81727f53ede..3baf0b5bcb3 100644 --- a/lib/portfolio/exporter.php +++ b/lib/portfolio/exporter.php @@ -809,7 +809,7 @@ class portfolio_exporter { */ public function get_tempfiles($skipfile='portfolio-export.zip') { $fs = get_file_storage(); - $files = $fs->get_area_files(SYSCONTEXTID, 'portfolio', 'exporter', $this->id, '', false); + $files = $fs->get_area_files(SYSCONTEXTID, 'portfolio', 'exporter', $this->id, 'sortorder, itemid, filepath, filename', false); if (empty($files)) { return array(); } diff --git a/mod/scorm/datamodels/aicclib.php b/mod/scorm/datamodels/aicclib.php index c926c12496e..43369fe5485 100644 --- a/mod/scorm/datamodels/aicclib.php +++ b/mod/scorm/datamodels/aicclib.php @@ -121,7 +121,7 @@ function scorm_parse_aicc($scorm) { $fs = get_file_storage(); - $files = $fs->get_area_files($context->id, 'mod_scorm', 'content', 0, '', false); + $files = $fs->get_area_files($context->id, 'mod_scorm', 'content', 0, 'sortorder, itemid, filepath, filename', false); $version = 'AICC'; $ids = array(); From 5fece0f28dcff610f945da7978e6213776167c20 Mon Sep 17 00:00:00 2001 From: Martin Dougiamas Date: Tue, 29 May 2012 12:58:24 +0800 Subject: [PATCH 416/455] MDL-33404 Fix defaults for ordinary files that are drag/dropped into the course page --- mod/resource/lib.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mod/resource/lib.php b/mod/resource/lib.php index 179c50761d9..d5f2081dbcc 100644 --- a/mod/resource/lib.php +++ b/mod/resource/lib.php @@ -500,7 +500,7 @@ function mod_resource_dndupload_handle($uploadinfo) { $data = new stdClass(); $data->course = $uploadinfo->course->id; $data->name = $uploadinfo->displayname; - $data->intro = '

                          '.$uploadinfo->displayname.'

                          '; + $data->intro = ''; $data->introformat = FORMAT_HTML; $data->coursemodule = $uploadinfo->coursemodule; $data->files = $uploadinfo->draftitemid; @@ -512,6 +512,8 @@ function mod_resource_dndupload_handle($uploadinfo) { $data->popupwidth = $config->popupwidth; $data->printheading = $config->printheading; $data->printintro = $config->printintro; + $data->showsize = $config->showsize; + $data->showtype = $config->showtype; return resource_add_instance($data, null); } From 7f1fcda5ad5d75719547996f7c5d880444bf3348 Mon Sep 17 00:00:00 2001 From: Aparup Banerjee Date: Tue, 29 May 2012 14:29:09 +0800 Subject: [PATCH 417/455] Revert "Merge branch 'wip-mdl-27120' of git://github.com/rajeshtaneja/moodle" MDL-27120 backup: reverting due to phpunit failure at backup/converter/moodle1/tests/fixtures/lib_test.php test_stash_storage() This reverts commit c70b7fd81fa8d40e453ad7f5fa1759df48ae549f, reversing changes made to e6f55285852d7dd7dd669578934c5d5b0f7e6557. --- .../moodle2/backup_xml_transformer.class.php | 20 -- backup/util/dbops/restore_dbops.class.php | 197 +++--------------- backup/util/plan/base_plan.class.php | 26 +-- backup/util/ui/backup_ui_stage.class.php | 22 +- backup/util/ui/base_moodleform.class.php | 46 ++-- 5 files changed, 66 insertions(+), 245 deletions(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index 25c8503bcf7..a3770d03528 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -27,13 +27,6 @@ defined('MOODLE_INTERNAL') || die(); -// Cache for storing link encoders, so that we don't need to call -// register_link_encoders each time backup_xml_transformer is constructed -// TODO MDL-25290 replace global with MUC code. -global $LINKS_ENCODERS_CACHE; - -$LINKS_ENCODERS_CACHE = array(); - /** * Class implementing the @xml_contenttrasnformed logic to be applied in moodle2 backups * @@ -138,19 +131,7 @@ class backup_xml_transformer extends xml_contenttransformer { return $result; } - /** - * Register all available content link encoders - * - * @return array encoder - * @todo MDL-25290 replace LINKS_ENCODERS_CACHE global with MUC code - */ private function register_link_encoders() { - global $LINKS_ENCODERS_CACHE; - // If encoder is linked, then return cached encoder. - if (!empty($LINKS_ENCODERS_CACHE)) { - return $LINKS_ENCODERS_CACHE; - } - $encoders = array(); // Add the course encoder @@ -179,7 +160,6 @@ class backup_xml_transformer extends xml_contenttransformer { // Add local encodes // TODO: Any interest? 1.9 never had that. - $LINKS_ENCODERS_CACHE = $encoders; return $encoders; } } diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index f9496ea04b2..e50c6e607df 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -28,38 +28,6 @@ * TODO: Finish phpdocs */ abstract class restore_dbops { - /** - * Keep cache of backup records. - * @var array - * @todo MDL-25290 static should be replaced with MUC code. - */ - private static $backupidscache = array(); - /** - * Keep track of backup ids which are cached. - * @var array - * @todo MDL-25290 static should be replaced with MUC code. - */ - private static $backupidsexist = array(); - /** - * Count is expensive, so manually keeping track of - * backupidscache, to avoid memory issues. - * @var int - * @todo MDL-25290 static should be replaced with MUC code. - */ - private static $backupidscachesize = 2048; - /** - * Count is expensive, so manually keeping track of - * backupidsexist, to avoid memory issues. - * @var int - * @todo MDL-25290 static should be replaced with MUC code. - */ - private static $backupidsexistsize = 10240; - /** - * Slice backupids cache to add more data. - * @var int - * @todo MDL-25290 static should be replaced with MUC code. - */ - private static $backupidsslice = 512; /** * Return one array containing all the tasks that have been included @@ -183,134 +151,6 @@ abstract class restore_dbops { return $problems; } - /** - * Return cached backup id's - * - * @param int $restoreid id of backup - * @param string $itemname name of the item - * @param int $itemid id of item - * @return array backup id's - * @todo MDL-25290 replace static backupids* with MUC code - */ - protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) { - global $DB; - - $key = "$itemid $itemname $restoreid"; - - // If record exists in cache then return. - if (isset(self::$backupidsexist[$key]) && isset(self::$backupidscache[$key])) { - return self::$backupidscache[$key]; - } - - // Clean cache, if it's full. - if (self::$backupidscachesize <= 0) { - // Remove some records, to keep memory in limit. - self::$backupidscache = array_slice(self::$backupidscache, self::$backupidsslice, null, true); - self::$backupidscachesize = self::$backupidscachesize + self::$backupidsslice; - } - if (self::$backupidsexistsize <= 0) { - self::$backupidsexist = array_slice(self::$backupidsexist, self::$backupidsslice, null, true); - self::$backupidsexistsize = self::$backupidsexistsize + self::$backupidsslice; - } - - // Retrive record from database. - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid - ); - if ($dbrec = $DB->get_record('backup_ids_temp', $record)) { - self::$backupidsexist[$key] = $dbrec->id; - self::$backupidscache[$key] = $dbrec; - self::$backupidscachesize--; - self::$backupidsexistsize--; - return self::$backupidscache[$key]; - } else { - return false; - } - } - - /** - * Cache backup ids' - * - * @param int $restoreid id of backup - * @param string $itemname name of the item - * @param int $itemid id of item - * @param array $extrarecord extra record which needs to be updated - * @return void - * @todo MDL-25290 replace static BACKUP_IDS_* with MUC code - */ - protected static function set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord) { - global $DB; - - $key = "$itemid $itemname $restoreid"; - - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid, - ); - - // If record is not cached then add one. - if (!isset(self::$backupidsexist[$key])) { - // If we have this record in db, then just update this. - if ($existingrecord = $DB->get_record('backup_ids_temp', $record)) { - self::$backupidsexist[$key] = $existingrecord->id; - self::$backupidsexistsize--; - self::update_backup_cached_record($record, $extrarecord, $key, $existingrecord); - } else { - // Add new record to cache and db. - $recorddefault = array ( - 'newitemid' => 0, - 'parentitemid' => null, - 'info' => null); - $record = array_merge($record, $recorddefault, $extrarecord); - $record['id'] = $DB->insert_record('backup_ids_temp', $record); - self::$backupidsexist[$key] = $record['id']; - self::$backupidsexistsize--; - if (self::$backupidscachesize > 0) { - // Cache new records if we haven't got many yet. - self::$backupidscache[$key] = (object) $record; - self::$backupidscachesize--; - } - } - } else { - self::update_backup_cached_record($record, $extrarecord, $key); - } - } - - /** - * Updates existing backup record - * - * @param array $record record which needs to be updated - * @param array $extrarecord extra record which needs to be updated - * @param string $key unique key which is used to identify cached record - * @param stdClass $existingrecord (optional) existing record - */ - protected static function update_backup_cached_record($record, $extrarecord, $key, $existingrecord = null) { - global $DB; - // Update only if extrarecord is not empty. - if (!empty($extrarecord)) { - $extrarecord['id'] = self::$backupidsexist[$key]; - $DB->update_record('backup_ids_temp', $extrarecord); - // Update existing cache or add new record to cache. - if (isset(self::$backupidscache[$key])) { - $record = array_merge((array)self::$backupidscache[$key], $extrarecord); - self::$backupidscache[$key] = (object) $record; - } else if (self::$backupidscachesize > 0) { - if ($existingrecord) { - self::$backupidscache[$key] = $existingrecord; - } else { - // Retrive record from database and cache updated records. - self::$backupidscache[$key] = $DB->get_record('backup_ids_temp', $record); - } - $record = array_merge((array)self::$backupidscache[$key], $extrarecord); - self::$backupidscache[$key] = (object) $record; - self::$backupidscachesize--; - } - } - } - /** * Given one role, as loaded from XML, perform the best possible matching against the assignable * roles, using different fallback alternatives (shortname, archetype, editingteacher => teacher, defaultcourseroleid) @@ -1379,7 +1219,16 @@ abstract class restore_dbops { $DB->insert_record('backup_files_temp', $filerec); } + public static function set_backup_ids_record($restoreid, $itemname, $itemid, $newitemid = 0, $parentitemid = null, $info = null) { + global $DB; + + // Build the basic (mandatory) record info + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid + ); // Build conditionally the extra record info $extrarecord = array(); if ($newitemid != 0) { @@ -1392,16 +1241,34 @@ abstract class restore_dbops { $extrarecord['info'] = base64_encode(serialize($info)); } - self::set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord); + // TODO: Analyze if some static (and limited) cache by the 3 params could save us a bunch of get_record() calls + // Note: Sure it will! And also will improve getter + if (!$dbrec = $DB->get_record('backup_ids_temp', $record)) { // Need to insert the complete record + $DB->insert_record('backup_ids_temp', array_merge($record, $extrarecord)); + + } else { // Need to update the extra record info if there is something to + if (!empty($extrarecord)) { + $extrarecord['id'] = $dbrec->id; + $DB->update_record('backup_ids_temp', $extrarecord); + } + } } public static function get_backup_ids_record($restoreid, $itemname, $itemid) { - $dbrec = self::get_backup_ids_cached($restoreid, $itemname, $itemid); + global $DB; - if ($dbrec && isset($dbrec->info) && is_string($dbrec->info)) { - $dbrec->info = unserialize(base64_decode($dbrec->info)); + // Build the basic (mandatory) record info to look for + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid + ); + // TODO: Analyze if some static (and limited) cache by the 3 params could save us a bunch of get_record() calls + if ($dbrec = $DB->get_record('backup_ids_temp', $record)) { + if ($dbrec->info != null) { + $dbrec->info = unserialize(base64_decode($dbrec->info)); + } } - return $dbrec; } diff --git a/backup/util/plan/base_plan.class.php b/backup/util/plan/base_plan.class.php index eab1869d6d3..3ed176b0bbf 100644 --- a/backup/util/plan/base_plan.class.php +++ b/backup/util/plan/base_plan.class.php @@ -61,12 +61,7 @@ abstract class base_plan implements checksumable, executable { // Append task settings to plan array, if not present, for comodity foreach ($task->get_settings() as $key => $setting) { if (!in_array($setting, $this->settings)) { - $name = $setting->get_name(); - if (!isset($this->settings[$name])) { - $this->settings[$name] = $setting; - } else { - throw new base_plan_exception('multiple_settings_by_name_found', $name); - } + $this->settings[] = $setting; } } } @@ -89,16 +84,23 @@ abstract class base_plan implements checksumable, executable { /** * return one setting by name, useful to request root/course settings - * that are, by definition, unique by name. + * that are, by definition, unique by name. Throws exception if multiple + * are found * - * @param string $name name of the setting - * @throws base_plan_exception if setting name is not found. + * TODO: Change this to string indexed array for quicker lookup. Not critical */ public function get_setting($name) { $result = null; - if (isset($this->settings[$name])) { - $result = $this->settings[$name]; - } else { + foreach ($this->settings as $key => $setting) { + if ($setting->get_name() == $name) { + if ($result != null) { + throw new base_plan_exception('multiple_settings_by_name_found', $name); + } else { + $result = $setting; + } + } + } + if (!$result) { throw new base_plan_exception('setting_by_name_not_found', $name); } return $result; diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index 799556157e0..1ce9053dd52 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -124,8 +124,6 @@ class backup_ui_stage_initial extends backup_ui_stage { // Store as a variable so we can iterate by reference $tasks = $this->ui->get_tasks(); // Iterate all tasks by reference - $add_settings = array(); - $dependencies = array(); foreach ($tasks as &$task) { // For the initial stage we are only interested in the root settings if ($task instanceof backup_root_task) { @@ -136,23 +134,17 @@ class backup_ui_stage_initial extends backup_ui_stage { if ($setting->get_name() == 'filename') { continue; } - $add_settings[] = array($setting, $task); + $form->add_setting($setting, $task); } // Then add all dependencies foreach ($settings as &$setting) { if ($setting->get_name() == 'filename') { continue; } - $dependencies[] = $setting; + $form->add_dependencies($setting); } } } - // Add all settings at once. - $form->add_settings($add_settings); - // Add dependencies. - foreach ($dependencies as $depsetting) { - $form->add_dependencies($depsetting); - } $this->stageform = $form; } // Return the form @@ -234,8 +226,6 @@ class backup_ui_stage_schema extends backup_ui_stage { $tasks = $this->ui->get_tasks(); $content = ''; $courseheading = false; - $add_settings = array(); - $dependencies = array(); foreach ($tasks as $task) { if (!($task instanceof backup_root_task)) { if (!$courseheading) { @@ -245,11 +235,11 @@ class backup_ui_stage_schema extends backup_ui_stage { } // First add each setting foreach ($task->get_settings() as $setting) { - $add_settings[] = array($setting, $task); + $form->add_setting($setting, $task); } // The add all the dependencies foreach ($task->get_settings() as $setting) { - $dependencies[] = $setting; + $form->add_dependencies($setting); } } else if ($this->ui->enforce_changed_dependencies()) { // Only show these settings if dependencies changed them. @@ -264,10 +254,6 @@ class backup_ui_stage_schema extends backup_ui_stage { } } } - $form->add_settings($add_settings); - foreach ($dependencies as $depsetting) { - $form->add_dependencies($depsetting); - } $this->stageform = $form; } return $this->stageform; diff --git a/backup/util/ui/base_moodleform.class.php b/backup/util/ui/base_moodleform.class.php index e0ffc0f9fcf..ad992602083 100644 --- a/backup/util/ui/base_moodleform.class.php +++ b/backup/util/ui/base_moodleform.class.php @@ -136,38 +136,24 @@ abstract class base_moodleform extends moodleform { * @return bool */ function add_setting(backup_setting $setting, base_task $task=null) { - return $this->add_settings(array(array($setting, $task))); - } - /** - * Adds multiple backup_settings as elements to the form - * @param array $settingstasks Consists of array($setting, $task) elements - * @return bool - */ - public function add_settings(array $settingstasks) { global $OUTPUT; - $defaults = array(); - foreach ($settingstasks as $st) { - list($setting, $task) = $st; - // If the setting cant be changed or isn't visible then add it as a fixed setting. - if (!$setting->get_ui()->is_changeable() || $setting->get_visibility() != backup_setting::VISIBLE) { - $this->add_fixed_setting($setting, $task); - continue; - } - - // First add the formatting for this setting - $this->add_html_formatting($setting); - - // Then call the add method with the get_element_properties array - call_user_func_array(array($this->_form, 'addElement'), $setting->get_ui()->get_element_properties($task, $OUTPUT)); - $defaults[$setting->get_ui_name()] = $setting->get_value(); - if ($setting->has_help()) { - list($identifier, $component) = $setting->get_help(); - $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component); - } - $this->_form->addElement('html', html_writer::end_tag('div')); + // If the setting cant be changed or isn't visible then add it as a fixed setting. + if (!$setting->get_ui()->is_changeable() || $setting->get_visibility() != backup_setting::VISIBLE) { + return $this->add_fixed_setting($setting, $task); } - $this->_form->setDefaults($defaults); + + // First add the formatting for this setting + $this->add_html_formatting($setting); + + // The call the add method with the get_element_properties array + call_user_func_array(array($this->_form, 'addElement'), $setting->get_ui()->get_element_properties($task, $OUTPUT)); + $this->_form->setDefault($setting->get_ui_name(), $setting->get_value()); + if ($setting->has_help()) { + list($identifier, $component) = $setting->get_help(); + $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component); + } + $this->_form->addElement('html', html_writer::end_tag('div')); return true; } /** @@ -331,4 +317,4 @@ abstract class base_moodleform extends moodleform { $this->definition_after_data(); } } -} +} \ No newline at end of file From f213bbd77a0ec89e8ddf223d6cd6db9aa1bee37f Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Thu, 7 Apr 2011 14:16:07 +0930 Subject: [PATCH 418/455] MDL-27120 backup: replace sequential scan search with hash-based lookup. --- backup/util/plan/base_plan.class.php | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/backup/util/plan/base_plan.class.php b/backup/util/plan/base_plan.class.php index 3ed176b0bbf..24becc6969b 100644 --- a/backup/util/plan/base_plan.class.php +++ b/backup/util/plan/base_plan.class.php @@ -61,7 +61,12 @@ abstract class base_plan implements checksumable, executable { // Append task settings to plan array, if not present, for comodity foreach ($task->get_settings() as $key => $setting) { if (!in_array($setting, $this->settings)) { - $this->settings[] = $setting; + $name = $setting->get_name(); + if(!isset($this->settings[$name])) { + $this->settings[$name] = $setting; + } else { + throw new base_plan_exception('multiple_settings_by_name_found', $name); + } } } } @@ -91,17 +96,10 @@ abstract class base_plan implements checksumable, executable { */ public function get_setting($name) { $result = null; - foreach ($this->settings as $key => $setting) { - if ($setting->get_name() == $name) { - if ($result != null) { - throw new base_plan_exception('multiple_settings_by_name_found', $name); - } else { - $result = $setting; - } - } - } - if (!$result) { - throw new base_plan_exception('setting_by_name_not_found', $name); + if(isset($this->settings[$name])) { + $result = $this->settings[$name]; + } else { + throw new base_plan_exception('setting_by_name_not_found', $name); } return $result; } From 631764ea2f47c1a1a4045517572800eb2e3fd37d Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Thu, 7 Apr 2011 15:38:10 +0930 Subject: [PATCH 419/455] MDL-27120 More efficient use of QuickForms in backup UI --- backup/util/ui/backup_ui_stage.class.php | 22 ++++++++++++--- backup/util/ui/base_moodleform.class.php | 34 +++++++++++++++++++++++- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index 1ce9053dd52..ca53c23e9ce 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -124,6 +124,8 @@ class backup_ui_stage_initial extends backup_ui_stage { // Store as a variable so we can iterate by reference $tasks = $this->ui->get_tasks(); // Iterate all tasks by reference + $add_settings = array(); + $dependencies = array(); foreach ($tasks as &$task) { // For the initial stage we are only interested in the root settings if ($task instanceof backup_root_task) { @@ -134,17 +136,23 @@ class backup_ui_stage_initial extends backup_ui_stage { if ($setting->get_name() == 'filename') { continue; } - $form->add_setting($setting, $task); + $add_settings[] = array($setting, $task); } // Then add all dependencies foreach ($settings as &$setting) { if ($setting->get_name() == 'filename') { continue; } - $form->add_dependencies($setting); + $dependencies[] = $setting; } } } + // Add all settings at once + $form->add_settings($add_settings); + // Add dependencies + foreach ($dependencies as $depsetting) { + $form->add_dependencies($setting); + } $this->stageform = $form; } // Return the form @@ -226,6 +234,8 @@ class backup_ui_stage_schema extends backup_ui_stage { $tasks = $this->ui->get_tasks(); $content = ''; $courseheading = false; + $add_settings = array(); + $dependencies = array(); foreach ($tasks as $task) { if (!($task instanceof backup_root_task)) { if (!$courseheading) { @@ -235,11 +245,11 @@ class backup_ui_stage_schema extends backup_ui_stage { } // First add each setting foreach ($task->get_settings() as $setting) { - $form->add_setting($setting, $task); + $add_settings[] = array($setting, $task); } // The add all the dependencies foreach ($task->get_settings() as $setting) { - $form->add_dependencies($setting); + $dependencies[] = $setting; } } else if ($this->ui->enforce_changed_dependencies()) { // Only show these settings if dependencies changed them. @@ -254,6 +264,10 @@ class backup_ui_stage_schema extends backup_ui_stage { } } } + $form->add_settings($add_settings); + foreach($dependencies as $depsetting) { + $form->add_dependencies($depsetting); + } $this->stageform = $form; } return $this->stageform; diff --git a/backup/util/ui/base_moodleform.class.php b/backup/util/ui/base_moodleform.class.php index ad992602083..652d5806470 100644 --- a/backup/util/ui/base_moodleform.class.php +++ b/backup/util/ui/base_moodleform.class.php @@ -156,6 +156,38 @@ abstract class base_moodleform extends moodleform { $this->_form->addElement('html', html_writer::end_tag('div')); return true; } + /** + * Adds multiple backup_settings as elements to the form + * @param array $settingstasks Consists of array($setting, $task) elements + * @return bool + */ + function add_settings(array $settingstasks) { + global $OUTPUT; + + $defaults = array(); + foreach ($settingstasks as $st) { + list($setting, $task) = $st; + // If the setting cant be changed or isn't visible then add it as a fixed setting. + if (!$setting->get_ui()->is_changeable() || $setting->get_visibility() != backup_setting::VISIBLE) { + $this->add_fixed_setting($setting, $task); + continue; + } + + // First add the formatting for this setting + $this->add_html_formatting($setting); + + // Then call the add method with the get_element_properties array + call_user_func_array(array($this->_form, 'addElement'), $setting->get_ui()->get_element_properties($task, $OUTPUT)); + $defaults[$setting->get_ui_name()] = $setting->get_value(); + if ($setting->has_help()) { + list($identifier, $component) = $setting->get_help(); + $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component); + } + $this->_form->addElement('html', html_writer::end_tag('div')); + } + $this->_form->setDefaults($defaults); + return true; + } /** * Adds a heading to the form * @param string $name @@ -317,4 +349,4 @@ abstract class base_moodleform extends moodleform { $this->definition_after_data(); } } -} \ No newline at end of file +} From d729ef29cf009dd4a0ce9ee5b4fcde6380926a6c Mon Sep 17 00:00:00 2001 From: Ashley Holman Date: Thu, 7 Apr 2011 18:36:43 +0930 Subject: [PATCH 420/455] MDL-27120 Add global cache to backup_xml_transformer::register_link_encoders() --- backup/moodle2/backup_xml_transformer.class.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index a3770d03528..fec3c591d39 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -32,6 +32,12 @@ defined('MOODLE_INTERNAL') || die(); * * TODO: Finish phpdocs */ + +// cache for storing link encoders, so that we don't need to call +// register_link_encoders each time backup_xml_transformer is constructed +global $LINKS_ENCODERS_CACHE; +$LINKS_ENCODERS_CACHE = array(); + class backup_xml_transformer extends xml_contenttransformer { private $absolute_links_encoders; // array of static methods to be called in order to @@ -41,13 +47,18 @@ class backup_xml_transformer extends xml_contenttransformer { private $unicoderegexp; // to know if the site supports unicode regexp public function __construct($courseid) { + global $LINKS_ENCODERS_CACHE; + $this->absolute_links_encoders = array(); $this->courseid = $courseid; // Check if we support unicode modifiers in regular expressions $this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false, // if regexp libraries don't support unicode // Register all the available content link encoders - $this->absolute_links_encoders = $this->register_link_encoders(); + if (!empty($LINKS_ENCODERS_CACHE)) { + $LINKS_ENCODERS_CACHE = $this->register_link_encoders(); + } + $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE; } public function process($content) { From ec404105ae9b8f157b2f429f0eb87f363c5cfa86 Mon Sep 17 00:00:00 2001 From: Jason Ilicic Date: Tue, 22 Nov 2011 10:34:56 +1030 Subject: [PATCH 421/455] mdl-27120 Fixed incorrect variable in parameter when adding form dependencies. --- backup/util/ui/backup_ui_stage.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index ca53c23e9ce..9b8f3f50b2b 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -151,7 +151,7 @@ class backup_ui_stage_initial extends backup_ui_stage { $form->add_settings($add_settings); // Add dependencies foreach ($dependencies as $depsetting) { - $form->add_dependencies($setting); + $form->add_dependencies($depsetting); } $this->stageform = $form; } From 28729e23a44ffe74045782fd9cd21439fd571af2 Mon Sep 17 00:00:00 2001 From: Adam Olley Date: Wed, 14 Sep 2011 11:42:03 +0930 Subject: [PATCH 422/455] mdl-27120 Fix static cache for backup_xml_transformer::register_link_encoders() --- backup/moodle2/backup_xml_transformer.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index fec3c591d39..7c3cd5515d7 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -55,7 +55,7 @@ class backup_xml_transformer extends xml_contenttransformer { $this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false, // if regexp libraries don't support unicode // Register all the available content link encoders - if (!empty($LINKS_ENCODERS_CACHE)) { + if (empty($LINKS_ENCODERS_CACHE)) { $LINKS_ENCODERS_CACHE = $this->register_link_encoders(); } $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE; From 066af1bbc78564222a5c69e13fe167d3c1ee35b9 Mon Sep 17 00:00:00 2001 From: Tony Levi Date: Mon, 11 Apr 2011 15:34:02 +0930 Subject: [PATCH 423/455] MDL-27120: Cache dirname transformations in progressive_parser::dirname --- backup/util/xml/parser/progressive_parser.class.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backup/util/xml/parser/progressive_parser.class.php b/backup/util/xml/parser/progressive_parser.class.php index 91bc85fc4b2..8b6df4b5ee9 100644 --- a/backup/util/xml/parser/progressive_parser.class.php +++ b/backup/util/xml/parser/progressive_parser.class.php @@ -149,7 +149,15 @@ class progressive_parser { * handling parser paths, see MDL-24381 */ public static function dirname($path) { - return str_replace('\\', '/', dirname($path)); + static $cache = array(); + + if (!isset($cache[$path])) { + if (count($cache) > 4096) + $cache = array(); + $cache[$path] = str_replace('\\', '/', dirname($path)); + } + + return $cache[$path]; } // Protected API starts here From 7f98b12f916d46740a09a9117be20f5e4c2c7eff Mon Sep 17 00:00:00 2001 From: Tony Levi Date: Sat, 16 Apr 2011 13:33:33 +0930 Subject: [PATCH 424/455] MDL-27120: Cache DB operations in restore_dbops --- backup/util/dbops/restore_dbops.class.php | 98 +++++++++++++++-------- 1 file changed, 66 insertions(+), 32 deletions(-) diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index e50c6e607df..08a7de567d0 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -28,6 +28,8 @@ * TODO: Finish phpdocs */ abstract class restore_dbops { + static $BACKUP_IDS_CACHE = array(); + static $BACKUP_IDS_EXIST = array(); /** * Return one array containing all the tasks that have been included @@ -151,6 +153,65 @@ abstract class restore_dbops { return $problems; } + protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) { + global $DB; + + $key = "$itemid $itemname $restoreid"; + + if (!isset(self::$BACKUP_IDS_EXIST[$key])) { + return false; + } + + if (isset(self::$BACKUP_IDS_CACHE[$key])) { + return self::$BACKUP_IDS_CACHE[$key]; + } + + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid + ); + + if (count(self::$BACKUP_IDS_CACHE) > 2048) { + $BACKUP_IDS_CACHE = array(); + } + + return self::$BACKUP_IDS_CACHE[$key] = $DB->get_record('backup_ids_temp', $record); + } + + protected static function set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord) { + global $DB; + + $key = "$itemid $itemname $restoreid"; + + if (!isset(self::$BACKUP_IDS_EXIST[$key])) { + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid, + 'newitemid' => 0, + 'parentitemid' => null, + 'info' => null + ); + $record = array_merge($record, $extrarecord); + $record['id'] = $DB->insert_record_raw('backup_ids_temp', $record); + self::$BACKUP_IDS_EXIST[$key] = $record['id']; + if (count(self::$BACKUP_IDS_CACHE) < 2048) { + // cache new records if we haven't got many yet + self::$BACKUP_IDS_CACHE[$key] = (object) $record; + } + } else { + if (!empty($extrarecord)) { + $extrarecord['id'] = self::$BACKUP_IDS_EXIST[$key]; + $DB->update_record('backup_ids_temp', $extrarecord); + if (isset(self::$BACKUP_IDS_CACHE[$key])) { + $record = array_merge((array)self::$BACKUP_IDS_CACHE[$key], $extrarecord); + self::$BACKUP_IDS_CACHE[$key] = (object) $record; + } + } + } + } + /** * Given one role, as loaded from XML, perform the best possible matching against the assignable * roles, using different fallback alternatives (shortname, archetype, editingteacher => teacher, defaultcourseroleid) @@ -1219,16 +1280,7 @@ abstract class restore_dbops { $DB->insert_record('backup_files_temp', $filerec); } - public static function set_backup_ids_record($restoreid, $itemname, $itemid, $newitemid = 0, $parentitemid = null, $info = null) { - global $DB; - - // Build the basic (mandatory) record info - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid - ); // Build conditionally the extra record info $extrarecord = array(); if ($newitemid != 0) { @@ -1241,34 +1293,16 @@ abstract class restore_dbops { $extrarecord['info'] = base64_encode(serialize($info)); } - // TODO: Analyze if some static (and limited) cache by the 3 params could save us a bunch of get_record() calls - // Note: Sure it will! And also will improve getter - if (!$dbrec = $DB->get_record('backup_ids_temp', $record)) { // Need to insert the complete record - $DB->insert_record('backup_ids_temp', array_merge($record, $extrarecord)); - - } else { // Need to update the extra record info if there is something to - if (!empty($extrarecord)) { - $extrarecord['id'] = $dbrec->id; - $DB->update_record('backup_ids_temp', $extrarecord); - } - } + self::set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord); } public static function get_backup_ids_record($restoreid, $itemname, $itemid) { - global $DB; + $dbrec = self::get_backup_ids_cached($restoreid, $itemname, $itemid); - // Build the basic (mandatory) record info to look for - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid - ); - // TODO: Analyze if some static (and limited) cache by the 3 params could save us a bunch of get_record() calls - if ($dbrec = $DB->get_record('backup_ids_temp', $record)) { - if ($dbrec->info != null) { - $dbrec->info = unserialize(base64_decode($dbrec->info)); - } + if ($dbrec && isset($dbrec->info) && is_string($dbrec->info)) { + $dbrec->info = unserialize(base64_decode($dbrec->info)); } + return $dbrec; } From a960dfa90089be5df711e886352383eb99b4742c Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Tue, 29 May 2012 15:00:19 +0800 Subject: [PATCH 425/455] MDL-33397 Filepicker: cancel button always present in private files --- user/files.php | 4 +--- user/files_form.php | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/user/files.php b/user/files.php index 5da4d8d4744..54f7962c75a 100644 --- a/user/files.php +++ b/user/files.php @@ -33,10 +33,8 @@ if (isguestuser()) { } $returnurl = optional_param('returnurl', '', PARAM_URL); -$returnbutton = true; if (empty($returnurl)) { - $returnbutton = false; $returnurl = new moodle_url('/user/files.php'); } @@ -58,7 +56,7 @@ $data->returnurl = $returnurl; $options = array('subdirs'=>1, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>-1, 'accepted_types'=>'*'); file_prepare_standard_filemanager($data, 'files', $options, $context, 'user', 'private', 0); -$mform = new user_files_form(null, array('data'=>$data, 'options'=>$options, 'cancelbutton'=>$returnbutton)); +$mform = new user_files_form(null, array('data'=>$data, 'options'=>$options)); if ($mform->is_cancelled()) { redirect($returnurl); diff --git a/user/files_form.php b/user/files_form.php index 535105607c2..55451daa8ce 100644 --- a/user/files_form.php +++ b/user/files_form.php @@ -33,12 +33,11 @@ class user_files_form extends moodleform { $data = $this->_customdata['data']; $options = $this->_customdata['options']; - $cancelbutton = isset($this->_customdata['cancelbutton']) ? $this->_customdata['cancelbutton'] : true; $mform->addElement('filemanager', 'files_filemanager', get_string('files'), null, $options); $mform->addElement('hidden', 'returnurl', $data->returnurl); - $this->add_action_buttons($cancelbutton, get_string('savechanges')); + $this->add_action_buttons(true, get_string('savechanges')); $this->set_data($data); } From e7b24943e6f89736772cf3530c8a9fd2d50b2e9b Mon Sep 17 00:00:00 2001 From: Rajesh Taneja Date: Tue, 17 Apr 2012 11:32:15 +0800 Subject: [PATCH 426/455] MDL-27120 backup: fixed docblock and code cleanup --- .../moodle2/backup_xml_transformer.class.php | 33 ++-- backup/util/dbops/restore_dbops.class.php | 164 ++++++++++++++---- backup/util/plan/base_plan.class.php | 14 +- backup/util/ui/backup_ui_stage.class.php | 8 +- backup/util/ui/base_moodleform.class.php | 22 +-- .../xml/parser/progressive_parser.class.php | 10 +- 6 files changed, 167 insertions(+), 84 deletions(-) diff --git a/backup/moodle2/backup_xml_transformer.class.php b/backup/moodle2/backup_xml_transformer.class.php index 7c3cd5515d7..25c8503bcf7 100644 --- a/backup/moodle2/backup_xml_transformer.class.php +++ b/backup/moodle2/backup_xml_transformer.class.php @@ -27,17 +27,18 @@ defined('MOODLE_INTERNAL') || die(); +// Cache for storing link encoders, so that we don't need to call +// register_link_encoders each time backup_xml_transformer is constructed +// TODO MDL-25290 replace global with MUC code. +global $LINKS_ENCODERS_CACHE; + +$LINKS_ENCODERS_CACHE = array(); + /** * Class implementing the @xml_contenttrasnformed logic to be applied in moodle2 backups * * TODO: Finish phpdocs */ - -// cache for storing link encoders, so that we don't need to call -// register_link_encoders each time backup_xml_transformer is constructed -global $LINKS_ENCODERS_CACHE; -$LINKS_ENCODERS_CACHE = array(); - class backup_xml_transformer extends xml_contenttransformer { private $absolute_links_encoders; // array of static methods to be called in order to @@ -47,18 +48,13 @@ class backup_xml_transformer extends xml_contenttransformer { private $unicoderegexp; // to know if the site supports unicode regexp public function __construct($courseid) { - global $LINKS_ENCODERS_CACHE; - $this->absolute_links_encoders = array(); $this->courseid = $courseid; // Check if we support unicode modifiers in regular expressions $this->unicoderegexp = @preg_match('/\pL/u', 'a'); // This will fail silently, returning false, // if regexp libraries don't support unicode // Register all the available content link encoders - if (empty($LINKS_ENCODERS_CACHE)) { - $LINKS_ENCODERS_CACHE = $this->register_link_encoders(); - } - $this->absolute_links_encoders = $LINKS_ENCODERS_CACHE; + $this->absolute_links_encoders = $this->register_link_encoders(); } public function process($content) { @@ -142,7 +138,19 @@ class backup_xml_transformer extends xml_contenttransformer { return $result; } + /** + * Register all available content link encoders + * + * @return array encoder + * @todo MDL-25290 replace LINKS_ENCODERS_CACHE global with MUC code + */ private function register_link_encoders() { + global $LINKS_ENCODERS_CACHE; + // If encoder is linked, then return cached encoder. + if (!empty($LINKS_ENCODERS_CACHE)) { + return $LINKS_ENCODERS_CACHE; + } + $encoders = array(); // Add the course encoder @@ -171,6 +179,7 @@ class backup_xml_transformer extends xml_contenttransformer { // Add local encodes // TODO: Any interest? 1.9 never had that. + $LINKS_ENCODERS_CACHE = $encoders; return $encoders; } } diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index 08a7de567d0..81dbaf6ea75 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -28,8 +28,38 @@ * TODO: Finish phpdocs */ abstract class restore_dbops { - static $BACKUP_IDS_CACHE = array(); - static $BACKUP_IDS_EXIST = array(); + /** + * Keep cache of backup records. + * @var array + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidscache = array(); + /** + * Keep track of backup ids which are cached. + * @var array + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidsexist = array(); + /** + * Count is expensive, so manually keeping track of + * backupidscache, to avoid memory issues. + * @var int + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidscachesize = 2048; + /** + * Count is expensive, so manually keeping track of + * backupidsexist, to avoid memory issues. + * @var int + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidsexistsize = 10240; + /** + * Slice backupids cache to add more data. + * @var int + * @todo MDL-25290 static should be replaced with MUC code. + */ + private static $backupidsslice = 512; /** * Return one array containing all the tasks that have been included @@ -153,61 +183,131 @@ abstract class restore_dbops { return $problems; } + /** + * Return cached backup id's + * + * @param int $restoreid id of backup + * @param string $itemname name of the item + * @param int $itemid id of item + * @return array backup id's + * @todo MDL-25290 replace static backupids* with MUC code + */ protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) { global $DB; $key = "$itemid $itemname $restoreid"; - if (!isset(self::$BACKUP_IDS_EXIST[$key])) { - return false; + // If record exists in cache then return. + if (isset(self::$backupidsexist[$key]) && isset(self::$backupidscache[$key])) { + // Return a copy of cached data, to avoid any alterations in cached data. + return clone self::$backupidscache[$key]; } - if (isset(self::$BACKUP_IDS_CACHE[$key])) { - return self::$BACKUP_IDS_CACHE[$key]; + // Clean cache, if it's full. + if (self::$backupidscachesize <= 0) { + // Remove some records, to keep memory in limit. + self::$backupidscache = array_slice(self::$backupidscache, self::$backupidsslice, null, true); + self::$backupidscachesize = self::$backupidscachesize + self::$backupidsslice; + } + if (self::$backupidsexistsize <= 0) { + self::$backupidsexist = array_slice(self::$backupidsexist, self::$backupidsslice, null, true); + self::$backupidsexistsize = self::$backupidsexistsize + self::$backupidsslice; } + // Retrive record from database. $record = array( 'backupid' => $restoreid, 'itemname' => $itemname, 'itemid' => $itemid ); - - if (count(self::$BACKUP_IDS_CACHE) > 2048) { - $BACKUP_IDS_CACHE = array(); + if ($dbrec = $DB->get_record('backup_ids_temp', $record)) { + self::$backupidsexist[$key] = $dbrec->id; + self::$backupidscache[$key] = $dbrec; + self::$backupidscachesize--; + self::$backupidsexistsize--; + return $dbrec; + } else { + return false; } - - return self::$BACKUP_IDS_CACHE[$key] = $DB->get_record('backup_ids_temp', $record); } + /** + * Cache backup ids' + * + * @param int $restoreid id of backup + * @param string $itemname name of the item + * @param int $itemid id of item + * @param array $extrarecord extra record which needs to be updated + * @return void + * @todo MDL-25290 replace static BACKUP_IDS_* with MUC code + */ protected static function set_backup_ids_cached($restoreid, $itemname, $itemid, $extrarecord) { global $DB; $key = "$itemid $itemname $restoreid"; - if (!isset(self::$BACKUP_IDS_EXIST[$key])) { - $record = array( - 'backupid' => $restoreid, - 'itemname' => $itemname, - 'itemid' => $itemid, - 'newitemid' => 0, - 'parentitemid' => null, - 'info' => null - ); - $record = array_merge($record, $extrarecord); - $record['id'] = $DB->insert_record_raw('backup_ids_temp', $record); - self::$BACKUP_IDS_EXIST[$key] = $record['id']; - if (count(self::$BACKUP_IDS_CACHE) < 2048) { - // cache new records if we haven't got many yet - self::$BACKUP_IDS_CACHE[$key] = (object) $record; + $record = array( + 'backupid' => $restoreid, + 'itemname' => $itemname, + 'itemid' => $itemid, + ); + + // If record is not cached then add one. + if (!isset(self::$backupidsexist[$key])) { + // If we have this record in db, then just update this. + if ($existingrecord = $DB->get_record('backup_ids_temp', $record)) { + self::$backupidsexist[$key] = $existingrecord->id; + self::$backupidsexistsize--; + self::update_backup_cached_record($record, $extrarecord, $key, $existingrecord); + } else { + // Add new record to cache and db. + $recorddefault = array ( + 'newitemid' => 0, + 'parentitemid' => null, + 'info' => null); + $record = array_merge($record, $recorddefault, $extrarecord); + $record['id'] = $DB->insert_record('backup_ids_temp', $record); + self::$backupidsexist[$key] = $record['id']; + self::$backupidsexistsize--; + if (self::$backupidscachesize > 0) { + // Cache new records if we haven't got many yet. + self::$backupidscache[$key] = (object) $record; + self::$backupidscachesize--; + } } } else { - if (!empty($extrarecord)) { - $extrarecord['id'] = self::$BACKUP_IDS_EXIST[$key]; - $DB->update_record('backup_ids_temp', $extrarecord); - if (isset(self::$BACKUP_IDS_CACHE[$key])) { - $record = array_merge((array)self::$BACKUP_IDS_CACHE[$key], $extrarecord); - self::$BACKUP_IDS_CACHE[$key] = (object) $record; + self::update_backup_cached_record($record, $extrarecord, $key); + } + } + + /** + * Updates existing backup record + * + * @param array $record record which needs to be updated + * @param array $extrarecord extra record which needs to be updated + * @param string $key unique key which is used to identify cached record + * @param stdClass $existingrecord (optional) existing record + */ + protected static function update_backup_cached_record($record, $extrarecord, $key, $existingrecord = null) { + global $DB; + // Update only if extrarecord is not empty. + if (!empty($extrarecord)) { + $extrarecord['id'] = self::$backupidsexist[$key]; + $DB->update_record('backup_ids_temp', $extrarecord); + // Update existing cache or add new record to cache. + if (isset(self::$backupidscache[$key])) { + $record = array_merge((array)self::$backupidscache[$key], $extrarecord); + self::$backupidscache[$key] = (object) $record; + } else if (self::$backupidscachesize > 0) { + if ($existingrecord) { + self::$backupidscache[$key] = $existingrecord; + } else { + // Retrive record from database and cache updated records. + self::$backupidscache[$key] = $DB->get_record('backup_ids_temp', $record); } + $record = array_merge((array)self::$backupidscache[$key], $extrarecord); + self::$backupidscache[$key] = (object) $record; + self::$backupidscachesize--; } } } diff --git a/backup/util/plan/base_plan.class.php b/backup/util/plan/base_plan.class.php index 24becc6969b..eab1869d6d3 100644 --- a/backup/util/plan/base_plan.class.php +++ b/backup/util/plan/base_plan.class.php @@ -62,7 +62,7 @@ abstract class base_plan implements checksumable, executable { foreach ($task->get_settings() as $key => $setting) { if (!in_array($setting, $this->settings)) { $name = $setting->get_name(); - if(!isset($this->settings[$name])) { + if (!isset($this->settings[$name])) { $this->settings[$name] = $setting; } else { throw new base_plan_exception('multiple_settings_by_name_found', $name); @@ -89,17 +89,17 @@ abstract class base_plan implements checksumable, executable { /** * return one setting by name, useful to request root/course settings - * that are, by definition, unique by name. Throws exception if multiple - * are found + * that are, by definition, unique by name. * - * TODO: Change this to string indexed array for quicker lookup. Not critical + * @param string $name name of the setting + * @throws base_plan_exception if setting name is not found. */ public function get_setting($name) { $result = null; - if(isset($this->settings[$name])) { - $result = $this->settings[$name]; + if (isset($this->settings[$name])) { + $result = $this->settings[$name]; } else { - throw new base_plan_exception('setting_by_name_not_found', $name); + throw new base_plan_exception('setting_by_name_not_found', $name); } return $result; } diff --git a/backup/util/ui/backup_ui_stage.class.php b/backup/util/ui/backup_ui_stage.class.php index 9b8f3f50b2b..799556157e0 100644 --- a/backup/util/ui/backup_ui_stage.class.php +++ b/backup/util/ui/backup_ui_stage.class.php @@ -147,9 +147,9 @@ class backup_ui_stage_initial extends backup_ui_stage { } } } - // Add all settings at once + // Add all settings at once. $form->add_settings($add_settings); - // Add dependencies + // Add dependencies. foreach ($dependencies as $depsetting) { $form->add_dependencies($depsetting); } @@ -265,8 +265,8 @@ class backup_ui_stage_schema extends backup_ui_stage { } } $form->add_settings($add_settings); - foreach($dependencies as $depsetting) { - $form->add_dependencies($depsetting); + foreach ($dependencies as $depsetting) { + $form->add_dependencies($depsetting); } $this->stageform = $form; } diff --git a/backup/util/ui/base_moodleform.class.php b/backup/util/ui/base_moodleform.class.php index 652d5806470..e0ffc0f9fcf 100644 --- a/backup/util/ui/base_moodleform.class.php +++ b/backup/util/ui/base_moodleform.class.php @@ -136,32 +136,14 @@ abstract class base_moodleform extends moodleform { * @return bool */ function add_setting(backup_setting $setting, base_task $task=null) { - global $OUTPUT; - - // If the setting cant be changed or isn't visible then add it as a fixed setting. - if (!$setting->get_ui()->is_changeable() || $setting->get_visibility() != backup_setting::VISIBLE) { - return $this->add_fixed_setting($setting, $task); - } - - // First add the formatting for this setting - $this->add_html_formatting($setting); - - // The call the add method with the get_element_properties array - call_user_func_array(array($this->_form, 'addElement'), $setting->get_ui()->get_element_properties($task, $OUTPUT)); - $this->_form->setDefault($setting->get_ui_name(), $setting->get_value()); - if ($setting->has_help()) { - list($identifier, $component) = $setting->get_help(); - $this->_form->addHelpButton($setting->get_ui_name(), $identifier, $component); - } - $this->_form->addElement('html', html_writer::end_tag('div')); - return true; + return $this->add_settings(array(array($setting, $task))); } /** * Adds multiple backup_settings as elements to the form * @param array $settingstasks Consists of array($setting, $task) elements * @return bool */ - function add_settings(array $settingstasks) { + public function add_settings(array $settingstasks) { global $OUTPUT; $defaults = array(); diff --git a/backup/util/xml/parser/progressive_parser.class.php b/backup/util/xml/parser/progressive_parser.class.php index 8b6df4b5ee9..91bc85fc4b2 100644 --- a/backup/util/xml/parser/progressive_parser.class.php +++ b/backup/util/xml/parser/progressive_parser.class.php @@ -149,15 +149,7 @@ class progressive_parser { * handling parser paths, see MDL-24381 */ public static function dirname($path) { - static $cache = array(); - - if (!isset($cache[$path])) { - if (count($cache) > 4096) - $cache = array(); - $cache[$path] = str_replace('\\', '/', dirname($path)); - } - - return $cache[$path]; + return str_replace('\\', '/', dirname($path)); } // Protected API starts here From 2bb9e531061316da85d642fd8486e2de10d16a40 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Tue, 29 May 2012 16:54:04 +0800 Subject: [PATCH 427/455] MDL-32779 course/format: Return to correct section When editing a single section mode item --- course/format/renderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course/format/renderer.php b/course/format/renderer.php index fb59c386a52..fcb5b2a822e 100644 --- a/course/format/renderer.php +++ b/course/format/renderer.php @@ -506,7 +506,7 @@ abstract class format_section_renderer_base extends plugin_renderer_base { $completioninfo = new completion_info($course); echo $completioninfo->display_help_icon(); - print_section($course, $thissection, $mods, $modnamesused, true); + print_section($course, $thissection, $mods, $modnamesused, true, '100%', false, true); if ($PAGE->user_is_editing()) { print_section_add_menus($course, $displaysection, $modnames); } From 311300e2085aeea2e9a13f4b622d58260b01c610 Mon Sep 17 00:00:00 2001 From: kordan Date: Tue, 29 May 2012 19:23:33 +0200 Subject: [PATCH 428/455] MDL-3389 mod_book: changed "Summary" to "Description" in mod_form --- mod/book/mod_form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/book/mod_form.php b/mod/book/mod_form.php index d58cce3d673..b795875c21a 100644 --- a/mod/book/mod_form.php +++ b/mod/book/mod_form.php @@ -45,7 +45,7 @@ class mod_book_mod_form extends moodleform_mod { $mform->setType('name', PARAM_CLEANHTML); } $mform->addRule('name', null, 'required', null, 'client'); - $this->add_intro_editor($config->requiremodintro, get_string('summary')); + $this->add_intro_editor($config->requiremodintro, get_string('moduleintro')); $alloptions = book_get_numbering_types(); $allowed = explode(',', $config->numberingoptions); From 7c89a18fca4886d2a9b5ca8383b4a63ba7be481b Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 28 May 2012 11:28:46 +0800 Subject: [PATCH 429/455] MDL-33326 filestorage tests: Actually verify results Rather than the placeholder tests which were added before to trigger DB incompatibilities --- lib/filestorage/tests/file_storage_test.php | 262 +++++++++++++++++--- 1 file changed, 228 insertions(+), 34 deletions(-) diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index d571bebba61..16dc4b25965 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -77,6 +77,30 @@ class filestoragelib_testcase extends advanced_testcase { $previewtinyicon = $fs->get_file_preview($file, 'thumb'); $this->assertInstanceOf('stored_file', $previewtinyicon); $this->assertEquals('6b9864ae1536a8eeef54e097319175a8be12f07c', $previewtinyicon->get_filename()); + + $this->setExpectedException('file_exception'); + $fs->get_file_preview($file, 'amodewhichdoesntexist'); + } + + public function test_get_file_preview_nonimage() { + $this->resetAfterTest(true); + $syscontext = context_system::instance(); + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => 'core', + 'filearea' => 'unittest', + 'itemid' => 0, + 'filepath' => '/textfiles/', + 'filename' => 'testtext.txt', + ); + + $fs = get_file_storage(); + $fs->create_file_from_string($filerecord, 'text contents'); + $textfile = $fs->get_file($syscontext->id, $filerecord['component'], $filerecord['filearea'], + $filerecord['itemid'], $filerecord['filepath'], $filerecord['filename']); + + $preview = $fs->get_file_preview($textfile, 'thumb'); + $this->assertFalse($preview); } /** @@ -209,20 +233,14 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertEquals($content, $importedfile->get_content()); } - /** - * TODO: the tests following this line were added to demonstrate specific Oracle problems in - * MDL-33172. They need to be improved to properly evalulate the results of the tests. This is - * tracked in MDL-33326. - */ private function setup_three_private_files() { - global $USER, $DB; $this->resetAfterTest(true); $generator = $this->getDataGenerator(); $user = $generator->create_user(); + $this->setUser($user->id); $usercontext = context_user::instance($user->id); - $USER = $DB->get_record('user', array('id'=>$user->id)); // create a user private file $file1 = new stdClass; $file1->contextid = $usercontext->id; @@ -235,53 +253,120 @@ class filestoragelib_testcase extends advanced_testcase { $fs = get_file_storage(); $userfile1 = $fs->create_file_from_string($file1, 'file1 content'); + $this->assertInstanceOf('stored_file', $userfile1); + $file2 = clone($file1); $file2->filename = '2.txt'; $userfile2 = $fs->create_file_from_string($file2, 'file2 content'); + $this->assertInstanceOf('stored_file', $userfile2); $file3 = clone($file1); $file3->filename = '3.txt'; $userfile3 = $fs->create_file_from_storedfile($file3, $userfile2); + $this->assertInstanceOf('stored_file', $userfile3); $user->ctxid = $usercontext->id; return $user; } - public function test_get_area_files() { $user = $this->setup_three_private_files(); $fs = get_file_storage(); // Get area files with default options. $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. $this->assertEquals(4, count($areafiles)); + // Verify structure. + foreach($areafiles as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } + // Get area files without a folder. - $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false); + $folderlessfiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'sortorder', false); // Should be the two files without folder. - $this->assertEquals(3, count($areafiles)); + $this->assertEquals(3, count($folderlessfiles)); + + // Verify structure. + foreach($folderlessfiles as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } // Get area files ordered by id (was breaking on oracle). - $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false); + $filesbyid = $fs->get_area_files($user->ctxid, 'user', 'private', false, 'id', false); // Should be the two files without folder. - $this->assertEquals(3, count($areafiles)); + $this->assertEquals(3, count($filesbyid)); + + // Verify structure. + foreach($filesbyid as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } // Test with an itemid with no files $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false); - // Should none - $this->assertEquals(0, count($areafiles)); + // Should be none + $this->assertEmpty($areafiles); } public function test_get_area_tree() { $user = $this->setup_three_private_files(); $fs = get_file_storage(); + // Get area files with default options. - $areafiles = $fs->get_area_tree($user->ctxid, 'user', 'private', 0); - $areafiles = $fs->get_area_tree($user->ctxid, 'user', 'private', 666); - //TODO: verify result!! MDL-33326 + $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0); + $this->assertEmpty($areatree['subdirs']); + $this->assertNotEmpty($areatree['files']); + $this->assertCount(3, $areatree['files']); + + // Ensure an empty try with a fake itemid. + $emptytree = $fs->get_area_tree($user->ctxid, 'user', 'private', 666); + $this->assertEmpty($emptytree['subdirs']); + $this->assertEmpty($emptytree['files']); + + // Create a subdir + $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/'); + $this->assertInstanceOf('stored_file', $dir); + + // Add a file to the subdir. + $filerecord = array( + 'contextid' => $user->ctxid, + 'component' => 'user', + 'filearea' => 'private', + 'itemid' => 0, + 'filepath' => '/testsubdir/', + 'filename' => 'test-get-area-tree.txt', + ); + + $directoryfile = $fs->create_file_from_string($filerecord, 'Test content'); + $this->assertInstanceOf('stored_file', $directoryfile); + + $areatree = $fs->get_area_tree($user->ctxid, 'user', 'private', 0); + + // At the top level there should still be 3 files. + $this->assertCount(3, $areatree['files']); + + // There should now be a subdirectory. + $this->assertCount(1, $areatree['subdirs']); + + // The test subdir is named testsubdir. + $subdir = $areatree['subdirs']['testsubdir']; + $this->assertNotEmpty($subdir); + // It should have one file we added. + $this->assertCount(1, $subdir['files']); + // And no subdirs itself. + $this->assertCount(0, $subdir['subdirs']); + + // verify the file is the one we added. + $subdirfile = reset($subdir['files']); + $this->assertInstanceOf('stored_file', $subdirfile); + $this->assertEquals($filerecord['filename'], $subdirfile->get_filename()); } public function test_get_file_by_id() { @@ -294,6 +379,10 @@ class filestoragelib_testcase extends advanced_testcase { $filebyid = reset($areafiles); $shouldbesame = $fs->get_file_by_id($filebyid->get_id()); $this->assertEquals($filebyid->get_contenthash(), $shouldbesame->get_contenthash()); + + // Test an id which doens't exist. + $doesntexist = $fs->get_file_by_id(99999); + $this->assertFalse($doesntexist); } public function test_get_file_by_hash() { @@ -305,6 +394,10 @@ class filestoragelib_testcase extends advanced_testcase { $filebyhash = reset($areafiles); $shouldbesame = $fs->get_file_by_hash($filebyhash->get_pathnamehash()); $this->assertEquals($filebyhash->get_id(), $shouldbesame->get_id()); + + // Test an hash which doens't exist. + $doesntexist = $fs->get_file_by_hash('DOESNTEXIST'); + $this->assertFalse($doesntexist); } public function test_get_references_by_storedfile() { @@ -316,7 +409,7 @@ class filestoragelib_testcase extends advanced_testcase { $testfile = reset($areafiles); $references = $fs->get_references_by_storedfile($testfile); - //TODO: verify result!! MDL-33326 + //TODO: verify result!! MDL-33368 } public function test_get_external_files() { @@ -329,43 +422,130 @@ class filestoragelib_testcase extends advanced_testcase { // this should break on oracle $fs->get_external_files($userrepository->id, 'id'); - //TODO: verify result!! MDL-33326 - } + //TODO: verify result!! MDL-33368 + } + + public function test_create_directory_contextid_negative() { + $fs = get_file_storage(); + + $this->setExpectedException('file_exception'); + $fs->create_directory(-1, 'core', 'unittest', 0, '/'); + } + + public function test_create_directory_contextid_invalid() { + $fs = get_file_storage(); + + $this->setExpectedException('file_exception'); + $fs->create_directory('not an int', 'core', 'unittest', 0, '/'); + } + + public function test_create_directory_component_invalid() { + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $this->setExpectedException('file_exception'); + $fs->create_directory($syscontext->id, 'bad/component', 'unittest', 0, '/'); + } + + public function test_create_directory_filearea_invalid() { + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $this->setExpectedException('file_exception'); + $fs->create_directory($syscontext->id, 'core', 'bad-filearea', 0, '/'); + } + + public function test_create_directory_itemid_negative() { + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $this->setExpectedException('file_exception'); + $fs->create_directory($syscontext->id, 'core', 'unittest', -1, '/'); + } + + public function test_create_directory_itemid_invalid() { + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $this->setExpectedException('file_exception'); + $fs->create_directory($syscontext->id, 'core', 'unittest', 'notanint', '/'); + } + + public function test_create_directory_filepath_invalid() { + $fs = get_file_storage(); + $syscontext = context_system::instance(); + + $this->setExpectedException('file_exception'); + $fs->create_directory($syscontext->id, 'core', 'unittest', 0, '/not-with-trailing/or-leading-slash'); + } public function test_get_directory_files() { $user = $this->setup_three_private_files(); $fs = get_file_storage(); - // This should also break on oracle. - $fs->create_directory($user->ctxid, 'user', 'private', 0, '/'); - //TODO: verify result!! MDL-33326 + $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/'); + $this->assertInstanceOf('stored_file', $dir); - // Don't recurse with dirs - $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id'); - //TODO: verify result!! MDL-33326 + // Add a file to the subdir. + $filerecord = array( + 'contextid' => $user->ctxid, + 'component' => 'user', + 'filearea' => 'private', + 'itemid' => 0, + 'filepath' => '/testsubdir/', + 'filename' => 'test-get-area-tree.txt', + ); + + $directoryfile = $fs->create_file_from_string($filerecord, 'Test content'); + $this->assertInstanceOf('stored_file', $directoryfile); // Don't recurse without dirs - $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id'); - //TODO: verify result!! MDL-33326 + $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id'); + // 3 files only. + $this->assertCount(3, $files); + foreach($files as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } + + // Don't recurse with dirs + $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id'); + // 3 files + 1 directory + $this->assertCount(4, $files); + foreach($files as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } // Recurse with dirs - $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id'); - //TODO: verify result!! MDL-33326 + $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id'); + // 3 files + 1 directory + 1 subdir file + $this->assertCount(5, $files); + foreach($files as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } + // Recurse without dirs - $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id'); - //TODO: verify result!! MDL-33326 + $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id'); + // 3 files + 1 subdir file + $this->assertCount(4, $files); + foreach($files as $key => $file) { + $this->assertInstanceOf('stored_file', $file); + $this->assertEquals($key, $file->get_pathnamehash()); + } } public function test_search_references() { $fs = get_file_storage(); $references = $fs->search_references('testsearch'); - //TODO: verify result!! MDL-33326 + //TODO: verify result!! MDL-33368 } public function test_search_references_count() { $fs = get_file_storage(); $references = $fs->search_references_count('testsearch'); - //TODO: verify result!! MDL-33326 + //TODO: verify result!! MDL-33368 } public function test_delete_area_files() { @@ -383,6 +563,20 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertEquals(0, count($areafiles)); } + public function test_delete_area_files_itemid() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + // Get area files with default options. + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + // Should be the two files we added plus the folder. + $this->assertEquals(4, count($areafiles)); + $fs->delete_area_files($user->ctxid, 'user', 'private', 9999); + + $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private'); + $this->assertEquals(4, count($areafiles)); + } + public function test_delete_area_files_select() { $user = $this->setup_three_private_files(); $fs = get_file_storage(); From 996f8b64421342c7b76b6d195d7ceb40327bdf4b Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 28 May 2012 11:29:44 +0800 Subject: [PATCH 430/455] MDL-33326 filestorage tests: Add more coverage --- lib/filestorage/tests/file_storage_test.php | 576 ++++++++++++++++++++ 1 file changed, 576 insertions(+) diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index 16dc4b25965..2659dd0f2e5 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -591,4 +591,580 @@ class filestoragelib_testcase extends advanced_testcase { // Should be the two files we added plus the folder. $this->assertEquals(0, count($areafiles)); } + + public function test_create_file_from_url() { + $this->resetAfterTest(true); + + $syscontext = context_system::instance(); + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => 'core', + 'filearea' => 'unittest', + 'itemid' => 0, + 'filepath' => '/downloadtest/', + ); + $url = 'http://download.moodle.org/unittest/test.html'; + + $fs = get_file_storage(); + + // Test creating file without filename. + $file1 = $fs->create_file_from_url($filerecord, $url); + $this->assertInstanceOf('stored_file', $file1); + + // Set filename. + $filerecord['filename'] = 'unit-test-filename.html'; + $file2 = $fs->create_file_from_url($filerecord, $url); + $this->assertInstanceOf('stored_file', $file2); + + // Use temporary file. + $filerecord['filename'] = 'unit-test-with-temp-file.html'; + $file3 = $fs->create_file_from_url($filerecord, $url, null, true); + $file3 = $this->assertInstanceOf('stored_file', $file3); + } + + public function test_cron() { + $this->resetAfterTest(true); + + // Note: this is only testing DB compatibility atm, rather than + // that work is done + $fs = get_file_storage(); + + $this->expectOutputRegex('/Cleaning up/'); + $fs->cron(); + } + + public function test_is_area_empty() { + $user = $this->setup_three_private_files(); + $fs = get_file_storage(); + + $this->assertFalse($fs->is_area_empty($user->ctxid, 'user', 'private')); + + // File area with madeup itemid should be empty. + $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999)); + // Still empty with dirs included. + $this->assertTrue($fs->is_area_empty($user->ctxid, 'user', 'private', 9999, false)); + } + + public function test_move_area_files_to_new_context() { + $this->resetAfterTest(true); + + // Create a course with a page resource. + $course = $this->getDataGenerator()->create_course(); + $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); + $page1context = context_module::instance($page1->cmid); + + + // Add a file to the page. + $fs = get_file_storage(); + $filerecord = array( + 'contextid' => $page1context->id, + 'component' => 'mod_page', + 'filearea' => 'content', + 'itemid' => 0, + 'filepath' => '/', + 'filename' => 'unit-test-file.txt', + ); + + $originalfile = $fs->create_file_from_string($filerecord, 'Test content'); + $this->assertInstanceOf('stored_file', $originalfile); + + $pagefiles = $fs->get_area_files($page1context->id, 'mod_page', 'content', 0, 'sortorder', false); + // Should be one file in filearea. + $this->assertFalse($fs->is_area_empty($page1context->id, 'mod_page', 'content')); + + // Create a new page. + $page2 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); + $page2context = context_module::instance($page2->cmid); + + // Newly created page area is empty. + $this->assertTrue($fs->is_area_empty($page2context->id, 'mod_page', 'content')); + + // Move the files. + $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content'); + + // page2 filearea should no longer be empty. + $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content')); + + // page1 filearea should now be empty. + $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content')); + + $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false); + $movedfile = reset($page2files); + + // The two files should have the same content hash. + $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash()); + } + + public function test_convert_image() { + global $CFG; + + $this->resetAfterTest(false); + + $filepath = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + $syscontext = context_system::instance(); + $filerecord = array( + 'contextid' => $syscontext->id, + 'component' => 'core', + 'filearea' => 'unittest', + 'itemid' => 0, + 'filepath' => '/images/', + 'filename' => 'testimage.jpg', + ); + + $fs = get_file_storage(); + $original = $fs->create_file_from_pathname($filerecord, $filepath); + + $filerecord['filename'] = 'testimage-converted-10x10.jpg'; + $converted = $fs->convert_image($filerecord, $original, 10, 10, true, 100); + $this->assertInstanceOf('stored_file', $converted); + + $filerecord['filename'] = 'testimage-convereted-nosize.jpg'; + $converted = $fs->convert_image($filerecord, $original); + $this->assertInstanceOf('stored_file', $converted); + } + + private function generate_file_record() { + $syscontext = context_system::instance(); + $filerecord = new stdClass(); + $filerecord->contextid = $syscontext->id; + $filerecord->component = 'core'; + $filerecord->filearea = 'phpunit'; + $filerecord->filepath = '/'; + $filerecord->filename = 'testfile.txt'; + $filerecord->itemid = 0; + + return $filerecord; + } + + public function test_create_file_from_storedfile_file_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $this->setExpectedException('file_exception'); + // Create a file from a file id which doesn't exist. + $fs->create_file_from_storedfile($filerecord, 9999); + } + + public function test_create_file_from_storedfile_contextid_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->contextid = 'invalid'; + + $this->setExpectedException('file_exception', 'Invalid contextid'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_component_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->component = 'bad/component'; + + $this->setExpectedException('file_exception', 'Invalid component'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_filearea_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->filearea = 'bad-filearea'; + + $this->setExpectedException('file_exception', 'Invalid filearea'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_itemid_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->itemid = 'bad-itemid'; + + $this->setExpectedException('file_exception', 'Invalid itemid'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_filepath_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->filepath = 'a-/bad/-filepath'; + + $this->setExpectedException('file_exception', 'Invalid file path'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_filename_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = ''; + + $this->setExpectedException('file_exception', 'Invalid file name'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_timecreated_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->timecreated = 'today'; + + $this->setExpectedException('file_exception', 'Invalid file timecreated'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_timemodified_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'invalid.txt'; + $filerecord->timemodified = 'today'; + + $this->setExpectedException('file_exception', 'Invalid file timemodified'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile_duplicate() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + + $fs = get_file_storage(); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + // Creating a file validating unique constraint. + $this->setExpectedException('stored_file_creation_exception'); + $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + } + + public function test_create_file_from_storedfile() { + $this->resetAfterTest(true); + + $syscontext = context_system::instance(); + + $filerecord = new stdClass(); + $filerecord->contextid = $syscontext->id; + $filerecord->component = 'core'; + $filerecord->filearea = 'phpunit'; + $filerecord->filepath = '/'; + $filerecord->filename = 'testfile.txt'; + $filerecord->itemid = 0; + + $fs = get_file_storage(); + + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + $this->assertInstanceOf('stored_file', $file1); + + $filerecord->filename = 'test-create-file-from-storedfile.txt'; + $file2 = $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + $this->assertInstanceOf('stored_file', $file2); + + // These will be normalised to current time.. + $filerecord->timecreated = -100; + $filerecord->timemodified= -100; + $filerecord->filename = 'test-create-file-from-storedfile-bad-dates.txt'; + + $file3 = $fs->create_file_from_storedfile($filerecord, $file1->get_id()); + $this->assertInstanceOf('stored_file', $file3); + + $this->assertNotEquals($file3->get_timemodified(), $filerecord->timemodified); + $this->assertNotEquals($file3->get_timecreated(), $filerecord->timecreated); + } + + public function test_create_file_from_string_contextid_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->contextid = 'invalid'; + + $this->setExpectedException('file_exception', 'Invalid contextid'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_component_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->component = 'bad/component'; + + $this->setExpectedException('file_exception', 'Invalid component'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_filearea_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->filearea = 'bad-filearea'; + + $this->setExpectedException('file_exception', 'Invalid filearea'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_itemid_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->itemid = 'bad-itemid'; + + $this->setExpectedException('file_exception', 'Invalid itemid'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_filepath_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->filepath = 'a-/bad/-filepath'; + + $this->setExpectedException('file_exception', 'Invalid file path'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_filename_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->filename = ''; + + $this->setExpectedException('file_exception', 'Invalid file name'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_timecreated_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->timecreated = 'today'; + + $this->setExpectedException('file_exception', 'Invalid file timecreated'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_timemodified_invalid() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->timemodified = 'today'; + + $this->setExpectedException('file_exception', 'Invalid file timemodified'); + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_string_duplicate() { + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $file1 = $fs->create_file_from_string($filerecord, 'text contents'); + + // Creating a file validating unique constraint. + $this->setExpectedException('stored_file_creation_exception'); + $file2 = $fs->create_file_from_string($filerecord, 'text contents'); + } + + public function test_create_file_from_pathname_contextid_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->contextid = 'invalid'; + + $this->setExpectedException('file_exception', 'Invalid contextid'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_component_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->component = 'bad/component'; + + $this->setExpectedException('file_exception', 'Invalid component'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_filearea_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->filearea = 'bad-filearea'; + + $this->setExpectedException('file_exception', 'Invalid filearea'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_itemid_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->itemid = 'bad-itemid'; + + $this->setExpectedException('file_exception', 'Invalid itemid'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_filepath_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->filepath = 'a-/bad/-filepath'; + + $this->setExpectedException('file_exception', 'Invalid file path'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_filename_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->filename = ''; + + $this->setExpectedException('file_exception', 'Invalid file name'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_timecreated_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->timecreated = 'today'; + + $this->setExpectedException('file_exception', 'Invalid file timecreated'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_timemodified_invalid() { + global $CFG; + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $this->resetAfterTest(true); + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $filerecord->timemodified = 'today'; + + $this->setExpectedException('file_exception', 'Invalid file timemodified'); + $file1 = $fs->create_file_from_pathname($filerecord, $path); + } + + public function test_create_file_from_pathname_duplicate_file() { + global $CFG; + $this->resetAfterTest(true); + + $path = $CFG->dirroot.'/lib/filestorage/tests/fixtures/testimage.jpg'; + + $filerecord = $this->generate_file_record(); + $fs = get_file_storage(); + + $file1 = $fs->create_file_from_pathname($filerecord, $path); + $this->assertInstanceOf('stored_file', $file1); + + // Creating a file validating unique constraint. + $this->setExpectedException('stored_file_creation_exception'); + $file2 = $fs->create_file_from_pathname($filerecord, $path); + } } From 294d976e288bd62b34655e2de520904b3b4ec1d2 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Wed, 30 May 2012 00:20:54 +0200 Subject: [PATCH 431/455] MDL-33326 filestorage tests: Coding style fixes --- lib/filestorage/tests/file_storage_test.php | 51 ++++++++++----------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index 2659dd0f2e5..41feea15ae5 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -281,7 +281,7 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertEquals(4, count($areafiles)); // Verify structure. - foreach($areafiles as $key => $file) { + foreach ($areafiles as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } @@ -292,7 +292,7 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertEquals(3, count($folderlessfiles)); // Verify structure. - foreach($folderlessfiles as $key => $file) { + foreach ($folderlessfiles as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } @@ -303,14 +303,14 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertEquals(3, count($filesbyid)); // Verify structure. - foreach($filesbyid as $key => $file) { + foreach ($filesbyid as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } // Test with an itemid with no files $areafiles = $fs->get_area_files($user->ctxid, 'user', 'private', 666, 'sortorder', false); - // Should be none + // Should be none. $this->assertEmpty($areafiles); } @@ -330,7 +330,7 @@ class filestoragelib_testcase extends advanced_testcase { $this->assertEmpty($emptytree['subdirs']); $this->assertEmpty($emptytree['files']); - // Create a subdir + // Create a subdir. $dir = $fs->create_directory($user->ctxid, 'user', 'private', 0, '/testsubdir/'); $this->assertInstanceOf('stored_file', $dir); @@ -363,7 +363,7 @@ class filestoragelib_testcase extends advanced_testcase { // And no subdirs itself. $this->assertCount(0, $subdir['subdirs']); - // verify the file is the one we added. + // Verify the file is the one we added. $subdirfile = reset($subdir['files']); $this->assertInstanceOf('stored_file', $subdirfile); $this->assertEquals($filerecord['filename'], $subdirfile->get_filename()); @@ -409,7 +409,7 @@ class filestoragelib_testcase extends advanced_testcase { $testfile = reset($areafiles); $references = $fs->get_references_by_storedfile($testfile); - //TODO: verify result!! MDL-33368 + // TODO MDL-33368 Verify result!! } public function test_get_external_files() { @@ -420,9 +420,9 @@ class filestoragelib_testcase extends advanced_testcase { $userrepository = reset($repos); $this->assertInstanceOf('repository', $userrepository); - // this should break on oracle + // This should break on oracle. $fs->get_external_files($userrepository->id, 'id'); - //TODO: verify result!! MDL-33368 + // TODO MDL-33368 Verify result!! } public function test_create_directory_contextid_negative() { @@ -503,34 +503,34 @@ class filestoragelib_testcase extends advanced_testcase { $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, false, 'id'); // 3 files only. $this->assertCount(3, $files); - foreach($files as $key => $file) { + foreach ($files as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } - // Don't recurse with dirs + // Don't recurse with dirs. $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', false, true, 'id'); - // 3 files + 1 directory + // 3 files + 1 directory. $this->assertCount(4, $files); - foreach($files as $key => $file) { + foreach ($files as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } - // Recurse with dirs + // Recurse with dirs. $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, true, 'id'); - // 3 files + 1 directory + 1 subdir file + // 3 files + 1 directory + 1 subdir file. $this->assertCount(5, $files); - foreach($files as $key => $file) { + foreach ($files as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } - // Recurse without dirs + // Recurse without dirs. $files = $fs->get_directory_files($user->ctxid, 'user', 'private', 0, '/', true, false, 'id'); - // 3 files + 1 subdir file + // 3 files + 1 subdir file. $this->assertCount(4, $files); - foreach($files as $key => $file) { + foreach ($files as $key => $file) { $this->assertInstanceOf('stored_file', $file); $this->assertEquals($key, $file->get_pathnamehash()); } @@ -539,13 +539,13 @@ class filestoragelib_testcase extends advanced_testcase { public function test_search_references() { $fs = get_file_storage(); $references = $fs->search_references('testsearch'); - //TODO: verify result!! MDL-33368 + // TODO MDL-33368 Verify result!! } public function test_search_references_count() { $fs = get_file_storage(); $references = $fs->search_references_count('testsearch'); - //TODO: verify result!! MDL-33368 + // TODO MDL-33368 Verify result!! } public function test_delete_area_files() { @@ -626,7 +626,7 @@ class filestoragelib_testcase extends advanced_testcase { $this->resetAfterTest(true); // Note: this is only testing DB compatibility atm, rather than - // that work is done + // that work is done. $fs = get_file_storage(); $this->expectOutputRegex('/Cleaning up/'); @@ -653,7 +653,6 @@ class filestoragelib_testcase extends advanced_testcase { $page1 = $this->getDataGenerator()->create_module('page', array('course'=>$course->id)); $page1context = context_module::instance($page1->cmid); - // Add a file to the page. $fs = get_file_storage(); $filerecord = array( @@ -682,16 +681,16 @@ class filestoragelib_testcase extends advanced_testcase { // Move the files. $fs->move_area_files_to_new_context($page1context->id, $page2context->id, 'mod_page', 'content'); - // page2 filearea should no longer be empty. + // Page2 filearea should no longer be empty. $this->assertFalse($fs->is_area_empty($page2context->id, 'mod_page', 'content')); - // page1 filearea should now be empty. + // Page1 filearea should now be empty. $this->assertTrue($fs->is_area_empty($page1context->id, 'mod_page', 'content')); $page2files = $fs->get_area_files($page2context->id, 'mod_page', 'content', 0, 'sortorder', false); $movedfile = reset($page2files); - // The two files should have the same content hash. + // The two files should have the same content hash. $this->assertEquals($movedfile->get_contenthash(), $originalfile->get_contenthash()); } From 64f812f924f8a5129eb30a9927d5d30865bbfd34 Mon Sep 17 00:00:00 2001 From: AMOS bot Date: Wed, 30 May 2012 00:31:17 +0000 Subject: [PATCH 432/455] Automatically generated installer lang files --- install/lang/es_mx/admin.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 install/lang/es_mx/admin.php diff --git a/install/lang/es_mx/admin.php b/install/lang/es_mx/admin.php new file mode 100644 index 00000000000..c50bbe74117 --- /dev/null +++ b/install/lang/es_mx/admin.php @@ -0,0 +1,33 @@ +. + +/** + * Automatically generated strings for Moodle 2.3dev installer + * + * Do not edit this file manually! It contains just a subset of strings + * needed during the very first steps of installation. This file was + * generated automatically by export-installer.php (which is part of AMOS + * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the + * list of strings defined in /install/stringnames.txt. + * + * @package installer + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['environmentrequireinstall'] = 'debe estar instalado y activado'; From 7ee1548acbf5ffa4431ced434e2bdc93937178f7 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Wed, 30 May 2012 08:37:56 +0800 Subject: [PATCH 433/455] MDL-33414: The setting $showviewlink needs to be passed by reference This was preventing the view full submission/feedback link from appearing everywhere in the assignment when the submission/feedback content had been truncated in the summary because it was too long (or too many files) --- mod/assign/assignmentplugin.php | 2 +- mod/assign/feedback/comments/locallib.php | 2 +- mod/assign/feedback/file/locallib.php | 2 +- mod/assign/submission/comments/locallib.php | 2 +- mod/assign/submission/file/locallib.php | 2 +- mod/assign/submission/onlinetext/locallib.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mod/assign/assignmentplugin.php b/mod/assign/assignmentplugin.php index 69b6ec4e653..dcb31e96b72 100644 --- a/mod/assign/assignmentplugin.php +++ b/mod/assign/assignmentplugin.php @@ -344,7 +344,7 @@ abstract class assign_plugin { * @param bool $showviewlink Modifed to return whether or not to show a link to the full submission/feedback * @return string - return a string representation of the submission in full */ - public function view_summary(stdClass $submissionorgrade, $showviewlink) { + public function view_summary(stdClass $submissionorgrade, & $showviewlink) { return ''; } diff --git a/mod/assign/feedback/comments/locallib.php b/mod/assign/feedback/comments/locallib.php index 7f97175c00e..dadd2a86680 100644 --- a/mod/assign/feedback/comments/locallib.php +++ b/mod/assign/feedback/comments/locallib.php @@ -105,7 +105,7 @@ class assign_feedback_comments extends assign_feedback_plugin { * @param bool $showviewlink Set to true to show a link to view the full feedback * @return string */ - public function view_summary(stdClass $grade, $showviewlink) { + public function view_summary(stdClass $grade, & $showviewlink) { $feedbackcomments = $this->get_feedback_comments($grade->id); if ($feedbackcomments) { $text = format_text($feedbackcomments->commenttext, $feedbackcomments->commentformat, array('context' => $this->assignment->get_context())); diff --git a/mod/assign/feedback/file/locallib.php b/mod/assign/feedback/file/locallib.php index 20c4be7ca1d..9989cf328ae 100644 --- a/mod/assign/feedback/file/locallib.php +++ b/mod/assign/feedback/file/locallib.php @@ -146,7 +146,7 @@ class assign_feedback_file extends assign_feedback_plugin { * @param bool $showviewlink - Set to true to show a link to see the full list of files * @return string */ - public function view_summary(stdClass $grade, $showviewlink) { + public function view_summary(stdClass $grade, & $showviewlink) { $count = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA); // show a view all link if the number of files is over this limit $showviewlink = $count > ASSIGNFEEDBACK_FILE_MAXSUMMARYFILES; diff --git a/mod/assign/submission/comments/locallib.php b/mod/assign/submission/comments/locallib.php index 43ee80da72b..eb879388757 100644 --- a/mod/assign/submission/comments/locallib.php +++ b/mod/assign/submission/comments/locallib.php @@ -53,7 +53,7 @@ class assign_submission_comments extends assign_submission_plugin { * @param bool $showviewlink - If the comments are long this is set to true so they can be shown in a separate page * @return string */ - public function view_summary(stdClass $submission, $showviewlink) { + public function view_summary(stdClass $submission, & $showviewlink) { // never show a link to view full submission $showviewlink = false; diff --git a/mod/assign/submission/file/locallib.php b/mod/assign/submission/file/locallib.php index b097c397301..3f95f343524 100644 --- a/mod/assign/submission/file/locallib.php +++ b/mod/assign/submission/file/locallib.php @@ -244,7 +244,7 @@ class assign_submission_file extends assign_submission_plugin { * @param bool $showviewlink Set this to true if the list of files is long * @return string */ - public function view_summary(stdClass $submission, $showviewlink) { + public function view_summary(stdClass $submission, & $showviewlink) { $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); // show we show a link to view all files for this plugin? diff --git a/mod/assign/submission/onlinetext/locallib.php b/mod/assign/submission/onlinetext/locallib.php index dcaf0c5531a..0ab3777664e 100644 --- a/mod/assign/submission/onlinetext/locallib.php +++ b/mod/assign/submission/onlinetext/locallib.php @@ -192,7 +192,7 @@ class assign_submission_onlinetext extends assign_submission_plugin { * @param bool $showviewlink - If the summary has been truncated set this to true * @return string */ - public function view_summary(stdClass $submission, $showviewlink) { + public function view_summary(stdClass $submission, & $showviewlink) { $onlinetextsubmission = $this->get_onlinetext_submission($submission->id); // always show the view link From 0047693f09077e78386bb3e67bab1f33cb73caf3 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Wed, 30 May 2012 09:01:11 +0800 Subject: [PATCH 434/455] MDL-33385: Assignment plugin settings not visible in admin tree. * Also fixes a regression where file_submissions were not set to default for new installs. --- mod/assign/settings.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mod/assign/settings.php b/mod/assign/settings.php index 7860b648ef6..187bc9a571a 100644 --- a/mod/assign/settings.php +++ b/mod/assign/settings.php @@ -36,6 +36,9 @@ $ADMIN->add('assignmentplugins', new admin_category('assignfeedbackplugins', $ADMIN->add('assignfeedbackplugins', new assign_admin_page_manage_assign_plugins('assignfeedback')); +assign_plugin_manager::add_admin_assign_plugin_settings('assignsubmission', $ADMIN, $settings, $module); +assign_plugin_manager::add_admin_assign_plugin_settings('assignfeedback', $ADMIN, $settings, $module); + if ($ADMIN->fulltree) { $menu = array(); foreach (get_plugin_list('assignfeedback') as $type => $notused) { @@ -54,4 +57,4 @@ if ($ADMIN->fulltree) { new lang_string('configshowrecentsubmissions', 'assign'), 0)); $settings->add(new admin_setting_configcheckbox('assign/submissionreceipts', get_string('sendsubmissionreceipts', 'mod_assign'), get_string('sendsubmissionreceipts_help', 'mod_assign'), 1)); -} \ No newline at end of file +} From 28e0c239ec63b8855ac23bf0ca0891751ef5eb79 Mon Sep 17 00:00:00 2001 From: Aaron Barnes Date: Tue, 29 May 2012 14:34:16 +1200 Subject: [PATCH 435/455] MDL-33398 completion: Fix coding error (should be arrays not objects) --- lib/completion/completion_criteria_activity.php | 2 +- lib/completion/completion_criteria_course.php | 2 +- lib/completion/completion_criteria_date.php | 2 +- lib/completion/completion_criteria_duration.php | 2 +- lib/completion/completion_criteria_grade.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/completion/completion_criteria_activity.php b/lib/completion/completion_criteria_activity.php index ba275468723..375c9663cbe 100644 --- a/lib/completion/completion_criteria_activity.php +++ b/lib/completion/completion_criteria_activity.php @@ -235,7 +235,7 @@ class completion_criteria_activity extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { - $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record->timecompleted); } $rs->close(); diff --git a/lib/completion/completion_criteria_course.php b/lib/completion/completion_criteria_course.php index 04be448241e..671eeb97e32 100644 --- a/lib/completion/completion_criteria_course.php +++ b/lib/completion/completion_criteria_course.php @@ -193,7 +193,7 @@ class completion_criteria_course extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { - $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record['timecompleted']); } $rs->close(); diff --git a/lib/completion/completion_criteria_date.php b/lib/completion/completion_criteria_date.php index bacc144955d..1d52e29806d 100644 --- a/lib/completion/completion_criteria_date.php +++ b/lib/completion/completion_criteria_date.php @@ -179,7 +179,7 @@ class completion_criteria_date extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql, array(time())); foreach ($rs as $record) { - $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record['timeend']); } $rs->close(); diff --git a/lib/completion/completion_criteria_duration.php b/lib/completion/completion_criteria_duration.php index 962b052fe4e..ead1a556c2b 100644 --- a/lib/completion/completion_criteria_duration.php +++ b/lib/completion/completion_criteria_duration.php @@ -229,7 +229,7 @@ class completion_criteria_duration extends completion_criteria { $now = time(); $rs = $DB->get_recordset_sql($sql, array($now, $now)); foreach ($rs as $record) { - $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); // Use time start if not 0, otherwise use timeenrolled if ($record->otimestart) { diff --git a/lib/completion/completion_criteria_grade.php b/lib/completion/completion_criteria_grade.php index 3e0da11715f..22a924f804a 100644 --- a/lib/completion/completion_criteria_grade.php +++ b/lib/completion/completion_criteria_grade.php @@ -215,7 +215,7 @@ class completion_criteria_grade extends completion_criteria { // Loop through completions, and mark as complete $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { - $completion = new completion_criteria_completion($record, DATA_OBJECT_FETCH_BY_KEY); + $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); $completion->mark_complete($record['timecompleted']); } $rs->close(); From 322945e9ca2fe104084de8de5423d4fe5487a54b Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Wed, 30 May 2012 10:05:10 +0800 Subject: [PATCH 436/455] MDL-33184 Filepicker: rephrased drag and drop sentence --- files/renderer.php | 3 +-- lang/en/moodle.php | 2 +- lib/outputrenderers.php | 6 ++++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/files/renderer.php b/files/renderer.php index ac8e5829463..3728a23443c 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -185,7 +185,6 @@ class core_files_renderer extends plugin_renderer_base { $strmakedir = get_string('makeafolder', 'moodle'); $strdownload = get_string('downloadfolder', 'repository'); $strloading = get_string('loading', 'repository'); - $strnofilesattached = get_string('nofilesattached', 'repository'); $strdroptoupload = get_string('droptoupload', 'moodle'); $icon_progress = $OUTPUT->pix_icon('i/loading_small', $strloading).''; $restrictions = $this->fm_print_restrictions($fm); @@ -220,7 +219,7 @@ class core_files_renderer extends plugin_renderer_base {
                          -
                          '.$strnofilesattached.' +
                          '.$strdndenabledinbox.'
                          '.$strdroptoupload.'
                          diff --git a/lang/en/moodle.php b/lang/en/moodle.php index 073d3eb405f..224b7411f87 100644 --- a/lang/en/moodle.php +++ b/lang/en/moodle.php @@ -466,7 +466,7 @@ $string['displayonpage'] = 'Display on page'; $string['dndenabled'] = 'Drag and drop available'; $string['dndenabled_help'] = 'You can drag one or more files from your desktop and drop them onto the box below to upload them.
                          Note: this may not work with other web browsers'; $string['dndenabled_insentence'] = 'drag and drop available'; -$string['dndenabled_inbox'] = 'drag and drop files here to upload them'; +$string['dndenabled_inbox'] = 'You can drag and drop files here to add them.'; $string['dnduploadwithoutcontent'] = 'This upload does not have any content'; $string['dndworkingfiletextlink'] = 'Drag and drop files, text or links onto course sections to upload them'; $string['dndworkingfilelink'] = 'Drag and drop files or links onto course sections to upload them'; diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 80f20c65824..697ca6f383c 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -2025,7 +2025,9 @@ class core_renderer extends renderer_base { $currentfile = $options->currentfile; if (empty($currentfile)) { - $currentfile = get_string('nofilesattached', 'repository'); + $currentfile = ''; + } else { + $currentfile .= ' - '; } if ($options->maxbytes) { $size = $options->maxbytes; @@ -2056,7 +2058,7 @@ EOD; $html .= <<
                          -
                          $currentfile - $strdndenabled
                          +
                          $currentfile$strdndenabled
                          {$strdroptoupload}
                          From f1bd371c79e1f37cfb97ffb1b62a9d0cd6fbea7e Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Wed, 30 May 2012 10:11:41 +0800 Subject: [PATCH 437/455] MDL-33373 fixed bug in backup of files as a regression from MDL-28666 --- backup/moodle2/backup_stepslib.php | 2 +- backup/util/dbops/backup_controller_dbops.class.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backup/moodle2/backup_stepslib.php b/backup/moodle2/backup_stepslib.php index d1be602bc8f..a2fa9488605 100644 --- a/backup/moodle2/backup_stepslib.php +++ b/backup/moodle2/backup_stepslib.php @@ -1414,7 +1414,7 @@ class backup_final_files_structure_step extends backup_structure_step { $file->set_source_sql("SELECT f.*, r.repositoryid, r.reference FROM {files} f - JOIN {files_reference} r + LEFT JOIN {files_reference} r ON r.id = f.referencefileid JOIN {backup_ids_temp} bi ON f.id = bi.itemid diff --git a/backup/util/dbops/backup_controller_dbops.class.php b/backup/util/dbops/backup_controller_dbops.class.php index ee98987a41d..68c17526d2f 100644 --- a/backup/util/dbops/backup_controller_dbops.class.php +++ b/backup/util/dbops/backup_controller_dbops.class.php @@ -420,7 +420,7 @@ abstract class backup_controller_dbops extends backup_dbops { $sql = "SELECT count(r.repositoryid) FROM {files} f - JOIN {files_reference} r + LEFT JOIN {files_reference} r ON r.id = f.referencefileid JOIN {backup_ids_temp} bi ON f.id = bi.itemid From 6b0e5f4d6d664b6f3a140d0a57c33d64247fad32 Mon Sep 17 00:00:00 2001 From: Rossiani Wijaya Date: Tue, 29 May 2012 14:19:35 +0800 Subject: [PATCH 438/455] MDL-32766 course view section log: fixed the forth param for restore rule specification to use course_section --- backup/moodle2/restore_final_task.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/moodle2/restore_final_task.class.php b/backup/moodle2/restore_final_task.class.php index 06674acaaa3..377011eef26 100644 --- a/backup/moodle2/restore_final_task.class.php +++ b/backup/moodle2/restore_final_task.class.php @@ -135,7 +135,7 @@ class restore_final_task extends restore_task { $rules[] = new restore_log_rule('course', 'report outline', 'report/outline/index.php?id={course}', '{course}'); $rules[] = new restore_log_rule('course', 'report participation', 'report/participation/index.php?id={course}', '{course}'); $rules[] = new restore_log_rule('course', 'report stats', 'report/stats/index.php?id={course}', '{course}'); - $rules[] = new restore_log_rule('course', 'view section', 'view.php?id={course}§ion={course_sectionnumber}', '{course}'); + $rules[] = new restore_log_rule('course', 'view section', 'view.php?id={course}§ion={course_sectionnumber}', '{course_section}'); // module 'user' rules $rules[] = new restore_log_rule('user', 'view', 'view.php?id={user}&course={course}', '{user}'); From 378eb6f6a2500d06e22408faa8e03daa30b2cd32 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Wed, 30 May 2012 16:34:11 +1200 Subject: [PATCH 439/455] Revert "Merge branch 'MDL-27675_master_wip' of git://github.com/grabs/moodle" This reverts commit a09a9be81210a29a0c093ff34dc5685c86b84022, reversing changes made to 08e0aaa1733489cee61b1c48e166a98ada4477cb. --- mod/feedback/complete.php | 8 +++++--- mod/feedback/complete_guest.php | 12 +++++++----- mod/feedback/item/captcha/lib.php | 9 --------- mod/feedback/item/feedback_item_class.php | 14 +++----------- mod/feedback/item/info/lib.php | 9 --------- mod/feedback/item/label/lib.php | 8 -------- mod/feedback/item/multichoice/lib.php | 9 --------- mod/feedback/item/multichoicerated/lib.php | 8 -------- mod/feedback/item/numeric/lib.php | 9 --------- mod/feedback/item/textarea/lib.php | 9 --------- mod/feedback/item/textfield/lib.php | 9 --------- mod/feedback/lib.php | 12 ------------ 12 files changed, 15 insertions(+), 101 deletions(-) diff --git a/mod/feedback/complete.php b/mod/feedback/complete.php index e4c202c50d9..7fee6412d83 100644 --- a/mod/feedback/complete.php +++ b/mod/feedback/complete.php @@ -507,8 +507,11 @@ if ($feedback_can_submit) { //get the value $frmvaluename = $feedbackitem->typ . '_'. $feedbackitem->id; if (isset($savereturn)) { - $value = isset($formdata->{$frmvaluename}) ? $formdata->{$frmvaluename} : null; - $value = feedback_clean_input_value($feedbackitem, $value); + if (isset($formdata->{$frmvaluename})) { + $value = $formdata->{$frmvaluename}; + } else { + $value = null; + } } else { if (isset($feedbackcompletedtmp->id)) { $value = feedback_get_item_value($feedbackcompletedtmp->id, @@ -527,7 +530,6 @@ if ($feedback_can_submit) { feedback_print_item_complete($feedbackitem, $value, $highlightrequired); echo $OUTPUT->box_end(); } - echo $OUTPUT->box_end(); $lastbreakposition = $feedbackitem->position; //last item-pos (item or pagebreak) diff --git a/mod/feedback/complete_guest.php b/mod/feedback/complete_guest.php index b472c09e023..25747a99082 100644 --- a/mod/feedback/complete_guest.php +++ b/mod/feedback/complete_guest.php @@ -72,7 +72,7 @@ if (isset($formdata->sesskey) AND !isset($formdata->gonextpage) AND !isset($formdata->gopreviouspage)) { - $gopage = (int) $formdata->lastpage; + $gopage = $formdata->lastpage; } if (isset($formdata->savevalues)) { $savevalues = true; @@ -441,10 +441,13 @@ if ($feedback_can_submit) { echo $OUTPUT->box_start('feedback_item_box_'.$align.$dependstyle); $value = ''; //get the value - $frmvaluename = $feedbackitem->typ . '_'. $feedbackitem->id; + $frmvaluename = $feedbackitem->typ.'_'.$feedbackitem->id; if (isset($savereturn)) { - $value = isset($formdata->{$frmvaluename}) ? $formdata->{$frmvaluename} : null; - $value = feedback_clean_input_value($feedbackitem, $value); + if (isset($formdata->{$frmvaluename})) { + $value = $formdata->{$frmvaluename}; + } else { + $value = null; + } } else { if (isset($feedbackcompletedtmp->id)) { $value = feedback_get_item_value($feedbackcompletedtmp->id, @@ -463,7 +466,6 @@ if ($feedback_can_submit) { feedback_print_item_complete($feedbackitem, $value, $highlightrequired); echo $OUTPUT->box_end(); } - echo $OUTPUT->box_end(); $lastbreakposition = $feedbackitem->position; //last item-pos (item or pagebreak) diff --git a/mod/feedback/item/captcha/lib.php b/mod/feedback/item/captcha/lib.php index 19fa17b7835..126d51e3417 100644 --- a/mod/feedback/item/captcha/lib.php +++ b/mod/feedback/item/captcha/lib.php @@ -326,13 +326,4 @@ class feedback_item_captcha extends feedback_item_base { public function can_switch_require() { return false; } - - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param($value, PARAM_RAW); - } } diff --git a/mod/feedback/item/feedback_item_class.php b/mod/feedback/item/feedback_item_class.php index 57f1d6d8180..981aefd58ea 100644 --- a/mod/feedback/item/feedback_item_class.php +++ b/mod/feedback/item/feedback_item_class.php @@ -128,14 +128,6 @@ abstract class feedback_item_base { */ abstract public function print_item_show_value($item, $value = ''); - /** - * cleans the userinput while submitting the form - * - * @param mixed $value - * @return mixed - */ - abstract public function clean_input_value($value); - } //a dummy class to realize pagebreaks @@ -183,7 +175,7 @@ class feedback_item_pagebreak extends feedback_item_base { } public function can_switch_require() { } - public function clean_input_value($value) { - } -} \ No newline at end of file +} + + diff --git a/mod/feedback/item/info/lib.php b/mod/feedback/item/info/lib.php index b58123fc12b..299fef24b04 100644 --- a/mod/feedback/item/info/lib.php +++ b/mod/feedback/item/info/lib.php @@ -388,13 +388,4 @@ class feedback_item_info extends feedback_item_base { public function can_switch_require() { return false; } - - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param($value, PARAM_INT); - } } diff --git a/mod/feedback/item/label/lib.php b/mod/feedback/item/label/lib.php index bd88d391eae..25c62a9f55d 100644 --- a/mod/feedback/item/label/lib.php +++ b/mod/feedback/item/label/lib.php @@ -270,12 +270,4 @@ class feedback_item_label extends feedback_item_base { } public function get_analysed($item, $groupid = false, $courseid = false) { } - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return ''; - } } diff --git a/mod/feedback/item/multichoice/lib.php b/mod/feedback/item/multichoice/lib.php index d48abbeca62..cfba141be16 100644 --- a/mod/feedback/item/multichoice/lib.php +++ b/mod/feedback/item/multichoice/lib.php @@ -826,13 +826,4 @@ class feedback_item_multichoice extends feedback_item_base { public function value_is_array() { return true; } - - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param_array($value, PARAM_INT); - } } diff --git a/mod/feedback/item/multichoicerated/lib.php b/mod/feedback/item/multichoicerated/lib.php index 47ecedb630f..031f7b89540 100644 --- a/mod/feedback/item/multichoicerated/lib.php +++ b/mod/feedback/item/multichoicerated/lib.php @@ -678,12 +678,4 @@ class feedback_item_multichoicerated extends feedback_item_base { return true; } - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param($value, PARAM_INT); - } } diff --git a/mod/feedback/item/numeric/lib.php b/mod/feedback/item/numeric/lib.php index eb2b7206231..23694137d8f 100644 --- a/mod/feedback/item/numeric/lib.php +++ b/mod/feedback/item/numeric/lib.php @@ -534,13 +534,4 @@ class feedback_item_numeric extends feedback_item_base { public function can_switch_require() { return true; } - - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param($value, PARAM_FLOAT); - } } diff --git a/mod/feedback/item/textarea/lib.php b/mod/feedback/item/textarea/lib.php index 8ed937075de..54df5e6e47e 100644 --- a/mod/feedback/item/textarea/lib.php +++ b/mod/feedback/item/textarea/lib.php @@ -333,13 +333,4 @@ class feedback_item_textarea extends feedback_item_base { public function can_switch_require() { return true; } - - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param($value, PARAM_CLEANHTML); - } } diff --git a/mod/feedback/item/textfield/lib.php b/mod/feedback/item/textfield/lib.php index c9a4dc67b6a..4051ffb97c0 100644 --- a/mod/feedback/item/textfield/lib.php +++ b/mod/feedback/item/textfield/lib.php @@ -320,13 +320,4 @@ class feedback_item_textfield extends feedback_item_base { public function can_switch_require() { return true; } - - /** - * Cleans the value coming from the user for a field of this type. - * @param mixed $value - * @return mixed - */ - public function clean_input_value($value) { - return clean_param($value, PARAM_CLEANHTML); - } } diff --git a/mod/feedback/lib.php b/mod/feedback/lib.php index e007c4e3d87..3c9809b9f08 100644 --- a/mod/feedback/lib.php +++ b/mod/feedback/lib.php @@ -2058,18 +2058,6 @@ function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid //functions to handle the values //////////////////////////////////////////////// -/** - * cleans the userinput while submitting the form. - * - * @param stdClass $item The feedback item record from the database that the value needs to be cleaned against. - * @param mixed $value - * @return mixed - */ -function feedback_clean_input_value($item, $value) { - $itemobj = feedback_get_item_class($item->typ); - return $itemobj->clean_input_value($value); -} - /** * this saves the values of an completed. * if the param $tmp is set true so the values are saved temporary in table feedback_valuetmp. From 927cb511666780f10130677cbb7e493d0c4e3c57 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 24 May 2012 14:30:04 +0200 Subject: [PATCH 440/455] MDL-32329 plugin manager returns plugins with unsatisfied dependencies --- lib/pluginlib.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/pluginlib.php b/lib/pluginlib.php index df5239c4995..08875353b71 100644 --- a/lib/pluginlib.php +++ b/lib/pluginlib.php @@ -280,25 +280,35 @@ class plugin_manager { } /** - * Checks all dependencies for all installed plugins. Used by install and upgrade. + * Checks all dependencies for all installed plugins + * + * This is used by install and upgrade. The array passed by reference as the second + * argument is populated with the list of plugins that have failed dependencies (note that + * a single plugin can appear multiple times in the $failedplugins). + * * @param int $moodleversion the version from version.php. + * @param array $failedplugins to return the list of plugins with non-satisfied dependencies * @return bool true if all the dependencies are satisfied for all plugins. */ - public function all_plugins_ok($moodleversion) { + public function all_plugins_ok($moodleversion, &$failedplugins = array()) { + + $return = true; foreach ($this->get_plugins() as $type => $plugins) { foreach ($plugins as $plugin) { if (!empty($plugin->versionrequires) && $plugin->versionrequires > $moodleversion) { - return false; + $return = false; + $failedplugins[] = $plugin->component; } if (!$this->are_dependencies_satisfied($plugin->get_other_required_plugins())) { - return false; + $return = false; + $failedplugins[] = $plugin->component; } } } - return true; + return $return; } /** From f1753a5b10ea992541c22773102e41a2b40fbdda Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Thu, 24 May 2012 14:31:13 +0200 Subject: [PATCH 441/455] MDL-32329 CLI install and upgrade scripts display plugins with unsatisfied dependencies --- admin/cli/install.php | 4 +++- admin/cli/install_database.php | 4 +++- admin/cli/upgrade.php | 4 +++- lang/en/admin.php | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/admin/cli/install.php b/admin/cli/install.php index dc65e318d14..03723ed6061 100644 --- a/admin/cli/install.php +++ b/admin/cli/install.php @@ -677,7 +677,9 @@ if (!$envstatus) { // Test plugin dependencies. require_once($CFG->libdir . '/pluginlib.php'); -if (!plugin_manager::instance()->all_plugins_ok($version)) { +$failed = array(); +if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) { + cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed))))); cli_error(get_string('pluginschecktodo', 'admin')); } diff --git a/admin/cli/install_database.php b/admin/cli/install_database.php index 2524c4101eb..313f3521d40 100644 --- a/admin/cli/install_database.php +++ b/admin/cli/install_database.php @@ -161,7 +161,9 @@ if (!$envstatus) { // Test plugin dependencies. require_once($CFG->libdir . '/pluginlib.php'); -if (!plugin_manager::instance()->all_plugins_ok($version)) { +$failed = array(); +if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) { + cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed))))); cli_error(get_string('pluginschecktodo', 'admin')); } diff --git a/admin/cli/upgrade.php b/admin/cli/upgrade.php index 33e66cc3a4f..7eb7ea0971c 100644 --- a/admin/cli/upgrade.php +++ b/admin/cli/upgrade.php @@ -109,7 +109,9 @@ if (!$envstatus) { } // Test plugin dependencies. -if (!plugin_manager::instance()->all_plugins_ok($version)) { +$failed = array(); +if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) { + cli_problem(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed))))); cli_error(get_string('pluginschecktodo', 'admin')); } diff --git a/lang/en/admin.php b/lang/en/admin.php index 2ac7b1e2a6b..e5901232eec 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -753,6 +753,7 @@ $string['pleaserefreshregistration'] = 'Your site has been registered with moodl $string['pleaseregister'] = 'Please register your site to remove this button'; $string['plugin'] = 'Plugin'; $string['plugins'] = 'Plugins'; +$string['pluginscheckfailed'] = 'Dependencies check failed for {$a->pluginslist}'; $string['pluginschecktodo'] = 'You must solve all the plugin requirements before proceeding to install this Moodle version!'; $string['pluginsoverview'] = 'Plugins overview'; $string['profilecategory'] = 'Category'; From 3a2300f552eac4e5570e628dfe0a748a4d7da79f Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 25 May 2012 10:38:48 +0200 Subject: [PATCH 442/455] MDL-32329 new plugininfo_base::is_core_dependency_satisfied() method The method's logic was previously implemented in all_plugins_ok() but we will need to call it separately. Also make the code cleaner. --- lib/pluginlib.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/pluginlib.php b/lib/pluginlib.php index 08875353b71..20f8a340254 100644 --- a/lib/pluginlib.php +++ b/lib/pluginlib.php @@ -296,7 +296,7 @@ class plugin_manager { foreach ($this->get_plugins() as $type => $plugins) { foreach ($plugins as $plugin) { - if (!empty($plugin->versionrequires) && $plugin->versionrequires > $moodleversion) { + if (!$plugin->is_core_dependency_satisfied($moodleversion)) { $return = false; $failedplugins[] = $plugin->component; } @@ -1620,6 +1620,22 @@ abstract class plugininfo_base { return $this->source === plugin_manager::PLUGIN_SOURCE_STANDARD; } + /** + * Returns true if the the given Moodle version is enough to run this plugin + * + * @param string|int|double $moodleversion + * @return bool + */ + public function is_core_dependency_satisfied($moodleversion) { + + if (empty($this->versionrequires)) { + return true; + + } else { + return (double)$this->versionrequires <= (double)$moodleversion; + } + } + /** * Returns the status of the plugin * From 39f15cc712b0007b78cbdf6f9f051430ff72a840 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 25 May 2012 10:44:29 +0200 Subject: [PATCH 443/455] MDL-32329 check for plugin dependencies during the pre-install checking This follows the same path as we have in CLI installers. Plugin dependencies are checked right after the environment checks and the install can't continue unless all dependencies are fixed. --- admin/index.php | 14 ++++++++++++ admin/renderer.php | 56 +++++++++++++++++++++++++++++++++++++--------- lang/en/admin.php | 1 + lang/en/plugin.php | 4 ++-- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/admin/index.php b/admin/index.php index 5b01be2749b..42fdeb25883 100644 --- a/admin/index.php +++ b/admin/index.php @@ -152,6 +152,20 @@ if (!core_tables_exist()) { die(); } + // check plugin dependencies + $failed = array(); + if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) { + $PAGE->navbar->add(get_string('pluginscheck', 'admin')); + $PAGE->set_title($strinstallation); + $PAGE->set_heading($strinstallation . ' - Moodle ' . $CFG->target_release); + + $output = $PAGE->get_renderer('core', 'admin'); + $url = new moodle_url('/admin/index.php', array('agreelicense' => 1, 'confirmrelease' => 1, 'lang' => $CFG->lang)); + echo $output->unsatisfied_dependencies_page($version, $failed, $url); + die(); + } + unset($failed); + //TODO: add a page with list of non-standard plugins here $strdatabasesetup = get_string('databasesetup'); diff --git a/admin/renderer.php b/admin/renderer.php index b7a1bab12db..a4de04ebab4 100644 --- a/admin/renderer.php +++ b/admin/renderer.php @@ -107,6 +107,28 @@ class core_admin_renderer extends plugin_renderer_base { return $output; } + /** + * Displays the list of plugins with unsatisfied dependencies + * + * @param double|string|int $version Moodle on-disk version + * @param array $failed list of plugins with unsatisfied dependecies + * @return string HTML + */ + public function unsatisfied_dependencies_page($version, array $failed, moodle_url $reloadurl) { + $output = ''; + + $output .= $this->header(); + $output .= $this->heading(get_string('pluginscheck', 'admin')); + $output .= $this->warning(get_string('pluginscheckfailed', 'admin', array('pluginslist' => implode(', ', array_unique($failed))))); + $output .= $this->plugins_check_table(plugin_manager::instance(), $version, array('xdep' => true)); + $output .= $this->warning(get_string('pluginschecktodo', 'admin')); + $output .= $this->continue_button($reloadurl); + + $output .= $this->footer(); + + return $output; + } + /** * Display the 'You are about to upgrade Moodle' page. The first page * during upgrade. @@ -563,13 +585,14 @@ class core_admin_renderer extends plugin_renderer_base { * This default implementation renders all plugins into one big table. The rendering * options support: * (bool)full = false: whether to display up-to-date plugins, too + * (bool)xdep = false: display the plugins with unsatisified dependecies only * * @param plugin_manager $pluginman provides information about the plugins. * @param int $version the version of the Moodle code from version.php. * @param array $options rendering options * @return string HTML code */ - public function plugins_check_table(plugin_manager $pluginman, $version, array $options = null) { + public function plugins_check_table(plugin_manager $pluginman, $version, array $options = array()) { global $CFG; $plugininfo = $pluginman->get_plugins(); @@ -578,11 +601,8 @@ class core_admin_renderer extends plugin_renderer_base { return ''; } - if (empty($options)) { - $options = array( - 'full' => false, - ); - } + $options['full'] = isset($options['full']) ? (bool)$options['full'] : false; + $options['xdep'] = isset($options['xdep']) ? (bool)$options['xdep'] : false; $table = new html_table(); $table->id = 'plugins-check'; @@ -667,15 +687,25 @@ class core_admin_renderer extends plugin_renderer_base { $statusisboring = in_array($statuscode, array( plugin_manager::PLUGIN_STATUS_NODB, plugin_manager::PLUGIN_STATUS_UPTODATE)); $dependenciesok = $pluginman->are_dependencies_satisfied( - $plugin->get_other_required_plugins()); - if ($isstandard and $statusisboring and $dependenciesok and empty($availableupdates)) { + $plugin->get_other_required_plugins()) && $plugin->is_core_dependency_satisfied($version); + + if ($options['xdep']) { + // we want to see only plugins with failed dependencies + if ($dependenciesok) { + continue; + } + + } else if ($isstandard and $statusisboring and $dependenciesok and empty($availableupdates)) { + // no change is going to happen to the plugin - display it only + // if the user wants to see the full list if (empty($options['full'])) { continue; } - } else { - $numofhighlighted[$type]++; } + // ok, the plugin should be displayed + $numofhighlighted[$type]++; + $row->cells = array($displayname, $rootdir, $source, $versiondb, $versiondisk, $requires, $status); $plugintyperows[] = $row; @@ -691,7 +721,11 @@ class core_admin_renderer extends plugin_renderer_base { $sumofhighlighted = array_sum($numofhighlighted); - if ($sumofhighlighted == 0) { + if ($options['xdep']) { + // we do not want to display no heading and links in this mode + $out = ''; + + } else if ($sumofhighlighted == 0) { $out = $this->output->container_start('nonehighlighted', 'plugins-check-info'); $out .= $this->output->heading(get_string('nonehighlighted', 'core_plugin')); if (empty($options['full'])) { diff --git a/lang/en/admin.php b/lang/en/admin.php index e5901232eec..620d790a0a8 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -753,6 +753,7 @@ $string['pleaserefreshregistration'] = 'Your site has been registered with moodl $string['pleaseregister'] = 'Please register your site to remove this button'; $string['plugin'] = 'Plugin'; $string['plugins'] = 'Plugins'; +$string['pluginscheck'] = 'Plugin dependencies check'; $string['pluginscheckfailed'] = 'Dependencies check failed for {$a->pluginslist}'; $string['pluginschecktodo'] = 'You must solve all the plugin requirements before proceeding to install this Moodle version!'; $string['pluginsoverview'] = 'Plugins overview'; diff --git a/lang/en/plugin.php b/lang/en/plugin.php index 3bc89ef8d37..3bba405afa6 100644 --- a/lang/en/plugin.php +++ b/lang/en/plugin.php @@ -31,7 +31,7 @@ $string['checkforupdates'] = 'Check for available updates'; $string['checkforupdateslast'] = 'Last check done on {$a}'; $string['displayname'] = 'Plugin name'; $string['moodleversion'] = 'Moodle {$a}'; -$string['nonehighlighted'] = 'No plugins require your attention during this upgrade'; +$string['nonehighlighted'] = 'No plugins require your attention now'; $string['nonehighlightedinfo'] = 'Display the list of all installed plugins anyway'; $string['noneinstalled'] = 'No plugins of this type are installed'; $string['notes'] = 'Notes'; @@ -52,7 +52,7 @@ $string['requiredby'] = 'Required by: {$a}'; $string['requires'] = 'Requires'; $string['rootdir'] = 'Directory'; $string['settings'] = 'Settings'; -$string['somehighlighted'] = 'Number of plugins requiring attention during this upgrade: {$a}'; +$string['somehighlighted'] = 'Number of plugins requiring your attention: {$a}'; $string['somehighlightedinfo'] = 'Display the full list of installed plugins'; $string['somehighlightedonly'] = 'Display only plugins requiring your attention'; $string['source'] = 'Source'; From ead8ba3b63cf67ddeac784e2bf8933a283347b3f Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Fri, 25 May 2012 11:17:43 +0200 Subject: [PATCH 444/455] MDL-32329 improved plugin dependencies check on upgrade Previously, it was the renderer method that actually called all_plugins_ok(). I believe that renderer methods should not be responsible for such an important step in the install/upgrade code flow. So dependencies are now checked by admin/index.php on upgrade, too. --- admin/index.php | 19 +++++++++++++++++++ admin/renderer.php | 18 +++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/admin/index.php b/admin/index.php index 42fdeb25883..bf3eea52aa6 100644 --- a/admin/index.php +++ b/admin/index.php @@ -252,6 +252,15 @@ if ($version > $CFG->version) { // upgrade $reloadurl = new moodle_url('/admin/index.php', array('confirmupgrade' => 1, 'confirmrelease' => 1)); + // check plugin dependencies first + $failed = array(); + if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) { + $output = $PAGE->get_renderer('core', 'admin'); + echo $output->unsatisfied_dependencies_page($version, $failed, $reloadurl); + die(); + } + unset($failed); + if ($fetchupdates) { // no sesskey support guaranteed here if (empty($CFG->disableupdatenotifications)) { @@ -304,6 +313,16 @@ if (moodle_needs_upgrading()) { } $output = $PAGE->get_renderer('core', 'admin'); + + // check plugin dependencies first + $failed = array(); + if (!plugin_manager::instance()->all_plugins_ok($version, $failed)) { + echo $output->unsatisfied_dependencies_page($version, $failed, $PAGE->url); + die(); + } + unset($failed); + + // dependencies check passed, let's rock! echo $output->upgrade_plugin_check_page(plugin_manager::instance(), available_update_checker::instance(), $version, $showallplugins, new moodle_url($PAGE->url), diff --git a/admin/renderer.php b/admin/renderer.php index a4de04ebab4..d3ac14c6da2 100644 --- a/admin/renderer.php +++ b/admin/renderer.php @@ -219,19 +219,15 @@ class core_admin_renderer extends plugin_renderer_base { $output .= $this->box_end(); $output .= $this->upgrade_reload($reloadurl); - if ($pluginman->all_plugins_ok($version)) { - if ($pluginman->some_plugins_updatable()) { - $output .= $this->container_start('upgradepluginsinfo'); - $output .= $this->help_icon('upgradepluginsinfo', 'core_admin', get_string('upgradepluginsfirst', 'core_admin')); - $output .= $this->container_end(); - } - $button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get'); - $button->class = 'continuebutton'; - $output .= $this->render($button); - } else { - $output .= $this->box(get_string('pluginschecktodo', 'admin'), 'environmentbox errorbox'); + if ($pluginman->some_plugins_updatable()) { + $output .= $this->container_start('upgradepluginsinfo'); + $output .= $this->help_icon('upgradepluginsinfo', 'core_admin', get_string('upgradepluginsfirst', 'core_admin')); + $output .= $this->container_end(); } + $button = new single_button($continueurl, get_string('upgradestart', 'admin'), 'get'); + $button->class = 'continuebutton'; + $output .= $this->render($button); $output .= $this->footer(); return $output; From e937c5456e8fe5e3ae5323f371629fa0c42c42cd Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Wed, 30 May 2012 10:32:48 +0200 Subject: [PATCH 445/455] MDL-32329 fixed missing phpdoc and improved coding style Credit goes to Aparup Banerjee for spotting this during the integration review. --- admin/renderer.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/admin/renderer.php b/admin/renderer.php index d3ac14c6da2..9b689a6903e 100644 --- a/admin/renderer.php +++ b/admin/renderer.php @@ -112,6 +112,7 @@ class core_admin_renderer extends plugin_renderer_base { * * @param double|string|int $version Moodle on-disk version * @param array $failed list of plugins with unsatisfied dependecies + * @param moodle_url $reloadurl URL of the page to recheck the dependencies * @return string HTML */ public function unsatisfied_dependencies_page($version, array $failed, moodle_url $reloadurl) { @@ -682,8 +683,10 @@ class core_admin_renderer extends plugin_renderer_base { $statusisboring = in_array($statuscode, array( plugin_manager::PLUGIN_STATUS_NODB, plugin_manager::PLUGIN_STATUS_UPTODATE)); - $dependenciesok = $pluginman->are_dependencies_satisfied( - $plugin->get_other_required_plugins()) && $plugin->is_core_dependency_satisfied($version); + + $coredependency = $plugin->is_core_dependency_satisfied($version); + $otherpluginsdependencies = $pluginman->are_dependencies_satisfied($plugin->get_other_required_plugins()); + $dependenciesok = $coredependency && $otherpluginsdependencies; if ($options['xdep']) { // we want to see only plugins with failed dependencies From 469fb5d6722678c68b3e8711b08d1271d3d8c411 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 14 May 2012 00:39:00 +0800 Subject: [PATCH 446/455] MDL-29857 - lib: Add an OAuth 2.0 client A generic OAuth 2.0 for the web application flow, tested against microsoft and google apis. Added a callback endpoint for requests so that clients can use a single endpoint (without GET params). I put this in /admin/ as I expect some sites will have .htaccess denying access to /lib/. --- admin/oauth2callback.php | 38 ++++++ lib/oauthlib.php | 262 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 admin/oauth2callback.php diff --git a/admin/oauth2callback.php b/admin/oauth2callback.php new file mode 100644 index 00000000000..364c0023de0 --- /dev/null +++ b/admin/oauth2callback.php @@ -0,0 +1,38 @@ +. + +/** + * An oauth2 redirection endpoint which can be used for an application: + * http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-3.1.2 + * + * This is used because some oauth servers will not allow a redirect urls + * with get params (like repository callback) and that needs to be called + * using the state param. + * + * @package core + * @copyright 2012 Dan Poltawski + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(dirname(__FILE__)).'/config.php'); + +// The authorization code generated by the authorization server. +$code = required_param('code', PARAM_RAW); +// The state parameter we've given (used in moodle as a redirect url). +$state = required_param('state', PARAM_URL); + +redirect(new moodle_url($state, array('code' => $code))); diff --git a/lib/oauthlib.php b/lib/oauthlib.php index 36ee14e9f9b..b4aa15b7500 100644 --- a/lib/oauthlib.php +++ b/lib/oauthlib.php @@ -1,5 +1,4 @@ . + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir.'/filelib.php'); + /** * OAuth helper class * @@ -349,3 +353,259 @@ class oauth_helper { return md5($mt . $rand); } } + +/** + * OAuth 2.0 Client for using web access tokens. + * + * http://tools.ietf.org/html/draft-ietf-oauth-v2-22 + * + * @package core + * @copyright Dan Poltawski + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class oauth2_client extends curl { + /** var string client identifier issued to the client */ + private $clientid = ''; + /** var string The client secret. */ + private $clientsecret = ''; + /** var string URL to return to after authenticating */ + private $returnurl = ''; + /** var string scope of the authentication request */ + private $scope = ''; + /** var stdClass access token object */ + private $accesstoken = null; + + /** + * Returns the auth url for OAuth 2.0 request + * @return string the auth url + */ + abstract protected function auth_url(); + + /** + * Returns the token url for OAuth 2.0 request + * @return string the auth url + */ + abstract protected function token_url(); + + /** + * Constructor. + * + * @param string $clientid + * @param string $clientsecret + * @param string $returnurl + * @param string $scope + */ + public function __construct($clientid, $clientsecret, $returnurl, $scope) { + parent::__construct(); + $this->clientid = $clientid; + $this->clientsecret = $clientsecret; + $this->returnurl = $returnurl; + $this->scope = $scope; + $this->accesstoken = $this->get_stored_token(); + } + + /** + * Is the user logged in? Note that if this is called + * after the first part of the authorisation flow the token + * is upgraded to an accesstoken. + * + * @return boolean true if logged in + */ + public function is_logged_in() { + // Has the token expired? + if (isset($this->accesstoken->expires) && time() >= $this->accesstoken->expires) { + $this->log_out(); + return false; + } + + // We have a token so we are logged in. + if (isset($this->accesstoken->token)) { + return true; + } + + // If we've been passed then authorization code generated by the + // authorization server try and upgrade the token to an access token. + $code = optional_param('code', null, PARAM_RAW); + if ($code && $this->upgrade_token($code)) { + return true; + } + + return false; + } + + /** + * Callback url where the request is returned to. + * + * @return moodle_url url of callback + */ + public static function callback_url() { + global $CFG; + + return new moodle_url('/admin/oauth2callback.php'); + } + + /** + * Returns the login link for this oauth request + * + * @return moodle_url login url + */ + public function get_login_url() { + + $callbackurl = self::callback_url(); + $url = new moodle_url($this->auth_url(), + array('client_id' => $this->clientid, + 'response_type' => 'code', + 'redirect_uri' => $callbackurl->out(false), + 'state' => $this->returnurl, + 'scope' => $this->scope, + )); + + return $url; + } + + /** + * Upgrade a authorization token from oauth 2.0 to an access token + * + * @param string $code the code returned from the oauth authenticaiton + * @return boolean true if token is upgraded succesfully + */ + public function upgrade_token($code) { + $callbackurl = self::callback_url(); + $params = array('client_id' => $this->clientid, + 'client_secret' => $this->clientsecret, + 'grant_type' => 'authorization_code', + 'code' => $code, + 'redirect_uri' => $callbackurl->out(false), + ); + + // Requests can either use http GET or POST. + if ($this->use_http_get()) { + $response = $this->get($this->token_url(), $params); + } else { + $response = $this->post($this->token_url(), $params); + } + + if (!$this->info['http_code'] === 200) { + throw new moodle_exception('Could not upgrade oauth token'); + } + + $r = json_decode($response); + + if (!isset($r->access_token)) { + return false; + } + + // Store the token an expiry time. + $accesstoken = new stdClass; + $accesstoken->token = $r->access_token; + $accesstoken->expires = (time() + ($r->expires_in - 10)); // Expires 10 seconds before actual expiry. + $this->store_token($accesstoken); + + return true; + } + + /** + * Logs out of a oauth request, clearing any stored tokens + */ + public function log_out() { + $this->store_token(null); + } + + /** + * Make a HTTP request, adding the access token we have + * + * @param string $url The URL to request + * @param array $options + * @return bool + */ + protected function request($url, $options = array()) { + $murl = new moodle_url($url); + + if ($this->accesstoken) { + if ($this->use_http_get()) { + // If using HTTP GET add as a parameter. + $murl->param('access_token', $this->accesstoken->token); + } else { + $this->setHeader('Authorization: Bearer '.$this->accesstoken->token); + } + } + + return parent::request($murl->out(false), $options); + } + + /** + * Multiple HTTP Requests + * This function could run multi-requests in parallel. + * + * @param array $requests An array of files to request + * @param array $options An array of options to set + * @return array An array of results + */ + protected function multi($requests, $options = array()) { + if ($this->accesstoken) { + $this->setHeader('Authorization: Bearer '.$this->accesstoken->token); + } + return parent::multi($requests, $options); + } + + /** + * Returns the tokenname for the access_token to be stored + * through multiple requests. + * + * The default implentation is to use the classname combiend + * with the scope. + * + * @return string tokenname for prefernce storage + */ + protected function get_tokenname() { + // This is unusual but should work for most purposes. + return get_class($this).'-'.md5($this->scope); + } + + /** + * Store a token between requests. Currently uses + * session named by get_tokenname + * + * @param stdClass|null $token token object to store or null to clear + */ + protected function store_token($token) { + global $SESSION; + + $this->accesstoken = $token; + $name = $this->get_tokenname(); + + if ($token !== null) { + $SESSION->{$name} = $token; + } else { + unset($SESSION->{$name}); + } + } + + /** + * Retrieve a token stored. + * + * @return stdClass|null token object + */ + protected function get_stored_token() { + global $SESSION; + + $name = $this->get_tokenname(); + + if (isset($SESSION->{$name})) { + return $SESSION->{$name}; + } + + return null; + } + + /** + * Should HTTP GET be used instead of POST? + * Some APIs do not support POST and want oauth to use + * GET instead (with the auth_token passed as a GET param). + * + * @return bool true if GET should be used + */ + protected function use_http_get() { + return false; + } +} From 4560fd1b669ad65149d8ca19fac9f4210358bd11 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Mon, 14 May 2012 00:42:24 +0800 Subject: [PATCH 447/455] MDL-29857 - google apis: Convert to OAuth 2.0 Updated the various plugins to use OAuth 2.0 for authentication against google apis. Google are phasing out AuthSub and pushing OAuth as the replacement. This changes repository_googledocs, repository_picasa, portfolio_googledocs and portfolio_picasa The token for requests is now stored in session rather than a user prefence and it persists less but doesn't bother the user more than necessary. The google docs portfolio plugin is converted to use resumable upload API as this appears to be what Google have replaced this with. Unfortunately unlike authsub OAuth will require some setup by admins, this is linked as a docs page. --- lib/googleapi.php | 515 ++++++------------ .../lang/en/portfolio_googledocs.php | 4 +- portfolio/googledocs/lib.php | 128 ++--- portfolio/googledocs/version.php | 6 +- portfolio/picasa/lang/en/portfolio_picasa.php | 4 +- portfolio/picasa/lib.php | 112 ++-- portfolio/picasa/version.php | 6 +- .../googledocs/db/upgrade.php | 28 +- .../lang/en/repository_googledocs.php | 7 +- repository/googledocs/lib.php | 106 ++-- repository/googledocs/version.php | 6 +- .../picasa/db/upgrade.php | 26 +- .../picasa/lang/en/repository_picasa.php | 6 +- repository/picasa/lib.php | 96 ++-- repository/picasa/version.php | 6 +- 15 files changed, 428 insertions(+), 628 deletions(-) rename portfolio/picasa/db/events.php => repository/googledocs/db/upgrade.php (58%) rename portfolio/googledocs/db/events.php => repository/picasa/db/upgrade.php (58%) diff --git a/lib/googleapi.php b/lib/googleapi.php index 51292947113..5994dd382d8 100644 --- a/lib/googleapi.php +++ b/lib/googleapi.php @@ -1,276 +1,62 @@ . + /** - * Moodle - Modular Object-Oriented Dynamic Learning Environment - * http://moodle.org - * Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com + * Simple implementation of some Google API functions for Moodle. * - * This program 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 2 of the License, or - * (at your option) any later version. + * @package core + * @copyright Dan Poltawski + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir.'/filelib.php'); +require_once($CFG->libdir.'/oauthlib.php'); + +/** + * Class for manipulating google documents through the google data api. * - * This program 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 this program. If not, see . + * Docs for this can be found here: + * {@link http://code.google.com/apis/documents/docs/2.0/developers_guide_protocol.html} * * @package core * @subpackage lib * @copyright Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * - * Simple implementation of some Google API functions for Moodle. - */ - -defined('MOODLE_INTERNAL') || die(); - - /** Include essential file */ -require_once($CFG->libdir.'/filelib.php'); - -/** - * Base class for google authenticated http requests - * - * Most Google API Calls required that requests are sent with an - * Authorization header + token. This class extends the curl class - * to aid this - * - * @package moodlecore - * @subpackage lib - * @copyright Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -abstract class google_auth_request extends curl { - protected $token = ''; - private $persistantheaders = array(); - - // Must be overridden with the authorization header name - public static function get_auth_header_name() { - throw new coding_exception('get_auth_header_name() method needs to be overridden in each subclass of google_auth_request'); - } - - protected function request($url, $options = array()){ - if($this->token){ - // Adds authorisation head to a request so that it can be authentcated - $this->setHeader('Authorization: '. $this->get_auth_header_name().'"'.$this->token.'"'); - } - - foreach($this->persistantheaders as $h){ - $this->setHeader($h); - } - - $ret = parent::request($url, $options); - // reset headers for next request - $this->header = array(); - return $ret; - } - - protected function multi($requests, $options = array()) { - if($this->token){ - // Adds authorisation head to a request so that it can be authentcated - $this->setHeader('Authorization: '. $this->get_auth_header_name().'"'.$this->token.'"'); - } - - foreach($this->persistantheaders as $h){ - $this->setHeader($h); - } - - $ret = parent::multi($requests, $options); - // reset headers for next request - $this->header = array(); - return $ret; - } - - public function get_sessiontoken(){ - return $this->token; - } - - public function add_persistant_header($header){ - $this->persistantheaders[] = $header; - } -} - -/******* - * The following two classes are usd to implement AuthSub google - * authtentication, as documented here: - * http://code.google.com/apis/accounts/docs/AuthSub.html - *******/ - -/** - * Used to uprade a google AuthSubRequest one-time token into - * a session token which can be used long term. - * - * @package moodlecore - * @subpackage lib - * @copyright Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class google_authsub_request extends google_auth_request { - const AUTHSESSION_URL = 'https://www.google.com/accounts/AuthSubSessionToken'; - - /** - * Constructor. Calls constructor of its parents - * - * @param string $authtoken The token to upgrade to a session token - */ - public function __construct($authtoken){ - parent::__construct(); - $this->token = $authtoken; - } - - /** - * Requests a long-term session token from google based on the - * - * @return string Sub-Auth token - */ - public function get_session_token(){ - $content = $this->get(google_authsub_request::AUTHSESSION_URL); - - if( preg_match('/token=(.*)/i', $content, $matches) ){ - return $matches[1]; - }else{ - throw new moodle_exception('could not upgrade google authtoken to session token'); - } - } - - public static function get_auth_header_name(){ - return 'AuthSub token='; - } -} - -/** - * Allows http calls using google subauth authorisation - * - * @package moodlecore - * @subpackage lib - * @copyright Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class google_authsub extends google_auth_request { - const LOGINAUTH_URL = 'https://www.google.com/accounts/AuthSubRequest'; - const VERIFY_TOKEN_URL = 'https://www.google.com/accounts/AuthSubTokenInfo'; - const REVOKE_TOKEN_URL = 'https://www.google.com/accounts/AuthSubRevokeToken'; - - /** - * Constructor, allows subauth requests using the response from an initial - * AuthSubRequest or with the subauth long-term token. Note that constructing - * this object without a valid token will cause an exception to be thrown. - * - * @param string $sessiontoken A long-term subauth session token - * @param string $authtoken A one-time auth token wich is used to upgrade to session token - * @param mixed @options Options to pass to the base curl object - */ - public function __construct($sessiontoken = '', $authtoken = '', $options = array()){ - parent::__construct($options); - - if( $authtoken ){ - $gauth = new google_authsub_request($authtoken); - $sessiontoken = $gauth->get_session_token(); - } - - $this->token = $sessiontoken; - if(! $this->valid_token() ){ - throw new moodle_exception('Invalid subauth token'); - } - } - - /** - * Tests if a subauth token used is valid - * - * @return boolean true if token valid - */ - public function valid_token(){ - $this->get(google_authsub::VERIFY_TOKEN_URL); - - if($this->info['http_code'] === 200){ - return true; - }else{ - return false; - } - } - - /** - * Calls googles api to revoke the subauth token - * - * @return boolean Returns true if token succesfully revoked - */ - public function revoke_session_token(){ - $this->get(google_authsub::REVOKE_TOKEN_URL); - - if($this->info['http_code'] === 200){ - $this->token = ''; - return true; - }else{ - return false; - } - } - - /** - * Creates a login url for subauth request - * - * @param string $returnaddr The address which the user should be redirected to recieve the token - * @param string $realm The google realm which is access is being requested - * @return string URL to bounce the user to - */ - public static function login_url($returnaddr, $realm){ - $uri = google_authsub::LOGINAUTH_URL.'?next=' - .urlencode($returnaddr) - .'&scope=' - .urlencode($realm) - .'&session=1&secure=0'; - - return $uri; - } - - public static function get_auth_header_name(){ - return 'AuthSub token='; - } -} - -/** - * Class for manipulating google documents through the google data api - * Docs for this can be found here: - * {@link http://code.google.com/apis/documents/docs/2.0/developers_guide_protocol.html} - * - * @package moodlecore - * @subpackage lib - * @copyright Dan Poltawski - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class google_docs { - // need both docs and the spreadsheets realm + /** @var string Realm for authentication, need both docs and spreadsheet realm */ const REALM = 'https://docs.google.com/feeds/ https://spreadsheets.google.com/feeds/ https://docs.googleusercontent.com/'; + /** @var string Document list url */ const DOCUMENTFEED_URL = 'https://docs.google.com/feeds/default/private/full'; - const USER_PREF_NAME = 'google_authsub_sesskey'; + /** @var string Upload url */ + const UPLOAD_URL = 'https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false'; - private $google_curl = null; + /** @var google_oauth oauth curl class for making authenticated requests */ + private $googleoauth = null; /** * Constructor. * - * @param object A google_auth_request object which can be used to do http requests + * @param google_oauth $googleoauth oauth curl class for making authenticated requests */ - public function __construct($google_curl){ - if(is_a($google_curl, 'google_auth_request')){ - $this->google_curl = $google_curl; - $this->google_curl->add_persistant_header('GData-Version: 3.0'); - }else{ - throw new moodle_exception('Google Curl Request object not given'); - } - } - - public static function get_sesskey($userid){ - return get_user_preferences(google_docs::USER_PREF_NAME, false, $userid); - } - - public static function set_sesskey($value, $userid){ - return set_user_preference(google_docs::USER_PREF_NAME, $value, $userid); - } - - public static function delete_sesskey($userid){ - return unset_user_preference(google_docs::USER_PREF_NAME, $userid); + public function __construct(google_oauth $googleoauth) { + $this->googleoauth = $googleoauth; + $this->googleoauth->setHeader('GData-Version: 3.0'); } /** @@ -279,21 +65,19 @@ class google_docs { * @param string $search A search string to do full text search on the documents * @return mixed Array of files formated for fileapoi */ - #FIXME - public function get_file_list($search = ''){ + public function get_file_list($search = '') { global $CFG, $OUTPUT; - $url = google_docs::DOCUMENTFEED_URL; + $url = self::DOCUMENTFEED_URL; - if($search){ + if ($search) { $url.='?q='.urlencode($search); } - $content = $this->google_curl->get($url); + $content = $this->googleoauth->get($url); $xml = new SimpleXMLElement($content); - $files = array(); - foreach($xml->entry as $gdoc){ + foreach ($xml->entry as $gdoc) { $docid = (string) $gdoc->children('http://schemas.google.com/g/2005')->resourceId; list($type, $docid) = explode(':', $docid); @@ -325,7 +109,7 @@ class google_docs { break; } - if(!empty($source)){ + if (!empty($source)) { $files[] = array( 'title' => $title, 'url' => "{$gdoc->link[0]->attributes()->href}", 'source' => $source, @@ -344,71 +128,98 @@ class google_docs { * @param object $file File object * @return boolean True on success */ - public function send_file($file){ - $this->google_curl->setHeader("Content-Length: ". $file->get_filesize()); - $this->google_curl->setHeader("Content-Type: ". $file->get_mimetype()); - $this->google_curl->setHeader("Slug: ". $file->get_filename()); + public function send_file($file) { + // First we create the 'resumable upload request'. + $this->googleoauth->setHeader("Content-Length: 0"); + $this->googleoauth->setHeader("X-Upload-Content-Length: ". $file->get_filesize()); + $this->googleoauth->setHeader("X-Upload-Content-Type: ". $file->get_mimetype()); + $this->googleoauth->setHeader("Slug: ". $file->get_filename()); + $this->googleoauth->post(self::UPLOAD_URL); - $this->google_curl->post(google_docs::DOCUMENTFEED_URL, $file->get_content()); + if ($this->googleoauth->info['http_code'] !== 200) { + throw new moodle_exception('Cantpostupload'); + } - if($this->google_curl->info['http_code'] === 201){ + // Now we http PUT the file in the location returned. + $location = $this->googleoauth->response['Location']; + if (empty($location)) { + throw new moodle_exception('Nouploadlocation'); + } + + // Reset the curl object for actually sending the file. + $this->googleoauth->clear_headers(); + $this->googleoauth->setHeader("Content-Length: ". $file->get_filesize()); + $this->googleoauth->setHeader("Content-Type: ". $file->get_mimetype()); + + // We can't get a filepointer, so have to copy the file.. + $tmproot = make_temp_directory('googledocsuploads'); + $tmpfilepath = $tmproot.'/'.$file->get_contenthash(); + $file->copy_content_to($tmpfilepath); + + // HTTP PUT the file. + $this->googleoauth->put($location, array('file'=>$tmpfilepath)); + + // Remove the temporary file we created.. + unlink($tmpfilepath); + + if ($this->googleoauth->info['http_code'] === 201) { return true; - }else{ + } else { return false; } } - public function download_file($url, $fp){ - return $this->google_curl->download(array( array('url'=>$url, 'file' => $fp) )); + /** + * Downloads a file using authentication + * + * @param string $url url of file + * @param string $path path to save file to + * @return array stucture for repository download_file + */ + public function download_file($url, $path) { + $content = $this->googleoauth->get($url); + file_put_contents($path, $content); + return array('path'=>$path, 'url'=>$url); } } /** - * Class for manipulating picasa through the google data api + * Class for manipulating picasa through the google data api. + * * Docs for this can be found here: * {@link http://code.google.com/apis/picasaweb/developers_guide_protocol.html} * - * @package moodlecore - * @subpackage lib + * @package core * @copyright Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class google_picasa { + /** @var string Realm for authentication */ const REALM = 'http://picasaweb.google.com/data/'; - const USER_PREF_NAME = 'google_authsub_sesskey_picasa'; + /** @var string Upload url */ const UPLOAD_LOCATION = 'https://picasaweb.google.com/data/feed/api/user/default/albumid/default'; + /** @var string photo list url */ const ALBUM_PHOTO_LIST = 'https://picasaweb.google.com/data/feed/api/user/default/albumid/'; + /** @var string search url */ const PHOTO_SEARCH_URL = 'https://picasaweb.google.com/data/feed/api/user/default?kind=photo&q='; + /** @var string album list url */ const LIST_ALBUMS_URL = 'https://picasaweb.google.com/data/feed/api/user/default'; + /** @var string manage files url */ const MANAGE_URL = 'http://picasaweb.google.com/'; - private $google_curl = null; + /** @var google_oauth oauth curl class for making authenticated requests */ + private $googleoauth = null; + /** @var string Last album name retrievied */ private $lastalbumname = null; /** * Constructor. * - * @param object A google_auth_request object which can be used to do http requests + * @param google_oauth $googleoauth oauth curl class for making authenticated requests */ - public function __construct($google_curl){ - if(is_a($google_curl, 'google_auth_request')){ - $this->google_curl = $google_curl; - $this->google_curl->add_persistant_header('GData-Version: 2'); - }else{ - throw new moodle_exception('Google Curl Request object not given'); - } - } - - public static function get_sesskey($userid){ - return get_user_preferences(google_picasa::USER_PREF_NAME, false, $userid); - } - - public static function set_sesskey($value, $userid){ - return set_user_preference(google_picasa::USER_PREF_NAME, $value, $userid); - } - - public static function delete_sesskey($userid){ - return unset_user_preference(google_picasa::USER_PREF_NAME, $userid); + public function __construct(google_oauth $googleoauth) { + $this->googleoauth = $googleoauth; + $this->googleoauth->setHeader('GData-Version: 2'); } /** @@ -417,16 +228,16 @@ class google_picasa { * @param object $file File object * @return boolean True on success */ - public function send_file($file){ - $this->google_curl->setHeader("Content-Length: ". $file->get_filesize()); - $this->google_curl->setHeader("Content-Type: ". $file->get_mimetype()); - $this->google_curl->setHeader("Slug: ". $file->get_filename()); + public function send_file($file) { + $this->googleoauth->setHeader("Content-Length: ". $file->get_filesize()); + $this->googleoauth->setHeader("Content-Type: ". $file->get_mimetype()); + $this->googleoauth->setHeader("Slug: ". $file->get_filename()); - $this->google_curl->post(google_picasa::UPLOAD_LOCATION, $file->get_content()); + $this->googleoauth->post(self::UPLOAD_LOCATION, $file->get_content()); - if($this->google_curl->info['http_code'] === 201){ + if ($this->googleoauth->info['http_code'] === 201) { return true; - }else{ + } else { return false; } } @@ -439,10 +250,10 @@ class google_picasa { * @param string $path The path to files (assumed to be albumid) * @return mixed $files A list of files for the file picker */ - public function get_file_list($path = ''){ - if(!$path){ + public function get_file_list($path = '') { + if (!$path) { return $this->get_albums(); - }else{ + } else { return $this->get_album_photos($path); } } @@ -453,8 +264,8 @@ class google_picasa { * @param int $albumid Photo album to list photos from * @return mixed $files A list of files for the file picker */ - public function get_album_photos($albumid){ - $albumcontent = $this->google_curl->get(google_picasa::ALBUM_PHOTO_LIST.$albumid); + public function get_album_photos($albumid) { + $albumcontent = $this->googleoauth->get(self::ALBUM_PHOTO_LIST.$albumid); return $this->get_photo_details($albumcontent); } @@ -475,8 +286,8 @@ class google_picasa { * @param string $query Search terms * @return mixed $files A list of files for the file picker */ - public function do_photo_search($query){ - $content = $this->google_curl->get(google_picasa::PHOTO_SEARCH_URL.htmlentities($query)); + public function do_photo_search($query) { + $content = $this->googleoauth->get(self::PHOTO_SEARCH_URL.htmlentities($query)); return $this->get_photo_details($content); } @@ -487,17 +298,17 @@ class google_picasa { * * @return mixes $files Array in the format get_listing uses for folders */ - public function get_albums(){ - $content = $this->google_curl->get(google_picasa::LIST_ALBUMS_URL); + public function get_albums() { + $content = $this->googleoauth->get(self::LIST_ALBUMS_URL); $xml = new SimpleXMLElement($content); $files = array(); - foreach($xml->entry as $album){ + foreach ($xml->entry as $album) { $gphoto = $album->children('http://schemas.google.com/photos/2007'); $mediainfo = $album->children('http://search.yahoo.com/mrss/'); - //hacky... + // Hacky... $thumbnailinfo = $mediainfo->group->thumbnail[0]->attributes(); $files[] = array( 'title' => (string) $album->title, @@ -505,7 +316,7 @@ class google_picasa { 'size' => (int) $gphoto->bytesUsed, 'path' => (string) $gphoto->id, 'thumbnail' => (string) $thumbnailinfo['url'], - 'thumbnail_width' => 160, // 160 is the native maximum dimension + 'thumbnail_width' => 160, // 160 is the native maximum dimension. 'thumbnail_height' => 160, 'children' => array(), ); @@ -522,22 +333,22 @@ class google_picasa { * @param string $rawxml XML from picasa api * @return mixed $files A list of files for the file picker */ - public function get_photo_details($rawxml){ + public function get_photo_details($rawxml) { $xml = new SimpleXMLElement($rawxml); $this->lastalbumname = (string)$xml->title; $files = array(); - foreach($xml->entry as $photo){ + foreach ($xml->entry as $photo) { $gphoto = $photo->children('http://schemas.google.com/photos/2007'); $mediainfo = $photo->children('http://search.yahoo.com/mrss/'); $fullinfo = $mediainfo->group->content->attributes(); - //hacky... + // Hacky... $thumbnailinfo = $mediainfo->group->thumbnail[0]->attributes(); - // Derive the nicest file name we can + // Derive the nicest file name we can. if (!empty($mediainfo->group->description)) { $title = shorten_text((string)$mediainfo->group->description, 20, false, ''); $title = clean_filename($title).'.jpg'; @@ -551,7 +362,7 @@ class google_picasa { 'size' => (int) $gphoto->size, 'path' => $gphoto->albumid.'/'.$gphoto->id, 'thumbnail' => (string) $thumbnailinfo['url'], - 'thumbnail_width' => 72, // 72 is the native maximum dimension + 'thumbnail_width' => 72, // 72 is the native maximum dimension. 'thumbnail_height' => 72, 'source' => (string) $fullinfo['url'], 'url' => (string) $fullinfo['url'] @@ -560,54 +371,36 @@ class google_picasa { return $files; } - } /** - * Beginings of an implementation of Clientogin authenticaton for google - * accounts as documented here: - * {@link http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html#ClientLogin} + * OAuth 2.0 client for Google Services * - * With this authentication we have to accept a username and password and to post - * it to google. Retrieving a token for use afterwards. - * - * @package moodlecore - * @subpackage lib - * @copyright Dan Poltawski + * @package core + * @copyright 2012 Dan Poltawski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class google_authclient extends google_auth_request { - const LOGIN_URL = 'https://www.google.com/accounts/ClientLogin'; - - public function __construct($sessiontoken = '', $username = '', $password = '', $options = array() ){ - parent::__construct($options); - - if($username and $password){ - $param = array( - 'accountType'=>'GOOGLE', - 'Email'=>$username, - 'Passwd'=>$password, - 'service'=>'writely' - ); - - $content = $this->post(google_authclient::LOGIN_URL, $param); - - if( preg_match('/auth=(.*)/i', $content, $matches) ){ - $sessiontoken = $matches[1]; - }else{ - throw new moodle_exception('could not upgrade authtoken'); - } - - } - - if($sessiontoken){ - $this->token = $sessiontoken; - }else{ - throw new moodle_exception('no session token specified'); - } +class google_oauth extends oauth2_client { + /** + * Returns the auth url for OAuth 2.0 request + * @return string the auth url + */ + protected function auth_url() { + return 'https://accounts.google.com/o/oauth2/auth'; } - public static function get_auth_header_name(){ - return 'GoogleLogin auth='; + /** + * Returns the token url for OAuth 2.0 request + * @return string the auth url + */ + protected function token_url() { + return 'https://accounts.google.com/o/oauth2/token'; + } + + /** + * Clear any headers in the curl object + */ + public function clear_headers() { + $this->header = array(); } } diff --git a/portfolio/googledocs/lang/en/portfolio_googledocs.php b/portfolio/googledocs/lang/en/portfolio_googledocs.php index f1c9262f823..0fb864dac40 100644 --- a/portfolio/googledocs/lang/en/portfolio_googledocs.php +++ b/portfolio/googledocs/lang/en/portfolio_googledocs.php @@ -1,5 +1,4 @@ To use the google docs portfolio you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; $string['noauthtoken'] = 'An authentication token has not been recieved from google. Please ensure you are allowing moodle to access your google account'; $string['nosessiontoken'] = 'A session token does not exist preventing export to google.'; $string['pluginname'] = 'Google Docs'; $string['sendfailed'] = 'The file {$a} failed to transfer to google'; +$string['secret'] = 'Secret'; diff --git a/portfolio/googledocs/lib.php b/portfolio/googledocs/lib.php index 2223f9d4831..c641f096df1 100644 --- a/portfolio/googledocs/lib.php +++ b/portfolio/googledocs/lib.php @@ -1,4 +1,19 @@ . + /** * Google Documents Portfolio Plugin * @@ -9,18 +24,10 @@ require_once($CFG->libdir.'/portfolio/plugin.php'); require_once($CFG->libdir.'/googleapi.php'); class portfolio_plugin_googledocs extends portfolio_plugin_push_base { - private $sessiontoken; + private $googleoauth = null; public function supported_formats() { - return array( - PORTFOLIO_FORMAT_PLAINHTML, - PORTFOLIO_FORMAT_IMAGE, - PORTFOLIO_FORMAT_TEXT, - PORTFOLIO_FORMAT_PDF, - PORTFOLIO_FORMAT_DOCUMENT, - PORTFOLIO_FORMAT_PRESENTATION, - PORTFOLIO_FORMAT_SPREADSHEET - ); + return array(PORTFOLIO_FORMAT_FILE); } public static function get_name() { @@ -28,29 +35,27 @@ class portfolio_plugin_googledocs extends portfolio_plugin_push_base { } public function prepare_package() { - // we send the files as they are, no prep required + // We send the files as they are, no prep required. return true; } - public function get_interactive_continue_url(){ + public function get_interactive_continue_url() { return 'http://docs.google.com/'; } public function expected_time($callertime) { - // we trust what the portfolio says + // We trust what the portfolio says. return $callertime; } public function send_package() { - - if(!$this->sessiontoken){ - throw new portfolio_plugin_exception('nosessiontoken', 'portfolio_googledocs'); + if (!$this->googleoauth) { + throw new portfolio_plugin_exception('noauthtoken', 'portfolio_googledocs'); } - $gdocs = new google_docs(new google_authsub($this->sessiontoken)); - + $gdocs = new google_docs($this->googleoauth); foreach ($this->exporter->get_tempfiles() as $file) { - if(!$gdocs->send_file($file)){ + if (!$gdocs->send_file($file)) { throw new portfolio_plugin_exception('sendfailed', 'portfolio_gdocs', $file->get_filename()); } } @@ -62,20 +67,12 @@ class portfolio_plugin_googledocs extends portfolio_plugin_push_base { return false; } - $sesskey = google_docs::get_sesskey($this->get('user')->id); - - if($sesskey){ - try{ - $gauth = new google_authsub($sesskey); - $this->sessiontoken = $sesskey; - return false; - }catch(Exception $e){ - // sesskey is not valid, delete store and re-auth - google_docs::delete_sesskey($this->get('user')->id); - } + $this->initialize_oauth(); + if ($this->googleoauth->is_logged_in()) { + return false; + } else { + return $this->googleoauth->get_login_url(); } - - return google_authsub::login_url($CFG->wwwroot.'/portfolio/add.php?postcontrol=1&id=' . $this->exporter->get('id') . '&sesskey=' . sesskey(), google_docs::REALM); } public function post_control($stage, $params) { @@ -83,43 +80,50 @@ class portfolio_plugin_googledocs extends portfolio_plugin_push_base { return; } - if(!array_key_exists('token', $params)){ - throw new portfolio_plugin_exception('noauthtoken', 'portfolio_googledocs'); + $this->initialize_oauth(); + if ($this->googleoauth->is_logged_in()) { + return false; + } else { + return $this->googleoauth->get_login_url(); } - - // we now have our auth token, get a session token.. - $gauth = new google_authsub(false, $params['token']); - $this->sessiontoken = $gauth->get_sessiontoken(); - - google_docs::set_sesskey($this->sessiontoken, $this->get('user')->id); } public static function allows_multiple_instances() { return false; } -} -/** - * Registers to the user_deleted event to revoke any - * subauth tokens we have from them - * - * @param $user user object - * @return boolean true in all cases as its only minor cleanup - */ -function portfolio_googledocs_user_deleted($user){ - // it is only by luck that the user prefstill exists now? - // We probably need a pre-delete event? - if($sesskey = google_docs::get_sesskey($user->id)){ - try{ - $gauth = new google_authsub($sesskey); - - $gauth->revoke_session_token(); - }catch(Exception $e){ - // we don't care that much about success- just being good - // google api citzens - return true; - } + public static function has_admin_config() { + return true; } - return true; + public static function get_allowed_config() { + return array('clientid', 'secret'); + } + + public function admin_config_form(&$mform) { + $a = new stdClass; + $a->docsurl = get_docs_url('Google_OAuth2_Setup'); + $a->callbackurl = google_oauth::callback_url()->out(false); + + $mform->addElement('static', null, '', get_string('oauthinfo', 'portfolio_googledocs', $a)); + + $mform->addElement('text', 'clientid', get_string('clientid', 'portfolio_googledocs')); + $mform->addElement('text', 'secret', get_string('secret', 'portfolio_googledocs')); + + $strrequired = get_string('required'); + $mform->addRule('clientid', $strrequired, 'required', null, 'client'); + $mform->addRule('secret', $strrequired, 'required', null, 'client'); + } + + private function initialize_oauth() { + $returnurl = new moodle_url('/portfolio/add.php'); + $returnurl->param('postcontrol', 1); + $returnurl->param('id', $this->exporter->get('id')); + $returnurl->param('sesskey', sesskey()); + + $clientid = $this->get_config('clientid'); + $secret = $this->get_config('secret'); + + $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_docs::REALM); + } } diff --git a/portfolio/googledocs/version.php b/portfolio/googledocs/version.php index 20446664e67..a64c628b0b5 100644 --- a/portfolio/googledocs/version.php +++ b/portfolio/googledocs/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011112900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2011112900; // Requires this Moodle version -$plugin->component = 'portfolio_googledocs'; // Full name of the plugin (used for diagnostics) +$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2012051100; // Requires this Moodle version. +$plugin->component = 'portfolio_googledocs'; // Full name of the plugin (used for diagnostics). $plugin->cron = 0; diff --git a/portfolio/picasa/lang/en/portfolio_picasa.php b/portfolio/picasa/lang/en/portfolio_picasa.php index fec154b9391..10c12e66152 100644 --- a/portfolio/picasa/lang/en/portfolio_picasa.php +++ b/portfolio/picasa/lang/en/portfolio_picasa.php @@ -1,5 +1,4 @@ To use the Picasa portfolio you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; $string['noauthtoken'] = 'An authentication token has not been recieved from google. Please ensure you are allowing moodle to access your google account'; $string['pluginname'] = 'Picasa'; $string['sendfailed'] = 'The file {$a} failed to transfer to picasa'; +$string['secret'] = 'Secret'; diff --git a/portfolio/picasa/lib.php b/portfolio/picasa/lib.php index a9ba23fd886..6d21336214b 100644 --- a/portfolio/picasa/lib.php +++ b/portfolio/picasa/lib.php @@ -1,4 +1,19 @@ . + /** * Picasa Portfolio Plugin * @@ -9,7 +24,7 @@ require_once($CFG->libdir.'/portfolio/plugin.php'); require_once($CFG->libdir.'/googleapi.php'); class portfolio_plugin_picasa extends portfolio_plugin_push_base { - private $sessionkey; + private $googleoauth = null; public function supported_formats() { return array(PORTFOLIO_FORMAT_IMAGE, PORTFOLIO_FORMAT_VIDEO); @@ -20,11 +35,11 @@ class portfolio_plugin_picasa extends portfolio_plugin_push_base { } public function prepare_package() { - // we send the files as they are, no prep required + // We send the files as they are, no prep required. return true; } - public function get_interactive_continue_url(){ + public function get_interactive_continue_url() { return 'http://picasaweb.google.com/'; } @@ -33,40 +48,31 @@ class portfolio_plugin_picasa extends portfolio_plugin_push_base { } public function send_package() { - if(!$this->sessionkey){ + if (!$this->googleoauth) { throw new portfolio_plugin_exception('noauthtoken', 'portfolio_picasa'); } - $picasa = new google_picasa(new google_authsub($this->sessionkey)); - + $picasa = new google_picasa($this->googleoauth); foreach ($this->exporter->get_tempfiles() as $file) { - if(!$picasa->send_file($file)){ + if (!$picasa->send_file($file)) { throw new portfolio_plugin_exception('sendfailed', 'portfolio_picasa', $file->get_filename()); } } } public function steal_control($stage) { - global $CFG; if ($stage != PORTFOLIO_STAGE_CONFIG) { return false; } - $sesskey = google_picasa::get_sesskey($this->get('user')->id); + $this->initialize_oauth(); - if($sesskey){ - try{ - $gauth = new google_authsub($sesskey); - $this->sessionkey = $sesskey; - return false; - }catch(Exception $e){ - // sesskey is not valid, delete store and re-auth - google_picasa::delete_sesskey($this->get('user')->id); - } + if ($this->googleoauth->is_logged_in()) { + return false; + } else { + return $this->googleoauth->get_login_url(); } - - return google_authsub::login_url($CFG->wwwroot.'/portfolio/add.php?postcontrol=1&id=' . $this->exporter->get('id') . '&sesskey=' . sesskey(), google_picasa::REALM); } public function post_control($stage, $params) { @@ -74,44 +80,50 @@ class portfolio_plugin_picasa extends portfolio_plugin_push_base { return; } - if(!array_key_exists('token', $params)){ - throw new portfolio_plugin_exception('noauthtoken', 'portfolio_picasa'); + $this->initialize_oauth(); + if ($this->googleoauth->is_logged_in()) { + return false; + } else { + return $this->googleoauth->get_login_url(); } + } - // we now have our auth token, get a session token.. - $gauth = new google_authsub(false, $params['token']); - - $this->sessionkey = $gauth->get_sessiontoken(); - - google_picasa::set_sesskey($this->sessionkey, $this->get('user')->id); + public static function has_admin_config() { + return true; } public static function allows_multiple_instances() { return false; } -} -/** - * Registers to the user_deleted event to revoke any - * subauth tokens we have from them - * - * @param $user user object - * @return boolean true in all cases as its only minor cleanup - */ -function portfolio_picasa_user_deleted($user){ - // it is only by luck that the user prefstill exists now? - // We probably need a pre-delete event? - if($sesskey = google_picasa::get_sesskey($user->id)){ - try{ - $gauth = new google_authsub($sesskey); - - $gauth->revoke_session_token(); - }catch(Exception $e){ - // we don't care that much about success- just being good - // google api citzens - return true; - } + public static function get_allowed_config() { + return array('clientid', 'secret'); } - return true; + public function admin_config_form(&$mform) { + $a = new stdClass; + $a->docsurl = get_docs_url('Google_OAuth2_Setup'); + $a->callbackurl = google_oauth::callback_url()->out(false); + + $mform->addElement('static', null, '', get_string('oauthinfo', 'portfolio_picasa', $a)); + + $mform->addElement('text', 'clientid', get_string('clientid', 'portfolio_picasa')); + $mform->addElement('text', 'secret', get_string('secret', 'portfolio_picasa')); + + $strrequired = get_string('required'); + $mform->addRule('clientid', $strrequired, 'required', null, 'client'); + $mform->addRule('secret', $strrequired, 'required', null, 'client'); + } + + private function initialize_oauth() { + $returnurl = new moodle_url('/portfolio/add.php'); + $returnurl->param('postcontrol', 1); + $returnurl->param('id', $this->exporter->get('id')); + $returnurl->param('sesskey', sesskey()); + + $clientid = $this->get_config('clientid'); + $secret = $this->get_config('secret'); + + $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_picasa::REALM); + } } diff --git a/portfolio/picasa/version.php b/portfolio/picasa/version.php index 7906a251af3..113c9cf9e0d 100644 --- a/portfolio/picasa/version.php +++ b/portfolio/picasa/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011112900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2011112900; // Requires this Moodle version -$plugin->component = 'portfolio_picasa'; // Full name of the plugin (used for diagnostics) +$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2012051100; // Requires this Moodle version. +$plugin->component = 'portfolio_picasa'; // Full name of the plugin (used for diagnostics). $plugin->cron = 0; diff --git a/portfolio/picasa/db/events.php b/repository/googledocs/db/upgrade.php similarity index 58% rename from portfolio/picasa/db/events.php rename to repository/googledocs/db/upgrade.php index 09ef7cca20c..76876a19ba2 100644 --- a/portfolio/picasa/db/events.php +++ b/repository/googledocs/db/upgrade.php @@ -15,19 +15,19 @@ // along with Moodle. If not, see . /** - * Add event handlers for the picasa portfolio. - * - * @package portfolio_picasa - * @category event - * @copyright 2009 Penny Leach - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @param int $oldversion the version we are upgrading from + * @return bool result */ +function xmldb_repository_googledocs_upgrade($oldversion) { + global $CFG, $DB; -$handlers = array ( - 'user_deleted' => array ( - 'handlerfile' => '/portfolio/picasa/lib.php', - 'handlerfunction' => 'portfolio_picasa_user_deleted', - 'schedule' => 'cron', - 'internal' => 0, - ), -); \ No newline at end of file + $dbman = $DB->get_manager(); + + if ($oldversion < 2012051400) { + // Delete old user preferences containing authsub tokens. + $DB->delete_records('user_preferences', array('name' => 'google_authsub_sesskey')); + upgrade_plugin_savepoint(true, 2012051400, 'repository', 'googledocs'); + } + + return true; +} diff --git a/repository/googledocs/lang/en/repository_googledocs.php b/repository/googledocs/lang/en/repository_googledocs.php index 38f1436b27a..8e8cf8034e1 100644 --- a/repository/googledocs/lang/en/repository_googledocs.php +++ b/repository/googledocs/lang/en/repository_googledocs.php @@ -1,5 +1,4 @@ To use the Google Docs repository you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; $string['pluginname'] = 'Google Docs'; -$string['configplugin'] = 'Configurate Google Docs plugin'; +$string['secret'] = 'Secret'; + diff --git a/repository/googledocs/lib.php b/repository/googledocs/lib.php index 36648bdb81e..6ccb33bc436 100644 --- a/repository/googledocs/lib.php +++ b/repository/googledocs/lib.php @@ -34,55 +34,40 @@ require_once($CFG->libdir.'/googleapi.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_googledocs extends repository { - private $subauthtoken = ''; + private $googleoauth = null; public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { - global $USER; parent::__construct($repositoryid, $context, $options); - // TODO: I wish there was somewhere we could explicitly put this outside of constructor.. - $googletoken = optional_param('token', false, PARAM_RAW); - if($googletoken){ - $gauth = new google_authsub(false, $googletoken); // will throw exception if fails - google_docs::set_sesskey($gauth->get_sessiontoken(), $USER->id); - } + $returnurl = new moodle_url('/repository/repository_callback.php', + array('callback' => 'yes', 'repo_id' =>$this->id)); + + $clientid = get_config('googledocs', 'clientid'); + $secret = get_config('googledocs', 'secret'); + $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_docs::REALM); + $this->check_login(); } public function check_login() { - global $USER; - - $sesskey = google_docs::get_sesskey($USER->id); - - if($sesskey){ - try{ - $gauth = new google_authsub($sesskey); - $this->subauthtoken = $sesskey; - return true; - }catch(Exception $e){ - // sesskey is not valid, delete store and re-auth - google_docs::delete_sesskey($USER->id); - } - } - - return false; + return $this->googleoauth->is_logged_in(); } - public function print_login($ajax = true){ - global $CFG; - if($ajax){ - $ret = array(); - $popup_btn = new stdClass(); - $popup_btn->type = 'popup'; - $returnurl = $CFG->wwwroot.'/repository/repository_callback.php?callback=yes&repo_id='.$this->id; - $popup_btn->url = google_authsub::login_url($returnurl, google_docs::REALM); - $ret['login'] = array($popup_btn); - return $ret; + public function print_login() { + $url = $this->googleoauth->get_login_url(); + + if ($this->options['ajax']) { + $popup = new stdClass(); + $popup->type = 'popup'; + $popup->url = $url->out(false); + return array('login' => array($popup)); + } else { + echo ''.get_string('login', 'repository').''; } } public function get_listing($path='', $page = '') { - $gdocs = new google_docs(new google_authsub($this->subauthtoken)); + $gdocs = new google_docs($this->googleoauth); $ret = array(); $ret['dynload'] = true; @@ -91,7 +76,7 @@ class repository_googledocs extends repository { } public function search($search_text, $page = 0) { - $gdocs = new google_docs(new google_authsub($this->subauthtoken)); + $gdocs = new google_docs($this->googleoauth); $ret = array(); $ret['dynload'] = true; @@ -99,37 +84,44 @@ class repository_googledocs extends repository { return $ret; } - public function logout(){ - global $USER; - - $token = google_docs::get_sesskey($USER->id); - - $gauth = new google_authsub($token); - // revoke token from google - $gauth->revoke_session_token(); - - google_docs::delete_sesskey($USER->id); - $this->subauthtoken = ''; - + public function logout() { + $this->googleoauth->log_out(); return parent::logout(); } public function get_file($url, $file = '') { - global $CFG; + $gdocs = new google_docs($this->googleoauth); + $path = $this->prepare_file($file); - - $fp = fopen($path, 'w'); - $gdocs = new google_docs(new google_authsub($this->subauthtoken)); - $gdocs->download_file($url, $fp); - - return array('path'=>$path, 'url'=>$url); + return $gdocs->download_file($url, $path); } public function supported_filetypes() { - return array('document'); + return '*'; } public function supported_returntypes() { return FILE_INTERNAL; } + + public static function get_type_option_names() { + return array('clientid', 'secret', 'pluginname'); + } + + public static function type_config_form($mform, $classname = 'repository') { + + $a = new stdClass; + $a->docsurl = get_docs_url('Google_OAuth2_Setup'); + $a->callbackurl = google_oauth::callback_url()->out(false); + + $mform->addElement('static', null, '', get_string('oauthinfo', 'repository_googledocs', $a)); + + parent::type_config_form($mform); + $mform->addElement('text', 'clientid', get_string('clientid', 'repository_googledocs')); + $mform->addElement('text', 'secret', get_string('secret', 'repository_googledocs')); + + $strrequired = get_string('required'); + $mform->addRule('clientid', $strrequired, 'required', null, 'client'); + $mform->addRule('secret', $strrequired, 'required', null, 'client'); + } } -//Icon from: http://www.iconspedia.com/icon/google-2706.html +// Icon from: http://www.iconspedia.com/icon/google-2706.html. diff --git a/repository/googledocs/version.php b/repository/googledocs/version.php index 79c6db7ff39..7269aa52195 100644 --- a/repository/googledocs/version.php +++ b/repository/googledocs/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011112900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2011112900; // Requires this Moodle version -$plugin->component = 'repository_googledocs'; // Full name of the plugin (used for diagnostics) +$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2012051100; // Requires this Moodle version. +$plugin->component = 'repository_googledocs'; // Full name of the plugin (used for diagnostics). diff --git a/portfolio/googledocs/db/events.php b/repository/picasa/db/upgrade.php similarity index 58% rename from portfolio/googledocs/db/events.php rename to repository/picasa/db/upgrade.php index b0d3d0c702f..545ce3b4fa5 100644 --- a/portfolio/googledocs/db/events.php +++ b/repository/picasa/db/upgrade.php @@ -15,21 +15,19 @@ // along with Moodle. If not, see . /** - * Add event handlers for the googledocs portfolio. - * - * @package portfolio_googledocs - * @category event - * @copyright 2009 Penny Leach - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @param int $oldversion the version we are upgrading from + * @return bool result */ +function xmldb_repository_picasa_upgrade($oldversion) { + global $CFG, $DB; -$handlers = array ( - 'user_deleted' => array ( - 'handlerfile' => '/portfolio/googledocs/lib.php', - 'handlerfunction' => 'portfolio_googledocs_user_deleted', - 'schedule' => 'cron', - 'internal' => 0, - ), -); + $dbman = $DB->get_manager(); + if ($oldversion < 2012051400) { + // Delete old user preferences storing authsub tokens. + $DB->delete_records('user_preferences', array('name' => 'google_authsub_sesskey_picasa')); + upgrade_plugin_savepoint(true, 2012051400, 'repository', 'picasa'); + } + return true; +} diff --git a/repository/picasa/lang/en/repository_picasa.php b/repository/picasa/lang/en/repository_picasa.php index 23d9dbe66bb..3c03022c12b 100644 --- a/repository/picasa/lang/en/repository_picasa.php +++ b/repository/picasa/lang/en/repository_picasa.php @@ -1,5 +1,4 @@ To use the Picasa repository you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; $string['picasa:view'] = 'View picasa repository'; $string['pluginname'] = 'Picasa web album'; -$string['configplugin'] = 'Picasa repository configuration'; +$string['secret'] = 'Secret'; diff --git a/repository/picasa/lib.php b/repository/picasa/lib.php index 6a83ca08238..902238025fa 100644 --- a/repository/picasa/lib.php +++ b/repository/picasa/lib.php @@ -36,58 +36,40 @@ require_once($CFG->libdir.'/googleapi.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class repository_picasa extends repository { - private $subauthtoken = ''; + private $googleoauth = null; public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) { - global $USER; parent::__construct($repositoryid, $context, $options); - // TODO: I wish there was somewhere we could explicitly put this outside of constructor.. - $googletoken = optional_param('token', false, PARAM_RAW); - if($googletoken){ - $gauth = new google_authsub(false, $googletoken); // will throw exception if fails - google_picasa::set_sesskey($gauth->get_sessiontoken(), $USER->id); - } + $returnurl = new moodle_url('/repository/repository_callback.php', + array('callback' => 'yes', 'repo_id' =>$this->id)); + + $clientid = get_config('picasa', 'clientid'); + $secret = get_config('picasa', 'secret'); + $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_picasa::REALM); + $this->check_login(); } public function check_login() { - global $USER; - - $sesskey = google_picasa::get_sesskey($USER->id); - - if($sesskey){ - try{ - $gauth = new google_authsub($sesskey); - $this->subauthtoken = $sesskey; - return true; - }catch(Exception $e){ - // sesskey is not valid, delete store and re-auth - google_picasa::delete_sesskey($USER->id); - } - } - - return false; + return $this->googleoauth->is_logged_in(); } - public function print_login(){ - global $CFG; - $returnurl = $CFG->wwwroot.'/repository/repository_callback.php?callback=yes&repo_id='.$this->id; - $authurl = google_authsub::login_url($returnurl, google_picasa::REALM); - if($this->options['ajax']){ - $ret = array(); - $popup_btn = new stdClass(); - $popup_btn->type = 'popup'; - $popup_btn->url = $authurl; - $ret['login'] = array($popup_btn); - return $ret; + public function print_login() { + $url = $this->googleoauth->get_login_url(); + + if ($this->options['ajax']) { + $popup = new stdClass(); + $popup->type = 'popup'; + $popup->url = $url->out(false); + return array('login' => array($popup)); } else { - echo 'Login'; + echo ''.get_string('login', 'repository').''; } } public function get_listing($path='', $page = '') { - $picasa = new google_picasa(new google_authsub($this->subauthtoken)); + $picasa = new google_picasa($this->googleoauth); $ret = array(); $ret['dynload'] = true; @@ -101,7 +83,7 @@ class repository_picasa extends repository { } public function search($search_text, $page = 0) { - $picasa = new google_picasa(new google_authsub($this->subauthtoken)); + $picasa = new google_picasa($this->googleoauth); $ret = array(); $ret['manage'] = google_picasa::MANAGE_URL; @@ -109,22 +91,12 @@ class repository_picasa extends repository { return $ret; } - public function logout(){ - global $USER; - - $token = google_picasa::get_sesskey($USER->id); - - $gauth = new google_authsub($token); - // revoke token from google - $gauth->revoke_session_token(); - - google_picasa::delete_sesskey($USER->id); - $this->subauthtoken = ''; - + public function logout() { + $this->googleoauth->log_out(); return parent::logout(); } - public function get_name(){ + public function get_name() { return get_string('pluginname', 'repository_picasa'); } public function supported_filetypes() { @@ -133,7 +105,27 @@ class repository_picasa extends repository { public function supported_returntypes() { return (FILE_INTERNAL | FILE_EXTERNAL); } + + public static function get_type_option_names() { + return array('clientid', 'secret', 'pluginname'); + } + + public static function type_config_form($mform, $classname = 'repository') { + $a = new stdClass; + $a->docsurl = get_docs_url('Google_OAuth2_Setup'); + $a->callbackurl = google_oauth::callback_url()->out(false); + + $mform->addElement('static', null, '', get_string('oauthinfo', 'repository_picasa', $a)); + + parent::type_config_form($mform); + $mform->addElement('text', 'clientid', get_string('clientid', 'repository_picasa')); + $mform->addElement('text', 'secret', get_string('secret', 'repository_picasa')); + + $strrequired = get_string('required'); + $mform->addRule('clientid', $strrequired, 'required', null, 'client'); + $mform->addRule('secret', $strrequired, 'required', null, 'client'); + } } // Icon for this plugin retrieved from http://www.iconspedia.com/icon/picasa-2711.html -// Where the license is said documented to be Free +// Where the license is said documented to be Free. diff --git a/repository/picasa/version.php b/repository/picasa/version.php index 5ee9d18b00a..471007a4cac 100644 --- a/repository/picasa/version.php +++ b/repository/picasa/version.php @@ -26,6 +26,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2011112900; // The current plugin version (Date: YYYYMMDDXX) -$plugin->requires = 2011112900; // Requires this Moodle version -$plugin->component = 'repository_picasa'; // Full name of the plugin (used for diagnostics) +$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2012051100; // Requires this Moodle version. +$plugin->component = 'repository_picasa'; // Full name of the plugin (used for diagnostics). From ce30ff5df04b5c4619eede6f43f6d2d3131cb2cb Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Wed, 30 May 2012 23:56:07 +0800 Subject: [PATCH 448/455] MDL-29857 google apis: OAuth 2.0 repository plugins upgrade We are disabling the plugins on upgrade and emailing admins about this if they have a plugin configured. This is required because OAuth 2 credentials are now required in the plugin configuration. NOTE: These strings are temporary and need to be improved. --- repository/googledocs/db/upgrade.php | 37 +++++++++++++++++++ .../lang/en/repository_googledocs.php | 3 ++ repository/googledocs/version.php | 2 +- repository/picasa/db/upgrade.php | 37 +++++++++++++++++++ .../picasa/lang/en/repository_picasa.php | 3 ++ repository/picasa/version.php | 2 +- 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/repository/googledocs/db/upgrade.php b/repository/googledocs/db/upgrade.php index 76876a19ba2..893ed39dced 100644 --- a/repository/googledocs/db/upgrade.php +++ b/repository/googledocs/db/upgrade.php @@ -29,5 +29,42 @@ function xmldb_repository_googledocs_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2012051400, 'repository', 'googledocs'); } + if ($oldversion < 2012053000) { + require_once($CFG->dirroot.'/repository/lib.php'); + $existing = $DB->get_record('repository', array('type' => 'googledocs'), '*', IGNORE_MULTIPLE); + + if ($existing) { + $googledocsplugin = new repository_type('googledocs', array(), true); + $googledocsplugin->delete(); + repository_googledocs_admin_upgrade_notification(); + } + + upgrade_plugin_savepoint(true, 2012053000, 'repository', 'googledocs'); + } + return true; } + +function repository_googledocs_admin_upgrade_notification() { + $admins = get_admins(); + + if (empty($admins)) { + return; + } + $mainadmin = reset($admins); + + foreach ($admins as $admin) { + $message = new stdClass(); + $message->component = 'moodle'; + $message->name = 'notices'; + $message->userfrom = $mainadmin; + $message->userto = $admin; + $message->smallmessage = get_string('oauth2upgrade_message_small', 'repository_googledocs'); + $message->subject = get_string('oauth2upgrade_message_subject', 'repository_googledocs'); + $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_googledocs'); + $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_googledocs'); + $message->fullmessageformat = FORMAT_PLAIN; + $message->notification = 1; + message_send($message); + } +} diff --git a/repository/googledocs/lang/en/repository_googledocs.php b/repository/googledocs/lang/en/repository_googledocs.php index 8e8cf8034e1..4f7faa7b324 100644 --- a/repository/googledocs/lang/en/repository_googledocs.php +++ b/repository/googledocs/lang/en/repository_googledocs.php @@ -26,6 +26,9 @@ $string['clientid'] = 'Client ID'; $string['configplugin'] = 'Configure Google Docs plugin'; $string['googledocs:view'] = 'View google docs repository'; $string['oauthinfo'] = '

                          To use the Google Docs repository you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; +$string['oauth2upgrade_message_subject'] = 'Important information regarding Google Docs repository plugin'; +$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Google Docs repository plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must add and reconfigure configure oauth credentials of this plugin.'; +$string['oauth2upgrade_message_small'] = 'The Google Docs repository plugin has been disabled until configured with OAuth2'; $string['pluginname'] = 'Google Docs'; $string['secret'] = 'Secret'; diff --git a/repository/googledocs/version.php b/repository/googledocs/version.php index 7269aa52195..2e03f6c9c43 100644 --- a/repository/googledocs/version.php +++ b/repository/googledocs/version.php @@ -25,6 +25,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2012053000; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2012051100; // Requires this Moodle version. $plugin->component = 'repository_googledocs'; // Full name of the plugin (used for diagnostics). diff --git a/repository/picasa/db/upgrade.php b/repository/picasa/db/upgrade.php index 545ce3b4fa5..082e5e3433f 100644 --- a/repository/picasa/db/upgrade.php +++ b/repository/picasa/db/upgrade.php @@ -29,5 +29,42 @@ function xmldb_repository_picasa_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2012051400, 'repository', 'picasa'); } + if ($oldversion < 2012053000) { + require_once($CFG->dirroot.'/repository/lib.php'); + $existing = $DB->get_record('repository', array('type' => 'picasa'), '*', IGNORE_MULTIPLE); + + if ($existing) { + $picasaplugin = new repository_type('picasa', array(), true); + $picasaplugin->delete(); + repository_picasa_admin_upgrade_notification(); + } + + upgrade_plugin_savepoint(true, 2012053000, 'repository', 'picasa'); + } + return true; } + +function repository_picasa_admin_upgrade_notification() { + $admins = get_admins(); + + if (empty($admins)) { + return; + } + $mainadmin = reset($admins); + + foreach ($admins as $admin) { + $message = new stdClass(); + $message->component = 'moodle'; + $message->name = 'notices'; + $message->userfrom = $mainadmin; + $message->userto = $admin; + $message->smallmessage = get_string('oauth2upgrade_message_small', 'repository_picasa'); + $message->subject = get_string('oauth2upgrade_message_subject', 'repository_picasa'); + $message->fullmessage = get_string('oauth2upgrade_message_content', 'repository_picasa'); + $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'repository_picasa'); + $message->fullmessageformat = FORMAT_PLAIN; + $message->notification = 1; + message_send($message); + } +} diff --git a/repository/picasa/lang/en/repository_picasa.php b/repository/picasa/lang/en/repository_picasa.php index 3c03022c12b..89d75a68079 100644 --- a/repository/picasa/lang/en/repository_picasa.php +++ b/repository/picasa/lang/en/repository_picasa.php @@ -25,6 +25,9 @@ $string['clientid'] = 'Client ID'; $string['configplugin'] = 'Picasa repository configuration'; $string['oauthinfo'] = '

                          To use the Picasa repository you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; +$string['oauth2upgrade_message_subject'] = 'Important information regarding Picasa repository plugin'; +$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Picasa repository plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must add and reconfigure configure oauth credentials of this plugin.'; +$string['oauth2upgrade_message_small'] = 'The Picasa repository plugin has been disabled until configured with OAuth2'; $string['picasa:view'] = 'View picasa repository'; $string['pluginname'] = 'Picasa web album'; $string['secret'] = 'Secret'; diff --git a/repository/picasa/version.php b/repository/picasa/version.php index 471007a4cac..c6dc0fc84ff 100644 --- a/repository/picasa/version.php +++ b/repository/picasa/version.php @@ -26,6 +26,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2012053000; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2012051100; // Requires this Moodle version. $plugin->component = 'repository_picasa'; // Full name of the plugin (used for diagnostics). From b7acfd645b4f71d3012e706f30dd4165c2b11e26 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Tue, 29 May 2012 14:35:25 +0800 Subject: [PATCH 449/455] MDL-29857 google apis: OAuth 2.0 portfolio plugins upgrade We are disabling the plugins if not configured. As part of this upgrade we will emailing admins about this change if they have a plugin configured. This is required because OAuth 2 credentials are now required in the plugin configuration. NOTE: These strings are temporary and need to be improved. --- portfolio/googledocs/db/upgrade.php | 67 +++++++++++++++++++ .../lang/en/portfolio_googledocs.php | 7 +- portfolio/googledocs/lib.php | 12 ++++ portfolio/googledocs/version.php | 2 +- portfolio/picasa/db/upgrade.php | 67 +++++++++++++++++++ portfolio/picasa/lang/en/portfolio_picasa.php | 7 +- portfolio/picasa/lib.php | 12 ++++ portfolio/picasa/version.php | 2 +- 8 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 portfolio/googledocs/db/upgrade.php create mode 100644 portfolio/picasa/db/upgrade.php diff --git a/portfolio/googledocs/db/upgrade.php b/portfolio/googledocs/db/upgrade.php new file mode 100644 index 00000000000..dfdc1dca43a --- /dev/null +++ b/portfolio/googledocs/db/upgrade.php @@ -0,0 +1,67 @@ +. + +/** + * @param int $oldversion the version we are upgrading from + * @return bool result + */ +function xmldb_portfolio_googledocs_upgrade($oldversion) { + global $CFG, $DB; + + $dbman = $DB->get_manager(); + + if ($oldversion < 2012053000) { + // Delete old user preferences containing authsub tokens. + $DB->delete_records('user_preferences', array('name' => 'google_authsub_sesskey')); + upgrade_plugin_savepoint(true, 2012053000, 'portfolio', 'googledocs'); + } + + if ($oldversion < 2012053001) { + $existing = $DB->get_record('portfolio_instance', array('plugin' => 'googledocs'), '*', IGNORE_MULTIPLE); + + if ($existing) { + portfolio_googledocs_admin_upgrade_notification(); + } + + upgrade_plugin_savepoint(true, 2012053001, 'portfolio', 'googledocs'); + } + + return true; +} + +function portfolio_googledocs_admin_upgrade_notification() { + $admins = get_admins(); + + if (empty($admins)) { + return; + } + $mainadmin = reset($admins); + + foreach ($admins as $admin) { + $message = new stdClass(); + $message->component = 'moodle'; + $message->name = 'notices'; + $message->userfrom = $mainadmin; + $message->userto = $admin; + $message->smallmessage = get_string('oauth2upgrade_message_small', 'portfolio_googledocs'); + $message->subject = get_string('oauth2upgrade_message_subject', 'portfolio_googledocs'); + $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_googledocs'); + $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_googledocs'); + $message->fullmessageformat = FORMAT_PLAIN; + $message->notification = 1; + message_send($message); + } +} diff --git a/portfolio/googledocs/lang/en/portfolio_googledocs.php b/portfolio/googledocs/lang/en/portfolio_googledocs.php index 0fb864dac40..c52bba14df5 100644 --- a/portfolio/googledocs/lang/en/portfolio_googledocs.php +++ b/portfolio/googledocs/lang/en/portfolio_googledocs.php @@ -23,9 +23,14 @@ */ $string['clientid'] = 'Client ID'; -$string['oauthinfo'] = '

                          To use the google docs portfolio you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; $string['noauthtoken'] = 'An authentication token has not been recieved from google. Please ensure you are allowing moodle to access your google account'; +$string['nooauthcredentials'] = 'OAuth credentials required.'; +$string['nooauthcredentials_help'] = 'To use the Google Docs portfolio plugin you must configure OAuth credentials in the portfolio settings.'; $string['nosessiontoken'] = 'A session token does not exist preventing export to google.'; +$string['oauthinfo'] = '

                          To use the google docs portfolio you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; +$string['oauth2upgrade_message_subject'] = 'Important information regarding Google Docs portfolio plugin'; +$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Google Docs portfolio plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must configure oauth credentials in this plugin.'; +$string['oauth2upgrade_message_small'] = 'The Google Docs portfolio plugin has been disabled until configured with OAuth2'; $string['pluginname'] = 'Google Docs'; $string['sendfailed'] = 'The file {$a} failed to transfer to google'; $string['secret'] = 'Secret'; diff --git a/portfolio/googledocs/lib.php b/portfolio/googledocs/lib.php index c641f096df1..9820246f9db 100644 --- a/portfolio/googledocs/lib.php +++ b/portfolio/googledocs/lib.php @@ -126,4 +126,16 @@ class portfolio_plugin_googledocs extends portfolio_plugin_push_base { $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_docs::REALM); } + + public function instance_sanity_check() { + $clientid = $this->get_config('clientid'); + $secret = $this->get_config('secret'); + + // If there is no oauth config (e.g. plugins upgraded from < 2.3 then + // there will be no config and this plugin should be disabled. + if (empty($clientid) or empty($secret)) { + return 'nooauthcredentials'; + } + return 0; + } } diff --git a/portfolio/googledocs/version.php b/portfolio/googledocs/version.php index a64c628b0b5..5cee5db320b 100644 --- a/portfolio/googledocs/version.php +++ b/portfolio/googledocs/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2012053001; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2012051100; // Requires this Moodle version. $plugin->component = 'portfolio_googledocs'; // Full name of the plugin (used for diagnostics). $plugin->cron = 0; diff --git a/portfolio/picasa/db/upgrade.php b/portfolio/picasa/db/upgrade.php new file mode 100644 index 00000000000..e5d1cca6d1d --- /dev/null +++ b/portfolio/picasa/db/upgrade.php @@ -0,0 +1,67 @@ +. + +/** + * @param int $oldversion the version we are upgrading from + * @return bool result + */ +function xmldb_portfolio_picasa_upgrade($oldversion) { + global $CFG, $DB; + + $dbman = $DB->get_manager(); + + if ($oldversion < 2012053000) { + // Delete old user preferences containing authsub tokens. + $DB->delete_records('user_preferences', array('name' => 'google_authsub_sesskey_picasa')); + upgrade_plugin_savepoint(true, 2012053000, 'portfolio', 'picasa'); + } + + if ($oldversion < 2012053001) { + $existing = $DB->get_record('portfolio_instance', array('plugin' => 'picasa'), '*', IGNORE_MISSING); + + if ($existing) { + portfolio_picasa_admin_upgrade_notification(); + } + + upgrade_plugin_savepoint(true, 2012053001, 'portfolio', 'picasa'); + } + + return true; +} + +function portfolio_picasa_admin_upgrade_notification() { + $admins = get_admins(); + + if (empty($admins)) { + return; + } + $mainadmin = reset($admins); + + foreach ($admins as $admin) { + $message = new stdClass(); + $message->component = 'moodle'; + $message->name = 'notices'; + $message->userfrom = $mainadmin; + $message->userto = $admin; + $message->smallmessage = get_string('oauth2upgrade_message_small', 'portfolio_picasa'); + $message->subject = get_string('oauth2upgrade_message_subject', 'portfolio_picasa'); + $message->fullmessage = get_string('oauth2upgrade_message_content', 'portfolio_picasa'); + $message->fullmessagehtml = get_string('oauth2upgrade_message_content', 'portfolio_picasa'); + $message->fullmessageformat = FORMAT_PLAIN; + $message->notification = 1; + message_send($message); + } +} diff --git a/portfolio/picasa/lang/en/portfolio_picasa.php b/portfolio/picasa/lang/en/portfolio_picasa.php index 10c12e66152..93781b6df96 100644 --- a/portfolio/picasa/lang/en/portfolio_picasa.php +++ b/portfolio/picasa/lang/en/portfolio_picasa.php @@ -23,8 +23,13 @@ */ $string['clientid'] = 'Client ID'; -$string['oauthinfo'] = '

                          To use the Picasa portfolio you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; $string['noauthtoken'] = 'An authentication token has not been recieved from google. Please ensure you are allowing moodle to access your google account'; +$string['nooauthcredentials'] = 'OAuth credentials required.'; +$string['nooauthcredentials_help'] = 'To use the Picasa portfolio plugin you must configure OAuth credentials in the portfolio settings.'; +$string['oauthinfo'] = '

                          To use the Picasa portfolio you must be registered with Google. Instructions for registing your installation with Google are described in Moodle Docs. The redirect url should be set to:

                          {$a->callbackurl}

                          '; +$string['oauth2upgrade_message_subject'] = 'Important information regarding Picasa portfolio plugin'; +$string['oauth2upgrade_message_content'] = 'As part of the upgrade to Moodle 2.3, the Picasa portfolio plugin has been disabled due to changes in Googles API. To re-enable your plugin, you must configure oauth credentials in this plugin.'; +$string['oauth2upgrade_message_small'] = 'The Picasa portfolio plugin has been disabled until configured with OAuth2'; $string['pluginname'] = 'Picasa'; $string['sendfailed'] = 'The file {$a} failed to transfer to picasa'; $string['secret'] = 'Secret'; diff --git a/portfolio/picasa/lib.php b/portfolio/picasa/lib.php index 6d21336214b..d637b54edca 100644 --- a/portfolio/picasa/lib.php +++ b/portfolio/picasa/lib.php @@ -126,4 +126,16 @@ class portfolio_plugin_picasa extends portfolio_plugin_push_base { $this->googleoauth = new google_oauth($clientid, $secret, $returnurl->out(false), google_picasa::REALM); } + + public function instance_sanity_check() { + $clientid = $this->get_config('clientid'); + $secret = $this->get_config('secret'); + + // If there is no oauth config (e.g. plugins upgraded from < 2.3 then + // there will be no config and this plugin should be disabled. + if (empty($clientid) or empty($secret)) { + return 'nooauthcredentials'; + } + return 0; + } } diff --git a/portfolio/picasa/version.php b/portfolio/picasa/version.php index 113c9cf9e0d..b56c5e65b00 100644 --- a/portfolio/picasa/version.php +++ b/portfolio/picasa/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2012051400; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2012053001; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2012051100; // Requires this Moodle version. $plugin->component = 'portfolio_picasa'; // Full name of the plugin (used for diagnostics). $plugin->cron = 0; From 602a76d86ae12a379aa5ae18980d1d2080e132f8 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 30 May 2012 14:48:39 -0600 Subject: [PATCH 450/455] MDL-33140 quiz browser security: block copy/paste more --- mod/quiz/module.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mod/quiz/module.js b/mod/quiz/module.js index fa45821d48e..c1bec7faa35 100644 --- a/mod/quiz/module.js +++ b/mod/quiz/module.js @@ -212,10 +212,13 @@ M.mod_quiz.secure_window = { window.location = 'about:blank'; } Y.delegate('contextmenu', M.mod_quiz.secure_window.prevent, document, '*'); - Y.delegate('mousedown', M.mod_quiz.secure_window.prevent_mouse, document, '*'); - Y.delegate('mouseup', M.mod_quiz.secure_window.prevent_mouse, document, '*'); - Y.delegate('dragstart', M.mod_quiz.secure_window.prevent, document, '*'); + Y.delegate('mousedown', M.mod_quiz.secure_window.prevent_mouse, document, '*'); + Y.delegate('mouseup', M.mod_quiz.secure_window.prevent_mouse, document, '*'); + Y.delegate('dragstart', M.mod_quiz.secure_window.prevent, document, '*'); Y.delegate('selectstart', M.mod_quiz.secure_window.prevent, document, '*'); + Y.delegate('cut', M.mod_quiz.secure_window.prevent, document, '*'); + Y.delegate('copy', M.mod_quiz.secure_window.prevent, document, '*'); + Y.delegate('paste', M.mod_quiz.secure_window.prevent, document, '*'); M.mod_quiz.secure_window.clear_status; Y.on('beforeprint', function() { Y.one(document.body).setStyle('display', 'none'); From cbdcdd473451db2bcea8a6a3d486d374fe8c9104 Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Thu, 31 May 2012 00:58:19 +0200 Subject: [PATCH 451/455] MDL-33434 dml: define expected results when unique constraint is violated on insert. --- lib/dml/tests/dml_test.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib/dml/tests/dml_test.php b/lib/dml/tests/dml_test.php index 0ef6eca624d..410c7ffef3b 100644 --- a/lib/dml/tests/dml_test.php +++ b/lib/dml/tests/dml_test.php @@ -2078,6 +2078,34 @@ class dml_testcase extends database_driver_testcase { $this->assertEquals(1e-300, $DB->get_field($tablename, 'onetext', array('id' => $id))); $id = $DB->insert_record($tablename, array('onetext' => 1e300)); $this->assertEquals(1e300, $DB->get_field($tablename, 'onetext', array('id' => $id))); + + // Test that inserting data violating one unique key leads to error. + // Empty the table completely. + $this->assertTrue($DB->delete_records($tablename)); + + // Add one unique constraint (index). + $key = new xmldb_key('testuk', XMLDB_KEY_UNIQUE, array('course', 'oneint')); + $dbman->add_key($table, $key); + + // Let's insert one record violating the constraint multiple times. + $record = (object)array('course' => 1, 'oneint' => 1); + $this->assertTrue($DB->insert_record($tablename, $record, false)); // insert 1st. No problem expected. + + // Re-insert same record, not returning id. dml_exception expected. + try { + $DB->insert_record($tablename, $record, false); + $this->fail("Expecting an exception, none occurred"); + } catch (exception $e) { + $this->assertTrue($e instanceof dml_exception); + } + + // Re-insert same record, returning id. dml_exception expected. + try { + $DB->insert_record($tablename, $record, true); + $this->fail("Expecting an exception, none occurred"); + } catch (exception $e) { + $this->assertTrue($e instanceof dml_exception); + } } public function test_import_record() { From a3fa993212fbee1fe6a1fb4f7b1069ba4595360a Mon Sep 17 00:00:00 2001 From: "Eloy Lafuente (stronk7)" Date: Thu, 31 May 2012 01:01:14 +0200 Subject: [PATCH 452/455] MDL-33434 mssql: Improve handling of returned ids on insert. This commit moves from the batch SCOPE_IDENTITY() way to return the inserted ids to the OUTPUT alternative (supported and recommended since 2005). Also the handling of possible return values is improved, with all the alternatives leading to expected results. --- lib/dml/mssql_native_moodle_database.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/dml/mssql_native_moodle_database.php b/lib/dml/mssql_native_moodle_database.php index 028538c4f2e..5ae728e86c6 100644 --- a/lib/dml/mssql_native_moodle_database.php +++ b/lib/dml/mssql_native_moodle_database.php @@ -826,7 +826,7 @@ class mssql_native_moodle_database extends moodle_database { } else { unset($params['id']); if ($returnid) { - $returning = "; SELECT SCOPE_IDENTITY()"; + $returning = "OUTPUT inserted.id"; } } @@ -838,18 +838,29 @@ class mssql_native_moodle_database extends moodle_database { $qms = array_fill(0, count($params), '?'); $qms = implode(',', $qms); - $sql = "INSERT INTO {" . $table . "} ($fields) VALUES($qms) $returning"; + $sql = "INSERT INTO {" . $table . "} ($fields) $returning VALUES ($qms)"; list($sql, $params, $type) = $this->fix_sql_params($sql, $params); $rawsql = $this->emulate_bound_params($sql, $params); $this->query_start($sql, $params, SQL_QUERY_INSERT); $result = mssql_query($rawsql, $this->mssql); - $this->query_end($result); + // Expected results are: + // - true: insert ok and there isn't returned information. + // - false: insert failed and there isn't returned information. + // - resource: insert executed, need to look for returned (output) + // values to know if the insert was ok or no. Posible values + // are false = failed, integer = insert ok, id returned. + $end = false; + if (is_bool($result)) { + $end = $result; + } else if (is_resource($result)) { + $end = mssql_result($result, 0, 0); // Fetch 1st column from 1st row. + } + $this->query_end($end); // End the query with the calculated $end. if ($returning !== "") { - $row = mssql_fetch_assoc($result); - $params['id'] = reset($row); + $params['id'] = $end; } $this->free_result($result); From e1041a38ca6279e0c6bcc63773a4ab3b77d2101c Mon Sep 17 00:00:00 2001 From: AMOS bot Date: Thu, 31 May 2012 00:31:19 +0000 Subject: [PATCH 453/455] Automatically generated installer lang files --- install/lang/es_mx/install.php | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 install/lang/es_mx/install.php diff --git a/install/lang/es_mx/install.php b/install/lang/es_mx/install.php new file mode 100644 index 00000000000..a3586f021e3 --- /dev/null +++ b/install/lang/es_mx/install.php @@ -0,0 +1,38 @@ +. + +/** + * Automatically generated strings for Moodle 2.3dev installer + * + * Do not edit this file manually! It contains just a subset of strings + * needed during the very first steps of installation. This file was + * generated automatically by export-installer.php (which is part of AMOS + * {@link http://docs.moodle.org/dev/Languages/AMOS}) using the + * list of strings defined in /install/stringnames.txt. + * + * @package installer + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['databasehost'] = 'host de la Base de Datos'; +$string['environmentsub2'] = 'Cada versión de Moodle tiene algún requisito mínimo de la versión de PHP y un número obligatorio de extensiones de PHP. Una comprobación del entorno completo se realiza antes de cada instalación y actualización. Por favor, póngase en contacto con el administrador del servidor si no sabe cómo instalar la nueva versión o habilitar las extensiones PHP.'; +$string['errorsinenvironment'] = '¡La comprobación del entorno falló!'; +$string['welcomep20'] = 'Si está viendo esta página es porque ha podido ejecutar el paquete {$a->packname} {$a->packversion} en su computadora. !Enhorabuena!'; +$string['welcomep30'] = 'Esta versión de {$a->installername} incluye las aplicaciones necesarias para que Moodle funcione en su computadora principalmente:'; +$string['welcomep60'] = 'Las siguientes páginas le guiarán a través de algunos sencillos pasos para configurar y ajustar Moodle en su computadora. Puede utilizar los valores por defecto sugeridos o, de forma opcional, modificarlos para que se ajusten a sus necesidades.'; From ccc604a24dc83f99bad68671d434e468f272e52f Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Thu, 31 May 2012 10:19:15 +0800 Subject: [PATCH 454/455] MDL-33398 Cron: fix wrong variable type in completion criterias --- lib/completion/completion_criteria_course.php | 2 +- lib/completion/completion_criteria_date.php | 2 +- lib/completion/completion_criteria_grade.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/completion/completion_criteria_course.php b/lib/completion/completion_criteria_course.php index 671eeb97e32..a25dea2ae6b 100644 --- a/lib/completion/completion_criteria_course.php +++ b/lib/completion/completion_criteria_course.php @@ -194,7 +194,7 @@ class completion_criteria_course extends completion_criteria { $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); - $completion->mark_complete($record['timecompleted']); + $completion->mark_complete($record->timecompleted); } $rs->close(); } diff --git a/lib/completion/completion_criteria_date.php b/lib/completion/completion_criteria_date.php index 1d52e29806d..baecc20f420 100644 --- a/lib/completion/completion_criteria_date.php +++ b/lib/completion/completion_criteria_date.php @@ -180,7 +180,7 @@ class completion_criteria_date extends completion_criteria { $rs = $DB->get_recordset_sql($sql, array(time())); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); - $completion->mark_complete($record['timeend']); + $completion->mark_complete($record->timeend); } $rs->close(); } diff --git a/lib/completion/completion_criteria_grade.php b/lib/completion/completion_criteria_grade.php index 22a924f804a..6bc32ed7236 100644 --- a/lib/completion/completion_criteria_grade.php +++ b/lib/completion/completion_criteria_grade.php @@ -216,7 +216,7 @@ class completion_criteria_grade extends completion_criteria { $rs = $DB->get_recordset_sql($sql); foreach ($rs as $record) { $completion = new completion_criteria_completion((array) $record, DATA_OBJECT_FETCH_BY_KEY); - $completion->mark_complete($record['timecompleted']); + $completion->mark_complete($record->timecompleted); } $rs->close(); } From 4db061680e56b45ae5cc2c1b832c6a6f42b5a924 Mon Sep 17 00:00:00 2001 From: Dan Poltawski Date: Fri, 1 Jun 2012 17:03:32 +0800 Subject: [PATCH 455/455] on-demand release 2.3dev --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index dd7484cfbb0..fd97b593aea 100644 --- a/version.php +++ b/version.php @@ -30,11 +30,11 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012052900.05; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012060100.00; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes -$release = '2.3dev (Build: 20120525)'; // Human-friendly version name +$release = '2.3dev (Build: 20120601)'; // Human-friendly version name $branch = '23'; // this version's branch $maturity = MATURITY_ALPHA; // this version's maturity level