Hi!

I need to alter the data that's being sent to a view when it's being displayed. I've tried the hook_views_pre_execute, hook_views_pre_build, and hook_views_pre_view hooks through a custom module to modify some data but all that's being sent to these functions are the actual Structure of the view, and not the Data of the view.

Any ideas?

Comments

zbricoleur’s picture

If you want to modify the data itself, you should be targeting the nodes, not the view. Node.tpl.php would be one place you could start.

DrupalNovice’s picture

I've tried to make my modifications through a hook_nodeapi hook in my custom module - filtering down to the view I want to alter, like this:

function mymodule_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if ($node->nid == 36 && $op == 'view') {
    print_r($node);
    exit();
  }

But the view has already retrieved the data and parsed it to HTML on this stage. Only way to modify anything now is to treat the HTML with regexp to suck out the data from the markup....

nevets’s picture

What are you actually trying to modify?

DrupalNovice’s picture

I'm actually trying to filter the data through custom PHP code. The filter settings in the Views UI (admin/build/views/edit/[name-of-theview]) does not give me the required flexibility in this case.

Any ideas?

nevets’s picture

What are you trying to filter on? Or is the question what are you trying to filter?

DrupalNovice’s picture

Sorry for being a mess with this..

I have a Custom Content Type named 'Messages'.

I have three fields in 'Messages':
- 'message' (Title)
- 'friends' (User Reference)
- 'roles' (Role Reference)

Here's the 'filter' code I wan't applied every time the view is being viewed:


/** 
 * Some code to check if user viewing this view Matches a user specified for the CCK-node (in the 'persons' field)
 */
  $userid = $user->uid;
  foreach ($node->friends as $uid) {
    foreach ($uid as $k=>$v) {
      if ($v == $userid) {
        //If this user equals one of the users specified in the node->persons field, return true
        return true
      }
    } 
  }

If a node doesn't have the user->uid in $node->persons, I'd like to hide that node.

nevets’s picture

I think this will do the trick with out any coding.

Add a relationship on the friends field to the view.

Now add a filter on "User: Current", set the relationship and set "Is the logged in user" to yes.

DrupalNovice’s picture

Thanks nevets. The problem is, though, that I need to do some more custom "filtering" (on the roles), and they're all in a OR relationship.
eg.
"if user does not match OR if roles does not match, then display nothing.
if user does not match OR(but) if roles Does match, then display that node.
if user Does match OR(but) if roles does not match, then display that node.
.

So I'd really need to modify the data Before it's rendered out.

Any ideas?

DrupalNovice’s picture

Hey, I'm using the View in a Panel by the way..

DrupalNovice’s picture

Ok, solved. Unfortunately, Views does not provide any hooks to modify data before its processed to HTML, so the only way to alter data is to hack the Views module.

So, if the options in the Views edit page (admin/build/views/edit/name_of_the_view) doesn't meet your requirements, add your custom code to the theme.inc file in views/themes/theme.inc. I added my modifications to the template_preprocess_views_view function.

As always when hacking modules, beware of the consiquensess that may arise at a later point.

Hope this will help someone!

nevets’s picture

Since that is a preprocess function you can override it, see: http://drupal.org/node/223430

DrupalNovice’s picture

Yes, but I could not get it to work - since theme.inc implements template_preprocess_hook my custom module must implement the moduleName_preprocess_hook, and the execution order becomes wrong - my code would have to execute before theme.inc's...

Or am I missing something obvious here?

nevets’s picture

Why can't it run second, it has all the same data and can over write earlier results if needed.

DrupalNovice’s picture

Well it was my guess actually.. I thought that if it run first, it would ..work....to be honest I don't know how I got that idea.. ;-P

But it doesn't seem to work..if I try mymodule_preprocess_views_view in my module's .module file, the data is not changed on the View at all.
But the hook IS called and executed; if I do an exit(); or print 'hello'; I can see that it runs.

It must be some mistake that I've made.

I must go now, but I'll come back in a couple of hours and fix this..

DrupalNovice’s picture

Back and fixed.

The problem was that template_preprocess_views_view throws the data ($vars->result) to $vars['rows'], which in turn is rendered to HTML in the template files (in the views/theme directory). So doing $vars->result in my mymodule_preprocess_views_view won't change the data that's being displayed in the view - I need to throw the changed data to $vars['rows']. I could have done the changes directly on $vars['rows'] of course.....

Good, no need of hacking the module!

Thanks nevets!

scottprive’s picture

>"Unfortunately, Views does not provide any hooks to modify data before its processed to HTML, so the only way to alter data is to hack the Views module. "

Views _pre_render and render are made for this. With prerender you can do all sorts of manipulation - sum the columns, dynamically set the view title... whatever you need.

I've actually got the code partly working, where I was able to search and replace field data in the view. You won't find many documented examples or tutorials, so it may as well be impossible (I gave up before I got what I wanted from it, and I just hacked the view template instead...)