Good evening.
I'm pretty new to drupal module programming so, plese, be patient.

I need to write a module to generate this behaviour:
1) at first I have to show a form with two fields (username and password)
2) the module process the data and make a query using that username/password couple
3) if the query is successfully executed I want to display some data taken from the query result.

This is what I wrote down in my .module file:

function gestione_pratiche_menu() {
  $items['gestione_pratiche/form'] = array(
    'title' => t('Consulta lo stato della tua pratica'),
    'page callback' => 'process_data',
    'access arguments' => array('access content'),
    'description' => t('Gestione Pratiche'),
    'type' => MENU_SUGGESTED_ITEM,
    'file' => 'gestione_pratiche.inc',
  );
  return $items;
}

function process_data(){
        // Here I need a way to retrieve my user ($u) and password ($p)
	$data = _gestione_pratiche_retrieveData($u,$p);
	
	if(!$data){
		return drupal_get_form('gestione_pratiche_form');
	} else {
		echo "show result";
	};
}

And here's my include (.inc) file:

function _gestione_pratiche_retrieveData($u,$p) {
	$res = db_query("SELECT p.nomecognome FROM {pratiche} p WHERE p.email='%s' and p.password='%s'", $u, $p);
	$data = db_fetch_object($res);
	return $data;
}

function gestione_pratiche_form($form_state) {
	$form = array();

    $form['email'] = array(
      '#type' => 'textfield',
      '#title' => t('Username'),
      '#description' => "Insert your username",
      '#size' => 30,
      '#maxlength' => 50,
    );
    $form['password'] = array(
      '#type' => 'password',
      '#title' => t('Password'),
      '#description' => "Insert your passeword",
      '#size' => 30,
      '#maxlength' => 50,
    );
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => 'Submit request',
    );
  
  return $form;
}

Let's analyse the problem:
I kow that the data inserted by the user are available (somewhere) into the $form_state variable. But this variable is not accessible from everywhere! I managed to pick data from it only adding a _submit handler at the end of my .inc file. Something like that:

function frm_gestione_pratiche_submit($form, &$form_state) {
  $u = $form_state['values']['email'];
  $p = $form_state['values']['password'];
}

But I cannot use the $u and $p variabiles where I need them!

I hope that the aim of my module is clear, so I ask you to help me finding a quick solution. I'm pretty sure that this is a very very easy and common problem to solve, but I can't do this all alone! :)

Many thanks!

Comments

RoloDMonkey’s picture

You are trying to put the cart before the horse. First, you need to show the form, then you need to process what is submitted.

In your .module file:


function gestione_pratiche_menu() {
  $items['gestione_pratiche/form'] = array(
    'title' => t('Consulta lo stato della tua pratica'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('gestione_pratiche_form'),
    'access arguments' => array('access content'),
    'description' => t('Gestione Pratiche'),
    'type' => MENU_SUGGESTED_ITEM,
    'file' => 'gestione_pratiche.inc',
  );
  return $items;
}

In your .include file:


function _gestione_pratiche_retrieveData($u,$p) {
    $res = db_query("SELECT p.nomecognome FROM {pratiche} p WHERE p.email='%s' and p.password='%s'", $u, $p);
    $data = db_fetch_object($res);
    return $data;
}

function gestione_pratiche_form($form_state) {
    $form = array();
    $form['email'] = array(
      '#type' => 'textfield',
      '#title' => t('Username'),
      '#description' => "Insert your username",
      '#size' => 30,
      '#maxlength' => 50,
    );
    $form['password'] = array(
      '#type' => 'password',
      '#title' => t('Password'),
      '#description' => "Insert your passeword",
      '#size' => 30,
      '#maxlength' => 50,
    );
    $form['submit'] = array(
      '#type' => 'submit',
      '#value' => 'Submit request',
    );
 
  return $form;
}

function frm_gestione_pratiche_submit($form, &$form_state) {
  $u = $form_state['values']['email'];
  $p = $form_state['values']['password'];
  $data = _gestione_pratiche_retrieveData($u,$p);
  if(!empty($data)) {
    drupal_set_message('show result');
  }
}

--

Read more at iRolo.net

sognotelematico’s picture

Hi,
thank you for yout reply.

One of my first attempt look similar to yours. I wrote down the function gestione_pratiche_form_submit(), and it works... but the real problem is: "how can I display the formatted results directly under my form?".

drupal_set_message() function only let me display a single string, not a table (or something more complicated).
If I modify the _submit hook like that

function gestione_pratiche_form_submit($form, &$form_state) {
  $u = $form_state['values']['email'];
  $p = $form_state['values']['password'];
  
  $data = _gestione_pratiche_retrieveData($u,$p);
  if(!empty($data)) {
    echo "this is my formatted data";
  }
}

... nothing appears!

Is there a solution?

RoloDMonkey’s picture

Hmm...

If you need to show both a form and data on a page, maybe you should look at how the 'Content' page works with the filter form on top. When the filter form is submitted, the options are saved in the session:

http://api.drupal.org/api/drupal/modules--node--node.admin.inc/function/...

Then, when the page is rebuilt, the session values are retreived:

http://api.drupal.org/api/drupal/modules--node--node.admin.inc/function/...

Last, the filter form and the node list are combined as two separate forms, node_filter_form() and node_admin_nodes():

http://api.drupal.org/api/drupal/modules--node--node.admin.inc/function/...

--

Read more at iRolo.net

sognotelematico’s picture

I don't really need to show both the form and the text together.
I'll be happy if the text is shown instead of the form (once the query has been executed).

Is it easier?

Drave Robber’s picture

Maybe you can use something like trick I used for poll crosstabulation (see empty form and after submission).

It goes like this:

* different menu callbacks for full and empty page:

function dr_crosstabs_menu() {
  $items['crosstabs/%/%'] = array(
    'title' => 'Crosstabs',
    'page callback' => 'dr_crosstabs_render',
    'page arguments' => array(1, 2),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  $items['crosstabs'] = array(
    'title' => 'Crosstabs',
    'page callback' => 'dr_crosstabs_empty',
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

* both of whom do however display form:

function dr_crosstabs_render($column, $row) {
  $output = drupal_get_form('dr_crosstabs_form');
  $crosstab = dr_crosstabs_build($column, $row); // here it call another function in the module...
  $output .= '<table><tr><td>';
  $output .= theme_item_list(array_slice($crosstab['columntable'], 1), '<a href="/node/' . $column . '">' . $crosstab['columntable'][0] . '</a>');
  // (...) (it's pretty long :)
  return $output;
}

function dr_crosstabs_empty() {
  $output = drupal_get_form('dr_crosstabs_form');
  return $output;
}

* and at the heart of trick is really this:

function dr_crosstabs_form_submit($form, &$form_state) {
  drupal_goto('crosstabs/' . $form_state['values']['column'] . '/' . $form_state['values']['row']);
}

So it simply feeds both values from form into the URL.

This requires some extra validation somewhere, as people can as well type (almost) everything they want into the URL.

sognotelematico’s picture

I'm not so sure to understand what you did... but I feel lucky and I'll try your solution.
I guess I'll have to modify here and there, but I'm pretty sure to have found the good way.

Thank you!

RoloDMonkey’s picture

I would not recommend this solution. This requires sending the username and password back to the browser (in the URL, no less). This is a Really Bad Idea.

--

Read more at iRolo.net

Drave Robber’s picture

You're right, I didn't quite think of that. In my case, those are pretty harmless numbers.