• Hello Fabrik Community

    Fabrik is now in the hands of the development team that brought you Fabrik for Joomla 4. We have recently transitioned the Fabrik site over to a new server and are busy trying to clean it up. We have upgraded the site to Joomla 4 and are running the latest version of Fabrik 4. We have also upgraded the Xenforo forum software to the latest version. Many of the widgets you might have been used to on the forum are no longer operational, many abandoned by the developers. We hope to bring back some of the important ones as we have time.

    Exciting times to be sure.

    The Fabrik 4.0 Official release is now available. In addition, the Fabrik codebase is now available in a public repository. See the notices about these in the announcements section

    We wish to shout out a very big Thank You to all of you who have made donations. They have really helped. But we can always use more...wink..wink..

    Also a big Thank You to those of you who have been assisting others in the forum. This takes a very big burden off of us as we work on bugs, the website and the future of Fabrik.

Show/Hide Dropdown Options based on user group

dboggs1994

New Member
Sorry if this has been addressed I may not be using the right search criteria. What I am trying to accomplish is a basic workflow approval engine based on status. I have a dropdown with a list of all statuses, however I only want certain statuses to be available to certain user groups involved in the workflow. For example requesters would have a draft and waiting approval status, whereas an approver would be able to approve etc... Is there a way to accomplish this using a dropdown? Using separate elements is another option but would rather use a dropdown.
 
You could use an eval populate script. On the advanced Tab of the Dropdown you can insert php code to populate the dropdown. In this code you can get the groups the user belongs to and then populate the drop down with the options they have rights to.
 
The problem with doing it with a dropdown with an eval script is that if User A edit the form and selects a status s/he has access to ... then User B edits it, and doesn't have access to that value ... it won't display correctly, 'cos the current value has no corresponding option.

I think a better approach would be to use a join element, to a 'status codes' table, which has the status title and the J! access level needed to use it, and use the 'eval options' to set any options they don't have access to to be disabled.

I just played around with this on my test site ... created a 'status_codes' table like ...

id - normal int primary key
status - field
access_level - join element to J!'s #__viewlevels table (using 'id' as value)

Then on another form, I added a join element to 'status_codes', with 'id' as the value and 'status' as the lable, and in the "Advanced" tab, in the Eval options:

Code:
db = JFactory::getDbo();
$query = $db->getQuery(true);
// select the 'access_level' for this status value
$query->select('access_level')->from('fab_status')->where('id = ' . $db->quote($opt->value));
$db->setQuery($query);
$access = $db->loadResult();
if (!empty($access)) {
  // if we got an access level, check to see if the logged on user is in that level
  $myLevels = $this->user->getAuthorisedViewLevels();
  if (!in_array($access, $myLevels)) {
    // if they don't have access, set disable
    $opt->disable = true;
  }
}

You should then have the complete list of statuses in the dropdown, but ones you don't have access to are disabled (greyed out).

The only wrinkle I ran into is the Use A / User B thing, whereby if User B doesn't have access to the current status and edits the form, the join element will show that value as the current selection (even though it's disabled) ... but when they submit the form, the value won't get submitted (HTML forms don't submit disabled values), so the selection gets cleared in the submitted form.

I kinda hacked round this with a commit:

https://github.com/Fabrik/fabrik/commit/d71044250dd1f2ed2577674807d7a14b272e15e4

(ignore the title of the commit) ... which automagically clears the 'disabled' attribute if the selected value is disabled, when submitting.

So ... if you do a github update, and follow the way I did it, that should work for you.

-- hugh
 
Hugh, I see what you mean about the user a/b thing, but wouldn't it be easier to simply set the options the user does not have access to as disabled in the option list when the dropdown is created via the eval script?

Something like this (no exactly executable, illustrative)

$option = JHTML::_('select.option', $item->id, $item->name );
if (no access to item>id)
$option->disable=true;
$options[] = $option;

Seems a little simpler to me.
 
But you run into the same issue there as I found in my example with the join element (see my previous post) ... options that are disabled don't get submitted with the form. That's an HTML thing, not a Fabrik thing. So if User B edits the form and the dropdown's current selection is disabled ... if they don't select one of the enabled options, the element's value will be null'ed out on submit.

I could fix that in a similar way to the fix I applied to the join element ... but ... a) the join element is already fixed to work round that, and b) it really is better to use a join to a "status" table, rather than building your own dropdown array. For example, if you want to change anything - add a new status, change the access level, etc ... all you have to do is add/edit a row in that 'status' table, through the normal Fabrik list/form methods. If you are rolling your own in a dropdown element, you have to go and write PHP code. So it's just a list, that looks like ...

Status | Access Level
------------------
Pending | Administrators
Completed | Very Special People
Disputed | Registered

... where the Access Level is literally the J! view levels.

Also ... my experience is that when you have a status field in one list/form, you invariably wind up having to reference it in other lists/forms. And setting up a join to the same table is a lot easier than recreating a custom dropdown.

-- hugh
 
I have a table with an element within it where I store the joomla view level required to view/edit it. The value stored in the field is fed from the joomla view levels table. I only want to allow the user to pick from that list, view levels that they are members of so I used the advanced tab as Hugh describes above using getAuthorisedViewLevels joomla method.

That works perfectly in the form. But I also want the filter to only contain values that the user is authorized to see. However, the filter values (drop down) don't appear to be impacted by my code. There does not appear to be a PHP way to filter the 'filter values' to include only those view levels from getAuthorisedViewLevels method.

