Add a function, to disable usage for reactions
authorJoshua Rüsweg <ruesweg@woltlab.com>
Wed, 4 Sep 2019 13:32:48 +0000 (15:32 +0200)
committerJoshua Rüsweg <ruesweg@woltlab.com>
Mon, 9 Sep 2019 17:59:09 +0000 (19:59 +0200)
com.woltlab.wcf/templates/userProfileLikes.tpl
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Reaction/Handler.js
wcfsetup/install/files/lib/acp/form/ReactionTypeAddForm.class.php
wcfsetup/install/files/lib/data/reaction/ReactionAction.class.php
wcfsetup/install/files/lib/data/reaction/type/ReactionType.class.php
wcfsetup/install/files/lib/system/reaction/ReactionHandler.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml
wcfsetup/setup/db/install.sql

index 260c314460e17f87c755e9b8d5284a8b17b7cad3..5dd3b3c8f43c9b5a025f36df10f7e44748d6d006 100644 (file)
@@ -18,7 +18,7 @@
                
                <ul class="buttonGroup" id="reactionType">
                        {foreach from=$__wcf->getReactionHandler()->getReactionTypes() item=reactionType name=reactionTypeLoop}
-                               <li><a class="button small jsTooltip" data-reaction-type-id="{$reactionType->reactionTypeID}" title="{$reactionType->getTitle()}">{@$reactionType->renderIcon()} <span class="invisible">{$reactionType->getTitle()}</span></a></li>
+                               <li><a class="button small jsTooltip" data-reaction-type-id="{$reactionType->reactionTypeID}" title="{$reactionType->getTitle()}" data-is-assignable="{if $reactionType->isAssignable}1{else}0{/if}">{@$reactionType->renderIcon()} <span class="invisible">{$reactionType->getTitle()}</span></a></li>
                        {/foreach}
                </ul>
        </li>
index 5e6b18046ec52a698a915a32e296ffecac813c84..782f8f95fcc23a111f6b0b089324263530076d2c 100644 (file)
@@ -217,7 +217,12 @@ define(
                                });
                                
                                if (reactionTypeID) {
-                                       elBySel('.reactionTypeButton[data-reaction-type-id="' + reactionTypeID + '"]', this._getPopover()).classList.add('active');
+                                       var reactionTypeButton = elBySel('.reactionTypeButton[data-reaction-type-id="' + reactionTypeID + '"]', this._getPopover());
+                                       reactionTypeButton.classList.add('active');
+                                       
+                                       if (~~elData(reactionTypeButton, 'is-assignable') === 0) {
+                                               elShow(reactionTypeButton);
+                                       }
                                }
                        },
                        
