Zalążek strony już mamy, warto więc dodać blok, który następnie będziemy mogli umieścić w wybranym przez nas regionie. W Drupalu 6 służyła do tego jedna funkcja hook_block(), która w wersji 7 wyewoluowała w więcej funkcji.

Deklaracja bloku

/**
 * Implements hook_block_info().
 */
function myblog_promoted_nodes_block_info() {
  $blocks['promoted'] = array(
    'info' => t('Promoted nodes'), 
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}

Część z dostępnych opcji hook_block_info() mogą być ustawione w panelu konfiguracji bloku lub modułach takich jak context umieszczających bloki w odpowiednich miejscach. Są to:

  • weight
  • status
  • region
  • visibility
  • pages

Z tego względu można spokojnie zostawić je puste - to uprawnione osoby powinny definiować tego typu ustawienia.

Element cache na czas developingu warto wyłączyć dzięki stałej DRUPAL_NO_CACHE. Warto jednak pamiętać, że na wersji produkcyjnej najlepiej usunąć tą linijkę lub wybrać któryś z mechanizmów cache'owania.

Z tego względu, że nasz blok jest dopiero zadeklarowany nigdzie się nie pokaże, nawet jeśli przeczyścimy pamięć podręczną systemu. Nic dziwnego, wszakże nie zawiera żadnej treści, nie ma nawet tytułu.

Definicja bloku

Z pomocą przychodzi kolejny hook - hook_block_view().

/**
 * Implements hook_block_view().
 */
function myblog_promoted_nodes_block_view($delta) {
  $block = array();
  switch($delta) {
    case 'promoted':
      $block['subject'] = t('Promoted nodes');
      $block['content'] = t('In the future you will see promoted nodes here.');
      break;
  }
  return $block;
}

Jak widać nie jest to szczególnie skomplikowane. $delta to oczywiście klucz zadeklarowany w hook_block_info(). Tak naprawdę wszystko, co musimy przekazać to tytuł bloku (który może być zmieniony przez administratora strony lub użytkowników z odpowiednimi uprawnieniami) i treść bloku.

Treść bloku bez żadnego problemu może być przekazana przez wywołanie funkcji, czy to z naszego czy z obcego modułu.

Można teraz np. za pomocą strony admin/structure/block przypisać nasz blok do odpowiedniego regionu. Tytuł i treść powinny się pokazać, w przypadku jakichkolwiek problemów warto przeczyścić cache.

Ekran sites/modules
Ekran sites/modules

Konfiguracja bloku

Drupal zapewnia mechanizmy, które umożliwiają personalizację danego bloku. Służą ku temu dwa hooki: hook_block_configure() oraz hook_block_save().
Zadaniem pierwszego jest wyświetlenie formularza administracyjnego na stronie bloku. To, co jest ważne, to fakt, że hook konfiguracji bloku można wywołać tylko z tego modułu, który deklaruje dany blok. hook_block_save() ma za zadanie zapisać konfigurację tam gdzie sobie tego zażyczymy. Zazwyczaj są to zmienne Drupala.

Jeśli chodzi o same zmienne warto napomknąć o dwóch sprawach. Są one składowane w tabeli {variable} w bazie danych. Jednakże Drupal w momencie gdy ładuje stronę zapisuje takie zmienne do pamięci, aby nie trzeba było niepotrzebnie odpytywać bazy. Ma to swoje plusy w postaci szybszego dostępu do często używanych danych, z drugiej jednak strony im więcej jest zmiennych, tym więcej danych system trzyma w pamięci, warto więc kontrolować co się dzieje w tabeli {variable}.

Aby nasz moduł był w pełni konfigurowalny warto dać użytkownikom możliwość zdefiniowania ile promowanych node'ów chcieliby wyświetlić w takim bloku. Warto również dodać checkbox, czy chcą oni linku więcej przekierowującego do strony z całą promowaną zawartością.

/**
 * Implements hook_block_configure().
 */
function myblog_promoted_nodes_block_configure($delta) {
  $form = array();
  if($delta == 'promoted') {
    $form['myblog_promoted_nodes'] = array(
      '#type' => 'fieldset',
      '#title' => 'MyBlog Promoted Nodes settings',
      '#collapsible' => TRUE,
    );
    $form['myblog_promoted_nodes']['number'] = array(
      '#type' => 'select',
      '#title' => t('Number of promoted nodes'),
      '#default_value' => variable_get('myblog_promoted_nodes_number', 5),
      '#options' => drupal_map_assoc(range(3, 7)),
    );
    $form['myblog_promoted_nodes']['more_link'] = array(
      '#type' => 'checkbox',
      '#title' => 'Show more link',
      '#default_value' => variable_get('myblog_promoted_nodes_more_link', 0),
    );
  }
  return $form;
}

Ten hook jest nieco bardziej dłuższy niż poprzednie, ale dalej ma prostą składnię.
Korzystamy tutaj z Form API Drupala. Tworzenie formularzy będzie dokładniej omówione na kolejnych stronach, pozwolę więc sobie ominąć dokładne omawianie tego dość prostego kodu.
To, co jest tutaj ważne to funkcja variable_get($nazwa_zmiennej, $domyślna_wartość). W przypadku, gdy jeszcze nie zostanie zapisana w bazie zmienna o podanej nazwie Drupal użyje wartości domyślnej. Później będzie używał tylko i wyłącznie tego, co zapiszemy.
W przypadku zmiennych również warto korzystać z przedrostka z nazwą naszej funkcji.

Po przejściu na stronę konfiguracji bloku powinniśmy bez problemu zauważyć nowy formularz pozwalający na spersonalizowanie bloku. Niestety - zapis wybranych elementów nie został jeszcze dodany, także mimo zapisania Drupal wraca do domyślnych, ustawionych w kodzie wartości.

Ekran sites/modules
Ekran sites/modules

Na szczęście zapisywanie jest również bardzo proste.

/** Implements hook_block_save().
 *
 */
function myblog_promoted_nodes_block_save($delta, $edit) {
  if($delta == 'promoted') {
    variable_set('myblog_promoted_nodes_number',
      $edit['myblog_promoted_nodes']['number']);
    variable_set('myblog_promoted_nodes_more_link',
      $edit['myblog_promoted_nodes']['more_link']);
  }
}

Uwaga na przyszłość - ze względu na zapis do bazy wartości konfiguracyjnych przez funkcję variable_set() będziemy musieli koniecznie przygotować plik .info, który w przypadku deinstalacji modułu usunie wszystkie dodane elementy. Będzie to omówione w przyszłych rozdziałach.

Jeśli macie zainstalowanego devela można skorzystać z funkcji dpm(), aby zapoznać się ze składnią zmiennej $edit.

Modyfikacja bloku zależnie od ustawień administracyjnych

Kiedy już mamy nasze ustawienia ładnie zapisane w zmiennych warto coś z nimi zrobić. Ze względu na zapytania do bazy, które będą omówione później zajmiemy się teraz prostszą sprawą, tzn. wyświetleniem odpowiedniego linku.

Musimy więc wrócić do funkcji myblog_promoted_nodes_block_view().
Aby dodać nasz link w przypadku, gdy odpowiednia opcja została zaznaczona wystarczy zmodyfikować następujący element:

$block['content'] = t('In the future you will see promoted nodes here.'); na
$block['content']['posts'] = array(
        '#theme' => 'item_list',
        '#items' => array(t('In the future you will see promoted nodes here.')),
      );
      if(variable_get('myblog_promoted_nodes_more_link', 0)) {
        $block['content']['more'] = array(
          '#theme' => 'more_link',
          '#url' => 'promoted',
          '#title' => t('See all promoted nodes.'),
        );
      }

Wykorzystujemy tutaj tzw. funkcje themujące. Drupal natrafiając na taką składnię szuka odpowiednio theme_item_list() oraz theme_more_link, a więc automatycznie dostosowuje wygląd do innych elementów podobnego typu używanych w systemie.
Kolejne elementy to parametry przesyłane do funkcji themującej. Warto zauważyć, że #items wymaga tablicy, dlatego nasz komunikat jest przekazany w takiej formie.

Ekran sites/modules

I jak widać w zależności od ustawień link się pojawia lub znika. Cel został osiągnięty.
W następnym kroku pokrótce omówię hook_init(), który w przypadku naszego modułu jest zbędny, natomiast od czasu do czasu potrafi się przydać.

Komentarze

  • Bardzo lubię Twojego bloga i uczę się właśnie pisania modułów razem z tym poradnikiem.
    Kiedy skopiowałam Twój kod okazało się, że w funkcji myblog_promoted_nodes_block_view jest chyba błąd i po "$block['subject'] = t('Promoted nodes')"powinen być średnik a nie przecinek (podobnie po $block['content']) tak jak to jest pokazane tutaj: http://api.drupal.org/api/drupal/modules!block!block.api.php/function/ho... .
    Nie zmienia to oczywiście faktu, że Twój tutorial jest bardzo pomocny, tym bardziej mi więc zależy, żeby początkujący jak ja nie musieli się martwić, że coś źle przepisali ;)

  • Jak najbardziej masz rację. Formalnie sprawdzam działanie kodu przed opublikowaniem, natomiast jak widać gubią mnie szybkie poprawki.
    Bardzo dziękuję za zwrócenie uwagi, poprawiłam.
    Dziękuję również za miłe słowa :) Kurs jest aktualnie rozszerzany offline, między innymi o tworzenie własnych hooków i system encji. Mam nadzieję, że w tym miesiącu uda mi się wrzucić kolejną paczkę.

Dodaj komentarz