* Obsolete interface `wcf\page\ITrackablePage` deprecated.
* PIP `wcf\system\package\plugin\SitemapPackageInstallationPlugin` removed.
* Option `share_buttons_show_count` removed.
+* Option `max_avatar_width` removed.
+* Option `max_avatar_height` removed.
#### Documentation
retro:wcf.acp.option.gravatar_default_type.retro]]></selectoptions>
<options>module_gravatar</options>
</option>
- <option name="max_avatar_width">
- <categoryname>user.avatar</categoryname>
- <optiontype>integer</optiontype>
- <defaultvalue>192</defaultvalue>
- <minvalue>96</minvalue>
- <suffix>pixel</suffix>
- </option>
- <option name="max_avatar_height">
- <categoryname>user.avatar</categoryname>
- <optiontype>integer</optiontype>
- <defaultvalue>192</defaultvalue>
- <minvalue>96</minvalue>
- <suffix>pixel</suffix>
- </option>
<!-- /user.avatar -->
<!-- user.signature -->
+++ /dev/null
-<dl class="wide">
- <dt>{lang}wcf.user.avatar.type.custom.crop{/lang}</dt>
- <dd>
- <div id="userAvatarCropSelection">
- {@$avatar->getImageTag()}
- <div id="userAvatarCropOverlay"></div>
- <div id="userAvatarCropOverlaySelection"></div>
- </div>
-
- <small>{lang}wcf.user.avatar.type.custom.crop.description{/lang}</small>
- </dd>
-</dl>
-
-<div class="formSubmit">
- <button data-type="save" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
-</div>
<dl class="avatarType jsOnly{if $errorField == 'custom'} formError{/if}" id="avatarUpload">
<dt>
{if $avatarType == 'custom'}
- {if $__wcf->getUserProfileHandler()->getAvatar()->canCrop()}
- {@$__wcf->getUserProfileHandler()->getAvatar()->getCropImageTag(96)}
- {else}
- {@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(96)}
- {/if}
+ {@$__wcf->getUserProfileHandler()->getAvatar()->getImageTag(96)}
{else}
<img src="{@$__wcf->getPath()}images/avatars/avatar-default.svg" alt="" class="userAvatarImage" style="width: 96px; height: 96px">
{/if}
//<![CDATA[
$(function() {
WCF.Language.addObject({
- 'wcf.user.avatar.type.custom.crop': '{lang}wcf.user.avatar.type.custom.crop{/lang}',
'wcf.user.avatar.upload.error.invalidExtension': '{lang}wcf.user.avatar.upload.error.invalidExtension{/lang}',
'wcf.user.avatar.upload.error.tooSmall': '{lang}wcf.user.avatar.upload.error.tooSmall{/lang}',
'wcf.user.avatar.upload.error.tooLarge': '{lang}wcf.user.avatar.upload.error.tooLarge{/lang}',
});
{if !$__wcf->user->disableAvatar}
- {if $__wcf->getUserProfileHandler()->getAvatar()->canCrop()}
- new WCF.User.Avatar.Upload(0, new WCF.User.Avatar.Crop({@$__wcf->getUserProfileHandler()->getAvatar()->avatarID}));
- {else}
- new WCF.User.Avatar.Upload();
- {/if}
+ new WCF.User.Avatar.Upload();
{/if}
});
//]]>
{capture assign='pageTitle'}{$user->username} - {lang}wcf.user.members{/lang}{/capture}
-{assign var='contentHeader' value=' '}{* necessary to hide default content header in heade.tpl *}
-
{capture assign='headContent'}
{event name='javascriptInclude'}
<script data-relocate="true">
</noscript>
{/capture}
-{include file='userHeader' assign='boxesTop'}
+{capture assign='contentHeader'}
+ <header class="contentHeader userProfileUser"{if $isAccessible}
+ data-object-id="{@$user->userID}"
+ {if $__wcf->session->getPermission('admin.user.canBanUser')}
+ data-banned="{@$user->banned}"
+ {/if}
+ {if $__wcf->session->getPermission('admin.user.canDisableAvatar')}
+ data-disable-avatar="{@$user->disableAvatar}"
+ {/if}
+ {if $__wcf->session->getPermission('admin.user.canDisableSignature')}
+ data-disable-signature="{@$user->disableSignature}"
+ {/if}
+ {if $__wcf->session->getPermission('admin.user.canEnableUser')}
+ data-is-disabled="{if $user->activationCode}true{else}false{/if}"
+ {/if}
+ {/if}>
+ <div class="contentHeaderIcon">
+ {if $user->userID == $__wcf->user->userID}
+ <a href="{link controller='AvatarEdit'}{/link}" class="jsTooltip" title="{lang}wcf.user.avatar.edit{/lang}">{@$user->getAvatar()->getImageTag(128)}</a>
+ {else}
+ <span>{@$user->getAvatar()->getImageTag(128)}</span>
+ {/if}
+ </div>
+
+ <div class="contentHeaderTitle">
+ <h1 class="contentTitle">
+ {$user->username}
+ {if $user->banned}<span class="icon icon16 fa-lock jsTooltip jsUserBanned" title="{lang}wcf.user.banned{/lang}"></span>{/if}
+ </h1>
+ {if MODULE_USER_RANK}
+ {if $user->getUserTitle()}
+ <span class="badge userTitleBadge{if $user->getRank() && $user->getRank()->cssClassName} {@$user->getRank()->cssClassName}{/if}">{$user->getUserTitle()}</span>
+ {/if}
+ {if $user->getRank() && $user->getRank()->rankImage}
+ <span class="userRankImage">{@$user->getRank()->getImage()}</span>
+ {/if}
+ {/if}
+ <div class="contentDescription">
+ <ul class="inlineList commaSeparated">
+ {if $user->isVisibleOption('gender') && $user->gender}<li>{lang}wcf.user.gender.{if $user->gender == 1}male{else}female{/if}{/lang}</li>{/if}
+ {if $user->isVisibleOption('birthday') && $user->getAge()}<li>{@$user->getAge()}</li>{/if}
+ {if $user->isVisibleOption('location') && $user->location}<li>{lang}wcf.user.membersList.location{/lang}</li>{/if}
+ {if $user->getOldUsername()}<li>{lang}wcf.user.profile.oldUsername{/lang}</li>{/if}
+ <li>{lang}wcf.user.membersList.registrationDate{/lang}</li>
+ {event name='userDataRow1'}
+ </ul>
+
+ {if $user->canViewOnlineStatus() && $user->getLastActivityTime()}
+ <ul class="inlineList commaSeparated">
+ <li>{lang}wcf.user.usersOnline.lastActivity{/lang}: {@$user->getLastActivityTime()|time}</li>
+ {if $user->getCurrentLocation()}<li>{@$user->getCurrentLocation()}</li>{/if}
+ </ul>
+ {/if}
+
+ <dl class="plain inlineDataList">
+ {include file='userInformationStatistics'}
+
+ {if $user->profileHits}
+ <dt{if $user->getProfileAge() > 1} title="{lang}wcf.user.profileHits.hitsPerDay{/lang}"{/if}>{lang}wcf.user.profileHits{/lang}</dt>
+ <dd>{#$user->profileHits}</dd>
+ {/if}
+ </dl>
+ </div>
+ </div>
+
+ <nav class="contentHeaderNavigation">
+ <ul class="userProfileButtonContainer">
+ {hascontent}
+ <li class="dropdown">
+ <a class="jsTooltip button dropdownToggle" title="{lang}wcf.user.profile.customization{/lang}"><span class="icon icon32 fa-pencil"></span> <span class="invisible">{lang}wcf.user.profile.customization{/lang}</span></a>
+ <ul class="dropdownMenu userProfileButtonMenu" data-menu="customization">
+ {content}
+ {event name='menuCustomization'}
+
+ {if $user->userID == $__wcf->user->userID}
+ <li><a href="{link controller='AvatarEdit'}{/link}">{lang}wcf.user.avatar.edit{/lang}</a></li>
+ {/if}
+
+ {if $user->canEdit() || ($__wcf->getUser()->userID == $user->userID && $user->canEditOwnProfile())}
+ <li><a href="#" class="jsButtonEditProfile">{lang}wcf.user.editProfile{/lang}</a></li>
+ {/if}
+ {/content}
+ </ul>
+ </li>
+ {/hascontent}
+
+ {hascontent}
+ <li class="dropdown">
+ <a class="jsTooltip button dropdownToggle" title="{lang}wcf.user.profile.user{/lang}"><span class="icon icon32 fa-user"></span> <span class="invisible">{lang}wcf.user.profile.dropdown.interaction{/lang}</span></a>
+ <ul class="dropdownMenu userProfileButtonMenu" data-menu="interaction">
+ {content}
+ {event name='menuInteraction'}
+
+ {if $user->userID != $__wcf->user->userID}
+ {if $user->isAccessible('canViewEmailAddress') || $__wcf->session->getPermission('admin.user.canEditMailAddress')}
+ <li><a href="mailto:{@$user->getEncodedEmail()}">{lang}wcf.user.button.mail{/lang}</a></li>
+ {elseif $user->isAccessible('canMail') && $__wcf->session->getPermission('user.profile.canMail')}
+ <li><a href="{link controller='Mail' object=$user}{/link}">{lang}wcf.user.button.mail{/lang}</a></li>
+ {/if}
+ {/if}
+
+ {if $user->userID != $__wcf->user->userID && $__wcf->session->getPermission('user.profile.canReportContent')}
+ <li class="jsReportUser" data-object-id="{@$user->userID}"><a href="#">{lang}wcf.user.profile.report{/lang}</a></li>
+ {/if}
+ {/content}
+ </ul>
+ </li>
+ {/hascontent}
+
+ {hascontent}
+ <li class="dropdown">
+ <a class="jsTooltip button dropdownToggle" title="{lang}wcf.user.searchUserContent{/lang}"><span class="icon icon32 fa-search"></span> <span class="invisible">{lang}wcf.user.searchUserContent{/lang}</span></a>
+ <ul class="dropdownMenu userProfileButtonMenu" data-menu="search">
+ {content}{event name='menuSearch'}{event name='quickSearchItems'}{/content}
+ </ul>
+ </li>
+ {/hascontent}
+
+ {hascontent}
+ <li class="dropdown">
+ <a class="jsTooltip button dropdownToggle" title="{lang}wcf.user.profile.management{/lang}"><span class="icon icon32 fa-cog"></span> <span class="invisible">{lang}wcf.user.profile.dropdown.management{/lang}</span></a>
+ <ul class="dropdownMenu userProfileButtonMenu" data-menu="management">
+ {content}
+ {event name='menuManagement'}
+
+ {if $isAccessible && $__wcf->user->userID != $user->userID && ($__wcf->session->getPermission('admin.user.canBanUser') || $__wcf->session->getPermission('admin.user.canDisableAvatar') || $__wcf->session->getPermission('admin.user.canDisableSignature') || ($__wcf->session->getPermission('admin.general.canUseAcp') && $__wcf->session->getPermission('admin.user.canEditUser')){event name='moderationDropdownPermissions'})}
+ {if $__wcf->session->getPermission('admin.user.canBanUser')}<li><a href="#" class="jsButtonUserBan">{lang}wcf.user.{if $user->banned}un{/if}ban{/lang}</a></li>{/if}
+ {if $__wcf->session->getPermission('admin.user.canDisableAvatar')}<li><a href="#" class="jsButtonUserDisableAvatar">{lang}wcf.user.{if $user->disableAvatar}enable{else}disable{/if}Avatar{/lang}</a></li>{/if}
+ {if $__wcf->session->getPermission('admin.user.canDisableSignature')}<li><a href="#" class="jsButtonUserDisableSignature">{lang}wcf.user.{if $user->disableSignature}enable{else}disable{/if}Signature{/lang}</a></li>{/if}
+ {if $__wcf->session->getPermission('admin.user.canEnableUser')}<li><a href="#" class="jsButtonUserEnable">{lang}wcf.acp.user.{if $user->activationCode}enable{else}disable{/if}{/lang}</a></li>{/if}
+
+ <li><a href="{link controller='UserEdit' object=$user isACP=true}{/link}" class="jsUserInlineEditor">{lang}wcf.user.edit{/lang}</a></li>
+ {/if}
+ {/content}
+ </ul>
+ </li>
+ {/hascontent}
+
+ {event name='contentHeaderNavigation'}
+ </ul>
+ </nav>
+
+ </header>
+{/capture}
{include file='userSidebar' assign='sidebarRight'}
+++ /dev/null
-{capture assign='__userProfileDescription'}
- <ul class="inlineList commaSeparated">
- {if $user->isVisibleOption('gender') && $user->gender}<li>{lang}wcf.user.gender.{if $user->gender == 1}male{else}female{/if}{/lang}</li>{/if}
- {if $user->isVisibleOption('birthday') && $user->getAge()}<li>{@$user->getAge()}</li>{/if}
- {if $user->isVisibleOption('location') && $user->location}<li>{lang}wcf.user.membersList.location{/lang}</li>{/if}
- {if $user->getOldUsername()}<li>{lang}wcf.user.profile.oldUsername{/lang}</li>{/if}
- <li>{lang}wcf.user.membersList.registrationDate{/lang}</li>
- {event name='userDataRow1'}
- </ul>
-
- {if $user->canViewOnlineStatus() && $user->getLastActivityTime()}
- <ul class="inlineList commaSeparated">
- <li>{lang}wcf.user.usersOnline.lastActivity{/lang}: {@$user->getLastActivityTime()|time}</li>
- {if $user->getCurrentLocation()}<li>{@$user->getCurrentLocation()}</li>{/if}
- </ul>
- {/if}
-{/capture}
-
-<div class="box userProfileHeader">
- <div class="boxContent">
- <div class="userProfileHeaderContainer">
- <div class="userProfileCoverPhoto"></div>
-
- <div class="userProfileUser"{if $isAccessible}
- data-object-id="{@$user->userID}"
- {if $__wcf->session->getPermission('admin.user.canBanUser')}
- data-banned="{@$user->banned}"
- {/if}
- {if $__wcf->session->getPermission('admin.user.canDisableAvatar')}
- data-disable-avatar="{@$user->disableAvatar}"
- {/if}
- {if $__wcf->session->getPermission('admin.user.canDisableSignature')}
- data-disable-signature="{@$user->disableSignature}"
- {/if}
- {if $__wcf->session->getPermission('admin.user.canEnableUser')}
- data-is-disabled="{if $user->activationCode}true{else}false{/if}"
- {/if}
- {/if}>
-
- <div class="layoutBoundary">
- <header class="contentHeader">
- {if $user->userID == $__wcf->user->userID}
- <a href="{link controller='AvatarEdit'}{/link}" class="contentHeaderIcon jsTooltip" title="{lang}wcf.user.avatar.edit{/lang}">{@$user->getAvatar()->getImageTag(160)}</a>
- {else}
- <span class="contentHeaderIcon">{@$user->getAvatar()->getImageTag(160)}</span>
- {/if}
-
- <div class="contentHeaderTitle">
- <h1 class="contentTitle">
- {$user->username}{if $user->banned} <span class="icon icon16 fa-lock jsTooltip jsUserBanned" title="{lang}wcf.user.banned{/lang}"></span>{/if}
- </h1>
- {if MODULE_USER_RANK}
- {if $user->getUserTitle()}
- <span class="badge userTitleBadge{if $user->getRank() && $user->getRank()->cssClassName} {@$user->getRank()->cssClassName}{/if}">{$user->getUserTitle()}</span>
- {/if}
- {if $user->getRank() && $user->getRank()->rankImage}
- <span class="userRankImage">{@$user->getRank()->getImage()}</span>
- {/if}
- {/if}
- <div class="contentDescription">
- {@$__userProfileDescription}
- </div>
- </div>
-
- <ul class="userProfileButtonContainer">
- {hascontent}
- <li>
- <a class="jsTooltip" title="{lang}wcf.user.profile.customization{/lang}"><span class="icon icon32 fa-pencil"></span> <span class="invisible">{lang}wcf.user.profile.customization{/lang}</span></a>
- <ul class="userProfileButtonMenu" data-menu="customization">
- {content}
- {event name='menuCustomization'}
-
- {if $user->userID == $__wcf->user->userID}
- <li><a href="{link controller='AvatarEdit'}{/link}">{lang}wcf.user.avatar.edit{/lang}</a></li>
- {/if}
-
- <li><a href="#" class="jsButtonEditCoverPhoto">todo: edit cover photo</a></li>
-
- {if $user->canEdit() || ($__wcf->getUser()->userID == $user->userID && $user->canEditOwnProfile())}
- <li class="divider"><a href="#" class="jsButtonEditProfile">{lang}wcf.user.editProfile{/lang}</a></li>
- {/if}
- {/content}
- </ul>
- </li>
- {/hascontent}
-
- {hascontent}
- <li>
- <a class="jsTooltip" title="{lang}wcf.user.profile.user{/lang}"><span class="icon icon32 fa-user"></span> <span class="invisible">{lang}wcf.user.profile.dropdown.interaction{/lang}</span></a>
- <ul class="userProfileButtonMenu" data-menu="interaction">
- {content}
- {event name='menuInteraction'}
-
- {if $user->userID != $__wcf->user->userID}
- {if $user->isAccessible('canViewEmailAddress') || $__wcf->session->getPermission('admin.user.canEditMailAddress')}
- <li><a href="mailto:{@$user->getEncodedEmail()}">{lang}wcf.user.button.mail{/lang}</a></li>
- {elseif $user->isAccessible('canMail') && $__wcf->session->getPermission('user.profile.canMail')}
- <li><a href="{link controller='Mail' object=$user}{/link}">{lang}wcf.user.button.mail{/lang}</a></li>
- {/if}
- {/if}
-
- {if $user->userID != $__wcf->user->userID && $__wcf->session->getPermission('user.profile.canReportContent')}
- <li class="jsReportUser divider" data-object-id="{@$user->userID}"><a href="#">{lang}wcf.user.profile.report{/lang}</a></li>
- {/if}
- {/content}
- </ul>
- </li>
- {/hascontent}
-
- {hascontent}
- <li>
- <a class="jsTooltip" title="{lang}wcf.user.searchUserContent{/lang}"><span class="icon icon32 fa-search"></span> <span class="invisible">{lang}wcf.user.searchUserContent{/lang}</span></a>
- <ul class="userProfileButtonMenu" data-menu="search">
- {content}{event name='menuSearch'}{/content}
- </ul>
- </li>
- {/hascontent}
-
- {hascontent}
- <li>
- <a class="jsTooltip" title="{lang}wcf.user.profile.management{/lang}"><span class="icon icon32 fa-cog"></span> <span class="invisible">{lang}wcf.user.profile.dropdown.management{/lang}</span></a>
- <ul class="userProfileButtonMenu" data-menu="management">
- {content}
- {event name='menuManagement'}
-
- {if $isAccessible && $__wcf->user->userID != $user->userID && ($__wcf->session->getPermission('admin.user.canBanUser') || $__wcf->session->getPermission('admin.user.canDisableAvatar') || $__wcf->session->getPermission('admin.user.canDisableSignature') || ($__wcf->session->getPermission('admin.general.canUseAcp') && $__wcf->session->getPermission('admin.user.canEditUser')){event name='moderationDropdownPermissions'})}
- {if $__wcf->session->getPermission('admin.user.canBanUser')}<li><a href="#" class="jsButtonUserBan">{lang}wcf.user.{if $user->banned}un{/if}ban{/lang}</a></li>{/if}
- {if $__wcf->session->getPermission('admin.user.canDisableAvatar')}<li><a href="#" class="jsButtonUserDisableAvatar">{lang}wcf.user.{if $user->disableAvatar}enable{else}disable{/if}Avatar{/lang}</a></li>{/if}
- {if $__wcf->session->getPermission('admin.user.canDisableSignature')}<li><a href="#" class="jsButtonUserDisableSignature">{lang}wcf.user.{if $user->disableSignature}enable{else}disable{/if}Signature{/lang}</a></li>{/if}
- {if $__wcf->session->getPermission('admin.user.canEnableUser')}<li><a href="#" class="jsButtonUserEnable">{lang}wcf.acp.user.{if $user->activationCode}enable{else}disable{/if}{/lang}</a></li>{/if}
-
- <li class="divider"><a href="{link controller='UserEdit' object=$user isACP=true}{/link}" class="jsUserInlineEditor">{lang}wcf.user.edit{/lang}</a></li>
- {/if}
- {/content}
- </ul>
- </li>
- {/hascontent}
-
- {event name='buttonMenu'}
- </ul>
- </header>
- </div>
- </div>
- </div>
-
- <div class="userProfileDescriptionMobile">
- <div class="layoutBoundary">
- {@$__userProfileDescription}
- </div>
- </div>
-
- <div class="userProfileDetails">
- {hascontent}
- <div class="layoutBoundary">
- <ul class="userStats">
- {content}
- {event name='statistics'}
-
- {if MODULE_LIKE && $user->likesReceived}
- <li>
- {if !$user->isProtected()}<a href="#" class="jsButtonUserLikes jsTooltip" title="{lang}wcf.like.showLikesReceived{/lang}">{/if}
- <span class="userStatsValue">{@$user->likesReceived|shortUnit}</span>
- <span class="userStatsTitle">{lang}wcf.like.likesReceived{/lang}</span>
- {if !$user->isProtected()}</a>{/if}
- </li>
- {/if}
-
- {if $user->activityPoints}
- <li>
- <a href="#" class="activityPointsDisplay jsTooltip" title="{lang}wcf.user.activityPoint.showActivityPoints{/lang}" data-user-id="{@$user->userID}">
- <span class="userStatsValue">{@$user->activityPoints|shortUnit}</span>
- <span class="userStatsTitle">{lang}wcf.user.activityPoint{/lang}</span>
- </a>
- </li>
- {/if}
-
- {if $user->profileHits}
- <li{if $user->getProfileAge() > 1} title="{lang}wcf.user.profileHits.hitsPerDay{/lang}"{/if}>
- <span class="userStatsValue">{@$user->profileHits|shortUnit}</span>
- <span class="userStatsTitle">{lang}wcf.user.profileHits{/lang}</span>
- </li>
- {/if}
- {/content}
- </ul>
- </div>
- {/hascontent}
- </div>
- </div>
-</div>
define('GOOGLE_PUBLIC_KEY', '');
define('GOOGLE_PRIVATE_KEY', '');
define('GRAVATAR_DEFAULT_TYPE', '404');
-define('MAX_AVATAR_WIDTH', 192);
-define('MAX_AVATAR_HEIGHT', 192);
define('SIGNATURE_MAX_IMAGE_HEIGHT', 150);
define('USER_TITLE_MAX_LENGTH', 25);
define('USER_FORBIDDEN_TITLES', '');
+++ /dev/null
-<dl class="wide">
- <dt>{lang}wcf.user.avatar.type.custom.crop{/lang}</dt>
- <dd>
- <div id="userAvatarCropSelection">
- {@$avatar->getImageTag()}
- <div id="userAvatarCropOverlay"></div>
- <div id="userAvatarCropOverlaySelection"></div>
- </div>
-
- <small>{lang}wcf.user.avatar.type.custom.crop.description{/lang}</small>
- </dd>
-</dl>
-
-<div class="formSubmit">
- <button data-type="save" class="buttonPrimary">{lang}wcf.global.button.save{/lang}</button>
-</div>
<dl class="jsOnly{if $errorType[customAvatar]|isset} formError{/if}" id="avatarUpload">
<dt>
{if $avatarType == 'custom'}
- {assign var='__customAvatar' value=$userAvatar->getImageTag(96)}
- {if $userAvatar->canCrop()}
- {assign var='__customAvatar' value=$__customAvatar|substr:0:-2}
- {assign var='__customAvatarTitle' value='wcf.user.avatar.type.custom.crop'|language}
- {append var='__customAvatar' value='class="userAvatarCrop jsTooltip" title="'|concat:$__customAvatarTitle:'">'}
- {/if}
-
- {@$__customAvatar}
+ {@$userAvatar->getImageTag(96)}
{else}
<img src="{@$__wcf->getPath()}images/avatars/avatar-default.svg" alt="" class="userAvatarImage icon96">
{/if}
//<![CDATA[
$(function() {
WCF.Language.addObject({
- 'wcf.user.avatar.type.custom.crop': '{lang}wcf.user.avatar.type.custom.crop{/lang}',
'wcf.user.avatar.upload.error.invalidExtension': '{lang}wcf.user.avatar.upload.error.invalidExtension{/lang}',
'wcf.user.avatar.upload.error.tooSmall': '{lang}wcf.user.avatar.upload.error.tooSmall{/lang}',
'wcf.user.avatar.upload.error.tooLarge': '{lang}wcf.user.avatar.upload.error.tooLarge{/lang}',
'wcf.user.avatar.upload.success': '{lang}wcf.user.avatar.upload.success{/lang}'
});
- {if $userAvatar && $userAvatar->canCrop()}
- new WCF.User.Avatar.Upload({@$user->userID}, new WCF.User.Avatar.Crop({@$userAvatar->avatarID}));
- {else}
- new WCF.User.Avatar.Upload({@$user->userID});
- {/if}
+ new WCF.User.Avatar.Upload({@$user->userID});
});
//]]>
</script>
*/
WCF.User.Avatar = {};
-/**
- * Handles cropping an avatar.
- */
-WCF.User.Avatar.Crop = Class.extend({
- /**
- * current crop setting in x-direction
- * @var integer
- */
- _cropX: 0,
-
- /**
- * current crop setting in y-direction
- * @var integer
- */
- _cropY: 0,
-
- /**
- * avatar crop dialog
- * @var jQuery
- */
- _dialog: null,
-
- /**
- * action proxy to send the crop AJAX requests
- * @var WCF.Action.Proxy
- */
- _proxy: null,
-
- /**
- * maximum size of thumbnails
- * @var integer
- */
- MAX_THUMBNAIL_SIZE: 128,
-
- /**
- * Creates a new instance of WCF.User.Avatar.Crop.
- *
- * @param integer avatarID
- */
- init: function(avatarID) {
- this._avatarID = avatarID;
-
- if (this._dialog) {
- this.destroy();
- }
- this._dialog = null;
-
- // check if object already had been initialized
- if (!this._proxy) {
- this._proxy = new WCF.Action.Proxy({
- success: $.proxy(this._success, this)
- });
- }
-
- $('.userAvatarCrop').click($.proxy(this._showCropDialog, this));
- },
-
- /**
- * Destroys the avatar crop interface.
- */
- destroy: function() {
- this._dialog.remove();
- },
-
- /**
- * Sends AJAX request to crop avatar.
- *
- * @param object event
- */
- _crop: function(event) {
- this._proxy.setOption('data', {
- actionName: 'cropAvatar',
- className: 'wcf\\data\\user\\avatar\\UserAvatarAction',
- objectIDs: [ this._avatarID ],
- parameters: {
- cropX: this._cropX,
- cropY: this._cropY
- }
- });
- this._proxy.sendRequest();
- },
-
- /**
- * Initializes the dialog after a successful 'getCropDialog' request.
- *
- * @param object data
- */
- _getCropDialog: function(data) {
- if (!this._dialog) {
- this._dialog = $('<div />').hide().appendTo(document.body);
- this._dialog.wcfDialog({
- title: WCF.Language.get('wcf.user.avatar.type.custom.crop')
- });
- }
-
- this._dialog.html(data.returnValues.template);
- this._dialog.find('button[data-type="save"]').click($.proxy(this._crop, this));
-
- this._cropX = data.returnValues.cropX;
- this._cropY = data.returnValues.cropY;
-
- var $image = $('#userAvatarCropSelection > img');
- $('#userAvatarCropSelection').css({
- height: $image.height() + 'px',
- width: $image.width() + 'px'
- });
- $('#userAvatarCropOverlaySelection').css({
- 'background-image': 'url(' + $image.attr('src') + ')',
- 'background-position': -this._cropX + 'px ' + -this._cropY + 'px',
- 'left': this._cropX + 'px',
- 'top': this._cropY + 'px'
- }).draggable({
- containment: 'parent',
- drag : $.proxy(this._updateSelection, this),
- stop : $.proxy(this._updateSelection, this)
- });
-
- this._dialog.find('button[data-type="save"]').click($.proxy(this._save, this));
-
- this._dialog.wcfDialog('render');
- },
-
- /**
- * Shows the cropping dialog.
- */
- _showCropDialog: function() {
- if (!this._dialog) {
- this._proxy.setOption('data', {
- actionName: 'getCropDialog',
- className: 'wcf\\data\\user\\avatar\\UserAvatarAction',
- objectIDs: [ this._avatarID ]
- });
- this._proxy.sendRequest();
- }
- else {
- this._dialog.wcfDialog('open');
- }
- },
-
- /**
- * Handles successful AJAX request.
- *
- * @param object data
- * @param string textStatus
- * @param jQuery jqXHR
- */
- _success: function(data, textStatus, jqXHR) {
- switch (data.actionName) {
- case 'getCropDialog':
- this._getCropDialog(data);
- break;
-
- case 'cropAvatar':
- $('#avatarUpload > dt > img').replaceWith($('<img src="' + data.returnValues.url + '" alt="" class="userAvatarCrop jsTooltip" title="' + WCF.Language.get('wcf.user.avatar.type.custom.crop') + '" />').css({
- width: '96px',
- height: '96px'
- }).click($.proxy(this._showCropDialog, this)));
-
- WCF.DOMNodeInsertedHandler.execute();
-
- this._dialog.wcfDialog('close');
-
- var $notification = new WCF.System.Notification();
- $notification.show();
- break;
- }
- },
-
- /**
- * Updates the current crop selection if the selection overlay is dragged.
- *
- * @param object event
- * @param object ui
- */
- _updateSelection: function(event, ui) {
- this._cropX = ui.position.left;
- this._cropY = ui.position.top;
-
- $('#userAvatarCropOverlaySelection').css({
- 'background-position': -ui.position.left + 'px ' + -ui.position.top + 'px'
- });
- }
-});
-
/**
* Avatar upload function
*
* @see WCF.Upload
*/
WCF.User.Avatar.Upload = WCF.Upload.extend({
- /**
- * handles cropping the avatar
- * @var WCF.User.Avatar.Crop
- */
- _avatarCrop: null,
-
/**
* user id of avatar owner
* @var integer
* Initalizes a new WCF.User.Avatar.Upload object.
*
* @param integer userID
- * @param WCF.User.Avatar.Crop avatarCrop
*/
- init: function(userID, avatarCrop) {
+ init: function(userID) {
this._super($('#avatarUpload > dd > div'), undefined, 'wcf\\data\\user\\avatar\\UserAvatarAction');
this._userID = userID || 0;
- this._avatarCrop = avatarCrop;
$('#avatarForm input[type=radio]').change(function() {
if ($(this).val() == 'custom') {
*/
_success: function(uploadID, data) {
if (data.returnValues.url) {
- this._updateImage(data.returnValues.url, data.returnValues.canCrop);
-
- if (data.returnValues.canCrop) {
- if (!this._avatarCrop) {
- this._avatarCrop = new WCF.User.Avatar.Crop(data.returnValues.avatarID);
- }
- else {
- this._avatarCrop.init(data.returnValues.avatarID);
- }
- }
- else if (this._avatarCrop) {
- this._avatarCrop.destroy();
- this._avatarCrop = null;
- }
+ this._updateImage(data.returnValues.url);
// hide error
$('#avatarUpload > dd > .innerError').remove();
* Updates the displayed avatar image.
*
* @param string url
- * @param boolean canCrop
*/
- _updateImage: function(url, canCrop) {
+ _updateImage: function(url) {
$('#avatarUpload > dt > img').remove();
var $image = $('<img src="' + url + '" class="userAvatarImage" alt="" />').css({
'height': 'auto',
'max-width': '96px',
'width': 'auto'
});
- if (canCrop) {
- $image.addClass('userAvatarCrop').addClass('jsTooltip');
- $image.attr('title', WCF.Language.get('wcf.user.avatar.type.custom.crop'));
- }
$('#avatarUpload > dt').prepend($image);
// init buttons
['ban', 'disableAvatar', 'disableSignature', 'enable'].forEach((function(action) {
- var button = elBySel('.jsButtonUser' + StringUtil.ucfirst(action), _userHeader);
+ var button = elBySel('.userProfileButtonMenu .jsButtonUser' + StringUtil.ucfirst(action));
// button is missing if users lacks the permission
if (button) {
case 'ban':
case 'unban':
elData(_userHeader, 'banned', (data.actionName === 'ban'));
- elBySel('.jsButtonUserBan', _userHeader).textContent = Language.get('wcf.user.' + (data.actionName === 'ban' ? 'unban' : 'ban'));
+ elBySel('.userProfileButtonMenu .jsButtonUserBan').textContent = Language.get('wcf.user.' + (data.actionName === 'ban' ? 'unban' : 'ban'));
var contentTitle = elBySel('.contentTitle', _userHeader);
var banIcon = elBySel('.jsUserBanned', contentTitle);
case 'disableAvatar':
case 'enableAvatar':
elData(_userHeader, 'disable-avatar', (data.actionName === 'disableAvatar'));
- elBySel('.jsButtonUserDisableAvatar', _userHeader).textContent = Language.get('wcf.user.' + (data.actionName === 'disableAvatar' ? 'enable' : 'disable') + 'Avatar');
+ elBySel('.userProfileButtonMenu .jsButtonUserDisableAvatar').textContent = Language.get('wcf.user.' + (data.actionName === 'disableAvatar' ? 'enable' : 'disable') + 'Avatar');
break;
case 'disableSignature':
case 'enableSignature':
elData(_userHeader, 'disable-signature', (data.actionName === 'disableSignature'));
- elBySel('.jsButtonUserDisableSignature', _userHeader).textContent = Language.get('wcf.user.' + (data.actionName === 'disableSignature' ? 'enable' : 'disable') + 'Signature');
+ elBySel('.userProfileButtonMenu .jsButtonUserDisableSignature').textContent = Language.get('wcf.user.' + (data.actionName === 'disableSignature' ? 'enable' : 'disable') + 'Signature');
break;
case 'enable':
case 'disable':
elData(_userHeader, 'is-disabled', (data.actionName === 'disable'));
- elBySel('.jsButtonUserEnable', _userHeader).textContent = Language.get('wcf.acp.user.' + (data.actionName === 'enable' ? 'disable' : 'enable'));
+ elBySel('.userProfileButtonMenu .jsButtonUserEnable').textContent = Language.get('wcf.acp.user.' + (data.actionName === 'enable' ? 'disable' : 'enable'));
break;
}
* avatar size
* @var integer
*/
- public $size = 150;
+ public $size = UserAvatar::AVATAR_SIZE;
/**
* @inheritDoc
if (!$this->user->userID) {
throw new IllegalLinkException();
}
-
- if (!empty($_REQUEST['size'])) {
- $this->size = intval($_REQUEST['size']);
- if (!in_array($this->size, UserAvatar::$avatarThumbnailSizes)) {
- $this->size = 150;
- }
- }
}
/**
* image size
* @var integer
*/
- public $size = 150;
+ public $size = UserAvatar::AVATAR_SIZE;
/**
* @inheritDoc
/**
* urls of this gravatar
- * @var string[]
+ * @var string
*/
- protected $url = [];
+ protected $url = '';
/**
* Creates a new Gravatar object.
* @inheritDoc
*/
public function getURL($size = null) {
- if ($size === null) $size = $this->size;
- else {
- switch ($size) {
- case 16:
- case 24:
- $size = 32;
- break;
- case 48:
- case 64:
- $size = 96;
- break;
- }
- }
-
- if (!isset($this->url[$size])) {
+ if (empty($this->url)) {
// try to use cached gravatar
- $cachedFilename = sprintf(self::GRAVATAR_CACHE_LOCATION, md5(mb_strtolower($this->gravatar)), $size, $this->fileExtension);
+ $cachedFilename = sprintf(self::GRAVATAR_CACHE_LOCATION, md5(mb_strtolower($this->gravatar)), $this->size, $this->fileExtension);
if (file_exists(WCF_DIR.$cachedFilename) && filemtime(WCF_DIR.$cachedFilename) > (TIME_NOW - (self::GRAVATAR_CACHE_EXPIRE * 86400))) {
- $this->url[$size] = WCF::getPath().$cachedFilename;
+ $this->url = WCF::getPath().$cachedFilename;
}
else {
- $this->url[$size] = LinkHandler::getInstance()->getLink('GravatarDownload', [
+ $this->url = LinkHandler::getInstance()->getLink('GravatarDownload', [
'forceFrontend' => true
- ], 'userID='.$this->userID.'&size='.$size);
+ ], 'userID='.$this->userID);
}
}
- return $this->url[$size];
+ return $this->url;
}
/**
return false;
}
}
-
- /**
- * @inheritDoc
- */
- public function getImageTag($size = null) {
- if ($size === null) $size = $this->size;
-
- $retinaSize = null;
- switch ($size) {
- case 16:
- $retinaSize = 32;
- break;
- case 24:
- case 32:
- case 48:
- $retinaSize = 96;
- break;
- case 96:
- $retinaSize = 128;
- break;
- }
-
- return '<img src="'.StringUtil::encodeHTML($this->getURL($size)).'" '.($retinaSize !== null ? ('srcset="'.StringUtil::encodeHTML($this->getURL($retinaSize)).' 2x" ') : '').'style="width: '.$size.'px; height: '.$size.'px" alt="" class="userAvatarImage">';
- }
-
- /**
- * @inheritDoc
- */
- public function canCrop() {
- return false;
- }
}
* Returns true if this avatar can be cropped.
*
* @return boolean
+ * @deprecated 3.0
*/
public function canCrop();
*
* @param integer $size
* @return string
+ * @deprecated 3.0
*/
public function getCropImageTag($size = null);
* @property-read integer $height
* @property-read integer|null $userID
* @property-read string $fileHash
- * @property-read integer $cropX
- * @property-read integer $cropY
*/
class UserAvatar extends DatabaseObject implements IUserAvatar {
/**
* needed avatar thumbnail sizes
* @var integer[]
+ * @deprecated 3.0
*/
public static $avatarThumbnailSizes = [32, 96, 128, 256];
/**
* maximum thumbnail size
* @var integer
+ * @deprecated 3.0
*/
public static $maxThumbnailSize = 128;
/**
* minimum height and width of an uploaded avatar
* @var integer
+ * @deprecated 3.0
*/
const MIN_AVATAR_SIZE = 96;
+ /**
+ * minimum height and width of an uploaded avatar
+ * @var integer
+ */
+ const AVATAR_SIZE = 128;
+
/**
* Returns the physical location of this avatar.
*
* @return string
*/
public function getFilename($size = null) {
- switch ($size) {
- case 16:
- case 24:
- $size = 32;
- break;
-
- case 48:
- case 64:
- if ($this->width > 96 || $this->height > 96) {
- $size = 96;
- }
- else {
- $size = null;
- }
- break;
-
- case 160:
- if ($this->width > 256 || $this->height > 256) {
- $size = 256;
- }
- else {
- $size = null;
- }
- break;
- }
-
return substr($this->fileHash, 0, 2) . '/' . ($this->avatarID) . '-' . $this->fileHash . ($size !== null ? ('-' . $size) : '') . '.' . $this->avatarExtension;
}
* @inheritDoc
*/
public function getURL($size = null) {
- if ($size !== null && $size !== 'resized') {
- if ($size >= $this->width || $size >= $this->height) $size = null;
- }
-
- return WCF::getPath() . 'images/avatars/' . $this->getFilename($size);
+ return WCF::getPath() . 'images/avatars/' . $this->getFilename();
}
/**
* @inheritDoc
*/
public function getImageTag($size = null) {
- $width = $this->width;
- $height = $this->height;
- if ($size !== null) {
- if ($this->width > $size && $this->height > $size) {
- $width = $height = $size;
- }
- else if ($this->width > $size || $this->height > $size) {
- $widthFactor = $size / $this->width;
- $heightFactor = $size / $this->height;
-
- if ($widthFactor < $heightFactor) {
- $width = $size;
- $height = round($this->height * $widthFactor, 0);
- }
- else {
- $width = round($this->width * $heightFactor, 0);
- $height = $size;
- }
- }
- }
-
- $retinaSize = null;
- switch ($size) {
- case 16:
- $retinaSize = 32;
- break;
-
- case 24:
- case 32:
- case 48:
- $retinaSize = 96;
- break;
-
- case 64:
- case 96:
- if ($this->width >= 128 && $this->height >= 128) {
- $retinaSize = 128;
- }
- break;
-
- case 128:
- if ($this->width >= 128 && $this->height >= 128) {
- $retinaSize = 256;
- }
- break;
- }
-
- return '<img src="'.StringUtil::encodeHTML($this->getURL($size)).'" '.($retinaSize !== null ? ('srcset="'.StringUtil::encodeHTML($this->getURL($retinaSize)).' 2x" ') : '').'style="width: '.$width.'px; height: '.$height.'px" alt="" class="userAvatarImage">';
+ return '<img src="'.StringUtil::encodeHTML($this->getURL($size)).'" style="width: '.$size.'px; height: '.$size.'px" alt="" class="userAvatarImage">';
}
/**
* @inheritDoc
*/
public function getCropImageTag($size = null) {
- $imageTag = $this->getImageTag($size);
-
- // append CSS classes and append title
- $title = StringUtil::encodeHTML(WCF::getLanguage()->get('wcf.user.avatar.type.custom.crop'));
-
- return str_replace('class="userAvatarImage"', 'class="userAvatarImage userAvatarCrop jsTooltip" title="'.$title.'"', $imageTag);
+ return '';
}
/**
* @inheritDoc
*/
public function canCrop() {
- return $this->width != $this->height && $this->width > self::$maxThumbnailSize && $this->height > self::$maxThumbnailSize;
+ return false;
}
}
use wcf\data\user\User;
use wcf\data\user\UserEditor;
use wcf\data\AbstractDatabaseObjectAction;
-use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\SystemException;
if (@copy($fileLocation, $avatar->getLocation())) {
@unlink($fileLocation);
- // create thumbnails
- $action = new UserAvatarAction([$avatar], 'generateThumbnails');
- $action->executeAction();
-
// delete old avatar
if ($user->avatarID) {
$action = new UserAvatarAction([$user->avatarID], 'delete');
// return result
return [
'avatarID' => $avatar->avatarID,
- 'canCrop' => $avatar->canCrop(),
'url' => $avatar->getURL(96)
];
}
return ['errorType' => $file->getValidationErrorType()];
}
- /**
- * Generates the thumbnails of the avatars in all needed sizes.
- */
- public function generateThumbnails() {
- if (empty($this->objects)) {
- $this->readObjects();
- }
-
- foreach ($this->getObjects() as $avatar) {
- $adapter = ImageHandler::getInstance()->getAdapter();
- $adapter->loadFile($avatar->getLocation());
-
- foreach (UserAvatar::$avatarThumbnailSizes as $size) {
- if ($avatar->width <= $size && $avatar->height <= $size) break 2;
-
- $thumbnail = $adapter->createThumbnail($size, $size, false);
- $adapter->writeImage($thumbnail, $avatar->getLocation($size));
- }
- }
- }
-
/**
* Fetches an avatar from a remote server and sets it for given user.
*/
if (@copy($filename, $avatar->getLocation())) {
@unlink($filename);
- // create thumbnails
- $action = new UserAvatarAction([$avatar], 'generateThumbnails');
- $action->executeAction();
-
$avatarID = $avatar->avatarID;
}
else {
*/
protected function enforceDimensions($filename) {
$imageData = getimagesize($filename);
- if ($imageData[0] > MAX_AVATAR_WIDTH || $imageData[1] > MAX_AVATAR_HEIGHT) {
+ if ($imageData[0] > UserAvatar::AVATAR_SIZE || $imageData[1] > UserAvatar::AVATAR_SIZE) {
try {
- $obtainDimensions = true;
- if (MAX_AVATAR_WIDTH / $imageData[0] < MAX_AVATAR_HEIGHT / $imageData[1]) {
- if (round($imageData[1] * (MAX_AVATAR_WIDTH / $imageData[0])) < 48) $obtainDimensions = false;
- }
- else {
- if (round($imageData[0] * (MAX_AVATAR_HEIGHT / $imageData[1])) < 48) $obtainDimensions = false;
- }
-
$adapter = ImageHandler::getInstance()->getAdapter();
$adapter->loadFile($filename);
$filename = FileUtil::getTemporaryFilename();
- $thumbnail = $adapter->createThumbnail(MAX_AVATAR_WIDTH, MAX_AVATAR_HEIGHT, $obtainDimensions);
+ $thumbnail = $adapter->createThumbnail(UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE, false);
$adapter->writeImage($thumbnail, $filename);
}
catch (SystemException $e) {
return $filename;
}
-
- /**
- * Validates the 'getCropDialog' action.
- */
- public function validateGetCropDialog() {
- $this->avatar = $this->getSingleObject();
- }
-
- /**
- * Returns the data for the dialog to crop an avatar.
- *
- * @return array
- */
- public function getCropDialog() {
- return [
- 'cropX' => $this->avatar->cropX,
- 'cropY' => $this->avatar->cropY,
- 'template' => WCF::getTPL()->fetch('avatarCropDialog', 'wcf', [
- 'avatar' => $this->avatar
- ])
- ];
- }
-
- /**
- * Validates the 'cropAvatar' action.
- */
- public function validateCropAvatar() {
- $this->avatar = $this->getSingleObject();
-
- // check if user can edit the given avatar
- if ($this->avatar->userID != WCF::getUser()->userID && !WCF::getSession()->getPermission('admin.user.canEditUser')) {
- throw new PermissionDeniedException();
- }
-
- if (!WCF::getSession()->getPermission('user.profile.avatar.canUploadAvatar') || UserProfileRuntimeCache::getInstance()->getObject($this->avatar->userID)->disableAvatar) {
- throw new PermissionDeniedException();
- }
-
- // check parameters
- $this->readInteger('cropX', true);
- $this->readInteger('cropY', true);
-
- if ($this->parameters['cropX'] < 0 || $this->parameters['cropX'] > $this->avatar->width - UserAvatar::$maxThumbnailSize) {
- throw new UserInputException('cropX');
- }
- if ($this->parameters['cropY'] < 0 || $this->parameters['cropY'] > $this->avatar->height - UserAvatar::$maxThumbnailSize) {
- throw new UserInputException('cropY');
- }
- }
-
- /**
- * Craps an avatar.
- */
- public function cropAvatar() {
- // created clipped avatar as base for new thumbnails
- $adapter = ImageHandler::getInstance()->getAdapter();
- $adapter->loadFile($this->avatar->getLocation());
- $adapter->clip($this->parameters['cropX'], $this->parameters['cropY'], UserAvatar::$maxThumbnailSize, UserAvatar::$maxThumbnailSize);
-
- // update thumbnails
- foreach (UserAvatar::$avatarThumbnailSizes as $size) {
- $thumbnail = $adapter->createThumbnail($size, $size);
- $adapter->writeImage($thumbnail, $this->avatar->getLocation($size));
- }
-
- // update database entry
- $this->avatar->update([
- 'cropX' => $this->parameters['cropX'],
- 'cropY' => $this->parameters['cropY']
- ]);
-
- return [
- 'url' => $this->avatar->getURL(96)
- ];
- }
}
* Deletes avatar files.
*/
public function deleteFiles() {
- foreach (UserAvatar::$avatarThumbnailSizes as $size) {
+ foreach (UserAvatar::$avatarThumbnailSizes as $size) { // delete wcf2.1 files
if ($this->width < $size && $this->height < $size) break;
@unlink($this->getLocation($size));
// check image size
try {
$imageData = getimagesize($uploadFile->getLocation());
- if ($imageData[0] < UserAvatar::MIN_AVATAR_SIZE || $imageData[1] < UserAvatar::MIN_AVATAR_SIZE) {
+ if ($imageData[0] < UserAvatar::AVATAR_SIZE || $imageData[1] < UserAvatar::AVATAR_SIZE) {
$uploadFile->setValidationErrorType('tooSmall');
return false;
}
<?php
namespace wcf\system\worker;
use wcf\data\like\Like;
+use wcf\data\user\avatar\UserAvatar;
+use wcf\data\user\avatar\UserAvatarEditor;
+use wcf\data\user\avatar\UserAvatarList;
use wcf\data\user\UserEditor;
use wcf\data\user\UserList;
use wcf\data\user\UserProfileAction;
use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\image\ImageHandler;
use wcf\system\user\activity\point\UserActivityPointHandler;
use wcf\system\WCF;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
}
+
+ // update old avatars
+ $avatarList = new UserAvatarList();
+ $avatarList->getConditionBuilder()->add('user_avatar.userID IN (?)', [$userIDs]);
+ $avatarList->getConditionBuilder()->add('(user_avatar.width <> ? OR user_avatar.height <> ?)', [UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE]);
+ $avatarList->readObjects();
+ foreach ($avatarList as $avatar) {
+ $width = $avatar->width;
+ $height = $avatar->height;
+ if ($width != $height) {
+ $width = $height = min($width, $height, UserAvatar::AVATAR_SIZE);
+ $adapter = ImageHandler::getInstance()->getAdapter();
+ $adapter->loadFile($avatar->getLocation());
+ $thumbnail = $adapter->createThumbnail($width, $height, false);
+ $adapter->writeImage($thumbnail, $avatar->getLocation());
+ }
+
+ if ($width < UserAvatar::AVATAR_SIZE || $height < UserAvatar::AVATAR_SIZE) {
+ }
+
+ $editor = new UserAvatarEditor($avatar);
+ $editor->update([
+ ]);
+ }
}
}
}
-.userProfileHeader.box {
- margin: 0;
-}
-.userProfileCoverPhoto {
- background-image: url('../images/user-profile-header.jpg'); // todo
- background-position: center;
- background-size: cover;
-
- /* adds a box-shadow on the top and bottom of the element to create perspective
- and a clear separation if the images color is close to the surrounding elements */
- box-shadow: inset 0 10px 10px -10px rgba(0, 0, 0, .6), inset 0 -10px 10px -10px rgba(0, 0, 0, .6);
-
- @include screen-md-up {
- height: 300px;
- }
-
- @include screen-sm-down {
- height: 200px;
- }
-
- &::after {
- bottom: 0;
- content: '';
- left: 0;
- position: absolute;
- right: 0;
- top: 0;
-
- @include screen-md-up {
- background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, .7) 100%);
- }
-
- @include screen-sm-down {
- background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 20%, rgba(0, 0, 0, .7) 100%);
- }
- }
-}
-
-.userProfileHeaderContainer {
- position: relative;
-}
-
.userProfileUser {
- position: absolute;
- width: 100%;
-
- @include screen-md-up {
- bottom: 0;
- }
-
- @include screen-sm-down {
- bottom: 10px;
- }
-
- .contentHeader {
- @include screen-md-up {
- align-items: flex-end;
- }
-
- @include screen-sm-down {
- align-items: center;
- display: flex;
- }
- }
-
- .contentHeaderIcon {
- align-items: center;
- background-color: #fff;
- border-radius: 50%;
- box-sizing: content-box;
- box-shadow: 0 3px 6px rgba(0 ,0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
- display: flex;
- justify-content: center;
-
- @include screen-md-up {
- border: 4px solid transparent;
- flex: 0 0 160px;
- height: 160px;
- margin-right: 20px;
- transform: translateY(50%);
- width: 160px;
- }
-
- @include screen-sm-down {
- border: 2px solid transparent;
- flex: 0 0 64px;
- height: 64px;
- margin-right: 10px;
- width: 64px;
- }
-
- img {
- @include screen-sm-down {
- width: 64px !important;
- height: 64px !important;
- }
- }
- }
-
- .contentHeaderTitle {
- align-items: center;
- color: #fff;
- text-shadow: 0 1px 4px rgba(0, 0, 0, .5);
-
- @include screen-md-up {
- display: flex;
- flex-wrap: wrap;
- padding-bottom: 10px;
-
- > .contentTitle {
- align-items: center;
- display: flex;
- flex: 0 0 auto;
- margin-right: 10px;
-
- > .icon {
- margin-left: 5px;
- }
- }
-
- > .userTitleBadge {
- flex: 0 0 auto;
- }
- }
- @include screen-sm-down {
- flex: 1 1 auto;
- }
-
- a {
- color: #fff;
- }
-
- > .userTitleBadge {
- box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
-
- @include screen-sm-down {
- margin-top: 5px;
- }
- }
-
- .icon {
- color: inherit;
- }
+ .contentHeaderIcon a {
+ display: block;
}
.contentDescription {
- @include screen-md-up {
- flex: 0 0 100%;
- margin-top: 5px;
-
- .inlineList:not(:first-child) {
- margin-top: 2px;
-
- @include wcfFontSmall;
- }
- }
-
- @include screen-sm-down {
- display: none;
- }
- }
-
- .userProfileButtonContainer {
- @include screen-md-up {
- display: flex;
- flex: 0 0 auto;
- margin-bottom: 20px;
- }
- @include screen-sm-down {
- display: block;
- position: absolute;
- right: 10px;
- bottom: 0;
- }
-
- > li {
- margin-left: 10px;
- position: relative;
-
- @include screen-md-up {
- flex: 0 0 auto;
- }
- @include screen-sm-down {
- margin-top: 10px;
- }
-
- > a {
- background-color: $wcfHeaderMenuBackground;
- border-radius: 50%;
- box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
- color: $wcfHeaderMenuLink;
- display: block;
- padding: 10px;
-
- @include screen-md-up {
- padding: 10px;
- }
- @include screen-sm-down {
- padding: 5px;
- }
-
- .icon {
- color: inherit;
-
- @include screen-sm-down {
- font-size: 18px;
- height: 24px;
- line-height: 24px;
- width: 24px;
- }
- }
- }
-
- > .userProfileButtonMenu {
- background-color: $wcfHeaderMenuDropdownBackground;
- box-shadow: 0 0 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
- border-radius: 0 0 3px 3px;
- padding: 5px 0;
- position: absolute;
- visibility: hidden;
- z-index: 1;
-
- @include screen-md-up {
- right: 0;
- }
- @include screen-sm-down {
- right: 40px;
- top: 0;
- }
-
- > li {
- &.divider:not(:first-child) {
- border-top: 1px solid $wcfHeaderMenuDropdownBackgroundActive;
- margin-top: 5px;
- padding-top: 5px;
- }
-
- > a {
- color: $wcfHeaderMenuDropdownLink;
- }
-
- > a,
- > span {
- display: block;
- padding: 7px 20px;
- white-space: nowrap;
- text-align: right;
- }
-
- &.active > a,
- > a:hover {
- background-color: $wcfHeaderMenuDropdownBackgroundActive;
- color: $wcfHeaderMenuDropdownLinkActive;
- text-decoration: none;
- }
- }
- }
-
- &:hover {
- > a {
- background-color: $wcfHeaderMenuLinkBackgroundActive;
- color: $wcfHeaderMenuLinkActive;
- }
-
- > .userProfileButtonMenu {
- visibility: visible;
- }
- }
- }
- }
-}
-
-.userProfileDescriptionMobile {
- @include screen-md-up {
- display: none;
- }
-
- @include screen-sm-down {
- border-bottom: 1px solid $wcfContentBorderInner;
-
- > .layoutBoundary {
- padding: 20px 10px;
- }
- }
-}
-
-.userProfileDetails {
- @include screen-md-up {
- min-height: 94px;
- }
-
- > .layoutBoundary {
- @include screen-md-up {
- padding: 20px 20px 20px 208px;
- }
- @include screen-sm-down {
- padding: 20px 0;
- }
- }
-
- .userStats {
- display: flex;
- flex-wrap: wrap;
- margin-bottom: -20px;
-
- li {
- flex: 0 0 auto;
- margin-bottom: 20px;
- padding: 0 10px;
- text-align: center;
- white-space: nowrap;
-
- @include screen-lg {
- width: 12%;
- }
- @include screen-sm-md {
- width: 25%;
- }
- @include screen-xs {
- width: 33%;
- }
-
- a {
- display: block;
- }
- }
-
- .userStatsValue {
- overflow: hidden;
-
- @include wcfFontTitle;
- }
-
- .userStatsTitle {
- color: $wcfContentDimmedText;
- display: block;
- margin-top: 4px;
- overflow: hidden;
- text-overflow: ellipsis;
-
- @include screen-sm-down {
- @include wcfFontSmall;
- }
- }
- }
-}
-
-#tpl_wcf_user .main {
- padding-top: 0;
-
- .userProfileContent,
- .sidebar {
margin-top: 20px;
}
}
<item name="wcf.acp.option.category.user.password"><![CDATA[Kennwort]]></item>
<item name="wcf.acp.option.category.user.ban"><![CDATA[Filter]]></item>
<item name="wcf.acp.option.category.user.3rdPartyAuth"><![CDATA[Authentifizierung über Drittanbieter]]></item>
- <item name="wcf.acp.option.max_avatar_height"><![CDATA[Maximale Avatar-Höhe]]></item>
- <item name="wcf.acp.option.max_avatar_width"><![CDATA[Maximale Avatar-Breite]]></item>
<item name="wcf.acp.option.module_gravatar"><![CDATA[Gravatare]]></item>
<item name="wcf.acp.option.module_gravatar.description"><![CDATA[Aktiviert die Unterstützung für Gravatare („Global Recognized Avatar“).]]></item>
<item name="wcf.acp.option.module_users_online"><![CDATA[„Benutzer online“-Anzeige]]></item>
<item name="wcf.user.avatar.edit"><![CDATA[Avatar verwalten]]></item>
<item name="wcf.user.avatar.error.disabled"><![CDATA[Der Administrator hat{if $__wcf->user->avatarID || $__wcf->user->enableGravatar} {if LANGUAGE_USE_INFORMAL_VARIANT}deinen{else}Ihren{/if} derzeitigen Avatar gesperrt und{/if} {if LANGUAGE_USE_INFORMAL_VARIANT}dir{else}Ihnen{/if} die weitere Nutzungsberechtigung der Avatar-Funktion {if !$__wcf->user->disableAvatarReason}entzogen.{else} aus folgenden Gründen entzogen: {$__wcf->user->disableAvatarReason}{/if}]]></item>
<item name="wcf.user.avatar.type.custom"><![CDATA[Eigenen Avatar hochladen]]></item>
- <item name="wcf.user.avatar.type.custom.crop"><![CDATA[Avatar zuschneiden]]></item>
- <item name="wcf.user.avatar.type.custom.crop.description"><![CDATA[Die verkleinerten Darstellungen {if LANGUAGE_USE_INFORMAL_VARIANT}deines{else}Ihres{/if} Avatars verwenden einen quadratischen Ausschnitt. {if LANGUAGE_USE_INFORMAL_VARIANT}Du kannst{else}Sie können{/if} den gewünschten Ausschnitt individuell festlegen, indem {if LANGUAGE_USE_INFORMAL_VARIANT}du{else}Sie{/if} den hervorgehobenen Bereich mit gedrückter Maustaste an die gewünschte Position {if LANGUAGE_USE_INFORMAL_VARIANT}verschiebst{else}verschieben{/if}.]]></item>
- <item name="wcf.user.avatar.type.custom.description"><![CDATA[Eigene Avatare dürfen die Dateiendungen {"\n"|str_replace:', ':$__wcf->session->getPermission('user.profile.avatar.allowedFileExtensions')} und maximal eine Größe von {@$__wcf->session->getPermission('user.profile.avatar.maxSize')|filesize} besitzen. Die Mindestgröße für Avatare liegt bei 96×96 Pixel, die empfohlene Maximalgröße bei {@MAX_AVATAR_WIDTH}×{@MAX_AVATAR_HEIGHT} Pixel, größere Avatare werden - sofern möglich - automatisch auf die Maximalgröße verkleinert.]]></item>
+ <item name="wcf.user.avatar.type.custom.description"><![CDATA[Eigene Avatare dürfen die Dateiendungen {"\n"|str_replace:', ':$__wcf->session->getPermission('user.profile.avatar.allowedFileExtensions')} und maximal eine Größe von {@$__wcf->session->getPermission('user.profile.avatar.maxSize')|filesize} besitzen. Die Maximalgröße für Avatare liegt bei 128×128 Pixel, größere Avatare werden - sofern möglich - automatisch auf die Maximalgröße verkleinert.]]></item>
<item name="wcf.user.avatar.type.gravatar"><![CDATA[Gravatar verwenden]]></item>
<item name="wcf.user.avatar.type.gravatar.description"><![CDATA[Bei einem Gravatar handelt es sich um einen global verfügbaren Avatar (Global Recognized Avatar), welcher mit {if LANGUAGE_USE_INFORMAL_VARIANT}deiner{else}Ihrer{/if} E-Mail-Adresse („{$__wcf->user->email}“) verknüpft ist. Auf der folgenden Website können Sie einen Gravatar anlegen: <a href="http://www.gravatar.com" class="externalURL"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>www.gravatar.com</a>]]></item>
<item name="wcf.user.avatar.type.gravatar.error.notFound"><![CDATA[Zu {if LANGUAGE_USE_INFORMAL_VARIANT}deiner{else}Ihrer{/if} E-Mail-Adresse konnte kein Gravatar gefunden werden.]]></item>
<item name="wcf.acp.option.category.user.password"><![CDATA[Password]]></item>
<item name="wcf.acp.option.category.user.ban"><![CDATA[Filter]]></item>
<item name="wcf.acp.option.category.user.3rdPartyAuth"><![CDATA[Third-Party Authentication]]></item>
- <item name="wcf.acp.option.max_avatar_height"><![CDATA[Maximum Avatar Height]]></item>
- <item name="wcf.acp.option.max_avatar_height.description"><![CDATA[The maximum height in pixels for avatars.]]></item>
- <item name="wcf.acp.option.max_avatar_width"><![CDATA[Maximum Avatar Width]]></item>
- <item name="wcf.acp.option.max_avatar_width.description"><![CDATA[The maximum width in pixels for avatars.]]></item>
<item name="wcf.acp.option.module_gravatar"><![CDATA[Gravatars]]></item>
<item name="wcf.acp.option.module_gravatar.description"><![CDATA[Enables support for Gravatars (“Global Recognized Avatar”).]]></item>
<item name="wcf.acp.option.module_users_online"><![CDATA[“Users Online” list]]></item>
<item name="wcf.user.avatar.edit"><![CDATA[Avatar Management]]></item>
<item name="wcf.user.avatar.error.disabled"><![CDATA[The administrators {if $__wcf->user->avatarID || $__wcf->user->enableGravatar}have banned your avatar and {/if}disallowed you from using an avatar{if $__wcf->user->disableAvatarReason}: {$__wcf->user->disableAvatarReason}{/if}.]]></item>
<item name="wcf.user.avatar.type.custom"><![CDATA[Upload Your Avatar]]></item>
- <item name="wcf.user.avatar.type.custom.crop"><![CDATA[Crop Avatar]]></item>
- <item name="wcf.user.avatar.type.custom.crop.description"><![CDATA[The scaled versions of your avatar are based on a square cutout. You may specify an individual cutout by holding down your mouse button and moving the highlighted area to the desired position.]]></item>
- <item name="wcf.user.avatar.type.custom.description"><![CDATA[You may use the following file extensions “{"\n"|str_replace:', ':$__wcf->session->getPermission('user.profile.avatar.allowedFileExtensions')}” for your avatar with a maximum file size of {@$__wcf->session->getPermission('user.profile.avatar.maxSize')|filesize}. The minimum dimensions are 96×96 pixel, it is recommended to provide a dimension of {@MAX_AVATAR_WIDTH}×{@MAX_AVATAR_HEIGHT} pixel. Any avatar that exceeds this limit will be scaled down if possible.]]></item>
+ <item name="wcf.user.avatar.type.custom.description"><![CDATA[You may use the following file extensions “{"\n"|str_replace:', ':$__wcf->session->getPermission('user.profile.avatar.allowedFileExtensions')}” for your avatar with a maximum file size of {@$__wcf->session->getPermission('user.profile.avatar.maxSize')|filesize}. The maximum dimensions are 128×128 pixel. Any avatar that exceeds this limit will be scaled down if possible.]]></item>
<item name="wcf.user.avatar.type.gravatar"><![CDATA[Use Gravatar]]></item>
<item name="wcf.user.avatar.type.gravatar.description"><![CDATA[Gravatar (Global Recognized Avatar) provides a globally reusable avatar connected with your email address “{$__wcf->user->email}”. Visit <a href="http://www.gravatar.com" class="externalURL"{if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}>www.gravatar.com</a> to set up or change your avatar.]]></item>
<item name="wcf.user.avatar.type.gravatar.error.notFound"><![CDATA[Your email address is not connected with a gravatar.]]></item>
width SMALLINT(5) NOT NULL DEFAULT 0,
height SMALLINT(5) NOT NULL DEFAULT 0,
userID INT(10),
- fileHash VARCHAR(40) NOT NULL DEFAULT '',
- cropX SMALLINT(5) NOT NULL DEFAULT 0,
- cropY SMALLINT(5) NOT NULL DEFAULT 0
+ fileHash VARCHAR(40) NOT NULL DEFAULT ''
);
DROP TABLE IF EXISTS wcf1_user_collapsible_content;