Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.0] Added possibility to batch remove a tag #3344

Open
jgerman-bot opened this issue Nov 14, 2024 · 0 comments
Open

[6.0] Added possibility to batch remove a tag #3344

jgerman-bot opened this issue Nov 14, 2024 · 0 comments

Comments

@jgerman-bot
Copy link

New language relevant PR in upstream repo: joomla/joomla-cms#40613 Here are the upstream changes:

Click to expand the diff!
diff --git a/administrator/language/en-GB/lib_joomla.ini b/administrator/language/en-GB/lib_joomla.ini
index b940984bcd512..154b38a64382f 100644
--- a/administrator/language/en-GB/lib_joomla.ini
+++ b/administrator/language/en-GB/lib_joomla.ini
@@ -379,8 +379,11 @@ JLIB_HTML_BATCH_MOVE="Move"
 JLIB_HTML_BATCH_MOVE_QUESTION="Action to Perform"
 JLIB_HTML_BATCH_NO_CATEGORY="- Don't copy or move -"
 JLIB_HTML_BATCH_NOCHANGE="- Keep original Access Levels -"
-JLIB_HTML_BATCH_TAG_LABEL="Add Tag"
+JLIB_HTML_BATCH_TAG_ADD="Add"
+JLIB_HTML_BATCH_TAG_ADDREMOVE_QUESTION="Action to Perform"
+JLIB_HTML_BATCH_TAG_LABEL="Add or Remove Tag"
 JLIB_HTML_BATCH_TAG_NOCHANGE="- Keep original Tags -"
+JLIB_HTML_BATCH_TAG_REMOVE="Remove"
 JLIB_HTML_BATCH_USER_LABEL="Set User."
 JLIB_HTML_BATCH_USER_NOCHANGE="- Keep original User -"
 JLIB_HTML_BATCH_USER_NOUSER="No User."