So, I tried to change the element from a join to a drop down where I could get more control. This works, except when I save the element it seems to try to change the database schema and I get a message

Code:
Update field structure for 'my field name' from INT(11) to TEXT.

If I press 'Save', I get a MySQL error:
Code:
1170 BLOB/TEXT column 'my_field_name' used in key specification without a key length.

As I said, the form and filter do work as I'd like but it bothers me to have this happening when I try to save the element. I thought of turning off schema updates for the list and I'd be more comfortable with that if I could turn it off just for this element. But it bothers me to turn it off for the entire list.

Is there a way to filter the elements drop-down filter values if I leave the element as a database join?

Is there a way to may a drop down play nice with the database?

Which is the best solution (these or others).

PS, I would have considered using a WHERE clause with a join to get the user's group list and intersect that with the view-level's for the user but since Joomla stores viewlevel group members in JSON it seems like query would be very complex and could break in future releases of Joomla.

Also noting that once I move the element to a drop-down, then filtering by that element is extremely slow, probably because the index had originally be setup to index integers when the dropdown is now storing the same numeric as a text. The key would be to allow the drop-down to store its value as integer, not text. Perhaps a specialized drop-down element is what is required.

Thanks,
Bruce
 
Last edited:
@pastvne
You should be able to do this with the databasejoin and Advanced/Eval options: return false for the ones the user shouldn't see.
 
@pastvne
You should be able to do this with the databasejoin and Advanced/Eval options: return false for the ones the user shouldn't see.
Thanks Troester. I do have it working with databasejoin advanced/eval options within the form view for the record. I'll re-check my results but my first test indicated that while it worked for the form view pull-down, the list filter was not filtered but contained all values as if the eval code didn't run. But, I'm going to re-check my work to make sure I didn't make a false observations. Thanks for the confirmation! Will report back here with my results.
 
@pastvne
You should be able to do this with the databasejoin and Advanced/Eval options: return false for the ones the user shouldn't see.

Hi Troester:
I went back and re-created my test. For this element, called csp_division, I added the following code to Advanced>Eval and it works within the edit/add form to filter the available pull-down options as I would expect:
Code:
$cspDb    = JFactory::getDbo();
$cspQuery = $cspDb->getQuery(true);
$myLevels = $this->user->getAuthorisedViewLevels();
$cspQuery->select('view_level')->from('csp_division')->where('id=' . $cspDb->quote($opt->value));
$cspDb->setQuery($cspQuery);
$viewLevel = $cspDb->loadResult();
if(empty($viewLevel)){
  return false;
} else {
  if(!in_array( (int) $viewLevel, $myLevels, true)){
    return false;
  }
}

I tested by assigning one of the records is the join table's view_level field to 'nobody' which is a Joomla view level that includes no Joomla groups.

When I edit or add a record into the list, the join element in the edit or add form is properly filtered to exclude the joined record whos view_level value had been set to 'nobody'.

But, I also need the Lists Filter pull-down to be similarly filtered. I notice that if I alter the eval code to throw an error and exit, that I can bring up the list and the filter for this field does not execute the eval code since it does not throw any error. So, it seems that the join element will eval the eval code for the element pull-down itself, but not for its filter.

I need to find a way to exclude the same records from the filter pull-down as I have from the form's element pull-down.

I'll look at, perhaps, the list plug-ins to see if any of those hooks would allow me to filter the options in the lists filter. I do see that under Data Where for the database join element properties, there is a field called Filter Where. But, it only accept a SQL query and not PHP code.

I am looking through the wiki and forums to see if there might be away to use global variables within the Filter Where query and then work out something that functions similarly to the PHP code above but in SQL instead. So, there seems to be some recognition within the definition of the database join element type that Advanced>eval is not intended for the list's filter and that this would need to be achieved in a different way. What would be ideal is if there was an option in the database join advanced>eval page where you could select "also apply to list filter".
 
Last edited:
Hi Troester:


I'll look at, perhaps, the list plug-ins to see if any of those hooks would allow me to filter the options in the lists filter. I do see that under Data Where for the database join element properties, there is a field called Filter Where. But, it only accept a SQL query and not PHP code.

I'm playing withe the PHP Event List plugin and I see a promising event hook called onMakeFilters which the wiki says "Called when the list HTML filters are loaded". There is not much documentation after that so it is hard to tell whether 'filters' means prefilters or URL filters or whether it means the pop-up List filters. So, I'll need to figure that out to determine if this hook could be used for my intended purposes. Assuming I figure that out, then I need to determine if there is a safe way to use Fabrik models to modify the filter options for this element.
 
I used the php_events once (yes, there's very little documentation). In the OnBuildQueryWhere the filters could be accessed with $model->filters.
Check with var_dump what you get (I only needed to check the elementID)
 
Excellent Troester. If I figure this out, I'll write a wiki contribution. As always, many thanks!

Update: Unfortunately, while that array looked promising, I've tried to override the multiple array elements with modified values and it has not impacted the content of the filter pull-down. If I understood where Fabrik builds the filter values, I might be able to hack that code to cause it to call the advanced/eval code for the filter as it does with the actual form element.

I'm gronking around in the plugins directory now trying to see how this is done.

Any advice appreciated,
Bruce
 
Last edited:
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top