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

[5.2] Delete user access level - check for levels in use #3234

Closed
jgerman-bot opened this issue Aug 9, 2024 · 1 comment · Fixed by #3235
Closed

[5.2] Delete user access level - check for levels in use #3234

jgerman-bot opened this issue Aug 9, 2024 · 1 comment · Fixed by #3235

Comments

@jgerman-bot
Copy link

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

Click to expand the diff!
diff --git a/administrator/components/com_users/src/Model/LevelModel.php b/administrator/components/com_users/src/Model/LevelModel.php
index f511143d530a..9164435c26b7 100644
--- a/administrator/components/com_users/src/Model/LevelModel.php
+++ b/administrator/components/com_users/src/Model/LevelModel.php
@@ -32,10 +32,86 @@
 class LevelModel extends AdminModel
 {
     /**
-     * @var array   A list of the access levels in use.
-     * @since   1.6
+     * Method to delete one or more access levels.
+     *
+     * @param   array  $pks  An array of primary keys.
+     *
+     * @return  boolean  True if successful, false if an error occurs.
+     *
+     * @since   __DEPLOY_VERSION__
      */
-    protected $levelsInUse = null;
+    public function delete(&$pks)
+    {
+        $pks   = (array) $pks;
+        $table = $this->getTable();
+
+        $levelsInUse = [];
+
+        // Iterate the items to delete each one.
+        foreach ($pks as $i => $pk) {
+            if ($table->load($pk)) {
+                // Check if the access level is being used.
+                $db    = $this->getDatabase();
+                $query = $db->getQuery(true)
+                    ->select('DISTINCT access');
+
+                // Get all tables that have the access field
+                $checkTables = $db->getTableList();
+                $prefix      = $db->getPrefix();
+
+                foreach ($checkTables as $checktable) {
+                    // Get all of the columns in the table
+                    $fields = $db->getTableColumns($checktable);
+
+                    /**
+                     * We are looking for the access field. If custom tables are using something other
+                     * than the 'access' field they are on their own unfortunately.
+                     * Also make sure the table prefix matches the live db prefix (eg, it is not a "bak_" table)
+                     */
+                    if (strpos($checktable, $prefix) === 0 && isset($fields['access'])) {
+                        // Lookup the distinct values of the field.
+                        $query->clear('from')
+                            ->from($db->quoteName($checktable));
+                        $db->setQuery($query);
+
+                        try {
+                            $values = $db->loadColumn();
+                        } catch (\RuntimeException $e) {
+                            $this->setError($e->getMessage());
+
+                            return false;
+                        }
+
+                        // Check if the table uses this access level
+                        if (\in_array($pk, $values)) {
+                            // Add the table to the list of tables that use this access level
+                            $levelsInUse[$pk][] = $checktable;
+
+                            // Remove the access level from the list of items to delete
+                            unset($pks[$i]);
+                        }
+                    }
+                }
+            }
+        }
+
+        if (!empty($levelsInUse)) {
+            $app = Factory::getApplication();
+            $app->enqueueMessage(Text::_('COM_USERS_ERROR_VIEW_LEVEL_IN_USE'), 'error');
+
+            foreach ($levelsInUse as $levelId => $usedIn) {
+                $msg = Text::sprintf('COM_USERS_ERROR_VIEW_LEVEL_IN_USE_DETAILS', $levelId, implode(', ', $usedIn));
+                $app->enqueueMessage($msg, 'error');
+            }
+        }
+
+        if (empty($pks)) {
+            // Nothing left to delete
+            return true;
+        }
+
+        return parent::delete($pks);
+    }
 
     /**
      * Method to test whether a record can be deleted.
@@ -65,61 +141,6 @@ protected function canDelete($record)
             }
         }
 
-        // Check if the access level is being used by any content.
-        if ($this->levelsInUse === null) {
-            // Populate the list once.
-            $this->levelsInUse = [];
-
-            $db    = $this->getDatabase();
-            $query = $db->getQuery(true)
-                ->select('DISTINCT access');
-
-            // Get all the tables and the prefix
-            $tables = $db->getTableList();
-            $prefix = $db->getPrefix();
-
-            foreach ($tables as $table) {
-                // Get all of the columns in the table
-                $fields = $db->getTableColumns($table);
-
-                /**
-                 * We are looking for the access field.  If custom tables are using something other
-                 * than the 'access' field they are on their own unfortunately.
-                 * Also make sure the table prefix matches the live db prefix (eg, it is not a "bak_" table)
-                 */
-                if (strpos($table, $prefix) === 0 && isset($fields['access'])) {
-                    // Lookup the distinct values of the field.
-                    $query->clear('from')
-                        ->from($db->quoteName($table));
-                    $db->setQuery($query);
-
-                    try {
-                        $values = $db->loadColumn();
-                    } catch (\RuntimeException $e) {
-                        $this->setError($e->getMessage());
-
-                        return false;
-                    }
-
-                    $this->levelsInUse = array_merge($this->levelsInUse, $values);
-
-                    // @todo Could assemble an array of the tables used by each view level list those,
-                    // giving the user a clue in the error where to look.
-                }
-            }
-
-            // Get uniques.
-            $this->levelsInUse = array_unique($this->levelsInUse);
-
-            // Ok, after all that we are ready to check the record :)
-        }
-
-        if (\in_array($record->id, $this->levelsInUse)) {
-            $this->setError(Text::sprintf('COM_USERS_ERROR_VIEW_LEVEL_IN_USE', $record->id, $record->title));
-
-            return false;
-        }
-
         return parent::canDelete($record);
     }
 
diff --git a/administrator/language/en-GB/com_users.ini b/administrator/language/en-GB/com_users.ini
index bc40ad27db63..be813a51a60c 100644
--- a/administrator/language/en-GB/com_users.ini
+++ b/administrator/language/en-GB/com_users.ini
@@ -104,7 +104,8 @@ COM_USERS_ERROR_LEVELS_NOLEVELS_SELECTED="No View Permission Level(s) selected."
 COM_USERS_ERROR_NO_ADDITIONS="The selected user(s) are already assigned to the selected group."
 COM_USERS_ERROR_NOT_IN_GROUP="The selected user(s) are not in the selected group."
 COM_USERS_ERROR_ONLY_ONE_GROUP="A user must belong to at least one group."
-COM_USERS_ERROR_VIEW_LEVEL_IN_USE="You can't delete the view access level '%d:%s' because it is being used by content."
+COM_USERS_ERROR_VIEW_LEVEL_IN_USE="You can't delete the view access level(s)"
+COM_USERS_ERROR_VIEW_LEVEL_IN_USE_DETAILS="Level with ID %d is being used in the database tables: %s."
 COM_USERS_FIELDS_USER_FIELDS_TITLE="Users: Fields"
 COM_USERS_FIELDS_USER_FIELD_ADD_TITLE="Users: New Field"
 COM_USERS_FIELDS_USER_FIELD_EDIT_TITLE="Users: Edit Field"
@zero-24
Copy link
Member

zero-24 commented Aug 9, 2024

PR #3235

@zero-24 zero-24 closed this as completed Aug 9, 2024
zero-24 added a commit that referenced this issue Aug 10, 2024
* add new string

* fix #3234

* com_users.ini aktualisieren

Co-authored-by: Tobias Zulauf <[email protected]>

---------

Co-authored-by: Tobias Zulauf <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants