Merge branch 'MDL-52934-master' of git://github.com/FMCorz/moodle

This commit is contained in:
David Monllao 2016-03-15 08:58:33 +08:00
commit 03bd6c21ad
6 changed files with 4 additions and 310 deletions

View File

@ -371,6 +371,9 @@ function upgrade_stale_php_files_present() {
global $CFG;
$someexamplesofremovedfiles = array(
// Removed in 3.1.
'/repository/boxnet/migrationv1.php',
'/repository/boxnet/cli/migrationv1.php',
// Removed in 3.0.
'/mod/lti/grade.php',
'/tag/coursetagslib.php',

View File

@ -1,61 +0,0 @@
<?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/>.
/**
* Box.net migration CLI script.
*
* @package repository_boxnet
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('CLI_SCRIPT', true);
require(__DIR__ . '/../../../config.php');
require_once($CFG->libdir . '/clilib.php');
require_once($CFG->dirroot . '/repository/boxnet/locallib.php');
// Now get cli options.
list($options, $unrecognized) = cli_get_params(array(
'help' => false,
'confirm' => '',
));
if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
}
$help =
"Box.net APIv1 migration tool.
Options:
-h, --help Print out this help
--confirm Proceed with the migration
Example:
\$ sudo -u www-data /usr/bin/php admin/tool/boxnetv1migrationtool/cli/migrate.php --confirm=1
";
if ($options['help'] || empty($options['confirm'])) {
echo $help;
die();
}
if ($options['confirm']) {
mtrace("Box.net migration running...");
repository_boxnet_migrate_references_from_apiv1();
}

View File

@ -32,18 +32,12 @@ $string['configplugin'] = 'Box configuration';
$string['filesourceinfo'] = 'Box ({$a->fullname}): {$a->filename}';
$string['information'] = 'Get a client ID and secret from the <a href="https://app.box.com/developers/services">Box developer page</a> for your Moodle site.';
$string['invalidpassword'] = 'Invalid password';
$string['migrationadvised'] = 'It appears that you were using Box with the API version 1, have you run the <a href="{$a}">migration tool</a> to convert the old references?';
$string['migrationinfo'] = '<p>As part of the migration to the new API provided by Box, your file references have to be migrated. Unfortunately the reference system is not compatible with the API v2, so we are going to download them and convert them to real files.</p>
<p>Please also be aware that the migration can <strong>take a very long time</strong>, depending on how many references are used, and how large their files are.</p>
<p>You can run the migration tool by clicking the button below, or alternatively by executing the CLI script: repository/boxnet/cli/migrationv1.php.</p>
<p>Find out more <a href="{$a->docsurl}">here</a>.</p>';
$string['migrationtool'] = 'Box APIv1 migration tool';
$string['nullfilelist'] = 'There are no files in this repository';
$string['password'] = 'Password';
$string['pluginname_help'] = 'Repository on Box';
$string['pluginname'] = 'Box';
$string['runthemigrationnow'] = 'Run the migration tool now';
$string['saved'] = 'Box data saved';
$string['shareurl'] = 'Share URL';
$string['username'] = 'Username for Box';
$string['warninghttps'] = 'Box requires your website to be using HTTPS in order for the repository to work.';

View File

@ -337,12 +337,6 @@ class repository_boxnet extends repository {
if (!is_https()) {
$mform->addElement('static', null, '', get_string('warninghttps', 'repository_boxnet'));
}
if (get_config('boxnet', 'api_key')) {
$url = new moodle_url('/repository/boxnet/migrationv1.php');
$url = $url->out();
$mform->addElement('static', null, '', get_string('migrationadvised', 'repository_boxnet', $url));
}
}
/**

View File

@ -22,170 +22,3 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Migrate the references to local files.
*
* As the APIv1 is reaching its end of life on the 14th of Dec 2013, and we cannot
* convert the existing references to new references, we need to convert them
* to real files.
*
* @todo Deprecate/remove this function after the 14th of December 2013.
* @return void
*/
function repository_boxnet_migrate_references_from_apiv1() {
global $DB;
// A string that the old references contain.
$apiv1signature = '/api/1.0/download/';
// Downloading the files could take a very long time!
@set_time_limit(0);
// Create directory to download temporary files.
$dir = make_temp_directory('download/repository_boxnet/');
// Create a dummy file for the broken files.
$fs = get_file_storage();
list($dummyhash, $dummysize, $unused) = $fs->add_string_to_pool('Lost reference from Box.net');
// Get the Box.net instances. There should be only one.
$sql = "SELECT i.id, i.typeid, r.id, r.type
FROM {repository} r, {repository_instances} i
WHERE i.typeid = r.id
AND r.type = :type";
$ids = $DB->get_fieldset_sql($sql, array('type' => 'boxnet'));
if (empty($ids)) {
// We did not find any instance of Box.net. Let's just ignore this migration.
mtrace('Could not find any instance of the repository, aborting migration...');
return;
}
// The next bit is copied from the function file_storage::instance_sql_fields()
// because it is private and there is nothing in file_storage that suits our needs here.
$filefields = array('contenthash', 'pathnamehash', 'contextid', 'component', 'filearea',
'itemid', 'filepath', 'filename', 'userid', 'filesize', 'mimetype', 'status', 'source',
'author', 'license', 'timecreated', 'timemodified', 'sortorder', 'referencefileid');
$referencefields = array('repositoryid' => 'repositoryid',
'reference' => 'reference',
'lastsync' => 'referencelastsync');
$fields = array();
$fields[] = 'f.id AS id';
foreach ($filefields as $field) {
$fields[] = "f.{$field}";
}
foreach ($referencefields as $field => $alias) {
$fields[] = "r.{$field} AS {$alias}";
}
$fields = implode(', ', $fields);
// We are not using repository::convert_references_to_local() or file_storage::get_external_files()
// because they would select too many records and load everything in memory as it is not using a recordset.
// Also, we filter the results not to get the draft area which should not be converted.
list($sqlfragment, $fragmentparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED);
$sql = "SELECT " . $fields . "
FROM {files_reference} r
LEFT JOIN {files} f
ON f.referencefileid = r.id
WHERE r.repositoryid $sqlfragment
AND f.referencefileid IS NOT NULL
AND NOT (f.component = :component
AND f.filearea = :filearea)";
// For each reference we download the file. Then we add it to the file pool and update the references.
// The reason why we are re-inventing the wheel here is because the current API ends up calling
// repository::get_file() which includes a download timeout. As we are trying our best to copy
// the files here, we want to ignre any timeout.
$filerecords = $DB->get_recordset_sql($sql, array_merge($fragmentparams, array('component' => 'user', 'filearea' => 'draft')));
$referenceids = array();
foreach ($filerecords as $filerecord) {
$file = $fs->get_file_instance($filerecord);
$reference = unserialize(repository_boxnet::convert_to_valid_reference($file->get_reference()));
if (empty($reference->downloadurl)) {
// Something is wrong...
mtrace('Skipping malformed reference (id: ' . $file->get_referencefileid() . ')');
continue;
} else if (strpos($reference->downloadurl, $apiv1signature) === false) {
// This is not an old reference, we are not supposed to work on thos.
mtrace('Skipping non APIv1 reference (id: ' . $file->get_referencefileid() . ')');
continue;
} else if (isset($referenceids[$file->get_referencefileid()])) {
// We have already worked on that reference, we skip any other file related to it.
// We cannot work on them here because they have been updated in the database but our
// recordset does not have those new values. They will be taken care of after this foreach.
continue;
}
mtrace('Starting migration of file reference ' . $file->get_referencefileid());
// Manually import the file to the file pool to prevent timeout limitations of the repository method get_file().
// We ignore the fact that the content of the file could exist locally because we want to synchronize the file
// now to prevent the repository to try to download the file as well.
$saveas = $dir . uniqid('', true) . '_' . time() . '.tmp';
$c = new curl();
$result = $c->download_one($reference->downloadurl, null, array('filepath' => $saveas, 'followlocation' => true));
$info = $c->get_info();
if ($result !== true || !isset($info['http_code']) || $info['http_code'] != 200) {
// There was a problem while trying to download the reference...
if ($fs->content_exists($file->get_contenthash()) && $file->get_contenthash() != sha1('')) {
// Fortunately we already had a local version of this reference, so we keep it. We have to
// set it synchronized or there is a risk that repository::sync_reference() will try to download
// the file again. We cannot use $file->get_contenthash() and $file->get_filesize() because they
// cause repository::sync_reference() to be called.
$file->set_synchronized($filerecord->contenthash, $filerecord->filesize);
mtrace('Could not download reference, using last synced file. (id: ' . $file->get_referencefileid() . ')');
} else {
// We don't know what the file was, but what can we do? In order to prevent a re-attempt to fetch the
// file in the next bit of this script (import_external_file()), we set a dummy content to the reference.
$file->set_synchronized($dummyhash, $dummysize);
mtrace('Could not download reference, dummy file used. (id: ' . $file->get_referencefileid() . ')');
}
} else {
try {
// The file has been downloaded, we add it to the file pool and synchronize
// all the files using this reference.
list($contenthash, $filesize, $unused) = $fs->add_file_to_pool($saveas);
$file->set_synchronized($contenthash, $filesize);
} catch (moodle_exception $e) {
// Something wrong happened...
mtrace('Something went wrong during sync (id: ' . $file->get_referencefileid() . ')');
}
}
// Log the reference IDs.
$referenceids[$file->get_referencefileid()] = $file->get_referencefileid();
// Now that the file is downloaded, we can loop over all the files using this reference
// to convert them to local copies. We have chosen to do that in this loop so that if the
// execution fails in the middle, we would not have to redownload the files again and again.
// By the way, we cannot use the records fetched in $filerecords because they will not be updated.
$sql = "SELECT " . $fields . "
FROM {files} f
LEFT JOIN {files_reference} r
ON f.referencefileid = r.id
WHERE f.referencefileid = :refid
AND NOT (f.component = :component
AND f.filearea = :filearea)";
$reffilerecords = $DB->get_recordset_sql($sql, array('component' => 'user', 'filearea' => 'draft',
'refid' => $file->get_referencefileid()));
foreach ($reffilerecords as $reffilerecord) {
$reffile = $fs->get_file_instance($reffilerecord);
try {
// Updating source to remove trace of APIv1 URL.
$reffile->set_source('Box APIv1 reference');
} catch (moodle_exception $e) {
// Do not fail for this lame reason...
}
try {
$fs->import_external_file($reffile);
mtrace('File using reference converted to local file (id: ' . $reffile->get_id() . ')');
} catch (moodle_exception $e) {
// Oh well... we tried what we could!
$reffile->delete_reference();
mtrace('Failed to convert file from reference to local file, sorry! (id: ' . $reffile->get_id() . ')');
}
}
}
mtrace('Migration finished.');
}

View File

@ -1,69 +0,0 @@
<?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/>.
/**
* Box.net APIv1 migration tool.
*
* This tool is intended to migrate the references of the APIv1 of Box.net
* as this API is going end of life in December 14th 2013. As there is no
* way to support the references in the APIv2, we will convert those old
* references to local files.
*
* This operation can take a long time depending on the number of references
* used and their size.
*
* @package repository_boxnet
* @copyright 2013 Frédéric Massart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @todo Deprecate/remove this tool after the 14th of December 2013.
*/
define('NO_OUTPUT_BUFFERING', true);
require_once(__DIR__ . '/../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once($CFG->dirroot . '/repository/boxnet/locallib.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
$title = get_string('migrationtool', 'repository_boxnet');
$PAGE->set_context(context_system::instance());
$PAGE->set_pagelayout('maintenance');
$PAGE->set_title($title);
$PAGE->set_heading($title);
$PAGE->set_url(new moodle_url('/repository/boxnet/migrationv1.php'));
$PAGE->navbar->add($title);
$confirm = optional_param('confirm', false, PARAM_BOOL);
echo $OUTPUT->header();
echo $OUTPUT->heading('Reference migration tool');
if ($confirm && confirm_sesskey()) {
echo html_writer::start_tag('pre', array());
repository_boxnet_migrate_references_from_apiv1();
echo html_writer::end_tag('pre', array());
} else {
$a = new stdClass();
$a->docsurl = get_docs_url('Box.net_APIv1_migration');
echo html_writer::tag('p', get_string('migrationinfo', 'repository_boxnet', $a));
$execurl = new moodle_url('/repository/boxnet/migrationv1.php', array('confirm' => 1, 'sesskey' => sesskey()));
$button = new single_button($execurl, get_string('runthemigrationnow', 'repository_boxnet'));
echo $OUTPUT->render($button);
}
echo $OUTPUT->footer();