Oczywiście, że jest to możliwe i nawet stosunkowo proste (chociaż Przemo nie ułatwia niektórych rzeczy, o czym przekonamy się za chwilę). Zacznijmy od rozeznania wroga, czyli tego gdzie należy zmiany wprowadzać:
- admin/admin_custom_fields.php - ten plik odpowiada za logikę pól profilowych w panelu administracyjnym. Najłatwiej dodać wartość domyślną do pola profilowego w momencie jego tworzenia, toteż "zapinamy" się z naszym kodem tutaj.
- templates/Saphic/admin/custom_fields.tpl - ten plik definiuje widok w/w funkcjonalności w panelu administracyjnym. Chcemy, żeby użytkownik mógł wprowadzić tę wartość z poziomu PA, więc trzeba tam wyświetlić dodatkowe pola. Na potrzeby przykładu rozważam styl Saphic.
- language/lang_polish/lang_custom_fields.php - ten plik definiuje wszelkie wyświetlane napisy w/w funkcjonalności w panelu administracyjnym. Na potrzeby przykładu rozważam tylko język polski.
- includes/usercp_register.php - ten plik definiuje logikę przy rejestracji użytkownika. Niestety musimy stąd pousuwać parę rzeczy, gdyż Przemo na siłę wypełnia pola profilowe pustymi ciągami znaków.
Na początek ręczna zmiana w bazie (musimy dodać nową kolumnę na wartość domyślną dla naszego pola). Możemy ją wyklikać z poziomu obsługi bazy danych, albo po prostu wykonać zapytanie:
- Kod: Zaznacz cały
ALTER TABLE `phpbb_profile_fields` ADD `def_value` VARCHAR(255) NOT NULL DEFAULT '' AFTER `min_value`;
W moim zamyśle umieszczam wartość domyślną pola profilowego pod wartością "minimalnej wartości" danego pola (ułatwia mi to później odnajdywanie odpowiednich fragmentów kodu: widzę, że coś jest robione z minimalną wartością = powinienem coś zrobić z domyślną). I tak po kolei:
admin/admin_custom_fields.php:
Dodaję w 48 linii:
- Kod: Zaznacz cały
$def_value = trim($HTTP_POST_VARS['def_value']);
Odpowiada to po prostu za zapamiętanie wprowadzonej do formularza wartości w momencie jego wysyłania (czyli zatwierdzania nowego pola przyciskiem). Wbudowana w php funkcja trim() po prostu usuwa nadmiarowe białe znaki z początku i końca, np. zamienia " spacje na początku" na "spacje na początku".
W linii 96 dodaję:
- Kod: Zaznacz cały
$def_value = '';
Jest to wartość domyślna naszej wartości domyślnej (heh), gdy dodajemy nowe pole. Jak widać inne pola również mają swoją wartość początkową (min = 1, max = 45), a wartość początkowa dla naszej wartości domyślnej to '' czyli pusty ciąg znaków.
W linii 123 dodaję:
- Kod: Zaznacz cały
$def_value = $row['def_value'];
Jest to wartość pobrana z bazy danych na potrzeby edycji już istniejącego pola profilowego.
Dalej zmieniamy linię 314:
- Kod: Zaznacz cały
$sql = "INSERT INTO " . FIELDS_TABLE . " (desc_short, desc_long, makelinks, max_value, min_value, def_value, numerics, jumpbox, requires, view_post, view_profile, set_form, no_forum, prefix, suffix, editable, view_by)
VALUES ('" . str_replace("\'", "''", $desc_short) . "', '" . str_replace("\'", "''", $desc_long) . "', $makelinks, $max_value, $min_value, '" . str_replace("\'", "''", $def_value) . "', $numerics, '" . str_replace("\'", "''", $jumpbox) . "', $requires, $view_post, $view_profile, $set_form, '" . str_replace("\'", "''", $no_forum_sql) . "', '" . str_replace("\'", "''", $prefix) . "', '" . str_replace("\'", "''", $suffix) . "', $editable, $view_by)";
Do zapytania SQL typu INSERT (wstawiającego do bazy danych) dorzucamy po prostu wartość naszej zmiennej $def_value. Idąc zgodnie z konwencją używamy str_replace("\'", "''", zmienna), co powoduje zastąpienie pojedynczego ' przez dwa ''. Zapobiega to wszelkiego rodzaju atakom, które przedwcześnie zmieniłyby zapytanie poprzez zamknięcie go znakiem '.
Dalej linię 334 zamieniamy na:
- Kod: Zaznacz cały
$field_type = ($numerics) ? "INT($max_value) DEFAULT '0' NOT NULL" : "VARCHAR($max_value) DEFAULT '$def_value' NOT NULL";
Ustawia to po prostu wartość domyślną danej kolumny tabeli USERS_TABLE na naszą wartość (czyli dokładnie to o co nam chodzi).
Niżej od linii 368 dodajemy wreszcie coś więcej kodu:
- Kod: Zaznacz cały
$sql = "SELECT def_value
FROM " . FIELDS_TABLE . "
WHERE id = $id_form";
if ( !($result = $db->sql_query($sql)) )
{
message_die(GENERAL_ERROR, 'Error checking fields table');
}
$row = $db->sql_fetchrow($result);
$prev_def_value = $row['def_value'];
Fragment ten odpowiada za zapamiętanie aktualnej wartości domyślnej pola profilowego, gdy chcemy ją edytować. Dzięki temu, przy ustawieniu nowej wartości domyślnej podmienimy wszystkie (zapamiętane teraz) wartości poprzednie.
Na tę edycję składają się trzy zapytania. Pierwsze w linii 379:
- Kod: Zaznacz cały
$sql = "UPDATE " . FIELDS_TABLE . "
SET desc_short = '" . str_replace("\'", "''", $desc_short) . "', desc_long = '" . str_replace("\'", "''", $desc_long) . "', makelinks = $makelinks, max_value = $max_value, min_value = $min_value, def_value = '" . str_replace("\'", "''", $def_value) . "', numerics = $numerics, jumpbox = '" . str_replace("\'", "''", $jumpbox) . "', requires = $requires, view_post = $view_post, view_profile = $view_profile, set_form = $set_form, no_forum = '" . str_replace("\'", "''", $no_forum_sql) . "', prefix = '" . str_replace("\'", "''", $prefix) . "', suffix = '" . str_replace("\'", "''", $suffix) . "', editable = $editable, view_by = $view_by
WHERE id = $id_form";
Odpowiada za zaktualizowanie wartości domyślnej danego pola w tabeli FIELDS_TABLE.
Drugie w linii 388:
- Kod: Zaznacz cały
$field_type = ($numerics) ? "INT($max_value) DEFAULT '0' NOT NULL" : "VARCHAR($max_value) DEFAULT '$def_value' NULL";
Uaktualnia wartość domyślną (analogicznie do tworzenia jej w linii 334).
Ostatnie w linii 398 dopisujemy sami:
- Kod: Zaznacz cały
$sql = "UPDATE " . USERS_TABLE . "
SET $column_name = '" . str_replace("\'", "''", $def_value) . "' WHERE $column_name = '$prev_def_value'";
if ( !$db->sql_query($sql) )
{
message_die(GENERAL_ERROR, 'Failed to update users table structure', '', __LINE__, __FILE__, $sql);
}
Podmieniamy użytkownikom w tabeli USERS_TABLE zapamiętaną wartość domyślną na nową (jeśli w międzyczasie sami zmienili wartość pola profilowego, to ta zmiana ich teraz już nie dotyczy).
Pozostaje już tylko powiązanie z widokiem. W linii 431:
- Kod: Zaznacz cały
'L_DEF_VALUE' => $lang['CF_def_value'],
Dodajemy naszą etykietę dla pola. Później pokażę zawartość pliku z tymi napisami w języku polskim.
No i w linii 468:
- Kod: Zaznacz cały
'DEF_VALUE' => xhtmlspecialchars($def_value),
Dodajemy naszą wartość do widoku, żeby ją móc zobaczyć na stronie.
templates/Saphic/admin/custom_fields.tplW linii 31 dodajemy:
- Kod: Zaznacz cały
<tr>
<td class="row1" width="45%">{L_DEF_VALUE}</td>
<td class="row2" width="55%"><input type="text" class="post" name="def_value" size="50" maxlength="150" value="{DEF_VALUE}"></td>
</tr>
Jest to po prostu kolejny rząd w widocznej tabeli. Dodajemy zarówno etykietę L_DEF_VALUE (którą wypełniliśmy wcześniej), jak i wartość DEF_VALUE (również wypełnioną pod koniec admin_custom_fields.php).
language/lang_polish/lang_custom_fields.phpPozostaje jeszcze dodać w polskiej wersji językowej naszą etykietę skrywającą się pod kluczem CF_def_value w linii 32:
- Kod: Zaznacz cały
$lang['CF_def_value'] = 'Warto¶æ domy¶lna';
Plik ten jest kodowany w Western (Windows 1252), stąd wklepujemy różne śmieszne znaczki zamiast polskich znaków.
includes/usercp_register.phpZauważamy, że to co nas interesuje dzieje się w linii 890:
- Kod: Zaznacz cały
$sql = "INSERT INTO " . USERS_TABLE . " (username, user_regdate, user_password, user_email, user_icq, user_website, user_occ, user_interests, user_from, " . $sql_custom_fields . " user_sig, user_sig_bbcode_uid, user_sig_image, user_avatar, user_avatar_type, user_viewemail, user_viewaim, user_aim, user_yim, user_msnm, user_attachsig, user_allowsmile, user_allowhtml, user_allowbbcode, user_allow_viewonline, user_notify, user_notify_gg, user_notify_pm, user_popup_pm, user_timezone, user_lang, user_custom_color, user_custom_rank, user_style, user_gender, allowpm, user_level, user_allow_pm, user_birthday, user_next_birthday_greeting, user_ip, user_ip_login_check, user_active, user_actkey)
VALUES ('" . str_replace("\'", "''", $username) . "', " . CR_TIME . ", '" . str_replace("\'", "''", $new_password) . "', '" . str_replace("\'", "''", $email) . "', '" . str_replace("\'", "''", $icq) . "', '" . str_replace("\'", "''", $website) . "', '" . str_replace("\'", "''", $occupation) . "', '" . str_replace("\'", "''", $interests) . "', '" . str_replace("\'", "''", $location) . "', " . $sql_custom_values . " '" . str_replace("\'", "''", $signature) . "', '$signature_bbcode_uid', $signature_sql, $avatar_sql, $viewemail, $viewaim, '" . str_replace("\'", "''", str_replace(' ', '+', $aim)) . "', '" . str_replace("\'", "''", $yim) . "', '" . str_replace("\'", "''", $msn) . "', $attachsig, $allowsmilies, $allowhtml, $allowbbcode, $allowviewonline, $notifyreply, $user_notify_gg, $notifypm, $popuppm, $user_timezone, '" . str_replace("\'", "''", $user_lang) . "', '" . str_replace("\'", "''", $custom_color) . "', '" . str_replace("\'", "''", $custom_rank) . "', $user_style, '$gender', $allowpm, 0, 1, '$birthday', '$next_birthday_greeting', '$user_ip', $user_ip_login_check, ";
Jest to zapytanie wstawiającego nowego użytkownika. Niestety domyślnie wszystkie wartości są inicjalizowane przez '', czyli pusty ciąg znaków w liniach 170-176:
- Kod: Zaznacz cały
if ( $custom_fields_exists )
{
for($i = 0; $i < count($fields_array); $i++)
{
$$fields_array[$i] = ($HTTP_POST_VARS[$fields_array[$i]] == 'no_image.gif') ? '' : ( (!is_array($HTTP_POST_VARS[$fields_array[$i]])) ? trim(xhtmlspecialchars($HTTP_POST_VARS[$fields_array[$i]])) : '' );
}
}
Widzicie te '' na końcu? To właśnie całe nasze zło. Następnie zauważamy, że faktyczna konstrukcja wartości do zapytania jest w bloku linii 806-819:
- Kod: Zaznacz cały
if ( $custom_fields_exists )
{
$sql_custom_fields = '';
$sql_custom_values = '';
for($i = 0; $i < count($custom_fields[0]); $i++)
{
if ( $custom_fields[11][$i] || $mode == 'register' )
{
$split_field = 'user_field_' . $custom_fields[0][$i];
$sql_custom_fields .= $split_field . ',';
$sql_custom_values .= '\'' . str_replace("\'", "''", $$split_field) . '\', ';
}
}
}
Interesuje nas najbardziej wewnętrzny if. Zamiast przepuszczać wszystkie pola dozwolone do edycji, lub gdy jesteśmy w trybie rejestracji my chcielibyśmy przepuszczać tylko te, które zostały ustawione. Poprawiony blok wygląda tak:
- Kod: Zaznacz cały
if ( $custom_fields_exists )
{
$sql_custom_fields = '';
$sql_custom_values = '';
for($i = 0; $i < count($custom_fields[0]); $i++)
{
if ( $custom_fields[11][$i] && !empty($$fields_array[$i]) )
{
$split_field = 'user_field_' . $custom_fields[0][$i];
$sql_custom_fields .= $split_field . ',';
$sql_custom_values .= '\'' . str_replace("\'", "''", $$split_field) . '\', ';
}
}
}
Jak widać zmienił się tylko ten jeden warunek (dodaliśmy sprawdzanie, czy użytkownik wprowadził daną wartość pola profilowego, czyli nie jest ono puste).
I to już wszystko. Mamy w pełni działające wartości domyślne dla naszych pól profilowych. Mogą je modyfikować zarówno użytkownicy, jak i można zmienić wartość domyślną na nową (co spowoduje uaktualnienie jej dla wszystkich użytkowników, którzy jej ręcznie nie zmienili). Enjoy!
PS. Jakby ktoś się pogubił w wyjaśnieniach to podrzucam gotową paczkę ze zmienionymi plikami:
http://www.filedropper.com/profilefieldsdefaultvalue (Dałem nawet komentarze //TU żeby łatwiej odnaleźć interesujące fragmenty)
//EDIT
Z racji, że moja pierwsza wersja nie pozwalała ustawiać pól profilowych przy rejestracji (nieostrożnie usunąłem ważne fragmenty w includes/usercp_register.php) poprawiłem poradnik (de facto wystarczy teraz zmienić linię 812 na zaproponowaną zamiast usuwać bloki kodu). Niestety nie chce mi się wrzucać poprawionej paczki #2lazy.