Skip to content

Commit

Permalink
MDL-14589 user icons now stored in file storage pool
Browse files Browse the repository at this point in the history
  • Loading branch information
skodak committed Jul 11, 2010
1 parent 37416d5 commit edfd6a5
Show file tree
Hide file tree
Showing 15 changed files with 277 additions and 129 deletions.
8 changes: 2 additions & 6 deletions admin/uploadpicture.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


2 changes: 1 addition & 1 deletion enrol/imsenterprise/enrol.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
4 changes: 1 addition & 3 deletions file.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion lib/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
52 changes: 52 additions & 0 deletions lib/db/upgradelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
26 changes: 25 additions & 1 deletion lib/formslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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
Expand Down
125 changes: 125 additions & 0 deletions lib/gdlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)) {
Expand All @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion lib/moodlelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
10 changes: 7 additions & 3 deletions lib/outputrenderers.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 16 additions & 1 deletion pluginfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down
Loading

0 comments on commit edfd6a5

Please sign in to comment.