1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-05-19 17:28:23 +03:00

fix #457 - кроп фото пользователя

This commit is contained in:
Mzhelskiy Maxim 2014-10-17 11:35:09 +07:00
parent eebd7a7e17
commit 23d83f1929
7 changed files with 306 additions and 86 deletions

View file

@ -81,6 +81,8 @@ class ActionSettings extends Action
$this->AddEvent('account', 'EventAccount');
$this->AddEventPreg('/^ajax-upload-photo$/i', '/^$/i', 'EventAjaxUploadPhoto');
$this->AddEventPreg('/^ajax-crop-photo$/i', '/^$/i', 'EventAjaxCropPhoto');
$this->AddEventPreg('/^ajax-crop-cancel-photo$/i', '/^$/i', 'EventAjaxCropCancelPhoto');
$this->AddEventPreg('/^ajax-remove-photo$/i', '/^$/i', 'EventAjaxRemovePhoto');
$this->AddEventPreg('/^ajax-change-avatar$/i', '/^$/i', 'EventAjaxChangeAvatar');
}
@ -110,18 +112,109 @@ class ActionSettings extends Action
if (!$oUser->isAllowEdit()) {
return $this->EventErrorDebug();
}
if (true !== $sResult = $this->User_UploadProfilePhoto($_FILES['photo'], $oUser)) {
$this->Message_AddError(is_bool($sResult) ? '' : $sResult, $this->Lang_Get('error'));
/**
* Копируем загруженный файл
*/
$sFileTmp = Config::Get('sys.cache.dir') . func_generator();
if (!move_uploaded_file($_FILES['photo']['tmp_name'], $sFileTmp)) {
return false;
}
/**
* Создаем аватар на основе фото
* Если объект изображения не создан, возвращаем ошибку
*/
$this->User_CreateProfileAvatar($oUser->getProfileFoto(), $oUser);
if (!$oImage = $this->Image_Open($sFileTmp)) {
$this->Fs_RemoveFileLocal($sFileTmp);
$this->Message_AddError($this->Image_GetLastError());
return;
}
/**
* Ресайзим и сохраняем именьшенную копию
* Храним две копии - мелкую для показа пользователю и крупную в качестве исходной для ресайза
*/
$sDir = Config::Get('path.uploads.images') . "/tmp/userphoto/{$oUser->getId()}";
if ($sFileOriginal = $oImage->resize(1000, null)->saveSmart($sDir, 'original')) {
if ($sFilePreview = $oImage->resize(350, null)->saveSmart($sDir, 'preview')) {
/**
* Сохраняем в сессии временный файл с изображением
*/
$this->Session_Set('sPhotoFileTmp', $sFileOriginal);
$this->Session_Set('sPhotoFilePreviewTmp', $sFilePreview);
$this->Viewer_AssignAjax('sTmpFile', $this->Fs_GetPathWeb($sFilePreview));
$this->Fs_RemoveFileLocal($sFileTmp);
return;
}
}
$this->Message_AddError($this->Image_GetLastError());
$this->Fs_RemoveFileLocal($sFileTmp);
}
$this->Viewer_AssignAjax('sChooseText', $this->Lang_Get('settings_profile_photo_change'));
$this->Viewer_AssignAjax('sFile', $oUser->getProfileFotoPath());
/**
* Обрезка фотографии в профиль пользователя
*/
protected function EventAjaxCropPhoto()
{
/**
* Устанавливаем формат Ajax ответа
*/
$this->Viewer_SetResponseAjax('json');
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {
return $this->EventErrorDebug();
}
$sFile = $this->Session_Get('sPhotoFileTmp');
$sFilePreview = $this->Session_Get('sPhotoFilePreviewTmp');
if (!$this->Image_IsExistsFile($sFile)) {
$this->Message_AddErrorSingle($this->Lang_Get('system_error'));
return;
}
if (true === ($res = $this->User_CreateProfilePhoto($sFile, $oUser, getRequest('size'),
getRequestStr('canvas_width')))
) {
$this->Image_RemoveFile($sFile);
$this->Image_RemoveFile($sFilePreview);
$this->Session_Drop('sPhotoFileTmp');
$this->Session_Drop('sPhotoFilePreviewTmp');
/**
* Создаем аватар на основе фото
*/
$this->User_CreateProfileAvatar($oUser->getProfileFoto(), $oUser);
$this->Viewer_AssignAjax('sChooseText', $this->Lang_Get('user.blocks.photo.change_photo'));
$this->Viewer_AssignAjax('sFile', $oUser->getProfileFotoPath());
} else {
$this->Message_AddError(is_string($res) ? $res : $this->Lang_Get('error'));
}
}
/**
* Удаляет временные файлы кропа фото
*/
protected function EventAjaxCropCancelPhoto()
{
/**
* Устанавливаем формат Ajax ответа
*/
$this->Viewer_SetResponseAjax('json');
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {
return $this->EventErrorDebug();
}
$sFile = $this->Session_Get('sPhotoFileTmp');
$sFilePreview = $this->Session_Get('sPhotoFilePreviewTmp');
$this->Image_RemoveFile($sFile);
$this->Image_RemoveFile($sFilePreview);
$this->Session_Drop('sPhotoFileTmp');
$this->Session_Drop('sPhotoFilePreviewTmp');
}
/**
@ -141,7 +234,7 @@ class ActionSettings extends Action
$this->User_DeleteProfilePhoto($oUser);
$this->User_DeleteProfileAvatar($oUser);
$this->User_Update($oUser);
$this->Viewer_AssignAjax('sChooseText', $this->Lang_Get('settings_profile_photo_upload'));
$this->Viewer_AssignAjax('sChooseText', $this->Lang_Get('user.blocks.photo.upload_photo'));
$this->Viewer_AssignAjax('sFile', $oUser->getProfileFotoPath());
}
@ -463,8 +556,8 @@ class ActionSettings extends Action
2) and func_check(getRequestStr('profile_birthday_year'), 'id', 4, 4)
) {
$this->oUserCurrent->setProfileBirthday(date("Y-m-d H:i:s",
mktime(0, 0, 0, getRequestStr('profile_birthday_month'), getRequestStr('profile_birthday_day'),
getRequestStr('profile_birthday_year'))));
mktime(0, 0, 0, getRequestStr('profile_birthday_month'), getRequestStr('profile_birthday_day'),
getRequestStr('profile_birthday_year'))));
} else {
$this->oUserCurrent->setProfileBirthday(null);
}

View file

@ -946,6 +946,10 @@ class ModuleBlog extends Module
)
);
$this->Cache_Delete("blog_{$iBlogId}");
/**
* Удаляем аватар
*/
$this->DeleteBlogAvatar($oBlog);
/**
* Удаляем связи пользователей блога.
*/

