שלום כולם, יש לי שאלה מציקה בנושא form api.
אני צריך ליצור טופס לסינון של מידע לפי תאריכים, את המידע אני מושך מ־sql (לאו דווקא nodes, אז views2 לא תמיד מתאים, מה גם שחלק מהשאילתות לא אפשריות ב־views, אז בואו נתעלם מהמודול הזה). כיוון שאני צריך למחזר את השלד הזה בכמה מקומות, חשבתי לבנות משהו גנרי יותר.
אז בניתי meta_form שלו אני קורא כאשר אני רוצה להציג מידע. הינה דוגמה לשימוש ב־meta form:
function my_module_supplier_fee($form_state)
{
module_load_include( "php", "my_module", "my_module_date_form" );
return my_module_get_date_form( $form_state, my_module_sum );
}
function my_module_sum($startdate , $enddate)
{
$output = "";
$query = "SELECT SUM(something) AS sum FROM this_table";
$result = db_query($query);
while($record = db_fetch_object($result)) {
$rows[] = array( round($record->sum, 2) );
}
// more code...
$output .= "<div>" . theme_table($header, $rows, $attributes, $caption) . "</div>";
return $output;
}
הכל נראה עובד די טוב, רק הינה הבעייה: אני מגיע לדף ומקבל טופס שנותן לי את הערכים של החודש הנוכחי, שולח את הטופס ומקבל נתונים. יפה, אני משנה את התאריך לינואר השנה, שולח מחדש ובתוצאה אני מקבל את חודש אוגוסט מחדש. הסיבה, היא שלא התבצעה קריאה לפונקציה $form['#submit'] שמוגדרת, ולכן הנתון של החודש ה"חדש" לא נשמר ב־storage, ולכן ביצירה המחודשת של הטופס אני לא מקבל את הנתון שאני מצפה.
סיכום: הטופס עובד רק בשליחה הראשונה ולא בשנייה. יש למישהו רעיון "מה הרסתי"? או האם יש אפשרות לעשות את זה בצורה אחרת, אני אשמח לרעיונות.
הינה הקוד שמייצר את ה"טופס" של הסינון:
// http://www.justin-cook.com/wp/2009/04/18/get-the-first-last-day-of-the-m...
function my_module_firstOfMonth() {
return date("Y-m-d", strtotime(date('m').'/01/'.date('Y').' 00:00:00'));
}
function my_module_lastOfMonth() {
return date("Y-m-d", strtotime('-1 second',strtotime('+1 month',strtotime(date('m').'/01/'.date('Y').' 00:00:00'))));
}
/**
* \brief Create a form which can filter data by date
*
* This function will return a piece of data, filtered by date. The data is
* returned by the passed function in the arguments. The basic usage is:
*
* \code
* function page1() {
* return drupal_get_form( 'form1' );
* }
*
* function form1($form_state) {
* module_load_include( "php", "my_module", "my_module_date_form" );
* return my_module_get_date_form( $form_state, get_form_data );
* }
*
* function get_form_data( $from, $to ){
* return "some date from date $from to date $to";
* }
* \endcode
*
* The function passed as second parameter gets 2 in paramters which represent
* the date the user chose, and return HTML which represent what you want to
* display.
*
* No validation or submit handling is needed, as all is done internally by this>
* function.
*
*/
function my_module_get_date_form( $form_state, $values_func ) {
$form = array();
$startDate = my_module_firstOfMonth();
$endDate = my_module_lastOfMonth();
$results_available = false;
if ($_GET['startdate']['date']){
drupal_set_message("GET detected - startdate");
$startDate = $_GET['startdate']['date'];
$results_available = true;
}
if ($_GET['enddate']['date']){
drupal_set_message("GET detected - enddate");
$startDate = $_GET['enddate']['date'];
$results_available = true;
}
if ($form_state['storage']['values']){
drupal_set_message("submit detected");
$startDate = $form_state['storage']['values']['startdate'];
$endDate = $form_state['storage']['values']['enddate'] ;
$results_available = true;
}
$format = 'Y-m-d';
$form['startdate'] = array(
'#type' => 'date_popup',
'#title' => t('From date'),
'#default_value' => $startDate,
'#date_format' => $format,
'#date_label_position' => 'none',
'#date_timezone' => 'Asia/Tel_Aviv',
// '#date_increment' => 15,
'#date_year_range' => '-7:+7',
);
$form['enddate'] = array(
'#type' => 'date_popup',
'#title' => t('To date'),
'#default_value' => $endDate,
'#date_format' => $format,
'#date_label_position' => 'within',
'#date_timezone' => 'Asia/Tel_Aviv',
// '#date_increment' => 15,
'#date_year_range' => '-7:+7',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
'#name' => 'submit',
'#color' => 'transparent',
'#style' => array('color' => 'transparent')
);
if ($results_available) {
$form['output'] = array( '#value' => $values_func($startDate, $endDate) );
}
$form['#validate'][] = 'my_module_get_date_form_validate';
$form['#submit'][] = 'my_module_get_date_form_submit';
$form['#cache'] = false;
$form['#rebuild'] = true;
return $form;
}
// validation function - do we need some?
function my_module_get_date_form_submit($form, &$form_state) {
return true;
}
// Idea taken from http://www.ferolen.com/blog/tag/form-api/
function my_module_get_date_form_submit($form, &$form_state) {
drupal_set_message("in submit - saving values");
$form_state['storage']['values'] = $form_state['values'];
$form_state['rebuild'] = true;
}
כדי לקצר תהליכים, אני אגיד גם
כדי לקצר תהליכים, אני אגיד גם מה הצלחתי לגלות בדרכים לא דרכים:
בפונקציה drupal_get_form יש קוד (1) שבודק האם הפונקציה $form['#submit'] קיימת, ומשום מה בפעם השנייה שאני עושה submit לטופס התנאי הזה לא מתקיים, וזה משהו שמאוד מפתיע אותי - הפונקציית submit לא קיימת ב"דרופל" ולכן היא לא נקראת.
מה? מי? איך מדבגים בעיות כאלו בכלל1??!?