Taki sobie blog ;]

kwiecień 5, 2009

Drupal module tutorial pt.2

Zaszufladkowany do: Drupal, moduły, tutorial — mstandio @ 02:34

     Druga część zmagań z Drupalem, implementacja bloku z formularzem, wraz z obsługą błędów, zapisem do bazy i wyświetlaniem komunikatów. Formularz korzysta z AHAH i JQuery, jakkolwiek działa także bez wsparcia JavaScriptu. Całość nie jest dopieszczona wizualnie, ale działa bez zarzutu ;]

$(document).ready(function(){
    $("input#edit-email-subscribtion").focus(function(){
        $(this).val("");
    });
});

    Prosta funkcja JQuery umieszczona w pliku “custom_newsletter.js” w folderze modułu. Jeżeli po załadowaniu strony zostanie zaznaczone pole o id=”edit-email-subscribtion” jego wartość zostanie ustawiona na pustą. Pozostałe fragmenty kodu należą do “custom_newsletter.module”

function custom_newsletter_init() {
  drupal_add_js(drupal_get_path('module', 'custom_newsletter') .'/custom_newsletter.js');
}

    Funkcja dodaje do nagłówków stron, w których używany jest moduł, link do powyższego pliku z JavaScriptem.

function custom_newsletter_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $block[0] = array(
        'info' => t('Subscription block'),
      );
      return $block;

    case 'view': default:
      if ($delta==0) {
        $block['subject'] = t('Newsletter');
        $block['content'] = custom_newsletter_contents();
      }
      return $block;
  }
}

    Funkcja deklarująca wyświetlany blok, część “list” odpowiada za wyświetlanie bloku w liście bloków, “view” determinuje jego wygląd na stronie. Więcej na: hook_block

function custom_newsletter_contents(){
  $msgfield = "<div id=custom_subscribtion_msgfield>".
                custom_newsletter_build_message(variable_get('subscribtion_state','')).
              "</div>";
  $contents = "<div>".$msgfield.drupal_get_form('custom_newsletter_form')."</div>";
  variable_del('subscribtion_state');
  return $contents;
}

    Funkcja wywoływana w celu wypełnienia bloku zawartością. Zawiera diva wyświetlającego komunikaty, oraz wywołanie funkcji generującej formularz.

function custom_newsletter_build_message($message){
  return '<hr />'.$message.'<hr />';
}

    Poglądowa wersja tworzenia komunikatu na podstawie wartości zadeklarowanej zmiennej. Przydałoby się zróżnicowanie komunikatów pod kątem treści i wyglądu, może kiedyś ;]

function custom_newsletter_form(){
  $form['email_subscribtion'] = array(
  '#type' => 'textfield',
  '#default_value' => t('enter email here'),
  '#size' => 20,
  '#maxlength' => 30,
  '#element_validate' => array('subscribtion_form_validate'),

  );

  $form['submit'] = array(
  '#type' => 'submit',
  '#value' => t('Subscribe'),
  '#submit' => array('custom_newsletter_form_submit'),

  '#ahah' => array(
        'path' => 'custom_newsletter/js',
        'wrapper' => 'custom_subscribtion_msgfield',
  		'method' => 'replace',
        'progress' => array('type' => 'throbber',),
  ),
  );
  return($form);
}

    Deklaracja poszczególnych pól formularza, przypisanie im właściwości oraz funkcji wywoływanych w celu walidacji pól oraz po zatwierdzeniu formularza. Sekcja #ahah określa reakcję na zatwierdzenie bez przeładowywania strony, określa kolejno link pod którym są opisane owe reakcje, następnie element zmieniany podczas działania funkcji, metodę zmiany oraz animację. Więcej na: form API

