Skip to content

Commit

Permalink
MDL-51789 users: Allow picture update from webservices.
Browse files Browse the repository at this point in the history
useredit_update_picture as moved to user_update_picture
as it's more general.  It was also moved to user/lib.php
so it can be used by both webservices and edit without more include files.
  • Loading branch information
mr-russ committed Jun 21, 2016
1 parent 49619ce commit 5407c5b
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 52 deletions.
61 changes: 61 additions & 0 deletions lib/classes/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,67 @@ public static function require_active_user($user, $checksuspended = false, $chec
}
}

/**
* Updates the provided users profile picture based upon the expected fields returned from the edit or edit_advanced forms.
*
* @param stdClass $usernew An object that contains some information about the user being updated
* @param array $filemanageroptions
* @return bool True if the user was updated, false if it stayed the same.
*/
public static function update_picture(stdClass $usernew, $filemanageroptions = array()) {
global $CFG, $DB;
require_once("$CFG->libdir/gdlib.php");

$context = context_user::instance($usernew->id, MUST_EXIST);
$user = core_user::get_user($usernew->id, 'id, picture', MUST_EXIST);

$newpicture = $user->picture;
// Get file_storage to process files.
$fs = get_file_storage();
if (!empty($usernew->deletepicture)) {
// The user has chosen to delete the selected users picture.
$fs->delete_area_files($context->id, 'user', 'icon'); // Drop all images in area.
$newpicture = 0;

} else {
// Save newly uploaded file, this will avoid context mismatch for newly created users.
file_save_draft_area_files($usernew->imagefile, $context->id, 'user', 'newicon', 0, $filemanageroptions);
if (($iconfiles = $fs->get_area_files($context->id, 'user', 'newicon')) && count($iconfiles) == 2) {
// Get file which was uploaded in draft area.
foreach ($iconfiles as $file) {
if (!$file->is_directory()) {
break;
}
}
// Copy file to temporary location and the send it for processing icon.
if ($iconfile = $file->copy_content_to_temp()) {
// There is a new image that has been uploaded.
// Process the new image and set the user to make use of it.
// NOTE: Uploaded images always take over Gravatar.
$newpicture = (int)process_new_icon($context, 'user', 'icon', 0, $iconfile);
// Delete temporary file.
@unlink($iconfile);
// Remove uploaded file.
$fs->delete_area_files($context->id, 'user', 'newicon');
} else {
// Something went wrong while creating temp file.
// Remove uploaded file.
$fs->delete_area_files($context->id, 'user', 'newicon');
return false;
}
}
}

if ($newpicture != $user->picture) {
$DB->set_field('user', 'picture', $newpicture, array('id' => $user->id));
return true;
} else {
return false;
}
}



