Hi

I'm trying to add an handler to a module specific view.

The new (customized) handler is : views_handler_argument_category_depth

Here's the content of the sites\all\modules\views\modules\category.views.inc

function category_views_data() {
$data = array();
...

$data['category_node']['cid'] = array(
'title' => t('ID'),
'help' => 'The category ID.',
'argument' => array(
'handler' => 'views_handler_argument_category_depth',
),
);
...

function category_views_handlers() {
return array(
'info' => array(
'path' => drupal_get_path('module', 'views') . '/modules/category',
),
'handlers' => array(
'views_handler_argument_category_depth' => array(
'parent' => 'views_handler_argument',
),
),
);
}

for now the views_handler_argument_category_depth is just a std handler renamed with a slight change in order to just attach the argument to the new handler.

The argument is recognized, in the views UI I can add it but then I have the following error :

Error: handler for category_node > cid doesn't exist!

I tried also to add it to the handlers directory in the views module, without sucsess.
I emptying the cache after every change, also restarted the apache server.

Can anybody help ?

Thanks
Nissim

Comments

dawehner’s picture

Status: Active » Postponed (maintainer needs more info)

Cool, someone with a real question. It does motivate much more to answer API questions :)

Do you have views_handler_argument_category_depth.inc in your module? There you also have to define this class, and extend views_handler_argument.

merlinofchaos’s picture

Status: Postponed (maintainer needs more info) » Fixed

As a start, that error indicates that, for whatever reason, the handler was not instantiated.

'path' => drupal_get_path('module', 'views') . '/modules/category',

That looks like a problem, since I don't think your module is the Views module. Marking this fixed since I bet this is the problem.

nissiml’s picture

Hi , thanks for replying.

I did have such a file, in views/modules/category
and it indeed extends from the correct parent.

merlinofchaos’s picture

Uh. You're not supposed to put your handlers in the views module. Are you actually editing views module code? If so, you really need to go back and read Drupal's best practices.

nissiml’s picture

I'm not changing the view core module code, just enhancing the view functionality of the category module which is very basic.
I don't care about the location of the file that holds the view hooks implementation.
Actually, I tried also to put the code in the category module itself without success.
Btw, views/modules contains such extensions for many modules.

Can you state the required and precise steps to add an handler ?

merlinofchaos’s picture

If you put *any* file in the 'views' directory, that is editing the module. Yes, Views ships with a bunch of stuff on behalf of core modules. I don't understand why you think it's okay to put your files there. It's an upgrade nightmare.

nissiml’s picture

I'm not changing the view core module code, just enhancing the view functionality of the category module which is very basic.
I don't care about the location of the file that holds the view hooks implementation.
Actually, I tried also to put the code in the category module itself without success.
Btw, views/modules contains such extensions for many modules.

Can you state the required and precise steps to add an handler ?

nissiml’s picture

Ok, thanks I solved the issue.

I have now a handler for category views that includes depth (based on taxonomy depth handler)
and it works !!


<?php
// $Id: views_handler_argument_numeric.inc,v 1.1 2008/09/03 19:21:28 merlinofchaos Exp $
/**
 * @file
 * Contains the numeric argument handler.
 */

/**
 * Basic argument handler for arguments that are numeric. Incorporates
 * break_phrase.
 *
 * @ingroup views_argument_handlers
 */
class views_handler_argument_category_depth extends views_handler_argument {
	
  function option_definition() {
    $options = parent::option_definition();

    $options['depth'] = array('default' => 0);
    $options['break_phrase'] = array('default' => FALSE);
    $options['set_breadcrumb'] = array('default' => FALSE);

    return $options;
  }

