Własne profile w Drupalu

UWAGA – artykuł odnosi się do Drupala w wersji 4.7.3!

Zastanawiałeś się czasem jak uatrakcyjnić profile użytkowników na swojej stronie? Te które są dostępne w standardzie nie wyglądają specjalnie atrakcyjnie – a wystarczy godzinka pracy i kilka ciekawych pomysłów, aby nabrały całkiem innego wymiaru. W dodatku wszystko zrobimy z pomocą potężnego systemu drupalowych szablonów (a więc brzuszek – rdzeń – naszego kropelka pozostanie bez zmian, co jest ważną cechą tej metody w kontekście aktualizacji do nowszych wersji drupala).

Dla kogo ten artykuł?

Prowadzący strony, w których profil użytkownika jest ważnym elementem, być może posiada wiele pól i kategorii, chcemy też zapanować nad jego wyglądem, oraz zachęcić i ułatwić użytkownikom wypełnianie profili.

Co osiągniemy?

Po wykonaniu ćwiczenia uzyskamy profile użytkowników z dowolnie rozmieszczonymi polami, linkami do edycji konkretnych kategorii, informacją o nie wypełnieniu danego pola (i linkiem do jego edycji – jeśli użytkownik ogląda swój profil). Pokażemy też listę ostatnich wpisów na blogu, ikonkę statusu GaduGadu oraz informację o tym czy użytkownik jest zalogowany.

Wykorzystano

Drupal 4.7.3, system szablonów PHPTemplate, rdzenny moduł profile, wiele porad z tej strony – http://drupal.org/node/35728

Dlaczego nie usernode i pochodne moduły? Bo ten sposób jest mniej „inwazyjny”, co nie znaczy lepszy – po prostu inny. Wszystkie zmiany można w prosty sposób cofnąć i powrócić do stanu sprzed zmian. Nie trzeba nic instalować, jeśli nawet zrezygnujemy z tej drogi powrót do starych profili zajmie nam minutę, a wprowadzone do profili dane nadal tam będą.

Zaczynamy!

Krok 0 – włączamy moduł profile i wymyślamy kilka pól

Jeśli jeszcze tego nie zrobiłeś – skocz na moment do administracji modułami i włącz moduł profile. Następnie stwórz kilka pól, dla naszego ćwiczenia przyjmijmy że strona zrzesza muzyków i zrobimy dla nich takie pola:

Kategoria kontakt

  • GG (profile_gg, jednowierszowe pole tekstowe)
  • TLEN (profile_tlen, jednowierszowe pole tekstowe)
  • MIASTO (profile_miasto, jednowierszowe pole tekstowe)
  • KRAJ (profile_kraj, jednowierszowe pole tekstowe)

Kategoria osobiste

  • STRONA WWW (profile_www, URL)
  • KILKA SŁÓW O MNIE (profile_bio, wielowierszowe pole tekstowe)
  • DATA URODZENIA (profile_urodziny, data)
  • JAK DŁUGO GRAM (profile_gramod, data)
  • ULUBIONE ZESPOŁY (profile_muza, tekstowe pole listy)
  • SZUKAM PRACY (profile_praca, lista wyboru) – możliwości TAK i NIE

Krok 1 – przechwycenie funkcji user_profile

Pierwsze co musimy zrobić to zajrzeć do katalogu z naszą skórką. Jeśli przykładowo używamy blue_mark, otwieramy sobie ścieżka-do-drupala/templates/blue_mark i szukamy pliku template.php (Być może wcale go tam nie ma – nie szkodzi. W takim wypadku stwórzmy nowy plik tekstowy i nazwijmy go template.php). Wewnątrz tego pliku musimy umieścić definicję funkcji, która „przechwyci” standardowe odwołanie do strony profilu.

A więc wklejamy do template.php co następuje:

<?php
/**
* złap funkcję theme_profile_profile i przekieruj ją na api szablonu
*/
function phptemplate_user_profile($user, $fields = array()) {
  // przekaż do phptemplate tablicę asocjacyjną z nazwami i wartościami pól profilu użytkownika
return _phptemplate_callback('user_profile', array('user' => $user, 'fields' => $fields));
  }
?>

i wchodzimy na dowolny profil naszej strony. Co się pokazało? Nic? Nie panikujmy – o to chodzi. Na razie nasza funkcja niewiele robi, aby ją „uzbroić” musimy wykonać trochę pracy.

Tu uwaga – jeśli w którymś momencie zdecydujemy się, że nie odpowiada nam taki sposób wyświetlania profili jaki omówimy poniżej, wystarczy że usuniemy powyższą funkcję z pliku template.php a wszystko będzie jak za dawnych dobrych czasów.

Krok 2 – tworzymy plik user_profile.tpl.php

I wrzucamy go do katalogu z naszym szablonem, tego samego co template.php. To nasza tabula rasa – pusta karta którą zapełnimy kawałkami kodu php i html, w celu totalnej kontroli nad wyglądem naszych profili. Totalna kontrola brzmi nieźle, co?

Zacznijmy od czegoś prostego – do pliku user_profile.tpl.php wklejmy następujący kod:

<div class="profil_uzytkownika">
<p><?php print $user->name ?></p>
<p>Miasto: <?php print $user->profile_miasto ?></p>
<p>Kraj: <?php print $user->profile_kraj ?></p>
<p>Ulubione zespoły: <?php print $user->profile_muza ?></p>
</div>

Teraz po wejściu na profil z wypełnionymi polami widzimy postęp. Jednak od razu zauważymy też kilka wad. Po pierwsze – w wypadku niewypełnionego pola będziemy widzieć puste miejsce obok etykiety, po drugie lista ulubionych zespołów pokazana jest w „czystej” postaci, to znaczy bez linków prowadzących do listy ludzi słuchających dany zespół. Nie jest to błąd – po prostu w Kroku 1 powiedzieliśmy drupalowi że sami zajmiemy się całą zabawą z wyświetlaniem profili, a więc nie oczekujmy że system coś za nas zrobi, tylko zakasajmy rękawy i do roboty.

Krok 3, 4, 5… n

Tutaj ograniczają nas już tylko: nasza wyobraźnia, pomysłowość, umiejętności programistyczne.

Najpierw dodajmy prosty kawałek kodu wyświetlający avatar użytkownika:

<?php if($user->picture) {
   echo '<img style="align:left;" src="/'.$user->picture.'">';
 }
?>

Następnie zróbmy coś z niewypełnionymi polami. Jeśli użytkownik nie wypełni danego pola pokażmy mu tekst zachęcający do uzupełnienia danych – a najlepiej link do edycji odpowiedniej kategorii profilu. Jeśli profil ogląda ktoś inny, po prostu poinformujmy, że dane pole jeszcze nie zostało wypełnione.

Zamieńmy zatem

<p>Miasto: <?php print $user->profile_miasto ?></p>

na:

<?php

$kategoria = 'Osobiste';
$nazwa_pola = 'user_miasto';
$tekst_zachety = 'uzupełnij profil o miasto';
$puste_pole = 'użytkownik nie wypełnił tego pola.';

if ($user->$nazwa_pola) {
  print '<a href="http://basoofka.net/profile/'.$nazwa_pola.'/'.$user->$nazwa_pola.'">'.$user->$nazwa_pola.'</a>';
}
else
{
  if ((user_access('administer users') || $GLOBALS['user']->uid == $user->uid) && (($user->$nazwa_pola) == "")) {
    echo '<a href="/user/'.$user->uid.'/edit/'.$kategoria .'">'.$tekst_zachety.'</a>';
  }
    else {
      echo $puste_pole;
    }
}
?>