/**
* Definition of user profile fields and the expected parameter type for data validation.
*
Expand Down
2 changes: 1 addition & 1 deletion user/edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@

// Update user picture.
if (empty($CFG->disableuserimages)) {
useredit_update_picture($usernew, $userform, $filemanageroptions);
core_user::update_picture($usernew, $filemanageroptions);
}

// Update mail bounces.
Expand Down
2 changes: 1 addition & 1 deletion user/editadvanced.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@

// Update user picture.
if (empty($USER->newadminuser)) {
useredit_update_picture($usernew, $userform, $filemanageroptions);
core_user::update_picture($usernew, $filemanageroptions);
}

// Update mail bounces.
Expand Down
57 changes: 7 additions & 50 deletions user/editlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,62 +164,19 @@ function useredit_update_user_preference($usernew) {
/**
* Updates the provided users profile picture based upon the expected fields returned from the edit or edit_advanced forms.
*
* @deprecated since Moodle 3.2 MDL-51789 - please use core_user::update_picture() instead.
* @todo MDL-54858 This will be deleted in Moodle 3.5.
* @see core_user::update_picture()
*
* @global moodle_database $DB
* @param stdClass $usernew An object that contains some information about the user being updated
* @param moodleform $userform The form that was submitted to edit the form
* @param moodleform $userform The form that was submitted to edit the form (unused)
* @param array $filemanageroptions
* @return bool True if the user was updated, false if it stayed the same.
*/
function useredit_update_picture(stdClass $usernew, moodleform $userform, $filemanageroptions = array()) {
global $CFG, $DB;
require_once("$CFG->libdir/gdlib.php");

$context = context_user::instance($usernew->id, MUST_EXIST);
$user = $DB->get_record('user', array('id' => $usernew->id), 'id, picture', MUST_EXIST);

$newpicture = $user->picture;
// Get file_storage to process files.
$fs = get_file_storage();
if (!empty($usernew->deletepicture)) {
// The user has chosen to delete the selected users picture.
$fs->delete_area_files($context->id, 'user', 'icon'); // Drop all images in area.
$newpicture = 0;

} else {
// Save newly uploaded file, this will avoid context mismatch for newly created users.
file_save_draft_area_files($usernew->imagefile, $context->id, 'user', 'newicon', 0, $filemanageroptions);
if (($iconfiles = $fs->get_area_files($context->id, 'user', 'newicon')) && count($iconfiles) == 2) {
// Get file which was uploaded in draft area.
foreach ($iconfiles as $file) {
if (!$file->is_directory()) {
break;
}
}
// Copy file to temporary location and the send it for processing icon.
if ($iconfile = $file->copy_content_to_temp()) {
// There is a new image that has been uploaded.
// Process the new image and set the user to make use of it.
// NOTE: Uploaded images always take over Gravatar.
$newpicture = (int)process_new_icon($context, 'user', 'icon', 0, $iconfile);
// Delete temporary file.
@unlink($iconfile);
// Remove uploaded file.
$fs->delete_area_files($context->id, 'user', 'newicon');
} else {
// Something went wrong while creating temp file.
// Remove uploaded file.
$fs->delete_area_files($context->id, 'user', 'newicon');
return false;
}
}
}

if ($newpicture != $user->picture) {
$DB->set_field('user', 'picture', $newpicture, array('id' => $user->id));
return true;
} else {
return false;
}
debugging('useredit_update_picture() is deprecated. Please use core_user::update_picture() instead.', DEBUG_DEVELOPER);
return core_user::update_picture($usernew, $filemanageroptions);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions user/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ public static function update_users_parameters() {
new external_value(core_user::get_property_type('middlename'), 'The middle name of the user', VALUE_OPTIONAL),
'alternatename' =>
new external_value(core_user::get_property_type('alternatename'), 'The alternate name of the user', VALUE_OPTIONAL),
'userpicture' =>
new external_value(PARAM_INT, 'The itemid where the new user picture '.
'has been uploaded to, 0 to delete', VALUE_OPTIONAL),
'customfields' => new external_multiple_structure(
new external_single_structure(
array(
Expand Down Expand Up @@ -426,10 +429,31 @@ public static function update_users($users) {

$params = self::validate_parameters(self::update_users_parameters(), array('users' => $users));

$filemanageroptions = array('maxbytes' => $CFG->maxbytes,
'subdirs' => 0,
'maxfiles' => 1,
'accepted_types' => 'web_image');

$transaction = $DB->start_delegated_transaction();

foreach ($params['users'] as $user) {
user_update_user($user, true, false);

// Update user picture if it was specified for this user.
if (empty($CFG->disableuserimages) && isset($user['userpicture'])) {
$userobject = (object)$user;

$userobject->deletepicture = null;

if ($user['userpicture'] == 0) {
$userobject->deletepicture = true;
} else {
$userobject->imagefile = $user['userpicture'];
}

core_user::update_picture($userobject, $filemanageroptions);
}

// Update user custom fields.
if (!empty($user['customfields'])) {

Expand Down
31 changes: 31 additions & 0 deletions user/tests/externallib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,22 @@ public function test_update_users() {

$this->resetAfterTest(true);

$wsuser = self::getDataGenerator()->create_user();
self::setUser($wsuser);

$context = context_user::instance($USER->id);
$contextid = $context->id;
$filename = "reddot.png";
$filecontent = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38"
. "GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";

// Call the files api to create a file.
$draftfile = core_files_external::upload($contextid, 'user', 'draft', 0, '/',
$filename, $filecontent, null, null);
$draftfile = external_api::clean_returnvalue(core_files_external::upload_returns(), $draftfile);

$draftid = $draftfile['itemid'];

$user1 = self::getDataGenerator()->create_user();

$user1 = array(
Expand All @@ -582,6 +598,7 @@ public function test_update_users() {
'email' => '[email protected]',
'description' => 'This is a description for user 1',
'city' => 'Perth',
'userpicture' => $draftid,
'country' => 'AU'
);

Expand All @@ -600,6 +617,20 @@ public function test_update_users() {
$this->assertEquals($dbuser->description, $user1['description']);
$this->assertEquals($dbuser->city, $user1['city']);
$this->assertEquals($dbuser->country, $user1['country']);
$this->assertNotEquals(0, $dbuser->picture, 'Picture must be set to the new icon itemid for this user');

// Confirm no picture change when parameter is not supplied.
unset($user1['userpicture']);
core_user_external::update_users(array($user1));
$dbusernopic = $DB->get_record('user', array('id' => $user1['id']));
$this->assertEquals($dbuser->picture, $dbusernopic->picture, 'Picture not change without the parameter.');

// Confirm delete of picture deletes the picture from the user record.
$user1['userpicture'] = 0;
core_user_external::update_users(array($user1));
$dbuserdelpic = $DB->get_record('user', array('id' => $user1['id']));
$this->assertEquals(0, $dbuserdelpic->picture, 'Picture must be deleted when sent as 0.');


// Call without required capability.
$this->unassignUserCapability('moodle/user:update', $context->id, $roleid);
Expand Down

0 comments on commit 5407c5b

Please sign in to comment.