@@ -306,6 +311,8 @@ define(
                                                reactionTypeItem.className = 'reactionTypeButton jsTooltip';
                                                elData(reactionTypeItem, 'reaction-type-id', reactionType.reactionTypeID);
                                                elData(reactionTypeItem, 'title', reactionType.title);
+                                               elData(reactionTypeItem, 'is-assignable', ~~reactionType.isAssignable);
+                                               
                                                reactionTypeItem.title = reactionType.title;
                                                
                                                var reactionTypeItemSpan = elCreate('span');
@@ -319,6 +326,10 @@ define(
                                                
                                                reactionTypeItem.addEventListener(WCF_CLICK_EVENT, this._react.bind(this, reactionType.reactionTypeID));
                                                
+                                               if (!reactionType.isAssignable) {
+                                                       elHide(reactionTypeItem);
+                                               }
+                                               
                                                popoverContentHTML.appendChild(reactionTypeItem);
                                        }
                                        
@@ -372,6 +383,8 @@ define(
                                if (this._popoverCurrentObjectId !== 0) {
                                        this._getPopover().classList.remove('active');
                                        
+                                       elBySelAll('.reactionTypeButton[data-is-assignable="0"]', this._getPopover(), elHide);
+                                       
                                        if (this._options.isButtonGroupNavigation) {
                                                this._objects.get(this._popoverCurrentObjectId).forEach(function (elementData) {
                                                        elementData.reactButton.closest('nav').style.cssText = "";
index 2cbade39ff18ef9b6cc377ca21d836df7c47070b..75f149597ac7ac68147738abd7b106e68a40015a 100644 (file)
@@ -4,6 +4,7 @@ use wcf\data\reaction\type\ReactionTypeAction;
 use wcf\data\reaction\type\ReactionTypeList;
 use wcf\form\AbstractFormBuilderForm;
 use wcf\system\form\builder\container\FormContainer;
+use wcf\system\form\builder\field\BooleanFormField;
 use wcf\system\form\builder\field\ShowOrderFormField;
 use wcf\system\form\builder\field\TitleFormField;
 use wcf\system\form\builder\field\UploadFormField;
@@ -60,7 +61,10 @@ class ReactionTypeAddForm extends AbstractFormBuilderForm {
                                ShowOrderFormField::create()
                                        ->description('wcf.acp.reactionType.showOrder.description')
                                        ->required()
-                                       ->options(new ReactionTypeList())
+                                       ->options(new ReactionTypeList()),
+                               BooleanFormField::create('isAssignable')
+                                       ->label('wcf.acp.reactionType.isAssignable')
+                                       ->description('wcf.acp.reactionType.isAssignable.description')
                        ]);
                
                $iconContainer = FormContainer::create('imageSection')
index 650e9f91dd9a0f54ddc900d456f59168d87c8b77..523fe88ae1c4573a4c97c0ffd55bb4e459f8e1f9 100644 (file)
@@ -201,6 +201,15 @@ class ReactionAction extends AbstractDatabaseObjectAction {
                                throw new PermissionDeniedException();
                        }
                }
+               
+               if (!$this->reactionType->isAssignable) {
+                       // check, if the reaction is reverted
+                       $like = Like::getLike($this->likeableObject->getObjectType()->objectTypeID, $this->likeableObject->getObjectID(), WCF::getUser()->userID);
+                       
+                       if (!$like->likeID || $like->reactionTypeID !== $this->reactionType->reactionTypeID) {
+                               throw new IllegalLinkException();
+                       }
+               }
        }
        
        /**
index fca986dc02c32910b0a92e6e1df9b95d5aaf692a..acbdffb2cd2ee7822f86ea4b9f03f706cef788b9 100644 (file)
@@ -11,12 +11,13 @@ use wcf\system\WCF;
  * @copyright  2001-2019 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\Data\Reaction\Type
- * @since       5.2
+ * @since      5.2
  *
  * @property-read      integer         $reactionTypeID         unique id of the reaction type
  * @property-read      string          $title
  * @property-read      integer         $showOrder              position of the reaction type in relation to the other reaction types
  * @property-read      string          $iconFile               the file location of the icon
+ * @property-read      boolean         $isAssignable           `1`, if the reaction can be assigned
  */
 class ReactionType extends DatabaseObject implements ITitledObject {
        /**
index 926e6a2cb15edf8471e68e3db70d7736885a26ae..028ad7a2a6e26871de0c6541ae68a2648ed6ae0d 100644 (file)
@@ -35,7 +35,7 @@ use wcf\util\StringUtil;
  * @copyright  2001-2019 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    WoltLabSuite\Core\System\Reaction
- * @since       5.2
+ * @since      5.2
  */
 class ReactionHandler extends SingletonFactory {
        /**
@@ -79,7 +79,8 @@ class ReactionHandler extends SingletonFactory {
                                'renderedIcon' => $reaction->renderIcon(), 
                                'iconPath' => $reaction->getIconPath(), 
                                'showOrder' => $reaction->showOrder, 
-                               'reactionTypeID' => $reaction->reactionTypeID
+                               'reactionTypeID' => $reaction->reactionTypeID, 
+                               'isAssignable' => $reaction->isAssignable,
                        ];
                }
                
index f7a0c2b9d0851a0501fe65be82173bafbe18b63e..07cda1e702c42840a004646f2278a7ea9eb40fc1 100644 (file)
@@ -2575,6 +2575,8 @@ Kein Abschnitt darf leer sein und alle Abschnitten dürfen nur folgende Zeichen
                <item name="wcf.acp.reactionType.type"><![CDATA[Reaktions-Typ]]></item>
                <item name="wcf.acp.reactionType.image"><![CDATA[Reaktions-Datei]]></item>
                <item name="wcf.acp.reactionType.showOrder.description"><![CDATA[Der Reaktions-Typ wird nach dem ausgewählten Reaktions-Typ angezeigt.]]></item>
+               <item name="wcf.acp.reactionType.isAssignable"><![CDATA[Kann verwendet werden]]></item>
+               <item name="wcf.acp.reactionType.isAssignable.description"><![CDATA[Wenn eine Reaktion nicht verwendet werden kann, können Benutzer nicht mit der Reaktion reagieren. Wurde auf einen Inhalt bereits mit der Reaktion reagiert, ist sie auch weiterhin für Benutzer sichtbar.]]></item>
        </category>
        <category name="wcf.acp.rebuildData">
                <item name="wcf.acp.rebuildData"><![CDATA[Anzeigen aktualisieren]]></item>
index b3c4886b71e6cae3f14414028ccdc127ea1082ed..b0e09914d1bc3b5ce1be6229e4c3ff395807d7ba 100644 (file)
@@ -2503,6 +2503,8 @@ If you have <strong>already bought the licenses for the listed apps</strong>, th
                <item name="wcf.acp.reactionType.type"><![CDATA[Reaction Type]]></item>
                <item name="wcf.acp.reactionType.image"><![CDATA[Reaction File]]></item>
                <item name="wcf.acp.reactionType.showOrder.description"><![CDATA[The reaction type will be shown after the selected reaction type.]]></item>
+               <item name="wcf.acp.reactionType.isAssignable"><![CDATA[Can be assigend]]></item>
+               <item name="wcf.acp.reactionType.isAssignable.description"><![CDATA[If a reaction cannot be used, users cannot react with the reaction. If a content has already been reacted to with the reaction, it remains visible to users.]]></item>
        </category>
        <category name="wcf.acp.rebuildData">
                <item name="wcf.acp.rebuildData"><![CDATA[Rebuild Data]]></item>
index 082f4c6ad8ef6634355efd3bf04fac41abc01d51..8e31d21f40e6705f52ff9713c7bb102c082e1129 100644 (file)
@@ -1201,7 +1201,8 @@ CREATE TABLE wcf1_reaction_type (
        reactionTypeID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
        title VARCHAR(255), 
        showOrder INT(10) NOT NULL DEFAULT 0,
-       iconFile MEDIUMTEXT
+       iconFile MEDIUMTEXT, 
+       isAssignable TINYINT(1) NOT NULL DEFAULT 1
 );
 
 DROP TABLE IF EXISTS wcf1_registry;