XF 2.0 Int permission inverse priority

CMTV

Well-known member
Hi!

By default, XenForo prioritizes the highest int permission value. I want the opposite thing.

Is there a way to inverse priority for int permission? If not, what is the best way to achieve this?

Will it be added as core feature in the future?
 
There aren't any plans to add this in the future. Note that the same roughly applies to non-int permissions in that the design roughly necessitates that they are written in a "positive" way (where yes mean more permissions than no). I appreciate that this is difficult for int permissions.

The short roughly is that there isn't a way to selectively flip a permission's calculation approach. It may be possible with a series of class overrides, though I'm not aware of anyone that's done it.
 
This add-on is capable of inverting priority to count lowest first. I never bothered writing it efficiently however, so it calculates on the fly when needed, as it's only ever needed when a post is submitted.
 
Ok. Here is an explained solution of how to get the lowest user permission value for specific user (many thanks to @Lukas W. The instructions below are based on his code).

----

Imagine we have a User entity under $user variable.

First of all, we need to get all users groups our user belongs to:
PHP:
$userGroups = $user->secondary_group_ids;
$userGroups[] = $user->user_group_id;

User permission values are stored in xf_permission_entry table. That is why we need to create a XF:PermissionEntry finder:
PHP:
/** @var Finder $permissionFinder */
$permissionFinder = \XF::finder('XF:PermissionEntry');

Now, it is time to specify what exactly we are looking for in the table:
PHP:
$permissionFinder
    ->where('permission_group_id', '**PERMISSION_GROUP_ID**')
    ->where('permission_id', '**PERMISSION_ID**')
    ->whereOr([
        ['user_group_id', $userGroups],
        ['user_id', $user->user_id]
    ]);

Change **PERMISSION_GROUP_ID** and **PERMISSION_ID** to a desired values.

Next, we need to retrieve selected entities from the database:
PHP:
$permissions = $permissionFinder->fetch();

Finally, we want to store the lowest permission value in $lowestValue variable. In order to do so, we are to iterate $permissions:
PHP:
// Getting the first permission value
$lowestValue = $permissions->first()->premission_value_int;

// Iterating retrieved permissions
/** @var PermissionEntry $permission */
foreach ($permissions as $permission)
{
    // If current permission int value is lower than $lowestValue, assign it to $lowestValue
    $lowestValue = min($lowestValue, $permission->permission_value_int);
}

That's all! You now have the lowest int permission value for current user in $lowestValue variable.

Keep in mind, that users can choose "No limits" option instead of providing an int value. "No limits" option equals -1. If you want to work with positive (+ zero) integers only, you will need to perform an additional check after iterating the array:
PHP:
if ($lowestValue === -1)
{
    $lowestValue = 0;
}

A zero (0) integer permission value is treaded as default "No" permission value by XenForo and, therefore, will not appear in $lowestValue. Make sure to use "No limits" option instead of using 0 as value!
 
Last edited:
Inverse priority on "Analyze permissions" page

In order to show the lowest permission value on "Analyze permissions" page, which is oftenly used to debug permissions, you need to extend XF\Admin\Controller\Permission class:

PHP:
<?php

namespace YOUR_ADDON_ID\XF\Admin\Controller;

class Permission extends XFCP_Permission
{
    public function actionAnalyze()
    {
        $view = parent::actionAnalyze();

        // Doing nothing if error happened
        if ($view instanceof \XF\Mvc\Reply\Error)
        {
            return $view;
        }

        // Ensure there is an analysis array
        if ($analysis = $view->getParam('analysis'))
        {
            // Getting an array of values for different groups (+ user value for specific users)
            $intermediates = $analysis['**PERMISSION_GROUP**']['**PERMISSION_ID**']['intermediates'];

            // Getting the first value
            $lowestValue = array_shift($intermediates)->value;

            // Iterating values
            foreach ($intermediates as $intermediate)
            {
                // A zero (0) value is equivalent to "No" and should not be counted (use "Unlimited" option instead)!
                if ($intermediate->value !== 0)
                {
                    // If current value is lower than $lowestValue, use it
                    $lowestValue = min($lowestValue, $intermediate->value);
                }
            }

            // Setting final value to $lowestValue
            $analysis['**PERMISSION_GROUP**']['**PERMISSION_ID**']['final'] = $lowestValue;

            $view->setParam('analysis', $analysis);
        }

        return $view;
    }
}

Again, don't forget to replace YOUR_ADDON_ID, **PERMISSION_GROUP_ID** and **PERMISSION_ID** with desired values.

Result:
1541338626926.webp
 
Last edited:
Top Bottom