Allow cover photos to be disabled, added default image
authorAlexander Ebert <ebert@woltlab.com>
Wed, 29 Nov 2017 17:46:40 +0000 (18:46 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Wed, 29 Nov 2017 17:46:40 +0000 (18:46 +0100)
Closes #2484

com.woltlab.wcf/userGroupOption.xml
wcfsetup/install/files/acp/templates/userAdd.tpl
wcfsetup/install/files/images/coverPhotos/default.jpg [new file with mode: 0644]
wcfsetup/install/files/lib/acp/form/UserEditForm.class.php
wcfsetup/install/files/lib/data/style/Style.class.php
wcfsetup/install/files/lib/data/style/StyleEditor.class.php
wcfsetup/install/files/lib/data/user/User.class.php
wcfsetup/install/files/lib/system/cronjob/UserBanCronjob.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml
wcfsetup/setup/db/install.sql

index f695d11524542e70872ea7af78a61888f540c30b..b1ad0ed58abbcb40c7784c0b683a61ed6fa3be37 100644 (file)
                                <usersonly>1</usersonly>
                                <options>module_user_signature</options>
                        </option>
+                       <option name="admin.user.canDisableCoverPhoto">
+                               <categoryname>admin.user.user</categoryname>
+                               <optiontype>boolean</optiontype>
+                               <defaultvalue>0</defaultvalue>
+                               <admindefaultvalue>1</admindefaultvalue>
+                               <usersonly>1</usersonly>
+                       </option>
                        <option name="admin.user.canMailUser">
                                <categoryname>admin.user.user</categoryname>
                                <optiontype>boolean</optiontype>
index 3951ea4ea8256c501a2d3ac2d7f2d800a1ce3e98..e41114dea3a586819dd0ab5d6d264fd82ceef245 100644 (file)
@@ -39,8 +39,9 @@
                                        <li><a href="{@$__wcf->getAnchor('signatureManagement')}">{lang}wcf.user.signature{/lang}</a></li>
                                {/if}
                                
-                               {if $action == 'edit'}
+                               {if $action === 'edit'}
                                        <li><a href="{@$__wcf->getAnchor('avatarForm')}">{lang}wcf.user.avatar{/lang}</a></li>
+                                       <li><a href="{@$__wcf->getAnchor('coverPhotoForm')}">{lang}wcf.user.coverPhoto{/lang}</a></li>
                                {/if}
                                
                                {event name='tabMenuTabs'}
                                
                                {event name='avatarFieldsets'}
                        </div>
+                       
+                       <div id="coverPhotoForm" class="tabMenuContent hidden">
+                               <section class="section">
+                                       <h2 class="sectionTitle">{lang}wcf.user.coverPhoto{/lang}</h2>
+                                       
+                                       {if $userCoverPhoto}
+                                               <dl>
+                                                       <dt></dt>
+                                                       <dd>
+                                                               <div id="coverPhotoPreview" style="background-image: url({$userCoverPhoto->getURL()})"></div>
+                                                       </dd>
+                                               </dl>
+                                       {else}
+                                               <p class="info">{lang}wcf.user.coverPhoto.noImage{/lang}</p>
+                                       {/if}
+                                       
+                                       {event name='coverPhotoFields'}
+                               </section>
+                               
+                               {if $__wcf->session->getPermission('admin.user.canDisableCoverPhoto')}
+                                       <section class="section">
+                                               <h2 class="sectionTitle">{lang}wcf.acp.user.disableCoverPhoto{/lang}</h2>
+                                               
+                                               <dl>
+                                                       <dt></dt>
+                                                       <dd>
+                                                               <label><input type="checkbox" id="disableCoverPhoto" name="disableCoverPhoto" value="1"{if $disableCoverPhoto == 1} checked{/if}> {lang}wcf.acp.user.disableCoverPhoto{/lang}</label>
+                                                       </dd>
+                                               </dl>
+                                               
+                                               <dl>
+                                                       <dt><label for="disableCoverPhotoReason">{lang}wcf.acp.user.disableCoverPhoto.reason{/lang}</label></dt>
+                                                       <dd>
+                                                               <textarea name="disableCoverPhotoReason" id="disableCoverPhotoReason" cols="40" rows="10">{$disableCoverPhotoReason}</textarea>
+                                                       </dd>
+                                               </dl>
+                                               
+                                               <dl>
+                                                       <dt></dt>
+                                                       <dd><label><input type="checkbox" id="disableCoverPhotoNeverExpires" name="disableCoverPhotoNeverExpires" value="1"{if !$disableCoverPhotoExpires} checked{/if}> {lang}wcf.acp.user.disableCoverPhoto.neverExpires{/lang}</label></dd>
+                                               </dl>
+                                               
+                                               <dl id="disableCoverPhotoExpiresSetting">
+                                                       <dt><label for="disableCoverPhotoExpires">{lang}wcf.acp.user.disableCoverPhoto.expires{/lang}</label></dt>
+                                                       <dd>
+                                                               <input type="date" name="disableCoverPhotoExpires" id="disableCoverPhotoExpires" min="{TIME_NOW|date:'Y-m-d'}" {if $disableCoverPhotoExpires} value="{$disableCoverPhotoExpires|date:'Y-m-d'}"{/if} class="medium">
+                                                               <small>{lang}wcf.acp.user.disableCoverPhoto.expires.description{/lang}</small>
+                                                       </dd>
+                                               </dl>
+                                               
+                                               {event name='disableAvatarFields'}
+                                       </section>
+                                       
+                                       <script data-relocate="true">
+                                               $('#disableCoverPhoto').change(function() {
+                                                       if ($('#disableCoverPhoto').is(':checked')) {
+                                                               $('#disableCoverPhotoReason').attr('readonly', false);
+                                                               $('#disableCoverPhotoNeverExpires, #disableCoverPhotoExpires').enable();
+                                                               $('#disableCoverPhotoReason, #disableCoverPhotoNeverExpires, #disableCoverPhotoExpires').parents('dl').removeClass('disabled');
+                                                       }
+                                                       else {
+                                                               $('#disableCoverPhotoReason').attr('readonly', true);
+                                                               $('#disableCoverPhotoNeverExpires, #disableCoverPhotoExpires').disable();
+                                                               $('#disableCoverPhotoReason, #disableCoverPhotoNeverExpires, #disableCoverPhotoExpires').parents('dl').addClass('disabled');
+                                                       }
+                                               });
+                                               
+                                               $('#disableCoverPhoto').change();
+                                               
+                                               $('#disableCoverPhotoNeverExpires').change(function() {
+                                                       if ($('#disableCoverPhotoNeverExpires').is(':checked')) {
+                                                               $('#disableCoverPhotoExpiresSetting').hide();
+                                                       }
+                                                       else {
+                                                               $('#disableCoverPhotoExpiresSetting').show();
+                                                       }
+                                               });
+                                               
+                                               $('#disableCoverPhotoNeverExpires').change();
+                                       </script>
+                               {/if}
+                               
+                               {event name='coverPhotoFieldsets'}
+                       </div>
                {/if}
                
                {event name='tabMenuContent'} {* deprecated event *}
diff --git a/wcfsetup/install/files/images/coverPhotos/default.jpg b/wcfsetup/install/files/images/coverPhotos/default.jpg
new file mode 100644 (file)
index 0000000..564bdad
Binary files /dev/null and b/wcfsetup/install/files/images/coverPhotos/default.jpg differ
index f38bdf1c1044014c1aacb17c52c0b8633591e379..e620f458e1e1eea5c60b0d9ca762f1d5b46a75a0 100755 (executable)
@@ -3,12 +3,14 @@ namespace wcf\acp\form;
 use wcf\data\user\avatar\Gravatar;
 use wcf\data\user\avatar\UserAvatar;
 use wcf\data\user\avatar\UserAvatarAction;
+use wcf\data\user\cover\photo\UserCoverPhoto;
 use wcf\data\user\group\UserGroup;
 use wcf\data\user\User;
 use wcf\data\user\UserAction;
 use wcf\data\user\UserEditor;
 use wcf\data\user\UserProfileAction;
 use wcf\form\AbstractForm;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
 use wcf\system\exception\IllegalLinkException;
 use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\UserInputException;
@@ -45,7 +47,7 @@ class UserEditForm extends UserAddForm {
         * user editor object
         * @var UserEditor
         */
-       public $user = null;
+       public $user;
        
        /**
         * ban status
@@ -69,7 +71,7 @@ class UserEditForm extends UserAddForm {
         * user avatar object
         * @var UserAvatar
         */
-       public $userAvatar = null;
+       public $userAvatar;
        
        /**
         * avatar type
@@ -95,6 +97,30 @@ class UserEditForm extends UserAddForm {
         */
        public $disableAvatarExpires = 0;
        
+       /**
+        * user cover photo object
+        * @var UserCoverPhoto
+        */
+       public $userCoverPhoto;
+       
+       /**
+        * true to disable this cover photo
+        * @var boolean
+        */
+       public $disableCoverPhoto = 0;
+       
+       /**
+        * reason
+        * @var string
+        */
+       public $disableCoverPhotoReason = '';
+       
+       /**
+        * date when the cover photo will be enabled again
+        * @var integer
+        */
+       public $disableCoverPhotoExpires = 0;
+       
        /**
         * @inheritDoc
         */
@@ -145,6 +171,14 @@ class UserEditForm extends UserAddForm {
                                if (isset($_POST['disableAvatarExpires'])) $this->disableAvatarExpires = @strtotime(StringUtil::trim($_POST['disableAvatarExpires']));
                        }
                }
+               
+               if (WCF::getSession()->getPermission('admin.user.canDisableCoverPhoto')) {
+                       if (!empty($_POST['disableCoverPhoto'])) $this->disableCoverPhoto = 1;
+                       if (isset($_POST['disableCoverPhotoReason'])) $this->disableCoverPhotoReason = StringUtil::trim($_POST['disableCoverPhotoReason']);
+                       if ($this->disableCoverPhoto && !isset($_POST['disableCoverPhotoNeverExpires'])) {
+                               if (isset($_POST['disableCoverPhotoExpires'])) $this->disableCoverPhotoExpires = @strtotime(StringUtil::trim($_POST['disableCoverPhotoExpires']));
+                       }
+               }
        }
        
        /**
@@ -161,10 +195,15 @@ class UserEditForm extends UserAddForm {
                
                parent::readData();
                
-               // get avatar object
+               // get the avatar object
                if ($this->avatarType == 'custom') {
                        $this->userAvatar = new UserAvatar($this->user->avatarID);
                }
+               
+               // get the user cover photo object
+               if ($this->user->coverPhotoHash) {
+                       $this->userCoverPhoto = UserProfileRuntimeCache::getInstance()->getObject($this->userID)->getCoverPhoto();
+               }
        }
        
        /**
@@ -191,10 +230,15 @@ class UserEditForm extends UserAddForm {
                $this->disableSignature = $this->user->disableSignature;
                $this->disableSignatureReason = $this->user->disableSignatureReason;
                $this->disableSignatureExpires = $this->user->disableSignatureExpires;
+               
                $this->disableAvatar = $this->user->disableAvatar;
                $this->disableAvatarReason = $this->user->disableAvatarReason;
                $this->disableAvatarExpires = $this->user->disableAvatarExpires;
                
+               $this->disableCoverPhoto = $this->user->disableCoverPhoto;
+               $this->disableCoverPhotoReason = $this->user->disableCoverPhotoReason;
+               $this->disableCoverPhotoExpires = $this->user->disableCoverPhotoExpires;
+               
                if ($this->user->avatarID) $this->avatarType = 'custom';
                else if (MODULE_GRAVATAR && $this->user->enableGravatar) $this->avatarType = 'gravatar';
        }
@@ -218,7 +262,11 @@ class UserEditForm extends UserAddForm {
                        'disableAvatarReason' => $this->disableAvatarReason,
                        'disableAvatarExpires' => $this->disableAvatarExpires,
                        'userAvatar' => $this->userAvatar,
-                       'banExpires' => $this->banExpires
+                       'banExpires' => $this->banExpires,
+                       'userCoverPhoto' => $this->userCoverPhoto,
+                       'disableCoverPhoto' => $this->disableCoverPhoto,
+                       'disableCoverPhotoReason' => $this->disableCoverPhotoReason,
+                       'disableCoverPhotoExpires' => $this->disableCoverPhotoExpires
                ]);
        }
        
@@ -310,6 +358,13 @@ class UserEditForm extends UserAddForm {
                        $data['data']['disableAvatarExpires'] = $this->disableAvatarExpires;
                }
                
+               // handle disabled cover photo
+               if (WCF::getSession()->getPermission('admin.user.canDisableCoverPhoto')) {
+                       $data['data']['disableCoverPhoto'] = $this->disableCoverPhoto;
+                       $data['data']['disableCoverPhotoReason'] = $this->disableCoverPhotoReason;
+                       $data['data']['disableCoverPhotoExpires'] = $this->disableCoverPhotoExpires;
+               }
+               
                $this->objectAction = new UserAction([$this->userID], 'update', $data);
                $this->objectAction->executeAction();
                
index 71abce2e0a87c07a21f113bcaa03f2966a255e67..698f95b9eae8e5704a620cafad2b52e211831faf 100644 (file)
@@ -197,7 +197,7 @@ class Style extends DatabaseObject {
                        return $this->styleID . '.' . $this->coverPhotoExtension;
                }
                
-               return 'default.png';
+               return 'default.jpg';
        }
        
        /**
index bff28f7a5798cf2030035bcef761577918c75504..c5affcfbc6a2002bb4b3e46a3719d176f43404a3 100644 (file)
@@ -575,7 +575,7 @@ class StyleEditor extends DatabaseObjectEditor implements IEditableCachedObject
                                                                case IMAGETYPE_PNG:
                                                                case IMAGETYPE_JPEG:
                                                                case IMAGETYPE_GIF:
-                                                                       $style->update(['coverPhotoExtension' => $fileExtension]);
+                                                                       $style->update(['coverPhotoExtension' => mb_substr($fileExtension, 1)]);
                                                        }
                                                }
                                        }
index 9f4e4349c3388de7b6868d34b0a91e1544dd11ed..42b69252d7713998f3998d4f88d2e85cbb4e2ac6 100644 (file)
@@ -67,6 +67,7 @@ use wcf\util\UserUtil;
  * @property-read       string          $coverPhotoHash                 hash of the user's cover photo
  * @property-read      string          $coverPhotoExtension            extension of the user's cover photo file
  * @property-read       integer         $disableCoverPhoto              is `1` if the user's cover photo has been disabled, otherwise `0`
+ * @property-read      string          $disableCoverPhotoReason        reason why the user's cover photo is disabled
  * @property-read      integer         $disableCoverPhotoExpires       timestamp at which the user's cover photo will automatically be enabled again
  */
 final class User extends DatabaseObject implements IRouteController, IUserContent {
index b3f70df74f710daa692321f6bc6111b19b27245c..7e68c17880ab2fc2b411a60d21a328fdd087a911 100644 (file)
@@ -65,5 +65,21 @@ class UserBanCronjob extends AbstractCronjob {
                        0,
                        TIME_NOW
                ]);