diff --git a/build/media_source/layouts/js/joomla/html/batch/batch-tag-addremove.es6.js b/build/media_source/layouts/js/joomla/html/batch/batch-tag-addremove.es6.js
new file mode 100644
index 0000000000000..54fa047e18ac2
--- /dev/null
+++ b/build/media_source/layouts/js/joomla/html/batch/batch-tag-addremove.es6.js
@@ -0,0 +1,42 @@
+/**
+ * @copyright  (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
+ * @license    GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+(() => {
+  const onSelect = () => {
+    const batchTag = document.getElementById('batch-tag-id');
+    const batchTagAddRemove = document.getElementById('batch-tag-addremove');
+    let batchSelector;
+
+    const onChange = () => {
+      if (!batchSelector.value
+          || (batchSelector.value && parseInt(batchSelector.value, 10) === 0)) {
+        batchTagAddRemove.classList.add('hidden');
+      } else {
+        batchTagAddRemove.classList.remove('hidden');
+      }
+    };
+
+    if (batchTag) {
+      batchSelector = batchTag;
+    }
+
+    if (batchTagAddRemove) {
+      batchTagAddRemove.classList.add('hidden');
+    }
+
+    if (batchTagAddRemove) {
+      batchSelector.addEventListener('change', onChange);
+    }
+
+    // Cleanup
+    document.removeEventListener('DOMContentLoaded', onSelect, true);
+  };
+
+  // Document loaded
+  document.addEventListener('DOMContentLoaded', onSelect, true);
+
+  // Joomla updated
+  document.addEventListener('joomla:updated', onSelect, true);
+})();
diff --git a/build/media_source/system/joomla.asset.json b/build/media_source/system/joomla.asset.json
index 1eae307baedf8..71dd180f0384d 100644
--- a/build/media_source/system/joomla.asset.json
+++ b/build/media_source/system/joomla.asset.json
@@ -304,6 +304,14 @@
         "defer": true
       }
     },
+    {
+      "name": "joomla.batch-tag-addremove",
+      "type": "script",
+      "uri": "layouts/joomla/html/batch/batch-tag-addremove.min.js",
+      "attributes": {
+        "defer": true
+      }
+    },
     {
       "name": "webcomponent.field-fancy-select-legacy",
       "type": "script",
diff --git a/language/en-GB/lib_joomla.ini b/language/en-GB/lib_joomla.ini
index 867b99ac71159..0254984502a2f 100644
--- a/language/en-GB/lib_joomla.ini
+++ b/language/en-GB/lib_joomla.ini
@@ -375,8 +375,11 @@ JLIB_HTML_BATCH_MOVE="Move"
 JLIB_HTML_BATCH_MOVE_QUESTION="Action to Perform"
 JLIB_HTML_BATCH_NO_CATEGORY="- Don't copy or move -"
 JLIB_HTML_BATCH_NOCHANGE="- Keep original Access Levels -"
-JLIB_HTML_BATCH_TAG_LABEL="Add Tag"
+JLIB_HTML_BATCH_TAG_ADD="Add"
+JLIB_HTML_BATCH_TAG_ADDREMOVE_QUESTION="Action to Perform"
+JLIB_HTML_BATCH_TAG_LABEL="Add or Remove Tag"
 JLIB_HTML_BATCH_TAG_NOCHANGE="- Keep original Tags -"
+JLIB_HTML_BATCH_TAG_REMOVE="Remove"
 JLIB_HTML_BATCH_USER_LABEL="Set User."
 JLIB_HTML_BATCH_USER_NOCHANGE="- Keep original User -"
 JLIB_HTML_BATCH_USER_NOUSER="No User."
diff --git a/layouts/joomla/html/batch/tag.php b/layouts/joomla/html/batch/tag.php
index 4112bb222b7fd..ea122fdf50e00 100644
--- a/layouts/joomla/html/batch/tag.php
+++ b/layouts/joomla/html/batch/tag.php
@@ -10,14 +10,35 @@
 
 defined('_JEXEC') or die;
 
+use Joomla\CMS\Factory;
 use Joomla\CMS\HTML\HTMLHelper;
 use Joomla\CMS\Language\Text;
 
+// Create the add/remove tag options.
+$options = [
+    HTMLHelper::_('select.option', 'a', Text::_('JLIB_HTML_BATCH_TAG_ADD')),
+    HTMLHelper::_('select.option', 'r', Text::_('JLIB_HTML_BATCH_TAG_REMOVE'))
+];
+
+/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
+$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
+$wa->useScript('joomla.batch-tag-addremove');
+
 ?>
-<label id="batch-tag-lbl" for="batch-tag-id">
+<label id="batch-tag-choose-action-lbl" for="batch-tag-id">
     <?php echo Text::_('JLIB_HTML_BATCH_TAG_LABEL'); ?>
 </label>
-<select name="batch[tag]" class="form-select" id="batch-tag-id">
-    <option value=""><?php echo Text::_('JLIB_HTML_BATCH_TAG_NOCHANGE'); ?></option>
-    <?php echo HTMLHelper::_('select.options', HTMLHelper::_('tag.tags', ['filter.published' => [1]]), 'value', 'text'); ?>
-</select>
+<div id="batch-tag-choose-action" class="control-group">
+    <select name="batch[tag]" class="form-select" id="batch-tag-id">
+        <option value=""><?php echo Text::_('JLIB_HTML_BATCH_TAG_NOCHANGE'); ?></option>
+        <?php echo HTMLHelper::_('select.options', HTMLHelper::_('tag.tags', ['filter.published' => [1]]), 'value', 'text'); ?>
+    </select>
+</div>
+<div id="batch-tag-addremove" class="control-group radio">
+    <fieldset id="batch-tag-addremove-id">
+        <legend>
+            <?php echo Text::_('JLIB_HTML_BATCH_TAG_ADDREMOVE_QUESTION'); ?>
+        </legend>
+        <?php echo HTMLHelper::_('select.radiolist', $options, 'batch[tag_addremove]', '', 'value', 'text', 'a'); ?>
+    </fieldset>
+</div>
diff --git a/libraries/src/Helper/TagsHelper.php b/libraries/src/Helper/TagsHelper.php
index d91f504701035..313c2e22fc3a2 100644
--- a/libraries/src/Helper/TagsHelper.php
+++ b/libraries/src/Helper/TagsHelper.php
@@ -821,8 +821,29 @@ public static function getTypes($arrayType = 'objectList', $selectTypes = null,
      * @return  boolean
      *
      * @since   3.1
+     *
+     * @deprecated  6.0 will be removed in 7.0
+     *              Please use postStore
      */
     public function postStoreProcess(TableInterface $table, $newTags = [], $replace = true)
