I use Views 2 & Drupal 6 and I can't find how to enter Views Argument Handling Code. I've enabled "use PHP for block visibility" but admin UI didn't change. How to use argument handling code in Views 2?

Comments

merlinofchaos’s picture

Status: Active » Fixed

You now have to use argument default setters and argument validators.

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

greg.harvey’s picture

Status: Closed (fixed) » Active

Ok, so how would one implement this sort of thing then?
http://drupal.org/node/70145#comment-204051

Validator code must return a TRUE or FALSE, so you can't do it there and default setters don't appear to be relevant - I guess this is just where you set the value of the argument if none is passed?

I gleaned from another post on the above page that argument handling code was probably never the proper place to do such things, and this hook looks promising:
http://views.doc.logrus.com/group__views__hooks.html#gf4d538493930fe0fa0...

However, there is no example code and I can't find any other modules implementing it. I'm going to have a play now, as it looks like it simply returns the view object and the whole query ready to be messed with...

greg.harvey’s picture

Answered my own question - you can rewrite the query using hook_views_query_alter(), which is probably where this sort of filtering should've happened in the first place. In my case I simply wanted to swap an 'equals' with 'greater than or equals' in one of my clauses. So I created a 'page' form of my view, invoked the hook and printed the query to screen:

function yourmodule_views_query_alter(&$view, &$query) {
  print_r($query);
}

Result looks like this:

views_query Object
(
    ... just over half way down ...

      [where] => Array
        (
            [0] => Array
                (
                    [clauses] => Array
                        (
                            [0] => node.status <> 0 OR node.uid = ***CURRENT_USER*** or ***ADMINISTER_NODES*** = 1
                            [1] => nodequeue_nodes_node.qid = %d
                            [2] => node.type = '%s'
                            [3] => DATE_FORMAT((FROM_UNIXTIME(node.changed) + INTERVAL 3600 SECOND), '%Y%m%%d') = '%s'
                        )

                    [args] => Array
                        (
                            [0] => 1
                            [1] => page
                            [2] => 20080825
                        )

                    [type] => AND
                )

        )
    ...
)

Great! I want to alter where clause 3, so in my own module:

function yourmodule_views_query_alter(&$view, &$query) {
  $query->where[0]['clauses'][3] = "DATE_FORMAT((FROM_UNIXTIME(node.changed) + INTERVAL 3600 SECOND), '%Y%m%%d') >= '%s'";
}

Now I just need to make sure this only acts on the view I want it to act on - finished code:

/**
 * Implementation of hook_views_query_alter()
 */
function yourmodule_views_query_alter(&$view, &$query) {
  if ($view->name == 'your_view_name') {
    $query->where[0]['clauses'][3] = "DATE_FORMAT((FROM_UNIXTIME(node.changed) + INTERVAL 3600 SECOND), '%Y%m%%d') >= '%s'";
  }
}

That's all there is to it! =)

merlinofchaos’s picture

Status: Active » Closed (fixed)

Resetting to closed status.

Archie Bunker’s picture

Can you do this code by just creating a block and manipulating the code or do you have to create a full-fledged module to do this?

greg.harvey’s picture

It's a hook, so no, you can't call it in a block. Here's how hooks work:

The module exposing the hook (in this case, the Views module) searches all installed modules (and sometimes theme template.php files too) for functions in the form this_module_hook_name, where this_module is the name of your module and hook_name (views_query_alter in this case) is the name of the hook the 'parent' module exposes. *IF IT FINDS SUCH A FUNCTION* it executes it.

If the function is in a block, it will clearly never work because the Views module won't look there.

luke.presley’s picture

Two notes to add to greg.harvey's fix.

First, if you use a wildcard argument then views won't include the argument in the where[0]['clauses'] array. Using greg's example, let's assume there are five arguments. If there are no wildcards, the arguments will be stored in the array as [0], [1], [2], [3], [4]. His target argument (node.changed) will be assigned to [3] as expected and the fix will work as expected. If the first argument is a wildcard, the arguments will be stored in the array as [0], [1], [2], [3] with node.changed being assigned to [2]. In this second scenario, the fix will fail. Either the query will be improperly filtered or views will error out and nothing will be displayed.

Second, if the view shows up in a block or for any other reason doesn't accept the arguments, views will error out and nothing will be displayed.

I'd recommend adding a second comparison to prevent these two scenarios. Look for my change in the IF statement.

/**
* Implementation of hook_views_query_alter()
*/
function yourmodule_views_query_alter(&$view, &$query) {
  if ($view->name == 'your_view_name' 
      And $query->where[0]['clauses'][3] = "DATE_FORMAT((FROM_UNIXTIME(node.changed) + INTERVAL 3600 SECOND), '%Y%m%%d') = %s") {
    $query->where[0]['clauses'][3] = "DATE_FORMAT((FROM_UNIXTIME(node.changed) + INTERVAL 3600 SECOND), '%Y%m%%d') >= '%s'";
  }
}
sbefort’s picture

I tweak an argument this way:

1. Click on the argument in views.
2. Under "Validator Options," select PHP Code.
3. In the PHP code, set $handler->argument to a different value.
4. Peform any additional validation.
5. Return TRUE;

Do you think I should be writing a custom module with hook_views_query_alter instead?

charlie-s’s picture

I know this issue is closed and quite old, but custom handlers allow you to do the kinds of things being asked for without doing query alters on the view which kind of mucks things up if you plan on changing the view.

Here's a post I just added where you can set a date argument to be >=, <=, or = the nodes filtered against: http://drupal.org/node/796650#comment-6044452 (any kind of argument could be extended to provide options within Views).