Jeśli ktoś nie jest programistą, może mieć problem ze zrozumieniem tego kodu, ale wystarczy wyjaśnić, że można go zastosować do dowolnego pola tekstowego – np, aby dodać do profilu pole z nazwą Kraju, wystarczy skopiować powyższy kod i zmodyfikować 2 zmienne:

$nazwa_pola = 'profile_kraj'; // jest to nazwa pola jaką widać w administracji polami profili.
$tekst_zachety = 'uzupełnij profil o kraj'; // jest to tekst jaki ma się pokazać w razie nie wypełnienia pola.

W poniższych przykładach pokazuję jak wyświetlić różne pola, ale nie umieszczam kodu odpowiadającego za komunikat o braku wypełnienia danego pola – liczę tu na Twoją, czytelniku, inteligencję i skorzystanie powyższego schematu.

Status GaduGadu

Kawałeczek kodu i jest:

<?php
if ($user->user_gg) {
  print '<a href="gg:'.$user->user_gg.'"><img src="http://status.gadu-gadu.pl/users/status.asp?id='.$user->user_gg.'&styl=1"> '.$user->user_gg.'</a>';
}
?>

Prywatna wiadomość

O ile mamy zainstalowany moduł prywatnych wiadomości.

<?php

print '<a title="prywatna wiadomość" href="http://basoofka.net/privatemsg/msgto/'.arg(1).'"><img title="prywatna wiadomość" alt="prywatna wiadomość"src="http://basoofka.net/themes/blue_mark/images/email.gif" border=0 /> Napisz do mnie PW</a>';

?>

Status

Jak sprawdzić czy dany użytkownik jest online? 2700 to liczba sekund od ostatniego kliknięcia danego użytkownika. Po tym czasie zostanie on uznany za użytkownika offline.

<?php

  $time_period = variable_get('user_block_seconds_online', 2700);
  $uid = arg(1); // get the current userid that is being viewed.
  $users = db_query("SELECT uid, name, access FROM {users} WHERE access >= %d AND uid = %d", time() - $time_period, $user->uid);
  $total_users = db_num_rows($users);

  if ($total_users == 1) {
    $output = t('Online');
  }
  else {
    $output = t('Offline');
  }

  print $output;

?>

Ile mam lat?

Jeśli chcesz wyświetlić w profilu tekst „Ten użytkownik ma xx lat”, użyj tego kawałka kodu (zakłada on, że masz pole typu data o nazwie profile_urodziny).

<?php
if ($user->profile_urodziny) {
    $year_diff = date("Y") - ($user->profile_urodziny{year});
    $month_diff = date("m") - ($user->profile_urodziny{month});
    $day_diff = date("d") - ($user->profile_urodziny{day});
    if ($month_diff < 0) $year_diff--;
    elseif ($month_diff == 0 && $day_diff < 0) $year_diff--;

    if ($year_diff > 4) {
      echo 'Ten użytkownik ma '.$year_diff.' lat. ';
    }
}

?>

Pole tekstowe

Chcesz dać użytkownikom pole do popisu? Tworząc pole typu „wielowierszowe pole tekstowe” (tutaj o nazwie profile_bio) i wklejając ten kod umożliwisz im skorzystanie z domyślnego formatu danych (np. bbcode) i użycia zdjęć, formatowania tekstu itd.

<?php

if($user->profile_bio) {
  echo (check_markup($user->profile_bio));
}

?>

Tekstowe pola listy

OK, ale kiedy wyświetlimy w nasz sposób tekstowe pole listy występuje jeden problem – kolejne słowa nie są linkami do listy użytkowników dla których wpisane słowo jest wspólne! I na to jest sposób – trzeba po prostu samemu zadbać (zakodować) o to, aby kolejne słowa były linkami. Poniżej kod dla pola profile_muza z kategorii Osobiste.