+    {
+        $this->postStore($table, $newTags, $replace);
+    }
+
+    /**
+     * Function that handles saving tags used in a table class after a store().
+     *
+     * @param   TableInterface  $table    Table being processed.
+     * @param   array           $newTags  Array of new tags.
+     * @param   boolean         $replace  Flag indicating if all existing tags should be replaced.
+     *                                    This flag takes precedence before $remove.
+     * @param   boolean         $remove   Flag indicating if the tags in $newTags should be removed.
+     *
+     * @return  boolean
+     *
+     * @since   __DEPLOY_VERSION__
+     */
+    public function postStore(TableInterface $table, $newTags = [], $replace = true, $remove = false)
     {
         if (!empty($table->newTags) && empty($newTags)) {
             $newTags = $table->newTags;
@@ -856,7 +877,11 @@ public function postStoreProcess(TableInterface $table, $newTags = [], $replace
                 $ucmId     = $ucmContentTable->core_content_id;
 
                 // Store the tag data if the article data was saved and run related methods.
-                $result = $result && $this->tagItem($ucmId, $table, $newTags, $replace);
+                if ($remove) {
+                    $result = $result && $this->unTagItem($ucmId, $table, $newTags);
+                } else {
+                    $result = $result && $this->tagItem($ucmId, $table, $newTags, $replace);
+                }
             }
         }
 
diff --git a/libraries/src/MVC/Model/AdminModel.php b/libraries/src/MVC/Model/AdminModel.php
index 7a53808244b3e..9a1ae67ce7dad 100644
--- a/libraries/src/MVC/Model/AdminModel.php
+++ b/libraries/src/MVC/Model/AdminModel.php
@@ -325,7 +325,13 @@ public function batch($commands, $pks, $contexts)
 
         foreach ($this->batch_commands as $identifier => $command) {
             if (!empty($commands[$identifier])) {
-                if (!$this->$command($commands[$identifier], $pks, $contexts)) {
+                if ($command === 'batchTag') {
+                    $removeTags = ArrayHelper::getValue($commands, 'tag_addremove', 'a') === 'r';
+
+                    if (!$this->batchTags($commands[$identifier], $pks, $contexts, $removeTags)) {
+                        return false;
+                    }
+                } elseif (!$this->$command($commands[$identifier], $pks, $contexts)) {
                     return false;
                 }
 
@@ -693,8 +699,28 @@ protected function batchMove($value, $pks, $contexts)
      * @return  boolean  True if successful, false otherwise and internal error is set.
      *
      * @since   3.1
+     *
+     * @deprecated  6.0 will be removed in 7.0
+     *              Please use batchTags
      */
     protected function batchTag($value, $pks, $contexts)
+    {
+        return $this->batchTags($value, $pks, $contexts);
+    }
+
+    /**
+     * Batch tag a list of item.
+     *
+     * @param   integer  $value       The value of the new tag.
+     * @param   array    $pks         An array of row IDs.
+     * @param   array    $contexts    An array of item contexts.
+     * @param   boolean  $removeTags  Flag indicating whether the tags in $value have to be removed.
+     *
+     * @return  boolean  True if successful, false otherwise and internal error is set.
+     *
+     * @since   __DEPLOY_VERSION__
+     */
+    protected function batchTags($value, $pks, $contexts, $removeTags = false)
     {
         // Initialize re-usable member properties, and re-usable local variables
         $this->initBatch();
@@ -711,6 +737,7 @@ protected function batchTag($value, $pks, $contexts)
                         'subject'     => $this->table,
                         'newTags'     => $tags,
                         'replaceTags' => false,
+                        'removeTags'  => $removeTags,
                     ]
                 );
 
diff --git a/plugins/behaviour/taggable/src/Extension/Taggable.php b/plugins/behaviour/taggable/src/Extension/Taggable.php
index b721d8bd15dbe..b2f054dded700 100644
--- a/plugins/behaviour/taggable/src/Extension/Taggable.php
+++ b/plugins/behaviour/taggable/src/Extension/Taggable.php
@@ -171,7 +171,7 @@ public function onTableAfterStore(AfterStoreEvent $event)
         $newTags = $table->newTags ?? [];
 
         if (empty($newTags)) {
-            $result = $tagsHelper->postStoreProcess($table);
+            $result = $tagsHelper->postStore($table);
         } else {
             if (\is_string($newTags) && (strpos($newTags, ',') !== false)) {
                 $newTags = explode(',', $newTags);
@@ -179,7 +179,7 @@ public function onTableAfterStore(AfterStoreEvent $event)
                 $newTags = (array) $newTags;
             }
 
-            $result = $tagsHelper->postStoreProcess($table, $newTags);
+            $result = $tagsHelper->postStore($table, $newTags);
         }
     }
 
@@ -231,6 +231,7 @@ public function onTableSetNewTags(SetNewTagsEvent $event)
         $table       = $event['subject'];
         $newTags     = $event['newTags'];
         $replaceTags = $event['replaceTags'];
+        $removeTags  = $event['removeTags'];
 
         // If the tags table doesn't implement the interface bail
         if (!($table instanceof TaggableTableInterface)) {
@@ -247,7 +248,7 @@ public function onTableSetNewTags(SetNewTagsEvent $event)
         $tagsHelper            = $table->getTagsHelper();
         $tagsHelper->typeAlias = $table->getTypeAlias();
 
-        if (!$tagsHelper->postStoreProcess($table, $newTags, $replaceTags)) {
+        if (!$tagsHelper->postStore($table, $newTags, $replaceTags, $removeTags)) {
             throw new \RuntimeException($table->getError());
         }
     }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants