Hi,

I have a hard time to create a new custom autocomplete path so i can use form_alter with autocomplete. See my OP here: http://drupal.org/node/970856

The task: Explain how to create a new autocomplete path that retrieves all results for a random cck value or a random value from the DB. (second might be better)

I´d like to post the results here, so everybody can benefit. (This will be usefull for many people)

The Bountie is 33$ and will be send via Paypal or regular Bank transfer.

Cant´t wait to see the results, John

Comments

jvizcarrondo’s picture

I'm not sure this works, is difficult to standardize the function for each cck type

function your_module_menu() {
    // path with autocomplete function for cck fields
    $items['cck_field/autocomplete'] = array(
      'title' => 'Autocomplete for cck fields',
      'page callback' => '_cck_fields_autocomplete',
      'access arguments' => array('use autocomplete'),  //or whatever permission makes sense
      'type' => MENU_CALLBACK
    );
  return $items;
}
function _cck_fields_autocomplete($cck_fields = '', $string = '') {
  $query = "SELECT type, multiple FROM {content_node_field} WHERE field_name like 'field_%s'";
  $result = db_query($query, $cck_fields);
  $data = db_fetch_array($result);
  $aux1 = 'value';
  if ($data['type'] == 'filefield') {
    $aux1 = 'fid';
  }
  if ($data['type'] == 'nodereference') {
    $aux1 = 'nid';
  }
  if ($data['type'] == 'userreference') {
    $aux1 = 'uid';
  }
  if ($data['type'] == 'link') {
    $aux1 = 'url';
  }
  if ($data['type'] == 'email') {
    $aux1 = 'email';
  }
  if (!$data['multiple']) {
    $query = "SELECT field_'%s'_'%s' FROM {content_type_'%s'} WHERE field_'%s'_'%s' like '%s'";
  }
  else {
    $query = "SELECT field_'%s'_'%s' FROM {content_'%s'} WHERE field_'%s'_'%s'  like '%s'";
  }
  $result = db_query_range($query, $cck_fields, $aux1, $cck_fields, $cck_fields, $aux1, $string, 0, 10);
  while ($edata = db_fetch_object($result)) {
    $matches["field_" . $edata->$cck_fields . "_" . $aux1] = check_plain("field_" . $edata->$cck_fields . "_" . $aux1);
  }
  // return for JS
  print drupal_to_js($matches);
  exit();
}

in form_alter (define your_cckfield)

$form['my_cck_field_filter_identifier']['#autocomplete_path'] = 'cck_field/autocomplete/your_cckfield';

if this does not work at all, it can give you an idea
Juan

sagar ramgade’s picture

Hi,
You are right it is difficult to standardize the module however here is the .module and the .info file with a slight modification of the above which lists 10 values starting with the entered letters. I have also kept it comma seperated like taxonomy tags. I hope it is correct :-)

<?php
// $Id: cck_autocomplete_help.module,v 1.0 2010/11/5 21:45:08 

function cck_autocomplete_help_form_alter(&$form, &$form_state, $form_id){
// To get the form id uncomment the line below and visit the node or any form.
//dpr($form_id); //if devel installed this will work
//echo '<pre>' . $form_id . '</pre>'; //using normal php if not using devel module
(if $form_id == 'your form id here'){
  $form['my_cck_field_filter_identifier']['#autocomplete_path'] = 'cck_field/autocomplete/your_cckfield';
  }
}

function cck_autocomplete_help_menu() {
    // path with autocomplete function for cck fields
    $items['cck_field/autocomplete'] = array(
      'title' => 'Autocomplete for cck fields',
      'page callback' => '_cck_fields_autocomplete',
      'access arguments' => array('use autocomplete'),  //or whatever permission makes sense
      'type' => MENU_CALLBACK
    );
  return $items;
}

function _cck_fields_autocomplete($cck_fields = '', $string = '') {
  $array = explode(',', $string);
  // Fetch last tag
  $last_string = trim(array_pop($array));
  $matches = array();
  if ($last_string != '') { 
      $query = "SELECT type, multiple FROM {content_node_field} WHERE field_name like 'field_%s'";
      $result = db_query($query, $cck_fields);
      $data = db_fetch_array($result);
      $aux1 = 'value';
      if ($data['type'] == 'filefield') {
        $aux1 = 'fid';
      }
      if ($data['type'] == 'nodereference') {
        $aux1 = 'nid';
      }
      if ($data['type'] == 'userreference') {
        $aux1 = 'uid';
      }
      if ($data['type'] == 'link') {
        $aux1 = 'url';
      }
      if ($data['type'] == 'email') {
        $aux1 = 'email';
      }
      if (!$data['multiple']) {
        $query1 = "SELECT field_'%s'_'%s' FROM {content_type_'%s'} WHERE LOWER(field_'%s'_'%s') LIKE LOWER('%s%%')";
      }
      else {
        $query1 = "SELECT field_'%s'_'%s' FROM {content_'%s'} WHERE LOWER(field_'%s'_'%s') LIKE ('%s%%')";
      }
      $result1 = db_query_range($query, $cck_fields, $aux1, $cck_fields, $cck_fields, $aux1, $string, 0, 10);
      $prefix = count($array) ? implode(', ', $array) .', ' : '';
      while ($edata = db_fetch_object($result1)) {
        if (strpos("field_" . $edata->$cck_fields . "_" . $aux1, ',') !== FALSE || strpos("field_" . $edata->$cck_fields . "_" . $aux1, '"') !== FALSE) {
                $name = '"'. str_replace('"', '""', "field_" . $edata->$cck_fields . "_" . $aux1) .'"';
            }
        $matches[$prefix . $name] = check_plain("field_" . $edata->$cck_fields . "_" . $aux1);
      }
  }
  // return for JS
  print drupal_to_js($matches);
  exit();
}
?>

here is the .info file

; $Id$ cck_autocomplete_help.info,v 1.0 2010/11/15 21:46:00 $
name = cck automcomplete help
description = Example for cck autocomplete fields
dependancies[] = content
package = Custom
core = 6.x

Acquia certified Developer, Back end and Front specialist
Need help? Please use my contact form

john_the_noob’s picture

wow, that looks great. will try it when back home :)

john_the_noob’s picture

Doesnt´t work yet.
There is an autocomplete widget and it performs a search but it is always empty. cck_field/autocomplete/your_cckfield/x always returns an empty array. Tried different values and different cckfields but nothing.

I changed only the cck_identifier and my_cck fields in form_alter as this module should make a path for every cck_field, yes ?

jvizcarrondo’s picture

your_cckfield is your cck field name, you should change this(eg: my_image), I'm not sure the added code:

$prefix = count($array) ? implode(', ', $array) .', ' : '';

$name = '"'. str_replace('"', '""', "field_" . $edata->$cck_fields . "_" . $aux1) .'"';
            }
        $matches[$prefix . $name] = check_plain("field_" . $edata->$cck_fields . "_" . $aux1);

Juan

john_the_noob’s picture

Hi Juan,

sure. I use cck_field/autocomplete/thename_from_cck, then i try cck_field/autocomplete/thename_from_cck/a just to see if it returns results beginning with 'a'. The first code returns 'null' (long search), the modified '[]' (short search).

jvizcarrondo’s picture

function _cck_fields_autocomplete($cck_fields = '', $string = '') {
  $query = "SELECT type, multiple FROM {content_node_field} WHERE field_name like 'field_%s'";
  $result = db_query($query, $cck_fields);
  $data = db_fetch_array($result);
  $aux1 = 'value';
  if ($data['type'] == 'filefield') {
    $aux1 = 'fid';
  }
  if ($data['type'] == 'nodereference') {
    $aux1 = 'nid';
  }
  if ($data['type'] == 'userreference') {
    $aux1 = 'uid';
  }
  if ($data['type'] == 'link') {
    $aux1 = 'url';
  }
  if ($data['type'] == 'email') {
    $aux1 = 'email';
  }
  if (!$data['multiple']) {
    $query = "SELECT field_'%s'_'%s' FROM {content_type_'%s'} WHERE field_'%s'_'%s' like '%s%'";
  }
  else {
    $query = "SELECT field_'%s'_'%s' FROM {content_'%s'} WHERE field_'%s'_'%s'  like '%s%'";
  }
  $result = db_query_range($query, $cck_fields, $aux1, $cck_fields, $cck_fields, $aux1, $string, 0, 10);
  while ($edata = db_fetch_object($result)) {
    $matches[$edata->"field_" . $cck_fields . "_" . $aux1] = check_plain($edata->"field_" . $cck_fields . "_" . $aux1);
  }
  // return for JS
  print drupal_to_js($matches);
  exit();
}

your cck_field without "field_" and in type script
Juan

john_the_noob’s picture

You tried this ? i Get
Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING, expecting T_STRING or T_VARIABLE or '{' or '$'..

in line: $matches[$edata->"field_" . $cck_fields . "_" . $aux1] = check_plain($edata->"field_" . $cck_fields . "_" . $aux1);

But can´t see the typo.

jvizcarrondo’s picture