<?php
 print 'Ulubiona muzyka, zespoły: ';
 if ($user->profile_muza) {

     $values = split("[,\n\r]", $user->profile_muza);

            $fields = array();
            foreach ($values as $value) {
              if ($value = trim($value)) {
                $fields[] = l($value, 'profile/profile_muza/'. $value) ;
              }
            }
            $wartosc_ulubione = implode(', ', $fields);

   print $wartosc_ulubione;
 } else { print 'użytkownik nie wypełnił pola'; }

?>

Ostatnie wpisy na blogu

Jeśli użytkownik prowadzi blog, dobrze byłoby wyświetlić ostatnie kilka wpisów. $nlimit steruje ilością wpisów.

<h1>Mój Blog:</h1>

<?php
    $output = '';
    $nlimit = 5;
    $userid=$user->uid;
    $result = db_query("SELECT n.created, n.title, n.nid, n.changed FROM node n WHERE n.uid = $userid AND n.type = 'blog' AND n.status = 1 ORDER BY n.changed DESC LIMIT $nlimit");
    $output .= "<div class=\"item-list\"><ul>\n";
    $lista = node_title_list($result);
    $lista = strip_tags($lista) ? $lista : 'Brak wpisów';
    $output .= $lista;
    $output .= "</ul></div>";
  print $output;
?>

Sposób wyświetlania odpowiedzi

Wybierz preferowany sposób wyświetlania odpowiedzi i kliknij "Zachowaj ustawienia", by wprowadzić zmiany.
Portret użytkownika lolki

Witam Stworzyłem modułem

Witam

Stworzyłem modułem Views tak że po wejściu na link http://www.example.com/photos/user/1 widać podstronę ze zdjęciami użytkownika w tym przypadku o ID 1, czy możesz podać kod który zrobi tak aby po wejściu na czyjś profil było widać odrazu pod jego profilem zdjęcia które dodał?

Portret użytkownika palik

podawałem link

moderator

W tekście jest link do wieeelu przykładów:

http://drupal.org/node/35728

i między innymi tego właśnie o co pytasz:

http://drupal.org/node/40087

pozdrawiam!

--
drupal w akcji?
http://palikowski.net
http://basoofka.net

Witam, bardzo dobry

Witam, bardzo dobry poradnik, tylko mam problem, bo nie mam możliwości wgrania avataru, oraz nie wyświetla mi się ikonka statusu gg. Proszę o pomoc

Portret użytkownika lolki

Ja mam podobny problem,

Ja mam podobny problem, dając ten kod

<?php if($user->picture) {
   echo '<img style="align:left;" src="/'.$user->picture.'">';
 }
?>

Nie wyświetla mi się obrazek, wygląda jakby była zła lokalizacja.

Mam jeszcze jedno pytanie, w tym kodzie jest chyba coś nie tak:

<?php

$kategoria = 'Osobiste';
$nazwa_pola = 'user_miasto';
$tekst_zachety = 'uzupełnij profil o miasto';
$puste_pole = 'użytkownik nie wypełnił tego pola.';

if ($user->$nazwa_pola) {
  print '<a href="http://basoofka.net/profile/'.$nazwa_pola.'/'.$user->$nazwa_pola.'">'.$user->$nazwa_pola.'</a>';
}
else
{
  if ((user_access('administer users') || $GLOBALS['user']->uid == $user->uid) && (($user->$nazwa_pola) == "")) {
    echo '<a href="/user/'.$user->uid.'/edit/'.$kategoria .'">'.$tekst_zachety.'</a>';
  }
    else {
      echo $puste_pole;
    }
}
?>

ponieważ robi on z miasta użytkownika odnośnik ale dokąd? Jak usunąć ten odnośnik?
I czy nie lepiej było by zrobić aby pola nie wypełnione były całkiem usuwane niż np przy 7 polach pisało że użytkownik nie wypełnił tego pola?
Ja bym był za taką możliwością.

Przy okazji to super poradnik tylko trzeba się dłużej przyglądnąć jak ktoś sie nie zna.