[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Box.net locallib. 19 * 20 * @package repository_boxnet 21 * @copyright 2013 Frédéric Massart 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 /** 26 * Migrate the references to local files. 27 * 28 * As the APIv1 is reaching its end of life on the 14th of Dec 2013, and we cannot 29 * convert the existing references to new references, we need to convert them 30 * to real files. 31 * 32 * @todo Deprecate/remove this function after the 14th of December 2013. 33 * @return void 34 */ 35 function repository_boxnet_migrate_references_from_apiv1() { 36 global $DB; 37 38 // A string that the old references contain. 39 $apiv1signature = '/api/1.0/download/'; 40 41 // Downloading the files could take a very long time! 42 @set_time_limit(0); 43 44 // Create directory to download temporary files. 45 $dir = make_temp_directory('download/repository_boxnet/'); 46 47 // Create a dummy file for the broken files. 48 $fs = get_file_storage(); 49 list($dummyhash, $dummysize, $unused) = $fs->add_string_to_pool('Lost reference from Box.net'); 50 51 // Get the Box.net instances. There should be only one. 52 $sql = "SELECT i.id, i.typeid, r.id, r.type 53 FROM {repository} r, {repository_instances} i 54 WHERE i.typeid = r.id 55 AND r.type = :type"; 56 $ids = $DB->get_fieldset_sql($sql, array('type' => 'boxnet')); 57 if (empty($ids)) { 58 // We did not find any instance of Box.net. Let's just ignore this migration. 59 mtrace('Could not find any instance of the repository, aborting migration...'); 60 return; 61 } 62 63 // The next bit is copied from the function file_storage::instance_sql_fields() 64 // because it is private and there is nothing in file_storage that suits our needs here. 65 $filefields = array('contenthash', 'pathnamehash', 'contextid', 'component', 'filearea', 66 'itemid', 'filepath', 'filename', 'userid', 'filesize', 'mimetype', 'status', 'source', 67 'author', 'license', 'timecreated', 'timemodified', 'sortorder', 'referencefileid'); 68 $referencefields = array('repositoryid' => 'repositoryid', 69 'reference' => 'reference', 70 'lastsync' => 'referencelastsync'); 71 $fields = array(); 72 $fields[] = 'f.id AS id'; 73 foreach ($filefields as $field) { 74 $fields[] = "f.{$field}"; 75 } 76 foreach ($referencefields as $field => $alias) { 77 $fields[] = "r.{$field} AS {$alias}"; 78 } 79 $fields = implode(', ', $fields); 80 81 // We are not using repository::convert_references_to_local() or file_storage::get_external_files() 82 // because they would select too many records and load everything in memory as it is not using a recordset. 83 // Also, we filter the results not to get the draft area which should not be converted. 84 list($sqlfragment, $fragmentparams) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED); 85 $sql = "SELECT " . $fields . " 86 FROM {files_reference} r 87 LEFT JOIN {files} f 88 ON f.referencefileid = r.id 89 WHERE r.repositoryid $sqlfragment 90 AND f.referencefileid IS NOT NULL 91 AND NOT (f.component = :component 92 AND f.filearea = :filearea)"; 93 94 // For each reference we download the file. Then we add it to the file pool and update the references. 95 // The reason why we are re-inventing the wheel here is because the current API ends up calling 96 // repository::get_file() which includes a download timeout. As we are trying our best to copy 97 // the files here, we want to ignre any timeout. 98 $filerecords = $DB->get_recordset_sql($sql, array_merge($fragmentparams, array('component' => 'user', 'filearea' => 'draft'))); 99 $referenceids = array(); 100 foreach ($filerecords as $filerecord) { 101 $file = $fs->get_file_instance($filerecord); 102 $reference = unserialize(repository_boxnet::convert_to_valid_reference($file->get_reference())); 103 104 if (empty($reference->downloadurl)) { 105 // Something is wrong... 106 mtrace('Skipping malformed reference (id: ' . $file->get_referencefileid() . ')'); 107 continue; 108 } else if (strpos($reference->downloadurl, $apiv1signature) === false) { 109 // This is not an old reference, we are not supposed to work on thos. 110 mtrace('Skipping non APIv1 reference (id: ' . $file->get_referencefileid() . ')'); 111 continue; 112 } else if (isset($referenceids[$file->get_referencefileid()])) { 113 // We have already worked on that reference, we skip any other file related to it. 114 // We cannot work on them here because they have been updated in the database but our 115 // recordset does not have those new values. They will be taken care of after this foreach. 116 continue; 117 } 118 119 mtrace('Starting migration of file reference ' . $file->get_referencefileid()); 120 121 // Manually import the file to the file pool to prevent timeout limitations of the repository method get_file(). 122 // We ignore the fact that the content of the file could exist locally because we want to synchronize the file 123 // now to prevent the repository to try to download the file as well. 124 $saveas = $dir . uniqid('', true) . '_' . time() . '.tmp'; 125 $c = new curl(); 126 $result = $c->download_one($reference->downloadurl, null, array('filepath' => $saveas, 'followlocation' => true)); 127 $info = $c->get_info(); 128 if ($result !== true || !isset($info['http_code']) || $info['http_code'] != 200) { 129 // There was a problem while trying to download the reference... 130 if ($fs->content_exists($file->get_contenthash()) && $file->get_contenthash() != sha1('')) { 131 // Fortunately we already had a local version of this reference, so we keep it. We have to 132 // set it synchronized or there is a risk that repository::sync_reference() will try to download 133 // the file again. We cannot use $file->get_contenthash() and $file->get_filesize() because they 134 // cause repository::sync_reference() to be called. 135 $file->set_synchronized($filerecord->contenthash, $filerecord->filesize); 136 mtrace('Could not download reference, using last synced file. (id: ' . $file->get_referencefileid() . ')'); 137 } else { 138 // We don't know what the file was, but what can we do? In order to prevent a re-attempt to fetch the 139 // file in the next bit of this script (import_external_file()), we set a dummy content to the reference. 140 $file->set_synchronized($dummyhash, $dummysize); 141 mtrace('Could not download reference, dummy file used. (id: ' . $file->get_referencefileid() . ')'); 142 } 143 } else { 144 try { 145 // The file has been downloaded, we add it to the file pool and synchronize 146 // all the files using this reference. 147 list($contenthash, $filesize, $unused) = $fs->add_file_to_pool($saveas); 148 $file->set_synchronized($contenthash, $filesize); 149 } catch (moodle_exception $e) { 150 // Something wrong happened... 151 mtrace('Something went wrong during sync (id: ' . $file->get_referencefileid() . ')'); 152 } 153 } 154 155 // Log the reference IDs. 156 $referenceids[$file->get_referencefileid()] = $file->get_referencefileid(); 157 158 // Now that the file is downloaded, we can loop over all the files using this reference 159 // to convert them to local copies. We have chosen to do that in this loop so that if the 160 // execution fails in the middle, we would not have to redownload the files again and again. 161 // By the way, we cannot use the records fetched in $filerecords because they will not be updated. 162 $sql = "SELECT " . $fields . " 163 FROM {files} f 164 LEFT JOIN {files_reference} r 165 ON f.referencefileid = r.id 166 WHERE f.referencefileid = :refid 167 AND NOT (f.component = :component 168 AND f.filearea = :filearea)"; 169 $reffilerecords = $DB->get_recordset_sql($sql, array('component' => 'user', 'filearea' => 'draft', 170 'refid' => $file->get_referencefileid())); 171 foreach ($reffilerecords as $reffilerecord) { 172 $reffile = $fs->get_file_instance($reffilerecord); 173 try { 174 // Updating source to remove trace of APIv1 URL. 175 $reffile->set_source('Box APIv1 reference'); 176 } catch (moodle_exception $e) { 177 // Do not fail for this lame reason... 178 } 179 try { 180 $fs->import_external_file($reffile); 181 mtrace('File using reference converted to local file (id: ' . $reffile->get_id() . ')'); 182 } catch (moodle_exception $e) { 183 // Oh well... we tried what we could! 184 $reffile->delete_reference(); 185 mtrace('Failed to convert file from reference to local file, sorry! (id: ' . $reffile->get_id() . ')'); 186 } 187 } 188 } 189 190 mtrace('Migration finished.'); 191 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |