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:
parent
eebd7a7e17
commit
23d83f1929
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -946,6 +946,10 @@ class ModuleBlog extends Module
|
|||
)
|
||||
);
|
||||
$this->Cache_Delete("blog_{$iBlogId}");
|
||||
/**
|
||||
* Удаляем аватар
|
||||
*/
|
||||
$this->DeleteBlogAvatar($oBlog);
|
||||
/**
|
||||
* Удаляем связи пользователей блога.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Загрузка фото в профиль пользователя
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue