Hello,

I'm trying to add a little image right next to a value inside a specific field of a view.
My tests involve views_pre_render hook in a drupal 6 environment.

function MYMODULE_views_pre_render(&$view) {

     if ($view->name=='MY_VIEW') {
              foreach($view->result as $row) {
                                   $row->MYFIELD.=" Only local images are allowed.";
              }
    }

}

The problem is that the img tag is properly filtered by the rendering process.
Am i using the wrong hook or i must, someway , disable the filtered html format option from inside my module?

Thank you in advance.

Comments

Tobias Xy’s picture

I think you can do this without custom php code (at least in Drupal 7, but maybe it is also possible in Drupal 6?):
Create a custom field (Field A) in your view behind the field you want to add the image (Field B).
Then hide Field B and add it into Field A by using token replacement. Then you can also add the image into Field A.

scoste’s picture

I really appreciate your solution, but its not what i really need.
My module has to manage a set of complex tasks which, among other things, are responsable to inject triggers into nodes and views.
That's why i'm looking for a solution which include custom php code inside hooks.

scoste’s picture

I heard that the most spread method is to add a .tpl file views-view-field--MYFIELD-value.tpl.php with the following code

        echo $row->node_data_MYFIELD_value." Only local images are allowed.";

It works but it's not what i need, i need the image injected directly by my module, who has to control every procedure of its tasks.

I thought that forcing the field format to full_html would be enough:

function MYMODULE_views_pre_render(&$view) {

     if ($view->name=='MY_VIEW') {
              $view->set_item_option('default', 'field', 'MYFIELD','format',2);

              foreach($view->result as $row) {
                                   $row->MYFIELD.=" Only local images are allowed.";
              }
    }

}

I can see with dpm the option actually set, but the final result on the browser rests the same: i see the html code as a string instead of its parsing effect.
Its seems that the view module doesn't care about any option forcing this sense... if it is plain text, plain text must remain!

So, i made it work with this very, very..... sadly bad solution:

function MYMODULE_views_pre_render(&$view) {

     if ($view->name=='MY_VIEW') {
              foreach($view->result as $rownumber => $row) {

                $inj_pattern=uniqid(true);
                $row->node_data_MYFIELD_value .="$inj_pattern";

                $image=create_image($vardata,$vardata,$vardata);            
                // i needed variable images

                $view->display['MYMODULE_injection'][$rownumber]=array(
                                     'image' => $image,
                                     'inj_pattern' => $inj_pattern
                 );
              }
    }
}

function call_contact_views_post_render(&$view,&$output,&$cache) {

     if($view->display['MYMODULE_injection']) {
           foreach($view->display['call_contact_injection'] as $row) {
                 $output=str_replace($row['inj_pattern'],$row['image'],$output);
           }
       }
}

As you can see, i basically marked the image spot with a pattern, put the pattern inside the view row data, and save the field specific image and pattern into a location inside the view object.
Then, with views_post_render hook, i REPEATEDLY scanned the rendered output string looking for patterns and replacing them with the correct image associated with the row field.

I highlighted REPEATEDLY because that's the key point which make the entire solution a really bad solution.
$output string must be unnecessarily scanned over and over again just for pattern matching.
This introduces a lot of overead, linearly incrementing with the number of rows and fields to be considered.

That is unaccetable! I feel like i'm wasting a lot of precious time swimming into an unstructured flow of data when this data were just structed and really easy to access only a moment ago!

That's what came out of my mind, i look forward to receive your opinions.

Thanks again.

Tobias Xy’s picture

I just tested this and wrote the following code snippet:

function custom_views_pre_render(&$view)
{
	foreach($view->result as &$res)
	{
		if($res->field_field_text)
			$res->field_field_text[0]['rendered']['#markup'] .= "Only local images are allowed.";
	}
}

In my view all the field_field_text's get the img tag added (as HTML!).

Does this help you?

Btw: In your example the "$row->MYFIELD" is an array, right?

scoste’s picture

That would be the best solution to adopt, but i can't make it work.

In my case $row->MYFIELD is an array but it doesn't contain the element [0]['rendered']

It is described as follows:

                  nid (String, 6 characters ) 761788
                  node_data_MYFIELD1 (NULL)
                  node_type (String, 7 characters ) mytype
                  node_vid (String, 6 characters ) 761831
                  node_data_MYFIELD2 (NULL)
                  node_title (String, 5 characters ) prova
                  node_data_MYFIELD3 (String, 2 characters ) 91
                  node_uid (String, 1 characters ) 0
                  node_data_MYFIELD4 (NULL)
                  ... fields

Nothing about rendering.
It is because of drupal 6 or am i missing something?

Tobias Xy’s picture

Oh, yes it's because of Drupal 6...

You could use the "Rewrite the output of this field" option in your view and of course it is possible to overwrite the template files of the view in your theme. But i know, you don't want it that way.

So you could register your own display handler via hook_views_handlers (https://api.drupal.org/api/views/docs%21docs.php/function/hook_views_han...). Install the advanced help module and you will find a documentation on how to do this (/help/views/api-handlers).

I never used to do that (so I am not entirely sure about that), but it seems to be the solution you are looking for.

scoste’s picture

Thanks for your tip, i tried to add a custom handler following this guide:
http://heididev.com/01/11/2011/custom-field-handlers-views-3

And it actually works.

Unfortunately this solution present some flexibility problem considering my module context.
My module has to take the fields to work with from a configuration table which is dynamically modified by the user.

Since every field needs its custom handler, and every handler needs a class code definition inside an inclusion file, there's a problem in creating dynamically those handlers.

My module should modify that inc file recreating class handlers code every time the user decides to modify the list of fields subjected to the module effects.
Furthermore my module should adapt hook_view_handlers to make view module recognize those changes, and then flush all the caches to make the hook function parsed.

It could be done of course, but would be unnecessarily too complex and inefficient.

If there aren't better solutions i'm considering to redesign my previous workaround in order to avoid the multiple scans problem which causes linear overhead.
I guess i can accept that compromise considering that it is a drupal 6 only limitation, when my module will be written in a drupal 7 environment it will be better.

I'll post the solution if someone is curious to see it.
Thanks again.