function custom_newsletter_menu() {
  $items = array();
  $items['custom_newsletter/js'] = array(
    'title' => 'Javascript Choice Form',
    'page callback' => 'custom_newsletter_js',
    'access arguments' => array('access custom_newsletter js'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

    Funkcja tworzy element menu (http://localhost/drupal/?q=custom_newsletter/js), pod którym znajduje się funkcja wywoływana po zatwierdzenia formularza z użyciem AHAH.

function custom_newsletter_js(){
    $form_state = array('storage' => NULL, 'submitted' => FALSE);
    $form_build_id = $_POST['form_build_id'];
    // Get the form from the cache.
    $form = form_get_cache($form_build_id, $form_state);
    $args = $form['#parameters'];
    $form_id = array_shift($args);
    // We will run some of the submit handlers so we need to disable redirecting.
    $form['#redirect'] = FALSE;
    // We need to process the form, prepare for that by setting a few internals
    // variables.
    $form['#post'] = $_POST;
    $form['#programmed'] = FALSE;
    $form_state['post'] = $_POST;
    // Build, validate and if possible, submit the form.
    drupal_process_form($form_id, $form, $form_state);
    // This call recreates the form relying solely on the form_state that the
    // drupal_process_form set up.
    $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
    // Render the new output.

    $coumunicate = custom_newsletter_build_message(variable_get('subscribtion_state',''));
    variable_del('subscribtion_state');
    return drupal_json(array('status' => TRUE, 'data' => $coumunicate));
}

    Funkcja pełna kodu świadczącego o kulawości AHAH, formularz należy najpierw zrekonstruować z keszu aby go zwalidować i zatwierdzić. Brzydki kod który nie wiadomo jak się zachowa przy kilku formularzach. Zwraca element json modyfikujący element określony w deklaracji formularza w sekcji ahah.

function custom_newsletter_form_submit($form, &$form_state){
  $form_values = $form_state['values'];
  $email=$form_values['email_subscribtion'];
  db_query("INSERT INTO {custom_newsletter} (id, email, hash) VALUES (%d, '%s', '%s')", 0, $email, substr(md5($email.time()),0,19));
}

    Funkcja wymieniona w deklaracji formularza, poza przekazaniem wartości pola formularza, warto zwrócić uwagę na database abstraction layer.

function subscribtion_form_validate($element, &$form_state) {
  if (empty($element['#value'])) {
    variable_set('subscribtion_state', 'ERROR');
    form_set_error('email_subscribtion', '', TRUE);
  }else{
    variable_set('subscribtion_state', 'OK');
  }
}

    Jest to funkcja wymieniona w deklaracji formularza, kod jest poglądowy, przydałoby się sprawdzanie regexem, oraz dublowania wpisów. Formularz nie zostaje zatwierdzony, jeżeli zostanie wywołana funkcja form_set_error. W tym przypadku pole wiadomości jest puste, żeby nie wyświetlać komunikatu błędu u góry strony.

    Pisanie w Drupal API potrafi być dość przyjemne kiedy już wiadomo o co chodzi. Człowiek staje się wygodny, tym bardziej dziwi toporność AHAH. Standardowe komunikaty błędów pojawiające się na górze strony nie są domyślnie obsługiwane przez AHAH i ich ewentualne wyświetlenie następuje dopiero po ręcznym przeładowaniu strony. Ponadto jego używanie jest tak mało intuicyjne, że aż powstał moduł mający temu zaradzić (AHAH helper module).
    Poza tym w kodzie widać moje pierwsze próby przekazywania zmiennych za pomocą funkcji variable_set(). Zmienne te są przechowywane w bazie i częste operacje na nich są zapewne mało efektywne, choć pewnie nie mają alternatywy w przypadku operacji AJAXowych.
    Warto zaopatrzyć się w moduł Cache Disable, wyłącza keszowanie bloków i elementów menu. Spowalnia to działanie całości, ale ułatwia pracę nad modułami, brak reakcji na zmiany w kodzie nie musi być leczony ręcznym usuwaniem keszu w bazie ;]

Coming soon: Strony konfiguracyjne oraz zarządzające modulem. Stay tuned ;]

Nie ma jeszcze komentarzy »

Brak komentarzy.

Kanał RSS z komentarzami do tego wpisu. Adres TrackBack

Dodaj komentarz

Blog na WordPress.com.