  function options_form(&$form, &$form_state) {
    parent::options_form($form, $form_state);
    $form['depth'] = array(
      '#type' => 'weight',
      '#title' => t('Depth'),
      '#default_value' => $this->options['depth'],
      '#description' => t('The depth will match nodes tagged with terms in the hierarchy. For example, if you have the term "fruit" and a child term "apple", with a depth of 1 (or higher) then filtering for the term "fruit" will get nodes that are tagged with "apple" as well as "fruit". If negative, the reverse is true; searching for "apple" will also pick up nodes tagged with "fruit" if depth is -1 (or lower).'),
    );

    $form['break_phrase'] = array(
      '#type' => 'checkbox',
      '#title' => t('Allow multiple terms per argument'),
      '#description' => t('If selected, users can enter multiple arguments in the form of 1+2+3. Due to the number of JOINs it would require, AND will be treated as OR with this argument.'),
      '#default_value' => !empty($this->options['break_phrase']),
    );

    $form['set_breadcrumb'] = array(
      '#type' => 'checkbox',
      '#title' => t("Set the breadcrumb for the term parents"),
      '#description' => t('If selected, the breadcrumb trail will include all parent terms, each one linking to this view. Note that this only works if just one term was received.'),
      '#default_value' => !empty($this->options['set_breadcrumb']),
    );
  }
/*
  function set_breadcrumb(&$breadcrumb) {
    if (empty($this->options['set_breadcrumb']) || !is_numeric($this->argument)) {
      return;
    }

    return views_taxonomy_set_breadcrumb($breadcrumb, $this);
  }

*/
  /**
   * Override default_actions() to remove summary actions.
   */
  function default_actions($which = NULL) {
    if ($which) {
      if (in_array($which, array('ignore', 'not found', 'empty', 'default'))) {
        return parent::default_actions($which);
      }
      return;
    }
    $actions = parent::default_actions();
    unset($actions['summary asc']);
    unset($actions['summary desc']);
    return $actions;
  }

  function query() {
    $this->ensure_my_table();

    if (!empty($this->options['break_phrase'])) {
      $cids = new stdClass();
      $cids->value = $this->argument;
      $cids = views_break_phrase($this->argument, $cids);
      if ($cids->value == -1) {
        return FALSE;
      }

      if (count($cids->value) > 1) {
        $placeholder = " IN (" . implode(', ', array_fill(0, sizeof($cids->value), '%d')) . ")";
      }
      else {
        $placeholder = " = %d";
      }

      $cids = $cids->value;
    }
    else {
      $placeholder = "= %d";
      $cids = array($this->argument);
    }
    $subquery = "\n  SELECT tn.vid FROM {category_node} tn\n";
    $where = "  WHERE tn.cid $placeholder\n";
    $args = $cids;
    $last = "tn";

    if ($this->options['depth'] > 0) {
      $subquery .= "    LEFT JOIN {category_hierarchy} th ON th.cid = tn.cid\n";
      $last = "th";
      foreach (range(1, abs($this->options['depth'])) as $count) {
        $subquery .= "    LEFT JOIN {category_hierarchy} th$count ON $last.parent = th$count.cid\n";
        $where .= "    OR th$count.cid $placeholder\n";
        $args = array_merge($args, $cids);
        $last = "th$count";
      }
    }
    else if ($this->options['depth'] < 0) {
      foreach (range(1, abs($this->options['depth'])) as $count) {
        $subquery .= "    LEFT JOIN {category_hierarchy} th$count ON $last.cid = th$count.parent\n";
        $where .= "    OR th$count.cid $placeholder\n";
        $args = array_merge($args, $cids);
        $last = "th$count";
      }
    }

    $this->query->add_where(0, "$this->table_alias.vid IN ($subquery$where  )", $args);
  }

  function title() {
    $term = category_get_category($this->argument);
    if (!empty($term)) {
      return check_plain($term->name);
    }
    // TODO review text
    return t('No name');
  }
	}


dawehner’s picture

Nevertheless whether it works or not, its just not nice, if the handler is still in the views directory.

nissiml’s picture

Do not worry, It's in the category module now, not in the views module code.

Status: Fixed » Closed (fixed)
Issue tags: -category

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