0

I've searched a lot the Views issue queue, searched for other modules, searched on stackexchange, but it seems that no one needs this functionality (or that there's another way to achieve it).

Use case: I have two content types: lecture and substitute teaching. A teacher uses the lecture content type when he has a normal lecture in a class where he has a chair. A teacher uses the substitute teaching when another teacher isn't at school (ill or in an excursion) and he has to replace the colleague.

In the lecture content type I have put an entity reference field named "chair", which filters the chairs so only the tearcher's ones are shown. For doing this I use the entity selection section of the field, and pass via token the teacher's uid to the view. But in the substitute teaching content type, I don't want to filter the chairs. Since a teacher could replace anyone, I need an unfiltered list of chairs.

Since the entity selection part of the field is applied everywhere this field is used, I had to create another entity reference field in the substitute teaching which references the chair content type, but without filtering. Having the same content type pointed, but using two different fields, is leading to maintenance nightmares (put both the content types and filter them based on chair field is nearly impossible), so I'm seeking for a different approach.

I think that a good one would be to pass to the view the uid and the content type. If the content type is "lecture", then apply filtering, otherwise don't. In this way I could use the same field in both the content types and everythig would work smothly. Well, it seems impossible to do such a simple thing.

The only solution that got me near the desired result was using conditional fields, but when filtering I got a bunch of empty option values where the view result was hidden, but it was selectable.

Any help or hint would be appreciated. Thanks!

2 Answers 2

0

One possibility is hook_views_pre_view()

function MYMODULE_views_pre_view(&$view, &$display_id, &$args) {

    if ($view->name == 'chairs' && $display_id == 'entityreference_1') {
        $node = menu_get_object();
        if ((is_object($node) && $node->type == 'substitute')
            || (arg(1) == 'add' && arg(2) == 'substitute')) {

            $args = array();
        }
    }
}

This solution is assuming the use of a contextual filter, with 'Display all results for the specified field' selected when the filter value is not available. This will remove the user id being passed as an argument when the content type is 'substitute.'

Another option might be a view with a relationship of 'Content: Author' and a filter (not contextual) for the current logged in user. The following could be used in that case to unset that filter if the content being added/edited is 'substitute.'

function MYMODULE_views_pre_view(&$view, &$display_id, &$args) {

    if ($view->name == 'chairs' && $display_id == 'entityreference_1') {
        $node = menu_get_object();
        if ((is_object($node) && $node->type == 'substitute')
            || (arg(1) == 'add' && arg(2) == 'substitute')) {

            unset($view->display_handler->default_display->options['filters']['uid_current']);
        }
    }
}

In this case it assumes the filter is a default for all displays for this view. If it is a filter an override for that display, the unset line will need to be:

unset($view->display_handler->options['filters']['uid_current']);

Fill in the machine names for your view name, display id and content type.

1
  • Thanks! I accept yours as the solution to my question, because it was the quickest to implement. I also like the Reynolds's one as it gives to me some good hints on how to alter a query by code. Many thanks to both of you! Commented Feb 16, 2015 at 17:37
0

You will have to add a custom module for this. I usually have one monolithic module that I add to every project that I name the same as my project for project specific tweaks like this.

In that module's module file, add this code:

function MODULE_views_query_alter(&$view, &$query){
  // target the correct view
  if ($view->name == 'chair' && $view->current_display == 'entityreference_1') {
    // target the correct path
    $node = menu_get_object();
    if ($node && arg(0) == 'node' && arg(2) == 'edit' && $node->type == 'lecture') {
      // edit page on lecture type
      $view->query->add_where("entityreference_tweak", "node.uid", $node->uid, '=');
    }
    else if (arg(0) == 'node' && arg(1) == 'add' && arg(2) == 'lecture')    
    // create page on lecture type
    {
      global $user;
      $view->query->add_where("entityreference_tweak", "node.uid", $user->uid, '=');
    }
  }
}

I named the entityreference view 'chair', the entityreference display took the default name 'entityreference_1', the lecture content type has the machine name 'lecture'. You need to substitute these name in the code above with your own machine names.

Then completely remove the contextual uid filter from your entity reference view and also do not pass anything to the view in the field settings of the content type. The code adds the filter dynamically. It checks if you are on a lecture edit/add page, then adds either the node author uid, or the uid of the currently logged in user.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.