View file

@ -1258,6 +1258,68 @@ class ModuleUser extends Module
return true;
}
/**
* Создает фото пользователя на основе области из изображения
*
* @param $sFileFrom
* @param $oUser
* @param $aSize
* @param null $iCanvasWidth
*
* @return bool
*/
public function CreateProfilePhoto($sFileFrom, $oUser, $aSize = null, $iCanvasWidth = null)
{
$aParams = $this->Image_BuildParams('profile_photo');
/**
* Если объект изображения не создан, возвращаем ошибку
*/
if (!$oImage = $this->Image_OpenFrom($sFileFrom, $aParams)) {
return $this->Image_GetLastError();
}
/**
* Вырезаем область из исходного файла
*/
if ($aSize) {
$oImage->cropFromSelected($aSize, $iCanvasWidth);
}
if ($sError = $this->Image_GetLastError()) {
return $sError;
}
/**
* Сохраняем во временный файл для дальнейшего ресайза
*/
if (false === ($sFileTmp = $oImage->saveTmp())) {
return $this->Image_GetLastError();
}
$sPath = $this->Image_GetIdDir($oUser->getId(), 'users');
/**
* Имя файла для сохранения
*/
$sFileName = func_generator(8);
/**
* Сохраняем копию нужного размера
*/
$aSize = $this->Media_ParsedImageSize(Config::Get('module.user.profile_photo_size'));
if ($aSize['crop']) {
$oImage->cropProportion($aSize['w'] / $aSize['h'], 'center');
}
if (!$sFileResult = $oImage->resize($aSize['w'], $aSize['h'], true)->saveSmart($sPath, $sFileName)) {
return $this->Image_GetLastError();
}
/**
* Теперь можно удалить временный файл
*/
$this->Fs_RemoveFileLocal($sFileTmp);
/**
* Если было старое фото, то удаляем
*/
$this->DeleteProfilePhoto($oUser);
$oUser->setProfileFoto($sFileResult);
$this->User_Update($oUser);
return true;
}
/**
* Загрузка фото в профиль пользователя
*

View file

@ -157,10 +157,7 @@ ls.user = (function ($) {
if (data.bStateError) {
ls.msg.error(data.sMsgTitle,data.sMsg);
} else {
$('.js-ajax-user-photo-image').attr('src',data.sFile);
$('.js-ajax-user-photo-upload-choose').html(data.sChooseText);
$('.js-ajax-user-photo-upload-remove').show();
$('.js-ajax-user-avatar-change').show();
this.cropProfilePhoto(data.sTmpFile, input.data('userId'));
}
form.remove();
}.bind(this));
@ -173,82 +170,146 @@ ls.user = (function ($) {
if (result.bStateError) {
ls.msg.error(null,result.sMsg);
} else {
$('.js-ajax-user-photo-image').attr('src',result.sFile);
$('.js-ajax-user-photo-upload-choose').html(result.sChooseText);
$('.js-ajax-user-photo-upload-remove').hide();
$('.js-ajax-user-avatar-change').hide();
$('.js-ajax-user-photo-image').attr('src',result.sFile);
$('.js-ajax-user-photo-upload-choose').html(result.sChooseText);
$('.js-ajax-user-photo-upload-remove').hide();
$('.js-ajax-user-avatar-change').hide();
}
});
}.bind(this));
return false;
};
this.cropProfilePhoto = function(src,idUser) {
this.showCropImage(src,{
crop_params : {
minSize: [100, 150]
},
save_params : {
user_id : idUser
},
save_url : aRouter.settings+'ajax-crop-photo/',
save_callback : function(result, modal, image, previews) {
$('.js-ajax-user-photo-image').attr('src',result.sFile);
$('.js-ajax-user-photo-upload-choose').html(result.sChooseText);
$('.js-ajax-user-photo-upload-remove').show();
$('.js-ajax-user-avatar-change').show();
},
modal_close_callback : function(e, modal) {
ls.ajax.load(aRouter.settings+'ajax-crop-cancel-photo/', { user_id: idUser });
}
});
return false;
};
this.changeProfileAvatar = function(idUser) {
var _this = this;
ls.modal.load(aRouter.ajax+'modal/image-crop/', {image_src: $('.js-ajax-user-photo-image').attr('src') }, {
aftershow: function( e, modal ) {
var image = modal.element.find('.js-crop-image'),
previews = modal.element.find('.js-crop-preview-image'),
submit = modal.element.find('.js-ajax-image-crop-submit');
function showPreview( coords ) {
previews.each(function() {
var preview = $( this ),
size = preview.data('size'),
rx = size / coords.w,
ry = size / coords.h;
preview.css({
width: Math.round( rx * image.width() ) + 'px',
height: Math.round( ry * image.height() ) + 'px',
marginLeft: '-' + Math.round( rx * coords.x ) + 'px',
marginTop: '-' + Math.round( ry * coords.y ) + 'px'
});
})
}
this.jcropImage && this.jcropImage.destroy();
image.css({
'width': 'auto',
'height': 'auto'
});
image.Jcrop({
minSize: [32, 32],
aspectRatio: 1,
onChange: showPreview,
onSelect: showPreview
}, function () {
_this.jcropImage = this;
var w=image.innerWidth();
var h=image.innerHeight();
w=w/2-75;
h=h/2-75;
w=w>0 ? Math.round(w) : 0;
h=h>0 ? Math.round(h) : 0;
this.setSelect([w, h, w+150, h+150]);
});
submit.on('click',function() {
var params={
user_id: idUser,
size: _this.jcropImage.tellSelect(),
canvas_width: image.innerWidth()
}
ls.ajax.load(aRouter.settings+'ajax-change-avatar/', params, function(result) {
if (result.bStateError) {
ls.msg.error(null,result.sMsg);
} else {
modal.hide();
}
});
});
},
center: false
});
this.showCropImage($('.js-ajax-user-photo-image').attr('src'),{
crop_w : 150,
crop_h : 150,
crop_params : {
minSize: [32, 32],
aspectRatio: 1
},
save_params : {
user_id : idUser
},
save_url : aRouter.settings+'ajax-change-avatar/'
});
return false;
};
this.showCropImage = function(src, params) {
params = params || {};
var _this = this;
ls.modal.load(aRouter.ajax+'modal/image-crop/', {image_src: src }, {
aftershow: function( e, modal ) {
var image = modal.element.find('.js-crop-image'),
previews = modal.element.find('.js-crop-preview-image'),
submit = modal.element.find('.js-ajax-image-crop-submit');
function showPreview( coords ) {
previews.each(function() {
var preview = $( this ),
size = preview.data('size'),
rx = size / coords.w,
ry = size / coords.h;
preview.css({
width: Math.round( rx * image.width() ) + 'px',
height: Math.round( ry * image.height() ) + 'px',
marginLeft: '-' + Math.round( rx * coords.x ) + 'px',
marginTop: '-' + Math.round( ry * coords.y ) + 'px'
});
})
}
_this.jcropImage && _this.jcropImage.destroy();
image.css({
'width': 'auto',
'height': 'auto'
});
var cropParams={
minSize: [32, 32],
aspectRatio: 0,
onChange: showPreview,
onSelect: showPreview
};
cropParams = $.extend({}, cropParams, params.crop_params || { });
image.Jcrop(cropParams, function () {
_this.jcropImage = this;
var iw=image.innerWidth();
var ih=image.innerHeight();
var sw = 0, sh = 0, ew = iw, eh = ih;
if (params.crop_w) {
if (!params.crop_h) {
params.crop_h = params.crop_w;
}
sw=iw/2-params.crop_w/2;
sh=ih/2-params.crop_h/2;
sw=sw>0 ? Math.round(sw) : 0;
sh=sh>0 ? Math.round(sh) : 0;
ew=sw+params.crop_w;
eh=sh+params.crop_h;
}
this.setSelect([sw, sh, ew, eh]);
});
submit.on('click',function() {
var paramsRequest={
size: _this.jcropImage.tellSelect(),
canvas_width: image.innerWidth()
};
paramsRequest = $.extend({}, paramsRequest, params.save_params || { });
ls.ajax.load(params.save_url, paramsRequest, function(result) {
if (result.bStateError) {
ls.msg.error(null,result.sMsg);
} else {
modal.hide();
if (params.save_callback) {
params.save_callback(result, modal, image, previews);
}
}
});
});
},
afterhide: function( e, modal ) {
if (params.modal_close_callback) {
params.modal_close_callback(e, modal);
}
},
center: false
});
return false;
};
return this;
}).call(ls.user || {}, jQuery);

View file

@ -7,7 +7,7 @@
<script type="text/javascript">
jQuery(document).ready(function($){
ls.geo.initSelect();
ls.userfield.iCountMax='{cfg name="module.user.userfield_max_identical"}';
//ls.userfield.iCountMax='{cfg name="module.user.userfield_max_identical"}';
});
</script>

View file

@ -29,5 +29,5 @@
{/block}
{block 'modal_footer_begin'}
{include 'components/button/button.tpl' text=$aLang.common.save sClasses='js-ajax-image-crop-submit' mods='primary'}
{include 'components/button/button.tpl' text=$aLang.common.save classes='js-ajax-image-crop-submit' mods='primary'}
{/block}

@ -1 +1 @@
Subproject commit 9361b97a3575adc03557c47aa15a2a9995cb00c5
Subproject commit 945a0ebea0ffb8fdb2ab1600bbe6bd52eee835b8