diff --git a/admin/uploadpicture.php b/admin/uploadpicture.php
index e8da6dcb698c4..e078cd48d0d21 100644
--- a/admin/uploadpicture.php
+++ b/admin/uploadpicture.php
@@ -241,12 +241,8 @@ function process_file ($file, $userfield, $overwrite) {
* @return bool
*/
function my_save_profile_image($id, $originalfile) {
- $destination = create_profile_image_destination($id, 'user');
- if ($destination === false) {
- return false;
- }
-
- return process_profile_image($originalfile, $destination);
+ $context = get_context_instance(CONTEXT_USER, $id);
+ return process_new_icon($context, 'user', 'icon', 0, $originalfile);
}
diff --git a/enrol/imsenterprise/enrol.php b/enrol/imsenterprise/enrol.php
index 1575f28905ffc..e10bb2415aefc 100644
--- a/enrol/imsenterprise/enrol.php
+++ b/enrol/imsenterprise/enrol.php
@@ -661,7 +661,7 @@ function process_person_tag($tagcontents){
$person->picture = 1;
//Llibreria creada per nosaltres mateixos.
require_once($CFG->dirroot.'/lib/gdlib.php');
- if ($usernew->picture = save_profile_image($id, $person->urlphoto,'user')) {
+ if ($usernew->picture = save_profile_image($id, $person->urlphoto,'user')) { TODO: use process_new_icon() instead
$DB->set_field('user', 'picture', $usernew->picture, array('id'=>$id)); /// Note picture in DB
}
}
diff --git a/file.php b/file.php
index 661453e646b7f..5f9a61c89e5d2 100644
--- a/file.php
+++ b/file.php
@@ -17,10 +17,8 @@
/**
* This script fetches legacy course files in dataroot directory, it is enabled
- * only if course->legacyfiles == 2.
+ * only if course->legacyfiles == 2. DO not link to this file in new code.
*
- * You should use the get_file_url() function, available in lib/filelib.php, to link to file.php.
- * This ensures proper formatting and offers useful options.
* Syntax: file.php/courseid/dir/dir/dir/filename.ext
* file.php/courseid/dir/dir/dir/filename.ext?forcedownload=1 (download instead of inline)
* file.php/courseid/dir (returns index.html from dir)
diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php
index 04350addefab0..d4df931d8b3c9 100644
--- a/lib/db/upgrade.php
+++ b/lib/db/upgrade.php
@@ -4723,12 +4723,18 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2010071000);
}
- if ($oldversion < 2010071001) {
+ if ($oldversion < 2010071001) {
// purge obsolete stats settings
unset_config('statscatdepth');
upgrade_main_savepoint(true, 2010071001);
}
+ if ($oldversion < 2010071100) {
+ // move user icons to file storage pool
+ upgrade_migrate_user_icons();
+ upgrade_main_savepoint(true, 2010071100);
+ }
+
return true;
}
diff --git a/lib/db/upgradelib.php b/lib/db/upgradelib.php
index e3a018f192c83..410cd6f982172 100644
--- a/lib/db/upgradelib.php
+++ b/lib/db/upgradelib.php
@@ -79,6 +79,58 @@ function upgrade_migrate_files_courses() {
return true;
}
+/**
+ * Internal function - do not use directly
+ */
+function upgrade_migrate_user_icons() {
+ global $CFG, $OUTPUT, $DB;
+
+ $fs = get_file_storage();
+
+ $icon = array('component'=>'user', 'filearea'=>'icon', 'itemid'=>0, 'filepath'=>'/');
+
+ $count = $DB->count_records('user', array('picture'=>1, 'deleted'=>0));
+ $pbar = new progress_bar('migratecoursefiles', 500, true);
+
+ $rs = $DB->get_recordset('user', array('picture'=>1, 'deleted'=>0), 'id ASC', 'id, picture');
+ $i = 0;
+ foreach ($rs as $user) {
+ $i++;
+ upgrade_set_timeout(60); /// Give upgrade at least 60 more seconds
+ $pbar->update($i, $count, "Migrated course files - course $i/$count.");
+
+ $context = get_context_instance(CONTEXT_USER, $user->id);
+
+ if ($fs->file_exists($context->id, 'user', 'icon', 0, '/', 'f1.jpg')) {
+ // already converted!
+ continue;
+ }
+
+ $level1 = floor($user->id / 1000) * 1000;
+ $userdir = "$CFG->dataroot/user/$level1/$user->id";
+ if (!file_exists("$userdir/f1.jpg") or !file_exists("$userdir/f2.jpg")) {
+ $userdir = "$CFG->dataroot/users/$user->id";
+ if (!file_exists("$userdir/f1.jpg") or !file_exists("$userdir/f2.jpg")) {
+ // no image found, sorry
+ $user->picture = 0;
+ $DB->update_record('user', $user);
+ continue;
+ }
+ }
+
+ $icon['contextid'] = $context->id;
+ $icon['filename'] = 'f1.jpg';
+ $fs->create_file_from_pathname($icon, "$userdir/f1.jpg");
+ $icon['filename'] = 'f2.jpg';
+ $fs->create_file_from_pathname($icon, "$userdir/f2.jpg");
+ }
+ $rs->close();
+
+ // purge all old user image dirs
+// remove_dir("$CFG->dataroot/user");
+// remove_dir("$CFG->dataroot/users");
+}
+
/**
* Internal function - do not use directly
*/
diff --git a/lib/formslib.php b/lib/formslib.php
index e0e29a4f3e24e..590b46c436e43 100644
--- a/lib/formslib.php
+++ b/lib/formslib.php
@@ -591,7 +591,6 @@ function save_file($elname, $pathname, $override=false) {
if (!$this->is_submitted() or !$this->is_validated()) {
return false;
}
-
if (file_exists($pathname)) {
if ($override) {
if (!@unlink($pathname)) {
@@ -626,6 +625,31 @@ function save_file($elname, $pathname, $override=false) {
return false;
}
+ /**
+ * Returns a temporary file, do not forget to delete after not needed any more.
+ *
+ * @param string $elname
+ * @return string or false
+ */
+ function save_temp_file($elname) {
+ if (!$this->get_new_filename($elname)) {
+ return false;
+ }
+ if (!$dir = make_upload_directory('temp/forms')) {
+ return false;
+ }
+ if (!$tempfile = tempnam($dir, 'tempup_')) {
+ return false;
+ }
+ if (!$this->save_file($elname, $tempfile, true)) {
+ // something went wrong
+ @unlink($tempfile);
+ return false;
+ }
+
+ return $tempfile;
+ }
+
/**
* Get draft files of a form element
* This is a protected method which will be used only inside moodleforms
diff --git a/lib/gdlib.php b/lib/gdlib.php
index 1982a94ebccf2..7b110af9a2f87 100644
--- a/lib/gdlib.php
+++ b/lib/gdlib.php
@@ -95,6 +95,8 @@ function ImageCopyBicubic ($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $
function delete_profile_image($id, $dir='users') {
global $CFG;
+//TODO: deprecate
+
require_once $CFG->libdir.'/filelib.php';
$location = $CFG->dataroot .'/'. $dir .'/'. $id;
@@ -117,6 +119,8 @@ function delete_profile_image($id, $dir='users') {
function create_profile_image_destination($id, $dir='user') {
global $CFG;
+//TODO: deprecate
+
umask(0000);
if (!file_exists($CFG->dataroot .'/'. $dir)) {
@@ -139,6 +143,121 @@ function create_profile_image_destination($id, $dir='user') {
return $destination;
}
+/**
+ * Stores optimised icon images in icon file area
+ *
+ * @param $context
+ * @param component
+ * @param $itemid
+ * @param $originalfile
+ * @return success
+ */
+function process_new_icon($context, $component, $filearea, $itemid, $originalfile) {
+ global $CFG;
+
+ if (empty($CFG->gdversion)) {
+ return false;
+ }
+
+ if (!is_file($originalfile)) {
+ return false;
+ }
+
+ $imageinfo = GetImageSize($originalfile);
+
+ if (empty($imageinfo)) {
+ return false;
+ }
+
+ $image->width = $imageinfo[0];
+ $image->height = $imageinfo[1];
+ $image->type = $imageinfo[2];
+
+ switch ($image->type) {
+ case IMAGETYPE_GIF:
+ if (function_exists('ImageCreateFromGIF')) {
+ $im = ImageCreateFromGIF($originalfile);
+ } else {
+ debugging('GIF not supported on this server');
+ return false;
+ }
+ break;
+ case IMAGETYPE_JPEG:
+ if (function_exists('ImageCreateFromJPEG')) {
+ $im = ImageCreateFromJPEG($originalfile);
+ } else {
+ debugging('JPEG not supported on this server');
+ return false;
+ }
+ break;
+ case IMAGETYPE_PNG:
+ if (function_exists('ImageCreateFromPNG')) {
+ $im = ImageCreateFromPNG($originalfile);
+ } else {
+ debugging('PNG not supported on this server');
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+
+
+ if (function_exists('ImageCreateTrueColor') and $CFG->gdversion >= 2) {
+ $im1 = ImageCreateTrueColor(100,100);
+ $im2 = ImageCreateTrueColor(35,35);
+ } else {
+ $im1 = ImageCreate(100,100);
+ $im2 = ImageCreate(35,35);
+ }
+
+ $cx = $image->width / 2;
+ $cy = $image->height / 2;
+
+ if ($image->width < $image->height) {
+ $half = floor($image->width / 2.0);
+ } else {
+ $half = floor($image->height / 2.0);
+ }
+
+ 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);
+
+ if (!function_exists('ImageJpeg')) {
+ debugging('Jpeg not supported on this server, please fix server configuration');
+ return false;
+ }
+
+ $fs = get_file_storage();
+
+ $icon = array('contextid'=>$context->id, 'component'=>$component, 'filearea'=>$filearea, 'itemid'=>$itemid, 'filepath'=>'/');
+
+ ob_start();
+ if (!ImageJpeg($im1, NULL, 90)) {
+ // keep old icons
+ ob_end_clean();
+ return false;
+ }
+ $data = ob_get_clean();
+ ImageDestroy($im1);
+ $icon['filename'] = 'f1.jpg';
+ $fs->delete_area_files($context->id, $component, $filearea, $itemid);
+ $fs->create_file_from_string($icon, $data);
+
+ ob_start();
+ if (!ImageJpeg($im2, NULL, 95)) {
+ ob_end_clean();
+ $fs->delete_area_files($context->id, $component, $filearea, $itemid);
+ return false;
+ }
+ $data = ob_get_clean();
+ ImageDestroy($im2);
+ $icon['filename'] = 'f2.jpg';
+ $fs->create_file_from_string($icon, $data);
+
+ return true;
+}
+
/**
* Given an upload manager with the right settings, this function performs a virus scan, and then scales and crops
* it and saves it in the right place to be a "user" or "group" image.
@@ -150,6 +269,8 @@ function create_profile_image_destination($id, $dir='user') {
*/
function save_profile_image($id, $userform, $dir='user') {
+//TODO: deprecate
+
$destination = create_profile_image_destination($id, $dir);
if ($destination === false) {
return false;
@@ -177,6 +298,8 @@ function save_profile_image($id, $userform, $dir='user') {
function process_profile_image($originalfile, $destination) {
global $CFG, $OUTPUT;
+//TODO: deprecate
+
if(!(is_file($originalfile) && is_dir($destination))) {
return false;
}
@@ -280,6 +403,8 @@ function process_profile_image($originalfile, $destination) {
function upgrade_profile_image($id, $dir='users') {
global $CFG, $OUTPUT;
+//TODO: deprecate
+
$im = ImageCreateFromJPEG($CFG->dataroot .'/'. $dir .'/'. $id .'/f1.jpg');
if (function_exists('ImageCreateTrueColor') and $CFG->gdversion >= 2) {
diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index 0e74d26a4b4b4..834eb1adc3938 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -3445,7 +3445,7 @@ function delete_user($user) {
// last course access not necessary either
$DB->delete_records('user_lastaccess', array('userid'=>$user->id));
- // final accesslib cleanup - removes all role assignments in user context and context itself
+ // final accesslib cleanup - removes all role assignments in user context and context itself, files, etc.
delete_context(CONTEXT_USER, $user->id);
require_once($CFG->dirroot.'/tag/lib.php');
diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php
index 0c67eaafa59a7..f49cec98bab2b 100644
--- a/lib/outputrenderers.php
+++ b/lib/outputrenderers.php
@@ -1728,9 +1728,13 @@ protected function render_user_picture(user_picture $userpicture) {
$class = $userpicture->class;
- if (!empty($user->picture)) {
- require_once($CFG->libdir.'/filelib.php');
- $src = new moodle_url(get_file_url($user->id.'/'.$file.'.jpg', null, 'user'));
+ if ($user->picture == 1) {
+ $usercontext = get_context_instance(CONTEXT_USER, $user->id);
+ $src = moodle_url::make_pluginfile_url($usercontext->id, 'user', 'icon', NULL, '/', $file);
+
+ } else if ($user->picture == 2) {
+ //TODO: gravatar user icon support
+
} else { // Print default user pictures (use theme version if available)
$class .= ' defaultuserpic';
$src = $this->pix_url('u/' . $file);
diff --git a/pluginfile.php b/pluginfile.php
index 98d4048bb0984..d8df6f011f28d 100644
--- a/pluginfile.php
+++ b/pluginfile.php
@@ -293,7 +293,22 @@
// ========================================================================================================================
} else if ($component === 'user') {
- if ($filearea === 'private' and $context->contextlevel == CONTEXT_USER) {
+ if ($filearea === 'icon' and $context->contextlevel == CONTEXT_USER) {
+ if (!empty($CFG->forcelogin) and !isloggedin()) {
+ // protect images if login required and not logged in;
+ // do not use require_login() because it is expensive and not suitable here anyway
+ redirect($OUTPUT->pix_url('u/f1'));
+ }
+ $filename = array_pop($args);
+ if ($filename !== 'f1' and $filename !== 'f2') {
+ redirect($OUTPUT->pix_url('u/f1'));
+ }
+ if (!$file = $fs->get_file($context->id, 'user', 'icon', 0, '/', $filename.'/.jpg')) {
+ redirect($OUTPUT->pix_url('u/f1'));
+ }
+ send_stored_file($file, 60*60*24); // enable long caching, there are many images on each page
+
+ } else if ($filearea === 'private' and $context->contextlevel == CONTEXT_USER) {
require_login();
if (isguestuser()) {
diff --git a/user/editlib.php b/user/editlib.php
index 409c9bcfbcb2f..315aa480ee172 100644
--- a/user/editlib.php
+++ b/user/editlib.php
@@ -36,14 +36,18 @@ function useredit_update_user_preference($usernew) {
function useredit_update_picture(&$usernew, $userform) {
global $CFG, $DB;
+ $fs = get_file_storage();
+ $context = get_context_instance(CONTEXT_USER, $usernew->id, MUST_EXIST);
+
if (isset($usernew->deletepicture) and $usernew->deletepicture) {
- $location = make_user_directory($usernew->id, true);
- @remove_dir($location);
+ $fs->delete_area_files($context->id, 'user', 'icon'); // drop all areas
$DB->set_field('user', 'picture', 0, array('id'=>$usernew->id));
- } else if ($userform->get_new_filename('imagefile')) {
- $usernew->picture = (int)save_profile_image($usernew->id, $userform, 'user', 'imagefile');
- $DB->set_field('user', 'picture', $usernew->picture, array('id'=>$usernew->id));
+ } else if ($iconfile = $userform->save_temp_file('imagefile')) {
+ if (process_new_icon($context, 'user', 'icon', 0, $iconfile)) {
+ $DB->set_field('user', 'picture', 1, array('id'=>$usernew->id));
+ }
+ @unlink($iconfile);
}
}
@@ -239,7 +243,7 @@ function useredit_shared_definition(&$mform, $editoroptions = null) {
$mform->addElement('static', 'currentpicture', get_string('currentpicture'));
$mform->addElement('checkbox', 'deletepicture', get_string('delete'));
- $mform->setDefault('deletepicture',false);
+ $mform->setDefault('deletepicture', 0);
$mform->addElement('filepicker', 'imagefile', get_string('newpicture'));
$mform->addHelpButton('imagefile', 'newpicture');
diff --git a/user/pix.php b/user/pix.php
deleted file mode 100644
index ecb8408929c11..0000000000000
--- a/user/pix.php
+++ /dev/null
@@ -1,35 +0,0 @@
-libdir.'/filelib.php');
-
- if (!empty($CFG->forcelogin) and !isloggedin()) {
- // protect images if login required and not logged in;
- // do not use require_login() because it is expensive and not suitable here anyway
- redirect($OUTPUT->pix_url('u/f1'));
- }
-
- $relativepath = get_file_argument();
-
- $args = explode('/', trim($relativepath, '/'));
-
- if (count($args) == 2) {
- $userid = (integer)$args[0];
- // do not serve images of deleted users
- if ($user = $DB->get_record('user', array('id'=>$userid, 'deleted'=>0, 'picture'=>1))) {
- $image = $args[1];
- $pathname = make_user_directory($userid, true) . "/$image";
- if (file_exists($pathname) and !is_dir($pathname)) {
- send_file($pathname, $image);
- }
- }
- }
-
- // picture was deleted - use default instead
- redirect($OUTPUT->pix_url('u/f1'));
diff --git a/userpix/index.php b/userpix/index.php
index 73d98e8aeb3d1..9c234a6c09474 100644
--- a/userpix/index.php
+++ b/userpix/index.php
@@ -1,40 +1,36 @@
set_url('/userpix/index.php');
+$PAGE->set_url('/userpix/index.php');
- require_login();
+require_login();
/// Remove the following three lines if you want everyone to access it
- require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
-
- if (!$users = $DB->get_records("user", array("picture"=>"1"), "lastaccess DESC", "id,firstname,lastname")) {
- print_error("nousers");
- }
-
- $title = get_string("users");
-
- $PAGE->navbar->add($title);
- $PAGE->set_title($title);
- $PAGE->set_heading($title);
- echo $OUTPUT->header();
-
- foreach ($users as $user) {
- $fullname = fullname($user);
- echo "wwwroot/user/view.php?id=$user->id&course=1\" ".
- "title=\"$fullname\">";
- require_once($CFG->libdir.'/filelib.php');
- $userpictureurl = get_file_url($user->id.'/f1.jpg', null, 'user');
- echo '';
- echo " \n";
- }
-
- echo $OUTPUT->footer();
+require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
+
+$title = get_string("users");
+
+$PAGE->navbar->add($title);
+$PAGE->set_title($title);
+$PAGE->set_heading($title);
+echo $OUTPUT->header();
+
+$rs = $DB->get_recordset_select("user", "deleted = 0 AND picture > 0", array(), "lastaccess DESC", user_picture::fields());
+foreach ($rs as $user) {
+ $fullname = fullname($user);
+ echo "wwwroot/user/view.php?id=$user->id&course=1\" ".
+ "title=\"$fullname\">";
+ require_once($CFG->libdir.'/filelib.php');
+ echo $OUTPUT->user_picture($user);
+ echo " \n";
+}
+$rs->close();
+
+echo $OUTPUT->footer();
diff --git a/userpix/upgrade.php b/userpix/upgrade.php
deleted file mode 100644
index 8017dcccb2fe0..0000000000000
--- a/userpix/upgrade.php
+++ /dev/null
@@ -1,37 +0,0 @@
-set_url('/userpix/upgrade.php');
-
- require_login();
-
- require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
-
- if (!$users = $DB->get_records("user", array("picture"=>"1"), "lastaccess DESC", "id,firstname,lastname")) {
- print_error('nousers');
- }
-
- $title = get_string("users");
-
- $PAGE->navbar->add($title);
- $PAGE->set_title($title);
- $PAGE->set_heading($title);
- echo $OUTPUT->header();
-
- foreach ($users as $user) {
- upgrade_profile_image($user->id);
- $fullname = fullname($user);
- echo "wwwroot/user/view.php?id=$user->id&course=1\"".
- "title=\"$fullname\">";
- require_once($CFG->libdir.'/filelib.php');
- $userpictureurl = get_file_url($user->id.'/f1.jpg', null, 'user');
- echo '';
- echo " \n";
- }
-
- echo $OUTPUT->footer();
diff --git a/version.php b/version.php
index 82e930d5342c2..17aad27bfbeb9 100644
--- a/version.php
+++ b/version.php
@@ -6,7 +6,7 @@
// This is compared against the values stored in the database to determine
// whether upgrades should be performed (see lib/db/*.php)
- $version = 2010071001; // YYYYMMDD = date of the last version bump
+ $version = 2010071100; // YYYYMMDD = date of the last version bump
// XX = daily increments
$release = '2.0 Preview 4+ (Build: 20100711)'; // Human-friendly version name