+               
+               // enable cover photos
+               $sql = "UPDATE  wcf".WCF_N."_user
+                       SET     disableCoverPhoto = ?,
+                               disableCoverPhotoExpires = ?
+                       WHERE   disableCoverPhoto = ?
+                               AND disableCoverPhotoExpires <> ?
+                               AND disableCoverPhotoExpires <= ?";
+               $statement = WCF::getDB()->prepareStatement($sql);
+               $statement->execute([
+                       0,
+                       0,
+                       1,
+                       0,
+                       TIME_NOW
+               ]);
        }
 }
index c5616dcd465a7c2ac8be3b4a95902df0e62eed37..7f2b33b18d608f7fd4c080e9679bad3eb6c35832 100644 (file)
@@ -2204,6 +2204,11 @@ Wenn {if LANGUAGE_USE_INFORMAL_VARIANT}du{else}Sie{/if} unter „Konfiguration 
                <item name="wcf.acp.user.disableAvatar.expires"><![CDATA[Entsperrung]]></item>
                <item name="wcf.acp.user.disableAvatar.expires.description"><![CDATA[Der Avatar des Benutzer wird zum festgelegten Zeitpunkt automatisch entsperrt.]]></item>
                <item name="wcf.acp.user.disableAvatar.neverExpires"><![CDATA[Dauerhafte Sperrung]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto"><![CDATA[Profilbild sperren]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.reason"><![CDATA[Begründung]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.expires"><![CDATA[Entsperrung]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.expires.description"><![CDATA[Das Profilbild des Benutzer wird zum festgelegten Zeitpunkt automatisch entsperrt.]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.neverExpires"><![CDATA[Dauerhafte Sperrung]]></item>
                <item name="wcf.acp.user.disableSignature.expires"><![CDATA[Entsperrung]]></item>
                <item name="wcf.acp.user.disableSignature.expires.description"><![CDATA[Die Signatur des Benutzer wird zum festgelegten Zeitpunkt automatisch entsperrt.]]></item>
                <item name="wcf.acp.user.disableSignature.neverExpires"><![CDATA[Dauerhafte Sperrung]]></item>
@@ -3931,9 +3936,12 @@ Die E-Mail-Adresse des neuen Benutzers lautet: {@$user->email}
        </category>
        
        <category name="wcf.user.coverPhoto">
+               <item name="wcf.user.coverPhoto"><![CDATA[Profilbild]]></item>
                <item name="wcf.user.coverPhoto.delete"><![CDATA[Profilbild löschen]]></item>
                <item name="wcf.user.coverPhoto.delete.confirmMessage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Willst du dein{else}Wollen Sie Ihr{/if} Profilbild wirklich löschen? Nach dem Löschen wird wieder das Standard-Bild angezeigt.]]></item>
                <item name="wcf.user.coverPhoto.edit"><![CDATA[Profilbild bearbeiten]]></item>
+               <item name="wcf.user.coverPhoto.error.disabled"><![CDATA[Der Administrator hat{if $__wcf->user->coverPhotoHash} {if LANGUAGE_USE_INFORMAL_VARIANT}dein{else}Ihr{/if} derzeitiges Profilbild gesperrt und{/if} {if LANGUAGE_USE_INFORMAL_VARIANT}dir{else}Ihnen{/if} die weitere Nutzungsberechtigung der Profilbild-Funktion {if !$__wcf->user->disableCoverPhotoReason}entzogen.{else} aus folgenden Gründen entzogen: {$__wcf->user->disableCoverPhotoReason}{/if}]]></item>
+               <item name="wcf.user.coverPhoto.noImage"><![CDATA[Der Benutzer hat noch kein Profilbild hochgeladen.]]></item>
                <item name="wcf.user.coverPhoto.upload"><![CDATA[Profilbild hochladen]]></item>
                <item name="wcf.user.coverPhoto.upload.description"><![CDATA[Minimale Bildgröße: {$coverPhotoDimensions.min.width}×{$coverPhotoDimensions.min.height} Pixel<br>Maximale Bildgröße: {$coverPhotoDimensions.max.width}×{$coverPhotoDimensions.max.height} Pixel<br>Erlaubte Dateiendungen: gif, jpg, jpeg, png<br>Maximale Dateigröße: {$__wcf->session->getPermission('user.profile.coverPhoto.maxSize')|filesize}]]></item>
                <item name="wcf.user.coverPhoto.upload.error.badImage"><![CDATA[{if LANGUAGE_USE_INFORMAL_VARIANT}Du hast{else}Sie haben{/if} kein gültiges Bild hochgeladen.]]></item>
index 5d9b2b6c7671e3b8d77539ef0868e595df596415..c96f84cb7b826c436d13332e262a56eb0bd8a400 100644 (file)
@@ -2145,6 +2145,11 @@ You can define the default sender in “Configuration » Options » General » E
                <item name="wcf.acp.user.disableAvatar.expires"><![CDATA[Unblocking]]></item>
                <item name="wcf.acp.user.disableAvatar.expires.description"><![CDATA[The avatar of the user will automatically be unblocked at the set time.]]></item>
                <item name="wcf.acp.user.disableAvatar.neverExpires"><![CDATA[Permanently Block]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto"><![CDATA[Block Cover Photo]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.reason"><![CDATA[Reason]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.expires"><![CDATA[Unblocking]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.expires.description"><![CDATA[The cover photo of the user will automatically be unblocked at the set time.]]></item>
+               <item name="wcf.acp.user.disableCoverPhoto.neverExpires"><![CDATA[Permanently Block]]></item>
                <item name="wcf.acp.user.disableSignature.expires"><![CDATA[Unblocking]]></item>
                <item name="wcf.acp.user.disableSignature.expires.description"><![CDATA[The signature of the user will automatically be unblocked at the set time.]]></item>
                <item name="wcf.acp.user.disableSignature.neverExpires"><![CDATA[Permanently Block]]></item>
@@ -3923,9 +3928,12 @@ Open the link below to access the user profile:
        </category>
        
        <category name="wcf.user.coverPhoto">
+               <item name="wcf.user.coverPhoto"><![CDATA[Cover Photo]]></item>
                <item name="wcf.user.coverPhoto.delete"><![CDATA[Delete Cover Photo]]></item>
                <item name="wcf.user.coverPhoto.delete.confirmMessage"><![CDATA[Do you really want to delete your cover photo? This will replace your current photo with the default image.]]></item>
                <item name="wcf.user.coverPhoto.edit"><![CDATA[Edit Cover Photo]]></item>
+               <item name="wcf.user.coverPhoto.error.disabled"><![CDATA[The administrators {if $__wcf->user->coverPhotoHash}have banned your cover photo and {/if}disallowed you from using a cover photo{if $__wcf->user->disableCoverPhotoReason}: {$__wcf->user->disableCoverPhotoReason}{/if}.]]></item>
+               <item name="wcf.user.coverPhoto.noImage"><![CDATA[The user has not yet uploaded a cover photo.]]></item>
                <item name="wcf.user.coverPhoto.upload"><![CDATA[Upload Cover Photo]]></item>
                <item name="wcf.user.coverPhoto.upload.description"><![CDATA[Minimum Image Size: {$coverPhotoDimensions.min.width}×{$coverPhotoDimensions.min.height} pixels<br>Maximum Image Size: {$coverPhotoDimensions.max.width}×{$coverPhotoDimensions.max.height} pixels<br>Allowed File Extensions: gif, jpg, jpeg, png<br>Maximum Filesize: {$__wcf->session->getPermission('user.profile.coverPhoto.maxSize')|filesize}]]></item>
                <item name="wcf.user.coverPhoto.upload.error.badImage"><![CDATA[The uploaded file is not an image.]]></item>
index 30634e9126cdcc7335442cd6245a7529447a94d3..10f7c052d8111822ef5e40365412610695078be7 100644 (file)
@@ -1430,6 +1430,7 @@ CREATE TABLE wcf1_user (
        coverPhotoHash CHAR(40) DEFAULT NULL,
        coverPhotoExtension VARCHAR(4) NOT NULL DEFAULT '',
        disableCoverPhoto TINYINT(1) NOT NULL DEFAULT 0,
+       disableCoverPhotoReason TEXT,
        disableCoverPhotoExpires INT(10) NOT NULL DEFAULT 0,
        
        KEY username (username),