function _cck_fields_autocomplete($cck_fields = '', $string = '') {
$query = "SELECT type, multiple FROM {content_node_field} WHERE field_name like 'field_%s'";
$result = db_query($query, $cck_fields);
$data = db_fetch_array($result);
$aux1 = 'value';
if ($data['type'] == 'filefield') {
$aux1 = 'fid';
}
if ($data['type'] == 'nodereference') {
$aux1 = 'nid';
}
if ($data['type'] == 'userreference') {
$aux1 = 'uid';
}
if ($data['type'] == 'link') {
$aux1 = 'url';
}
if ($data['type'] == 'email') {
$aux1 = 'email';
}
if (!$data['multiple']) {
$query = "SELECT field_'%s'_'%s' FROM {content_type_'%s'} WHERE field_'%s'_'%s' like '%s%'";
}
else {
$query = "SELECT field_'%s'_'%s' FROM {content_'%s'} WHERE field_'%s'_'%s' like '%s%'";
}
$result = db_query_range($query, $cck_fields, $aux1, $cck_fields, $cck_fields, $aux1, $string, 0, 10);
$fields_aux = "field_" . $cck_fields . "_" . $aux1;
while ($edata = db_fetch_object($result)) {

$matches[$edata->$fields_aux] = check_plain($edata->$fields_aux);
}
// return for JS
print drupal_to_js($matches);
exit();
}

john_the_noob’s picture

Hi Juan,

thx for your quick reply. Typo is gone. But cck_field/autocomplete/cck_field_name always returns 'null' regardless if there is a parameter or not or if i use field_cckname or just cckname.

I am sorry that this takes so long !

john_the_noob’s picture

Maybe this helps: I added
$matches[0] = 'test';
before
// return for JS
print drupal_to_js($matches);
and it now always returns test. So that part of the code works for sure.

jvizcarrondo’s picture

Try change

while ($edata = db_fetch_object($result)) {

$matches[$edata->$fields_aux] = check_plain($edata->$fields_aux);
}

to

while ($edata = db_fetch_object($result)) {

$matches[] = check_plain($edata->$fields_aux);
}

OR TRY

$matches[] = "TEST";

see output, I can't try this now

john_the_noob’s picture

$matches[] = "TEST"; adds TEST as expected.

Adding it inside while ($edata = db_fetch_object($result)) returns null.

jvizcarrondo’s picture

function _cck_fields_autocomplete had many mistakes, I've fixed this and seems to work

<?php
function _cck_fields_autocomplete($cck_fields = '', $string = '') {
  $query = "SELECT nf.type, nf.multiple, fi.type_name " .
    "FROM {content_node_field} nf " .
    " LEFT JOIN {content_node_field_instance} AS fi ON fi.field_name = nf.field_name " .
    " WHERE nf.field_name LIKE 'field_%s%'";
  $result = db_query($query, $cck_fields);
  $data = db_fetch_array($result);
  $aux1 = 'value';
  if ($data['type'] == 'filefield') {
    $aux1 = 'fid';
  }
  if ($data['type'] == 'nodereference') {
    $aux1 = 'nid';
  }
  if ($data['type'] == 'userreference') {
    $aux1 = 'uid';
  }
  if ($data['type'] == 'link') {
    $aux1 = 'url';
  }
  if ($data['type'] == 'email') {
    $aux1 = 'email';
  }
  if (!$data['multiple']) {
    $query = "SELECT field_%s_%s FROM {content_type_%s} WHERE field_%s_%s LIKE LOWER('%s%')";
    $result = db_query_range($query, $cck_fields, $aux1, $data['type_name'], $cck_fields, $aux1, $string, 0, 10);
  }
  else {
    $query = "SELECT field_%s_%s FROM {content_%s} WHERE field_%s_%s LIKE LOWER('%s%')";
    $result = db_query_range($query, $cck_fields, $aux1, $cck_fields, $cck_fields, $aux1, $string, 0, 10);
  }

  $fields_aux = "field_" . $cck_fields . "_" . $aux1;
  while ($edata = db_fetch_object($result)) {
    $matches[$edata->$fields_aux] = check_plain($edata->$fields_aux);
  }
  // return for JS
  print drupal_to_js($matches);
  exit();
}
?>

Juan

john_the_noob’s picture

Juan, you are fucking awesome and clearly deserve the bounty !

(pm me your e-mail for paypal please)

Now i have to find out how to retrieve taxonomy tags by node type ;)

jseltzer’s picture

Or was that just part of it? What was needed to get it working on your end?

For a exposed filter form with multiple text fields that I wanted to use auto-complete would I need to roll this into separate functions for each field?

Thanks much,
Jared

jvizcarrondo’s picture

No, you don't need separate functions, only you can use form_alter and change fields in form (see http://drupal.org/node/970856 in this post), for each field that yo want change EG:

<?php
$form['my_cck_yourfield']['#autocomplete_path'] = 'cck_field/autocomplete/yourfield';
?>

hoping to help
Juan

ccshannon’s picture

Subscribe