diff --git a/mod/book/db/upgrade.php b/mod/book/db/upgrade.php index 3fb10859cf3..c4709f003cd 100644 --- a/mod/book/db/upgrade.php +++ b/mod/book/db/upgrade.php @@ -40,6 +40,152 @@ function xmldb_book_upgrade($oldversion) { // Moodle v2.3.0 release upgrade line // Put any upgrade step following this + // Note: The next steps (up to 2012061710 included, are a "replay" of old upgrade steps, + // because some sites updated to Moodle 2.3 didn't have the latest contrib mod_book + // installed, so some required changes were missing. + // + // All the steps are run conditionally so sites upgraded from latest contrib mod_book or + // new (2.3 and upwards) sites won't get affected. + // + // See MDL-35297 and commit msg for more information. + + if ($oldversion < 2012061703) { + // Rename field summary on table book to intro + $table = new xmldb_table('book'); + $field = new xmldb_field('summary', XMLDB_TYPE_TEXT, null, 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, 2012061703, 'book'); + } + + if ($oldversion < 2012061704) { + // Define field introformat to be added to book + $table = new xmldb_table('book'); + $field = new xmldb_field('introformat', XMLDB_TYPE_INTEGER, '4', null, 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 + // Si está activo el htmleditor!!!!! + 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, 2012061704, 'book'); + } + + if ($oldversion < 2012061705) { + // Define field introformat to be added to book + $table = new xmldb_table('book_chapters'); + $field = new xmldb_field('contentformat', XMLDB_TYPE_INTEGER, '4', null, 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, 2012061705, 'book'); + } + + if ($oldversion < 2012061706) { + 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, 2012061706, 'book'); + } + + if ($oldversion < 2012061707) { + // 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, 2012061707, 'book'); + } + + if ($oldversion < 2012061708) { + unset_config('book_tocwidth'); + + // book savepoint reached + upgrade_mod_savepoint(true, 2012061708, 'book'); + } + + if ($oldversion < 2012061709) { + require_once("$CFG->dirroot/mod/book/db/upgradelib.php"); + + mod_book_migrate_all_areas(); + + upgrade_mod_savepoint(true, 2012061709, 'book'); + } + + if ($oldversion < 2012061710) { + + // 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, 2012061710, 'book'); + } + // End of MDL-35297 "replayed" steps. return true; } diff --git a/mod/book/db/upgradelib.php b/mod/book/db/upgradelib.php new file mode 100644 index 00000000000..5411930443c --- /dev/null +++ b/mod/book/db/upgradelib.php @@ -0,0 +1,168 @@ +. + +/** + * 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 diff --git a/mod/book/version.php b/mod/book/version.php index e187cb33144..f37c00d4531 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 = 2012061702; // The current module version (Date: YYYYMMDDXX) +$module->version = 2012061710; // The current module version (Date: YYYYMMDDXX) $module->requires = 2012061700; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs)