rFramework 2.01

Transkrypt

rFramework 2.01
rFramework 2.01 - Dokumentacja
Łukasz Rydzkowski
Spis treści
Spis treści ...................................................................................................................................... 2
Lista zmian..................................................................................................................................... 6
1.
Wstęp .................................................................................................................................. 7
2.
Wymagania .......................................................................................................................... 8
3.
Podstawowe założenia przyjęte podczas pisania framework’a .......................................... 9
4.
Struktura katalogów aplikacji pisanych w oparciu o rFramework .................................... 10
5.
4.1.
Główny katalog framework’a .................................................................................... 10
4.2.
Katalog public ............................................................................................................ 10
4.2.1.
Plik index.php ........................................................................................................ 10
4.2.2.
Plik autoload.php................................................................................................... 11
4.2.3.
Plik info.php ........................................................................................................... 11
4.2.4.
Plik install.php ....................................................................................................... 11
4.2.5.
Plik test.php ........................................................................................................... 11
4.2.6.
Pliki .htaccess, htaccess.lang oraz htaccess.standard ........................................... 12
4.2.7.
Pliki web.config, web.config.lang oraz web.config.standard ................................ 12
4.3.
Katalog css ................................................................................................................. 12
4.4.
Katalog fonts.............................................................................................................. 12
4.5.
Katalog img ................................................................................................................ 12
4.6.
Katalog js ................................................................................................................... 12
Moduł Core 1.01 ................................................................................................................ 13
5.1.
Wstęp ........................................................................................................................ 13
5.2.
Struktura katalogów modułu..................................................................................... 13
5.2.1.
Katalog config ........................................................................................................ 13
5.2.2.
Katalog controller .................................................................................................. 13
5.2.3.
Katalog db .............................................................................................................. 13
5.2.4.
Katalog errors ........................................................................................................ 14
5.2.5.
Katalog frontend.................................................................................................... 14
5.2.6.
Katalog templates .................................................................................................. 14
5.2.7.
Katalog utils ........................................................................................................... 14
5.2.8.
Katalog view .......................................................................................................... 14
5.3.
Obsługa żądań ........................................................................................................... 15
5.3.1.
Tablica routingu ..................................................................................................... 15
5.3.2.
Kontroler................................................................................................................ 17
2
5.3.3.
Strona startowa aplikacji ....................................................................................... 18
5.4.
Dołączanie do aplikacji zewnętrznych bibliotek PHP ................................................ 18
5.5.
Widok ........................................................................................................................ 19
5.6.
Baza danych ............................................................................................................... 20
5.7.
Elementy frontend’u ................................................................................................. 21
5.7.1.
Przenoszenie elementów frontend’u z katalogu modułu do katalogu public....... 21
5.7.2.
Kod JavaScript ........................................................................................................ 21
5.7.2.1. Wstęp .......................................................................................................... 21
5.7.2.2. Struktury klaso podobne ............................................................................. 22
5.7.2.3. Message.js ................................................................................................... 23
5.7.2.4. ErrorHandler.js ............................................................................................ 23
5.7.2.5. MessageHandler.js ...................................................................................... 24
5.7.2.6. ConfirmQuestionHandler.js ........................................................................ 24
5.7.2.7. Data.js ......................................................................................................... 24
5.7.2.8. Table.js ........................................................................................................ 25
5.7.2.9. JsRenderLoader.js ....................................................................................... 26
5.7.2.10. AppException.js......................................................................................... 26
5.7.2.11. Utils.js ........................................................................................................ 27
6.
Moduł App 2.01 ................................................................................................................. 28
6.1.
Wstęp ........................................................................................................................ 28
6.2.
Konfiguracja aplikacji ................................................................................................. 28
6.2.1.
Wstęp .................................................................................................................... 28
6.2.2.
APP_VERSION ........................................................................................................ 28
6.2.3.
APP_NAME ............................................................................................................ 28
6.2.4.
APP_CREATION_YEAR............................................................................................ 29
6.2.5.
$templateDir ......................................................................................................... 29
6.2.6.
ENVIRONMENT_TYPE ............................................................................................ 29
6.2.7.
MAIN_SITE_KEY ..................................................................................................... 29
6.2.8.
FRIENDLY_LINKS .................................................................................................... 29
6.2.9.
COPY_FRONTEND_FILES ........................................................................................ 29
6.2.10. $copyFrontendException ..................................................................................... 30
6.2.11. SESSION_KEY ........................................................................................................ 30
6.2.12. REMEMBER_LAST_SITE ........................................................................................ 30
6.2.13. TITLE_SITE_PREFIX ............................................................................................... 30
6.2.14. TITLE_SITE_SUFIX ................................................................................................. 30
3
6.2.15. SHOW_APP_VERSION_IN_TITLE .......................................................................... 30
6.2.16. TRANSLATIONS_HANDLING ................................................................................. 30
6.2.17. DEFAULT_LANGUAGE .......................................................................................... 30
6.2.18. $availableLang...................................................................................................... 31
6.2.19. $modules.............................................................................................................. 31
6.2.20. DATABASE_TYPE .................................................................................................. 31
6.2.21. $mailData ............................................................................................................. 31
6.3.
Widok ........................................................................................................................ 31
6.4.
Elementy frontend’u ................................................................................................. 32
6.4.1.
Kod CSS .................................................................................................................. 32
6.4.2.
Kod JavaScript ........................................................................................................ 32
6.4.2.1. Wstęp .......................................................................................................... 32
6.4.2.2. Site.js ........................................................................................................... 32
7.
Mechanizm tłumaczenia witryny ...................................................................................... 34
8.
Moduł User 1.52 ................................................................................................................ 37
8.1.
Wstęp ........................................................................................................................ 37
8.2.
Ustawienia ................................................................................................................. 37
8.2.1.
Wstęp .................................................................................................................... 37
8.2.2.
$requiredModules ................................................................................................. 37
8.2.3.
SITE_AFTER_LOGIN ................................................................................................ 37
8.2.4.
ADMIN_USER_CONFIRM ....................................................................................... 37
8.2.5.
ADMIN_TYPE ......................................................................................................... 37
8.2.6.
EMAIL_MAX_LANGTH ........................................................................................... 38
8.2.7.
PASSWORD_MIN_LENGTH .................................................................................... 38
8.2.8.
PASSWORD_MAX_LENGTH ................................................................................... 38
8.2.9.
FIRSTNAME_MAX_LENGTH ................................................................................... 38
8.2.10. LASTNAME_MAX_LENGTH................................................................................... 38
8.2.11. USER_TYPE_NAME_MAX_LENGTH ...................................................................... 38
8.2.12. USER_TYPE_ID_MIN_VAL..................................................................................... 38
8.2.13. USER_TYPE_ID_MAX_VAL .................................................................................... 38
8.2.14. EDIT_BLOCK_TIME ............................................................................................... 38
8.2.15. USE_RECAPTCHA .................................................................................................. 39
8.2.16. PATH_TO_CAPTCHA_LIB ...................................................................................... 39
8.2.17. RECAPTCHA_PUBLIC_KEY..................................................................................... 39
8.2.18. RECAPTCHA_PRIVATE_KEY .................................................................................. 39
4
8.3.
Struktura klas kontrolerów modułu .......................................................................... 39
8.4.
Struktura szablonów Smarty ..................................................................................... 40
8.5.
Strony modułu ........................................................................................................... 40
8.5.1.
Strona logowania ................................................................................................... 40
8.5.2.
Strona rejestracji ................................................................................................... 40
8.5.3.
Strona potwierdzania konta .................................................................................. 41
8.5.4.
Strona odzyskiwania hasła..................................................................................... 41
8.5.5.
Konto użytkownika ................................................................................................ 41
8.5.6.
Strona zarządzania użytkownikami ....................................................................... 41
8.5.7.
Strona zarządzania typami użytkowników ............................................................ 41
8.6.
Struktura kodu JavaScript .......................................................................................... 42
8.7.
Struktura bazy danych ............................................................................................... 43
8.7.1.
Wstęp .................................................................................................................... 43
8.7.2.
Tabela user ............................................................................................................ 43
8.7.3.
Tabela user_type ................................................................................................... 44
8.7.4.
Tabela user_modification ...................................................................................... 44
8.7.5.
Tabela user_type_modification............................................................................. 44
8.8.
Integracja z innymi modułami ................................................................................... 45
8.9.
Testowanie modułu ................................................................................................... 47
9.
Moduł ListSupport 1.35 ..................................................................................................... 47
10.
Moduł ModuleCreator 1.15............................................................................................... 47
5
Lista zmian
Wersja
Data modyfikacji
2.01
07.01.2017
Lista zmian
Modyfikacje w rozdziałach 4.2.4. Plik install.php, 4.6. Katalog js,
5.7.1. Przenoszenie elementów frontend’u z katalogu modułu do
katalogu public. Zmiana rozdziału 6.2.10. COPY_JS_LIBS na 6.2.10.
$copyFrontendException. Aktualizacja związana jest ze zmianami
wprowadzonymi w mechanizmie przenoszenia zawartości
katalogów frontend z katalogów modułów do katalogu public.
Dodanie listy zmian.
6
1. Wstęp
Niniejszy dokument stanowi dokumentację framework’a o nazwie rFramework
wykorzystywanego do budowy aplikacji internetowych w oparciu o języki programowania PHP i
JavaScript, arkusze styli CSS oraz system szablonów Smarty. Bardzo duży nacisk został położony
na modułowość aplikacji pisanych w oparciu o rFramework. Podział na moduły został
zastosowany w strukturze katalogów z kodem PHP oraz szablonami Smarty, w strukturze
katalogów ze stylami CSS oraz w strukturze katalogów z kodem JavaScript. Opisywana wersja
kodu zawiera siedem modułów. Pierwszy z nich o nazwie Core odpowiedzialny jest za działanie
wszystkich podstawowych mechanizmów framework’a. Z założenia moduł ten nie powinien być
w żaden sposób modyfikowany podczas pisania aplikacja. Drugi moduł o nazwie App stanowi
trzon aplikacji zawierający ustawienia aplikacji oraz podstawowe szablony Smarty, pliki CSS,
obrazy i czcionki. Proces tworzenia aplikacji powinien rozpoczynać się od wprowadzenia
modyfikacji w tym module. Trzeci moduł o nazwie User odpowiada za działanie systemu
użytkowników. Czwarty moduł o nazwie ModuleCreator umożliwia utworzenie struktury plików
oraz katalogów stanowiących szkielet nowego modułu, co bardzo przyśpiesza rozpoczęcie pracy
nad nowymi modułami aplikacji. Piąty moduł o nazwie ListSupport zawiera implementację
stronicowania oraz filtrowania pobieranych danych. Szósty moduł o nazwie ClientInfoRegister
odpowiada za zapisywanie w bazie informacji o adresie ip oraz przeglądarce użytkownika
korzystającego z aplikacji. Ostatni moduł o nazwie JsRenderSample udostępnia użytkownikowi
stronę zawierającą przykłady wykorzystania systemu szablonów JsRender1. Każdy z modułów
działających w systemie może być pisany w oparciu o wzorzec MVC tak jak moduły App, User,
ModuleCreator, ClientInfoRegister oraz JsRenderSample jednak nie jest to wymagane.
1
https://www.jsviews.com/
7
2. Wymagania
Aplikacje pisane w oparciu o rFramework mogą działać na serwerze Apache lub IIS z
zainstalowanym PHP w wersji co najmniej 5.5. Jeśli aplikacja napisana w oparciu o opisywany
framework ma komunikować się z bazą danych MsSQL to w PHP musi być zainstalowany moduł
PHP PDO SqlSrv2. Dodatkowo przeglądarka użytkownika musi mieć włączoną obsługę języka
JavaScript oraz w przypadku wykorzystywania przeglądarki Internet Explorer musi to być
minimum wersja 9 tej przeglądarki. Należy jednak pamiętać o tym że w starszych wersjach
przeglądarki Internet Explorer niektóre elementy strony mogą nie wyglądać tak jak na nowszych
przeglądarkach ze względu na brak obsługi niektórych styli CSS.
2
https://www.microsoft.com/en-us/download/details.aspx?id=20098
8
3. Podstawowe założenia przyjęte podczas pisania framework’a



Język PHP:
o Każda klasa znajduje się w oddzielnym pliku o takiej samej nazwie jak nazwa klasy.
o Nazwy klas pisane są w notacji upper camel case3.
o Nazwy zmiennych oraz składowych klas w tym metod pisane są w notacji lower camel
case4.
o W każdym pliku z klasą definiowana jest przestrzeń nazw budowana na podstawie
ścieżki do pliku począwszy od katalogu modułu. Na przykład gdy plik AppSettings.php
znajduje się w katalogu src/App/config to klasa AppSettings znajdująca się w tym
pliku znajduje się w przestrzeni nazw \App\config.
o Za obsługę pojedynczego żądania odpowiada pojedyncza metoda kontrolera.
o W metodach kontrolera znajduje się minimalna ilość kodu potrzebna do obsługi
żądania. Cała logika znajduje się w zewnętrznych klasach, których metody
wywoływane są w kontrolerze.
o Operacje na zmiennych sesyjnych wykonywane są tylko w metodach klas
kontrolerów.
o Do tworzenia kodu odpowiedzialnego za wykonywanie operacji na bazie danych
wykorzystywany jest wzorzec polegający na tworzeniu klas reprezentujących
poszczególne tabele w bazie danych.
o Teksty wyświetlane użytkownikowi znajdują się w szablonach Smarty lub w
zewnętrznych plikach, z których są pobierane. Takie podejście ma na celu
odseparowanie kodu od wyświetlanego tekstu oraz ścisłe określenie miejsc gdzie
mogą znaleźć się komunikaty co powinno ułatwić późniejsze znalezienie oraz edycję
tych komunikatów.
Język JavaScript:
o Obiekty, struktury klaso podobne (więcej na temat tych struktur można znaleźć w
rozdziale 5.7.2.2 Struktury klaso podobne) oraz funkcje zwracające obiekty znajdują
się w oddzielnych plikach o takiej samej nazwie jak znajdująca się w tym pliku jedna
z tych trzech struktur.
o Nazwy, opisanych w pierwszym podpunkcie, podstawowych struktur
wykorzystywanych w kodzie JavaScript pisane są w notacji upper camel case.
o Nazwy zmiennych oraz elementów składowych struktur klaso podobnych pisane są
w notacji lower camel case.
o Tekst wyświetlany użytkownikowi przechowywany jest w specjalnie do tego
przeznaczonych obiektach i pobierany w kodzie na podstawie identyfikatorów (patrz
rozdział 5.7.2.3 Message.js).
Inne:
o Elementy frontend’u związane z danym modułem, takie jak pliki z kodem JavaScript,
pliki z kodem CSS, obrazki oraz czcionki powinny znaleźć się w podkatalogach
katalogu frontend, który z kolei powinien znajdować się w głównym katalogu modułu
(więcej informacji na ten temat można znaleźć w rozdziale 5.7.1 Przenoszenie
elementów frontend’u z katalogu modułu do katalogu public).
3
4
https://en.wikipedia.org/wiki/Camel_case
https://en.wikipedia.org/wiki/Camel_case
9
4. Struktura katalogów aplikacji pisanych w oparciu o rFramework
4.1. Główny katalog framework’a
Struktura katalogów przykładowej aplikacji napisanej w
oparciu o przedstawiony w niniejszym dokumencie framework
została zaprezentowana na Rysunku 4.1. Pierwszy katalog o
nazwie db zawiera plik bazy danych SQLite. Oprócz tego systemu
bazodanowego framework umożliwia również wykorzystywanie
systemów relacyjnych baz danych MySql, MsSql oraz PgSql.
Kolejny katalog o nazwie doc zawiera dokumentację
framework’a. Katalog libs zawiera zewnętrzne biblioteki napisane
w języku PHP. W przykładowej aplikacji można tam znaleźć
następujące biblioteki:
JavaScriptPacker – biblioteka wykorzystywana do
minimalizowania plików z kodem JavaScript.
PHPMailer – biblioteka umożliwiająca wysyłanie
wiadomości email z poziomu kodu PHP.
Smarty – system szablonów,
Recaptcha – biblioteka odpowiedzialna za działanie
elementu captcha5.




Katalog logs zawiera logi błędów PHP oraz logi zapisywane w
kodzie aplikacji. Następny katalog, o nazwie public stanowi
główny katalog aplikacji. Dzięki temu, że głównym katalogiem
aplikacji jest jeden z podkatalogów framework’a użytkownik nie
ma dostępu do logów lub do kodu poszczególnych modułów
bezpośrednio z poziomu przeglądarki internetowej. Więcej
informacji o zawartości katalogu public można znaleźć w
podrozdziale 4.2 Katalog public. W ostatnim katalogu o nazwie
src znajdują się wszystkie moduły aplikacji napisane w języku
PHP. Kod każdego z modułów znajduje się w oddzielnym
podkatalogu, którego nazwa stanowi nazwę danego modułu w
notacji upper camel case.
4.2. Katalog public
4.2.1.
Rysunek 4.1
Plik index.php
Najważniejszy element w katalogu public stanowi plik index.php, który zawiera kod
wywoływany w momencie odebrania żądania z przeglądarki użytkownika. W pliku tym
uruchamiany jest mechanizm sesji za pomocą funkcji session_start(). Następnie ustawiany jest
katalog od którego rozpoczynają się relatywne ścieżki wykorzystywane w kodzie PHP na katalog
rodzica katalogu public za pomocą poniższego kodu:
chdir(dirname(__DIR__));
5
https://www.google.com/recaptcha/intro/index.html
10
Kolejny krok stanowi dołączenie pliku autoload.php zawierającego funkcję odpowiedzialną za
automatyczne dołączanie plików z klasami PHP na podstawie przestrzeni nazw. Przestrzenie nazw
wszystkich klas stanowią odzwierciedlenie ścieżki do pliku z klasą począwszy od głównego
katalogu modułu, a więc w przypadku gdy plik o nazwie Cookie.php znajduje się w katalogu
src/User/model to klasa Cookie znajduje się w przestrzeni nazw \User\model. Wszystkie klasy w
systemie znajdują się w plikach o takich samych nazwach jak nazwa klasy, a co za tym idzie każda
klasa znajduję się w oddzielnym pliku. W kolejnych krokach sprawdzana jest wersja PHP,
opisywany framework wymaga PHP w wersji o numerze nie mniejszym niż 5.5. Jeśli aplikacja
zostanie uruchomiona na serwerze z zainstalowanym PHP o numerze mniejszym niż 5.5 to
zostanie wyświetlony odpowiedni komunikat i aplikacja przerwie swoje działanie. Kolejny krok
stanowi ustawienie wyświetlania lub nie wyświetlania błędów PHP na ekranie przeglądarki w
zależności od ustawień w pliku konfiguracyjnym (klasa \App\config\AppSettings) oraz
zdefiniowanie funkcji które zapisują błędy PHP w plikach z logami. Po wykonaniu wszystkich
powyższych
operacji
wywoływana
jest
właściwa
metoda
framework’a
(\App\controller\Controller::servRequest()) odpowiedzialna za obsługę żądań.
4.2.2.
Plik autoload.php
Jak już wspomniano w poprzednim podrozdziale w pliku autoload.php znajduje się funkcja
odpowiedzialna za automatyczne dołączanie plików z klasami PHP na podstawie przestrzeni nazw.
4.2.3.
Plik info.php
Plik zawierający polecenie phpinfo() odpowiedzialne za wyświetlenie strony z informacjami
o serwerze www oraz informacjami o wersji i ustawieniach PHP.
4.2.4.
Plik install.php
Plik o nazwie install.php zawiera kod odpowiedzialny za instalację aplikacji. W procesie
instalacji można wyróżnić dwa etapy.
Pierwszy etap polega na przeprowadzeniu modyfikacji w kodzie PHP aplikacji. W pierwszym
kroku w pliku konfiguracyjnym aplikacji \App\config\AppSettings ustawiane jest działanie
aplikacji w trybie produkcyjnym. Następnie w pliku konfiguracyjnym wyłączany jest automatyczny
mechanizm przenoszenia elementów frontend’u (czyli wszystkich plików wyświetlanych bądź
przetwarzanych przez przeglądarkę takich jak na przykład obrazki, czcionki, źródła CSS oraz źródła
JavaScript) z katalogów modułów do katalogu public (więcej informacji na temat tego
mechanizmu można znaleźć w rozdziale 5.7.1 Przenoszenie elementów frontend’u z katalogu
modułu do katalogu public). W kolejnym kroku aktualizowana jest w pliku konfiguracyjnym lista
aktywnych modułów. W przedostatnim kroku w pliku konfiguracyjnym aktualizowane są dane
dostępowe do bazy danych. Ostatni krok polega na zmodyfikowaniu kodu klasy
\Core\config\Routing w taki sposób aby przy każdym żądaniu nie trzeba było pobierać tablic
routingu ze wszystkich aktywnych modułów aplikacji (więcej informacji na temat tablicy routingu
można znaleźć w rozdziale 5.3.1 Tablica routingu).
Drugi etap polega na skopiowaniu elementów frontend’u z katalogów modułów do
katalogu public oraz na zminimalizowaniu źródeł CSS oraz źródeł JavaScript.
Na samym końcu z katalogu public usuwane są pliki info.php, htaccess.lang,
htaccess.standard, web.config.lang, web.config.standard oraz sam plik install.php.
4.2.5.
Plik test.php
Plik o nazwie test.php zawiera kod umożliwiający przeprowadzanie operacji przydatnych
podczas testowania aplikacji. W aktualnej wersji framework’a plik zawiera kod odpowiedzialny za
11
wstawienie do bazy losowych danych dotyczących zarejestrowanych użytkowników – mechanizm
związany z modułem User opisanym w rozdziale 8 Moduł User 1.5.
4.2.6.
Pliki .htaccess, htaccess.lang oraz htaccess.standard
Plik .htaccess wykorzystywany jest w sytuacji gdy aplikacja działa na serwerze Apache i
zawiera kod odpowiedzialny za działanie „przyjaznych” linków (więcej informacji na ten temat
można znaleźć w rozdziale 5.3.2 Kontroler). W pliku htaccess.standard znajduje się kod, który
powinien zostać przeniesiony do pliku .htaccess w przypadku gdy w aplikacji nie jest włączona
obsługa wielu wersji językowych. W przeciwnym wypadku w pliku .htaccess powinien znaleźć się
kod z pliku htaccess.lang.
4.2.7.
Pliki web.config, web.config.lang oraz web.config.standard
Plik web.config wykorzystywany jest w sytuacji gdy aplikacja działa na serwerze IIS i zawiera
kod odpowiedzialny za działanie „przyjaznych” linków (więcej informacji na ten temat można
znaleźć w rozdziale 5.3.2 Kontroler). W pliku web.config.standard znajduje się kod, który powinien
zostać przeniesiony do pliku web.config w przypadku gdy w aplikacji nie jest włączona obsługa
wielu wersji językowych. W przeciwnym wypadku w pliku web.config powinien znaleźć się kod z
pliku web.config.lang.
4.3. Katalog css
Katalog css zawiera pliki z arkuszami styli CSS. Pliki znajdują się w katalogach o nazwach
modułów do których należą poszczególne style. Style wykorzystywane na stronach
przyporządkowanych do różnych modułów znajdują się w katalogu App.
4.4. Katalog fonts
Katalog fonts zawiera pliki z czcionkami wykorzystywanymi w aplikacji. Czcionki znajdują
się w katalogach o nazwach modułów do których należą. Czcionki wykorzystywane na stronach
przyporządkowanych do różnych modułów znajdują się w katalogu App.
4.5. Katalog img
Katalog img zawiera pliki z obrazkami oraz ikony wykorzystywane w aplikacji. Obrazki
znajdują się w katalogach o nazwach modułów do których należą. Obrazki wykorzystywane na
stronach przyporządkowanych do różnych modułów znajdują się w katalogu App.
4.6. Katalog js
Ostatni katalog o nazwie js zawiera wszystkie skrypty JavaScript wykorzystywane w
aplikacji, w tym również zewnętrzne biblioteki wykorzystywane przez aplikację. Pliki znajdują się
w katalogach o nazwach modułów, z którymi są związane.
12
5. Moduł Core 1.01
5.1. Wstęp
Moduł Core stanowi integralną część framwork’a i zawiera
wszystkie podstawowe mechanizmy wykorzystywane we
wszystkich pozostałych modułach aplikacji. Moduł jest ściśle
związany z modułem App bez którego nie będzie działać
prawidłowo. Warto pamiętać że moduł jest domyślnie aktywny i
jego nazwa nie musi być podawana w tablicy
\App\config\AppSettings::$modules (patrz rozdział 6.2.19
$modules). Struktura katalogów modułu Core została
przedstawiona na rysunku 5.1.
5.2. Struktura katalogów modułu
5.2.1.
Katalog config
Pierwszy katalog o nazwie config zawiera cztery klasy.
Pierwszą klasę stanowi klasa Settings, po której powinny
dziedziczyć wszystkie klasy zawierające ustawienia poszczególnych
modułów aplikacji. Klasa ta zawiera dwie statyczne metody.
Pierwsza z nich umożliwia pobranie wartości prywatnych
składowych klas z ustawieniami. Druga natomiast umożliwia
sprawdzenie istnienia prywatnych składowych klas z ustawieniami.
Drugą klasę w katalogu config stanowi klasa CoreSettings, która
zawiera informacje o wersji modułu oraz o minimalnej wersji PHP
potrzebnej do działania modułu. W opisywanym katalogu znajduje
się również klasa Routing oraz klasa CoreRouting, która dziedziczy
po klasie Routing. Obie klasy zawierają mechanizmy
odpowiedzialne za obsługę żądań.
5.2.2.
Katalog controller
W katalogu controller znajdują się dwie klasy. Pierwsza z
Rysunek 5.1
nich o nazwie Controller zawiera mechanizmy odpowiedzialne za
obsługę żądań. Po tej klasie powinny dziedziczyć, pośrednio lub bezpośrednio, wszystkie klasy
kontrolerów modułów aplikacji. Druga klasa znajdująca się w opisywanym katalogu, o nazwie
CoreController, zawiera dwie metody odpowiedzialne za obsługę dwóch żądań asynchronicznych.
Pierwsza metoda obsługuje żądanie zapisania w plikach z logami błędów, które wystąpiły w kodzie
JavaScript. Natomiast druga metoda odpowiada za obsługę żądania pobrania zawartości szablonu
JsRender. Więcej informacji na temat tego mechanizmu można znaleźć w rozdziale 5.7.2.9
JsRenderLoader.js.
5.2.3.
Katalog db
Kolejny katalog w strukturze katalogów modułu Core o nazwie db zawiera klasy
odpowiedzialne za dostęp do bazy danych. Znajduje się tam klasa Database odpowiedzialna za
nawiązywanie połączeń do różnych systemów zarządzania bazami danych. Drugą klasę znajdującą
się w katalogu db stanowi klasa Table po której muszą dziedziczyć wszystkie klasy stanowiące
odwzorowanie poszczególnych tabel z bazy danych.
13
5.2.4.
Katalog errors
Katalog o nazwie errors zawiera klasę AppException, która dziedziczy po wbudowanej w
język PHP klasie Exception i wykorzystywana jest do wyrzucania wyjątków związanych z
działaniem aplikacji. Kolejną klasę, która dziedziczy po klasie Exception stanowi klasa
WrongUrlException, która wykorzystywana jest do wyrzucania wyjątków związanych z próbą
przejścia pod nieprawidłowy adres strony. Oprócz tego znajduje się tam również klasa Debug
zawierająca metody umożliwiające zapisywanie w logach czasu wykonywania wybranego
fragmentu kodu oraz klasa Logs zawierająca metody odpowiedzialne za zapisywanie w logach
różnego rodzaju informacji w tym błędów aplikacji oraz błędów wykonywania skryptów PHP.
5.2.5.
Katalog frontend
Katalog frontend zawiera pliki z kodem JavaScript stanowiącym integralną część
framework’a (więcej informacji na ten temat można znaleźć w rozdziale 5.7 Elementy frontend’u).
5.2.6.
Katalog templates
W katalogu templates znajduje się podkatalog templates_c, który zawiera pliki tymczasowe
automatycznie generowane przez system szablonów Smarty.
5.2.7.
Katalog utils
W przedostatnim katalogu modułu Core o nazwie utils znaleźć można klasę Cookie
odpowiedzialną za pobieranie oraz zapisywanie w plikach COOKIE informacji o wybranej przez
użytkownika wersji językowej aplikacji (patrz rozdział 7 Mechanizm tłumaczenia witryny) oraz o
adresie ostatnio otwartej w aplikacji strony (patrz rozdział 6.2.12 REMEMBER_LAST_SITE). Kolejna
klasa, o nazwie JsRender zawiera metodę odpowiedzialną za pobieranie zawartości szablonów
JsRender (patrz rozdział 5.7.2.9 JsRenderLoader.js). Następna klasa, o nazwie Mail
odpowiedzialna jest za wysyłanie wiadomości email przy wykorzystaniu biblioteki PHPMailer.
Kolejna klasa, o nazwie Module zawiera metody umożliwiające sprawdzenie tego czy moduł jest
aktywny oraz sprawdzenie tego czy inne moduły wymagane przez dany moduł są również
aktywne. Ostatnia klasa w katalogu utils nazywa się Utils i zawiera różnego rodzaju uniwersalne
metody, które mogą być wykorzystane w różnych modułach aplikacji.
Oprócz opisanych powyżej klas w katalogu utils znajduje się również podkatalog o nazwie
installer, w którym znajdują się dwie klasy. Klasa Installer zawiera metody wywoływane w celu
zainstalowania aplikacji. Natomiast klasa o nazwie Compilation zawiera metody statyczną
odpowiedzialne za wprowadzenie modyfikacji w kodzie framework’a podczas przeprowadzania
instalacji aplikacji.
5.2.8.
Katalog view
W katalogu view znajdują się trzy klasy związane z mechanizmem wyświetlania stron
budowanych przy wykorzystaniu systemu szablonów Smarty. Najważniejszą klasę stanowi
abstrakcyjna klasa View inicjalizująca system szablonów Smarty. Każda strona udostępniania
przez aplikację powinna być reprezentowana przez klasę, która dziedziczy po klasie View. Kolejną
klasę znajdującą się w opisywanym katalogu stanowi klasa Link. Klasa ta udostępnia metodę
Link::getLink(), która na podstawie identyfikatora strony z tablicy routingu zwraca odnośnik do tej
strony (więcej informacji na temat tablicy routingu można znaleźć w rozdziale 5.3.1 Tablica
routingu). Ostatnią klasę stanowi klasa Lang umożliwiająca tłumaczenie tekstów (więcej
informacji na temat mechanizmów tłumaczenia witryny można znaleźć w rozdziale 7 Mechanizm
tłumaczenia witryny).
14
5.3. Obsługa żądań
5.3.1.
Tablica routingu
Tablica routingu zawiera informacje o tym, które metody kontrolera mają zostać wywołane w
przypadku nadejścia konkretnych żądań do aplikacji. Tablicę o nazwie $routingArr definiuje się w
klasie \<<nazwa_modułu>>\config\<<nazwa_modułu>>Routing, która powinna dziedziczyć po
klasie \Core\config\Routing. Przykładowa tablica $routingArr wygląda następująco:
protected static $routingArr = array(
'allSites' => array(
'ajax'
=> array(
'checkUserExist' => array(
'method'
=> 'checkUserExistAction',
'controller'
=> 'User\controller\UserController'
),
'updateModificationDate' => array(
'method'
=> 'updateModificationDateAction',
'controller'
=> 'User\controller\ModificationController'
),
'cancelModification' => array(
'method'
=> 'cancelModificationAction',
'controller'
=> 'User\controller\ModificationController'
)
)
),
'loginSite' => array(
'controller'
=> 'User\controller\AccessController',
'view'
=> 'User\view\sites\LoginView',
'title'
=> 'Logowanie',
'address'
=> 'logowanie',
'startAction'
=> array(
'method'
=> array(
'checkUser'
),
'trueResult'
=> array(
'redirectToMainSite'
)
),
'ajax'
=> array(
'login'
=> array(
'method'
=> 'loginAction'
),
)
),
'registerSite' => array(
'controller'
=> 'User\controller\AccessController',
'view'
=> 'User\view\sites\RegisterView',
'title'
=> 'Rejestracja',
'address'
=> 'rejestracja',
'startAction'
=> array(
'method'
=> array(
'checkUser'
),
'trueResult'
=> array(
'redirectToMainSite'
)
),
'ajax'
=> array(
'register'
=> array(
'method'
=> 'registerAction'
),
'confirm'
=> array(
'method'
=> 'confirmUser'
),
)
),
'usersListSite' => array(
'controller'
=> 'User\controller\UsersListController',
'view'
=> 'User\view\sites\lists\UsersListView',
'title'
=> 'Użytkownicy',
'address'
=> 'uzytkownicy',
'startAction'
=> array(
15
'method'
=> array(
'checkUser',
'userIsAdmin'
),
'falseResult'
=> array(
'redirectToLoginSite',
'redirectToMainSite'
)
),
'viewMethods'
=> array(
'setViewParams'
),
'ajax'
=> array(
'getUsersList' => array(
'method'
=> 'getUsersListAction'
),
'removeUser'
=> array(
'method'
=> 'removeUserAction'
)
)
),
'logout' => array(
'controller'
'method'
'address'
)
=> 'User\controller\AccessController',
=> 'logout',
=> 'wyloguj'
);
Klucze tablicy (loginSite, registerSite, usersListSite oraz logout) stanowią identyfikatory stron
aplikacji. Każdy z wymienionych kluczy wskazuje na tablicę, która może zawierać następujące
elementy:






controller – nazwa klasy kontrolera, w którym znajduje się metoda odpowiedzialna za
obsługę żądania, wraz z przestrzenią nazw (element wymagany),
view – nazwa klasy widoku, która odpowiedzialna jest za wyświetlenie odpowiedniego
szablonu Smarty, wraz z przestrzenią nazw,
method – metoda kontrolera wywoływana w momencie nadejścia synchronicznego
żądania na adres strony podany w elemencie address, metoda musi zwracać tablicę
asocjacyjną zawierającą elementy przekazywane do szablonów Smarty, w przypadku braku
elementów przekazywanych do szablonów zwracana tablica może być pusta,
title – tytuł strony wyświetlany na pasku tytułowym zakładki przeglądarki,
address – adres strony (element wymagany),
startAction – tablica zawierająca informacje dotyczące operacji wykonywanych przed
metodą kontrolera wywoływaną w momencie nadejścia żądania na stronę opisywaną
przez dany fragment tablicy (może to być na przykład weryfikacja czy użytkownik jest
zalogowany), w przypadku braku zdefiniowanej metody kontrolera, metody z tablicy
wykonywane są przed wyświetleniem strony,
o method – lista metod kontrolera, które są wywoływane przed właściwą metodą
wywoływaną w momencie nadejścia żądania, do metod nie są przekazywane żadne
parametry, metody muszą zwracać wartość typu bool oraz metody są wywoływane
w takiej kolejności w jakiej znajdują się w tablicy,
o trueResult – lista metod wykonywanych w przypadku gdy metoda z tablicy method,
która znajduje się pod indeksem odpowiadającym indeksowi metody z tablicy
trueResult zwróci wartość true,
o falseResult – lista metod wykonywanych w przypadku gdy metoda z tablicy method,
która znajduje się pod indeksem odpowiadającym indeksowi metody z tablicy
falseResult zwróci wartość false,
16


viewMethods – tablica zawierająca metody klasy kontrolera, które są wywoływane przed
właściwą metodą kontrolera w celu inicjalizacji tablicy asocjacyjnej zawierającej elementy
przekazywane do szablonów Smarty, klucze generowanej tablicy stanowią nazwy
zmiennych w szablonach natomiast wartości tablicy stanowią wartości poszczególnych
zmiennych (w przypadku braku zdefiniowanej metody kontrolera metody z tablicy
wykonywane są przed wyświetleniem strony),
ajax – tablica zawierająca informacje dotyczące obsługi żądań asynchronicznych POST dla
danej strony, klucze tablicy stanowią wartości elementu request tablicy POST natomiast
wewnątrz tablic na które wskazują poszczególne klucze znajdują się nazwy wywoływanych,
w przypadku nadejścia tego typu żądania, metod kontrolera (w takim przypadku główna
metoda kontrolera wskazana w elemencie method tablicy wskazywanej przez klucz
stanowiący identyfikator strony nie jest wywoływana).
Identyfikatory stron muszą być unikalne w obrębie tablic routingu wszystkich aktywnych
modułów aplikacji. Identyfikatory mogą mieć dowolną wartość oprócz zarezerwowanego ciągu
znaków allSites, który jest wykorzystywany do definiowania fragmentu tablicy routingu
odpowiedzialnego za obsługę żądań przychodzących na dowolny adres aplikacji. Fragment tablicy
routingu wskazywany przez klucz allSites może zawierać jedynie element ajax, natomiast
poszczególne elementy tablicy ajax muszą zawierać elementy controller oraz method. Co więcej
element allSites może znaleźć się w tablicach routingu więcej niż jednego modułu.
5.3.2.
Kontroler
Za obsługę żądań przychodzących do aplikacji odpowiedzialne są metody znajdujące się w klasach
kontrolerów. Klasy te powinny znaleźć się w katalogu controller, który powinien się znajdować w
głównym katalogu modułu zawierającego te klasy. Każda z klas kontrolera powinna dziedziczyć
bezpośrednio lub pośrednio po klasie \Core\controller\Controller. Klasa Controller odpowiada za
wywołanie odpowiedniej metody jednej z klas dziedziczących po klasie Controller na podstawie
parametrów żądania oraz informacji znajdującej się w tablicy routingu stanowiącej połączenie
tablic routingu wszystkich aktywnych modułów. Klasa Controller obsługuje dwa podstawowe typy
żądań:


żądania synchroniczne,
żądania asynchroniczne (ajax).
Typ żądania jest sprawdzany poprzez weryfikację zmiennej $_SERVER[‘http_X_REQUEST_WITH’].
Odnośniki do poszczególnych stron aplikacji są w formacie:
adres_serwera/index.php?url=link, gdzie link może mieć wartość np. 'adres',
'adres/adres2/adres3', 'adres/adres1'
Na pasku przeglądarki odnośniki mogą wyświetlać się w powyższym formacie lub też w formacie
przyjaznym użytkownikowi. W drugim przypadku w katalogu public musi się znaleźć plik
web.config zawierający kod z pliku web.config.standard (serwer IIS) lub plik .htaccess zawierający
kod z pliku htaccess.standard (serwer Apache) oraz w klasie \App\config\AppSettings stała
FRIENDLY_LINKS musi mieć wartość true. Odnośniki w takim wypadku mają format:
adres_serwera/adres/adres2 tłumaczone na adres_serwera/index.php?url=adres/adres2
W przypadku nadejścia żądania synchronicznego, gdy fragment tablicy routingu odpowiedzialny
za daną stronę zawiera informacje o klasie widoku to metoda kontrolera przyjmuje następujące
parametry:
17
$controllerObj->$methodName($post, $get, $viewParams, $additionalParameters);




$post – tablica POST,
$get – tablica GET,
$viewParams - tablica asocjacyjna zawierająca elementy przekazywane do szablonów
Smarty, klucze stanowią nazwy elementów natomiast wartości tablicy stanowią wartości
poszczególnych elementów,
$additionalParameters – tablica zawierająca dodatkowe elementy z wartości elementu url
tablicy
GET,
tzn.
jeśli
w
przeglądarce
zostanie
wywołany
adres
adres_serwera/index.php?url=adres/adres2/adres3/parametr1/parametr2, a w tablicy
routingu znajdzie się element address, który ma wartość adres/adres2/adres3 i
jednocześnie
nie
istnieje
element
address,
który
ma
wartość
adres/adres2/adres3/parametr1 lub wartość adres/adres2/adres3/parametr1/parametr2
to tablica $additionalParameters będzie zawierała pod indeksem 0 wartość parametr2,
natomiast pod indeksem 1 wartość parametr1.
Dodatkowo metoda musi zwracać tablicę $viewParams. W przypadku gdy nadejdzie żądanie
synchroniczne, a fragment tablicy routingu odpowiedzialny za daną stronę nie będzie zawierał
informacji o klasie widoku to metoda kontrolera przyjmuje następujące parametry:
$controllerObj->$methodName($post, $get, $additionalParameters);
W przypadku nadejścia żądania asynchronicznego z przekazaną tablicą POST (mechanizm AJAX)
to wywoływana metoda kontrolera przyjmuje następujące parametry:
$controllerObj->$methodName($post, $get, $additionalParameters);
Struktura tablicy POST przekazywanej w momencie wysłania żądania asynchronicznego jest z góry
ustalona i wygląda następująco:
array(
'data'
'request'
);
=> $data,
=> $request
Element $data stanowi tablicę asocjacyjną zawierającą właściwe dane przekazywane w żądaniu,
natomiast element $request stanowi identyfikator żądania, który określa to, która metoda
kontrolera powinna zostać wywołana w celu obsłużenia tego żądania (patrz tablica ajax w tablicy
routingu).
5.3.3.
Strona startowa aplikacji
Identyfikator strony, która domyślnie wyświetla się w momencie otwarcia aplikacji bez
podania dokładnego adresu do konkretnej strony, definiuje się w stałej MAIN_SITE_KEY, która
znajduje się w klasie \App\config\AppSettings.
5.4. Dołączanie do aplikacji zewnętrznych bibliotek PHP
Ścieżki do zewnętrznych bibliotek PHP, które dołączane są przez dany moduł definiuje się
w statycznej tablicy $additionalIncludeArr, która powinna znaleźć się w klasie
\<<nazwa_modułu>>\config\<<nazwa_modułu>>Routing, która musi dziedziczyć po klasie
\Core\config\Routing. W przypadku modułu Core jest to klasa \Core\config\CoreRouting. Klucze
tablicy stanowią nazwy klas, natomiast wartości stanowią tablice zawierające ścieżki do plików,
które zostaną dołączone w przypadku odwołania się do klasy z klucza tablicy. Początek każdej
ścieżki stanowi główny katalog aplikacji. Mechanizm dołączania plików znajduje się w pliku
18
public/autoload.php. Przykładowa tablica $additionalIncludeArr z modułu Core została
przedstawiona poniżej:
protected static $additionalIncludeArr = array(
'Smarty'
=> 'libs/Smarty-3.1.29/libs/Smarty.class.php',
'PHPMailer'
=> array(
'libs/PHPMailer5.2.14/class.phpmailer.php',
'libs/PHPMailer5.2.14/class.smtp.php'
),
'JavaScriptPacker'
=> 'libs/JavaScriptPacker/class.JavaScriptPacker.php'
);
Jeśli w aplikacji zbudowanej w oparciu o opisywany w niniejszej dokumentacji framework znajdzie
się tablica jak powyżej to poniższa linia kodu spowoduje załączenie plików o nazwach
class.phpmailer.php oraz class.smtp.php znajdujących się w katalogu libs/PHPMailer-5.2.14:
$phpMailer = new \PHPMailer();
W przypadku gdy z jakiegoś powodu konieczne okaże się dołączenie pliku z kodem PHP nie
zawierającym żadnej klasy to programista musi zrobić to ręcznie wykorzystując do tego funkcje
wbudowane w język PHP, takie jak include_once lub require_once.
5.5. Widok
Pierwszy element związany z widokiem aplikacji stanowi system szablonów Smarty. Ścieżki
do katalogów zawierających pliki *.tpl z szablonami definiuje się w plikach konfiguracyjnych
modułów w składowej $templateDir.
Drugi element związany z widokiem aplikacji stanowią klasy PHP. Każdą ze stron aplikacji
powinna reprezentować klasa zawierająca następujące składowe:


$siteName - zawiera nazwę strony lub grupy stron do której przyporządkowana jest dana
strona, wartość elementu może być na przykład wykorzystywana w oznaczaniu odnośnika
w menu, który dotyczy aktualnie wyświetlonej strony,
$templateName - zawiera nazwę pliku *.tpl z szablonem strony, w większości przypadków
wartość tego elementu jest taka sama jak wartość elementu $siteName.
Każda z tych klas powinna dziedziczyć po abstrakcyjnej klasie \Core\view\View odpowiedzialnej
za wyświetlenie odpowiedniego szablonu Smarty. Klasa ta posiada metodę
\Core\view\View::display(), która inicjalizuje zmienne, które później mogą być wykorzystywane
w kodzie szablonów. Klasy dziedziczące po klasie \Core\view\View mogą rozszerzać tę metodę w
celu inicjalizacji własnych zmiennych potrzebnych do wyświetlenia danej strony. Oprócz klasy
\Core\view\View z widokiem aplikacji ściśle związana jest klasa \Core\view\Link zawierająca
metodę statyczną \Core\view\Link::getLink() przyjmującą jako parametr identyfikator jednej ze
stron aplikacji stanowiący jednocześnie klucz z tablicy routingu (więcej na temat tablicy routingu
można znaleźć w rozdziale 5.3.1 Tablica routingu). Metoda ta zwraca odnośnik do strony w
formacie zależnym od wartości stałej FRIENDLY_LINKS z klasy \App\config\AppSettings.
Wykorzystywana jest ona zarówno bezpośrednio w kodzie PHP do tworzenia przekierowań jak i
w szablonach Smarty do generowania odnośników. Kolejną istotną klasę stanowi klasa o nazwie
Lang, która wykorzystywana jest do zapewnienia działania mechanizmów tłumaczenia witryny.
Zawiera ona między innymi metodę Lang::translate() która wykorzystywana jest w szablonach
Smarty do tłumaczenia tekstu. Więcej informacji na temat mechanizmu tłumaczeń aplikacji
można znaleźć w rozdziale 7 Mechanizm tłumaczenia witryny.
19
5.6. Baza danych
Do wykonywania wszystkich operacji na bazie danych wykorzystywana jest wbudowana w
PHP klasa PDO (PHP Data Objects). Framework obsługuje następujące systemy zarządzania
bazami danych:




MySQL,
MsSQL,
SQLite,
PgSQL.
Najważniejszą klasę framework’a związaną z obsługą bazy danych stanowi klasa
\Core\db\Database. Klasa ta zawiera publiczną, statyczną metodę Database::connect(), która
nawiązuje połączenie do bazy danych poprzez inicjalizację obiektu klasy PDO, a następnie zwraca
ten obiekt. Metoda przyjmuje następujące parametry:



$dbType – opcjonalny parametr stanowiący znacznik reprezentujący system zarządzania
bazami danych do którego ma zostać nawiązane połączenie. Obsługiwane znaczniki to:
sqlite, mysql, mssql oraz pgsql. W przypadku braku parametru połączenie nawiązywane
jest do systemu zarządzania bazami danych reprezentowanego przez znacznik podany w
stałej \App\config\AppSettings::DATABASE_TYPE.
$connectionId – opcjonalny parametr stanowiący identyfikator połączenia. Dzięki
zastosowaniu tego parametru można nawiązać kilka połączeń do tego samego systemu
zarządzania bazami danych.
$dbTypeConnectionInfoIndex – opcjonalny parametr stanowiący indeks z tablicy
przechowującej dane do połączenia do bazy danych pod którym znajdują się dane, które
należy wykorzystać podczas nawiązywania połączenia. Tablice zawierające dane do
połączenia do poszczególnych systemów zarządzania bazami danych znajdują się w klasie
\App\config\AppSettings
i
nazywają
się:
$sqliteDatabaseConnectArr,
$mysqlDatabaseConnectArr,
$mssqlDatabaseConnectArr
oraz
$pgsqlDatabaseConnectArr.
Klasa \Core\db\Database zawiera również publiczne metody umożliwiające rozpoczęcie
transakcji (Database::beginTransaction()), cofnięcie transakcji (Database::rollbackTransaction())
oraz zatwierdzenie transakcji (Database::commitTransaction()). Ostatnią publiczną metodą klasy
\Core\db\Database jest metoda Database::prepareNames(), która zastępuje w przekazanym w
parametrze $sql ciągu znaków elementy {prefix} oraz {sufix} na znaki, które powinny zostać użyte
przed oraz po nazwach tabel i kolumn. O tym jakie znaki zostaną wstawione decyduje wartość
drugiego parametru metody o nazwie $databaseType lub wartość stałej
\App\config\AppSettings::DATABASE_TYPE w przypadku gdy parametr $databaseType nie
zostanie przekazany. Dzięki tej metodzie można w kodzie aplikacji przygotować uniwersalne
polecenie SQL, które po podmianie ciągów znaków {prefix} oraz {sufix} będzie mogło zostać
wykorzystane na różnych typach bazy danych.
Drugą klasą z modułu Core związaną z obsługą bazy danych stanowi klasa \Core\db\Table.
Po tej klasie powinny dziedziczyć wszystkie klasy pisane w oparciu o wzorzec odpowiedzialny za
wykonywanie operacji na bazie danych, który wykorzystany został w module User. Wzorzec ten
polega na tworzeniu klas reprezentujących tabele w bazie danych. Każda z tych klas powinna
zawierać składowe reprezentujące kolumny tabeli wraz z metodami dostępowymi do tych
zmiennych (tak zwane gettery oraz settery) oraz dwie podstawowe metody. Pierwszą z nich jest
20
metoda statyczna o nazwie getRow() przyjmująca jako parametr identyfikator rekordu z tabeli
reprezentowanej przez daną klasę i zwracająca obiekt tej klasy z uzupełnionymi wartościami
zmiennych reprezentujących kolumny tego rekordu. Drugą metodę stanowi metoda wywoływana
na rzecz obiektu klasy o nazwie save() zapisująca w bazie rekord reprezentowany przez ten obiekt.
Metoda przyjmuje jako parametr nazwę wykonywanej na bazie operacji:


insert – w przypadku gdy metoda ma wstawić nowy rekord,
update – w przypadku gdy metoda ma zaktualizować istniejący rekord.
W zależności od potrzeb, klasy pisane w oparciu o ten wzorzec mogą posiadać również inne
metody umożliwiające na przykład pobranie rekordu w oparciu o inną kolumnę niż metoda
getRow(), pobraniu tablicy rekordów czy też zwrócenie tablicy asocjacyjnej zawierającej dane
przechowywane w obiekcie na rzecz którego metoda została wywołana.
5.7. Elementy frontend’u
5.7.1.
Przenoszenie elementów frontend’u z katalogu modułu do katalogu public
Wszystkie elementy frontend’u modułu, czyli wszystkie elementy wyświetlane lub
przetwarzane w przeglądarce użytkownika, takie jak pliki z kodem JavaScript, pliki z kodem CSS,
obrazki oraz czcionki powinny znajdować się w podkatalogach katalogu frontend znajdującego się
bezpośrednio w katalogu modułu. Framework posiada mechanizm umożliwiający automatyczne
przeniesienie tych elementów z katalogów modułów do odpowiednich podkatalogów katalogu
public. Mechanizm ten opiera się o stałą \App\config\AppSettings::COPY_FRONTEND_FILES. W
przypadku gdy ta stała ma wartość true oraz aplikacja jest w trybie developerskim (stała
\App\config\AppSettings::ENVIRONMENT_TYPE ma wartość dev) to przed obsługą każdego
synchronicznego żądania, które przychodzi do aplikacji dla każdego podkatalogu katalogu
frontend wszystkich aktywnych modułów wykonywana jest następująca operacja (należy przy
tym pamiętać że moduły Core oraz App są domyślnie aktywne):

Cała zawartość katalogu src/<<nazwa_modułu>>/frontend/<<katalog>>/ jest kopiowana
do katalogu public/<<katalog>>/<<nazwa_modułu>>/.
Dodatkowo w klasie AppSettings znajduje się tablica $copyFrontendException, w której można
podać nazwy podkatalogów katalogu frontend, które nie mają być kopiowanie do katalogu public.
W przypadku gdy kopiowany plik już istnieje w katalogu docelowym to jest on
nadpisywany. Opisywany mechanizm ma celu zagwarantowanie tego aby cała struktura plików
oraz katalogów związanych z danym modułem znalazła się w jednym katalogu. Ma to ułatwić
pracę programiście i wyeliminować potrzebę skakania pomiędzy różnymi katalogami w celu edycji
plików związanych z tym samym modułem. Dodatkowo w znacznym stopniu upraszcza to proces
aktualizacji modułu.
5.7.2.
Kod JavaScript
5.7.2.1. Wstęp
W module Core znajduje się kilka zewnętrznych bibliotek JavaScript stanowiących
integralną część framework’a oraz kilka uniwersalnych obiektów odpowiedzialnych między
innymi za wyświetlanie użytkownikowi komunikatów czy też za obsługę żądań AJAX. Struktura
katalogów zawierających pliki z kodem JavaScript modułu przedstawiona została na Rysunku 5.2.
21
5.7.2.2. Struktury klaso podobne
Dzięki zastosowaniu biblioteki Class znajdującej
się w pliku src/Core/frontend/js/libs/class/Class.js
można w języku JavaScript tworzyć struktury klaso
podobne, które zawierają pola oraz metody i mogą po
sobie dziedziczyć analogicznie jak dzieje się to w języku
PHP. W celu zdefiniowania klasy należy wykorzystać
metodę Class.define(), która przyjmuje dwa parametry
stanowiące:


nazwę klasy,
obiekt zawierający składowe i metody klasy w
tym opcjonalnie nazwę klasy po której
dziedziczy definiowana klasa.
Dodatkowo możliwe jest tworzenie konstruktorów
poprzez zdefiniowanie w klasie metody o nazwie init.
Przykładowy kod odpowiedzialny za zdefiniowanie
klasy o nazwie UserSite, która dziedziczy po klasie Site
wygląda następująco:
Class.define('UserSite', {
/**
* Nazwa klasy po której dziedziczy klasa
UserSite.
*/
extend: 'Site',
/**
* Metoda wyświetlająca animację ładowania.
*/
showLoadingAnimation: function()
{
$('.formCurtain').show();
$('#errorInfo').hide().next().hide().next().show();
},
/**
* Konstruktor.
*/
init: function()
{
this.callMethod('Site', 'init');
}
});
Rysunek 5.2
Klasa zdefiniowana w powyższym kodzie posiada metodę o nazwie init, która stanowi konstruktor
klasy i jest automatycznie wywoływana podczas tworzenia obiektu klasy. Wewnątrz metody jest
wywoływana metoda init z klasy Site czyli klasy po której dziedziczy definiowana tu klasa UserSite.
Kod odpowiedzialny za utworzenie obiektu klasy UserSite wygląda następująco:
var userSiteObj = Class.create('UserSite');
Ostatnim istotnym mechanizmem biblioteki Class jest możliwość weryfikacji tego czy dany obiekt
stanowi instancję podanej klasy. Odbywa się to za pomocą metody Class.is():
var result = Class.is('Site', userSiteObj);
Zmienna result po wykonaniu powyższego kodu będzie zawierać wartość true, ponieważ obiekt
userSiteObj stanowi instancję klasy UserSite, która dziedziczy po klasie Site.
22
5.7.2.3. Message.js
W pliku src/Core/frontend/js/src/message/Message.js znajduje się obiekt odpowiedzialny
za mechanizmy związane z przechowywaniem komunikatów wykorzystywanych w kodzie
JavaScript. Obiekt zawiera metodę Message.getMsg() zwracającą tekst na podstawie
identyfikatora tekstu oraz typu tekstu. Metoda przyjmuje również trzeci, opcjonalny parametr
stanowiący nazwę obiektu, w którym znajduje się komunikat. W przypadku gdy parametr nie
zostanie przekazany to tekst wyszukiwany jest w obiekcie Message oraz we wszystkich obiektach
o nazwach znajdujących się w tablicy Message.msgObjects. W celu dodania nazwy obiektu do tej
tablicy należy skorzystać z metody Message.registerMsgObject(). Poniżej został przedstawiony
przykładowy obiekt przechowujący komunikaty:
var UserMessage =
{
errors: {
'emptyEmail': {
'pl': 'Adres email nie może być pusty.',
'en': 'E-mail address can not be empty.'
}
},
confirms: {
'modifyAccount': {
'pl': 'Operacja modyfikowania danych użytkownika przebiegła prawidłowo.',
'en': 'Operation modifying user data is dealt with correctly.'
},
'successGetUserData': {
'pl': 'Dane użytkownika zostały pobrane prawidłowo.',
'en': 'User data were collected properly.'
}
},
userListHeaders: {
'email': {
'pl': 'E-mail',
'en': 'E-mail'
}
},
questions: {
'removeUser': {
'pl': {
'title': 'Usuwanie użytkownika',
'text': 'Jesteś pewien że chcesz usunąć użytkowników o następujących
adresach email: {0}?'
},
'en': {
'title': 'Deleting a user',
'text': 'Are you sure you want to remove users with the following email
addresses: {0}?'
}
}
}
};
Poniżej została przedstawiona przykładowa zawartość tablicy Message.msgObjects:
msgObjects: ['ModuleCreatorMessage', 'UserMessage']
W sytuacji gdy zawartość tablicy Message.msgObjects jest taka jak ta przedstawiona powyżej oraz
w szablonie aplikacji został załączony plik z obiektem UserMessage w takiej formie jak obiekt
przedstawiony powyżej to aby pobrać w kodzie na przykład komunikat o treści „Dane użytkownika
zostały pobrane prawidłowo.” należy wywołać metodę Message.getMsg() na jeden z dwóch
poniższych sposobów.
Message.getMsg('modifyAccount', 'confirms');
Message.getMsg('modifyAccount', 'confirms', 'UserMessage');
5.7.2.4. ErrorHandler.js
23
Obiekt
ErrorHandler
znajdujący
się
w
pliku
src/Core/frontend/js/src/message/ErrorHandler.js odpowiada za działanie mechanizmu
wyświetlania użytkownikowi komunikatów z błędami. Najważniejszą metodę obiektu stanowi
metoda ErrorHandler.showError() odpowiedzialna za wyświetlenie komunikatu z błędem. Poniżej
została przedstawiona lista parametrów przekazywanych do metody:





error – identyfikator błędu lub obiekt Error lub obiekt AppException. W przypadku gdy jako
parametr zostanie przekazany obiekt Error lub obiekt AppException to jako identyfikator
błędu brana jest składowa message tego obiektu. Identyfikator błędu powinien znaleźć się
w obiekcie zawierającym teksty wyświetlane użytkownikowi, więcej informacji na ten
temat można znaleźć w poprzednim rozdziale.
msgObject – opcjonalny parametr stanowiący nazwę obiektu w którym znajduje się
komunikat błędu, więcej informacji na ten temat można znaleźć w poprzednim rozdziale.
varArr – opcjonalny parametr stanowiący tablicę zawierającą ciągi znaków podstawione
pod specjalne elementy w komunikacie błędu. Elementy pod które podstawiane są
elementy z tablicy są w formacie: {0}, {1} itd.
alternativeHideFunc – opcjonalny parametr stanowiący funkcję wywoływaną w momencie
zamykania okna z błędem.
focusFunc – opcjonalny parametr stanowiący funkcję wywoływaną w momencie
wystąpienia zdarzenia zamykania okna z błędem za pomocą przycisku Esc oraz podczas
wystąpienia zdarzenia mouseup na przycisku zamykania okna. Funkcja przeznaczona jest
do ustawiania focusa na polu formularza którego dotyczy wyświetlany błąd.
5.7.2.5. MessageHandler.js
Obiekt
MessageHandler
znajdujący
się
w
pliku
src/Core/frontend/js/src/message/MessageHandler.js odpowiada za wyświetlanie komunikatów
na przykład potwierdzających wykonaną operację. Najważniejszą metodą obiektu jest metoda
MessageHandler.showMsg() odpowiedzialna za wyświetlenie komunikatu. Pierwszy parametr
stanowi identyfikator komunikatu. Kolejne trzy parametry są takie same jak drugi, trzeci oraz
czwarty parametr metody ErrorHandler.showError() opisanej w poprzednim rozdziale.
5.7.2.6. ConfirmQuestionHandler.js
Obiekt
ConfirmQuestionHandler
znajdujący
się
w
pliku
src/Core/frontend/js/src/message/ConfirmQuestionHandler.js odpowiada za wyświetlanie pytań
potwierdzających chęć wykonania przez użytkownika wybranej akcji. Najważniejszą metodę
obiektu stanowi metoda ConfirmQuestionHandler.showQuestion() odpowiedzialna za
wyświetlanie pytania potwierdzającego. Pierwszy parametr stanowi identyfikator pytania.
Kolejne dwa parametry metody są takie same jak drugi oraz trzeci parametr metody
ErrorHandler.showError() opisanej w rozdziale 5.7.2.4 ErrorHandler.js. Natomiast ostatnie dwa
parametry stanowią funkcje wywoływane w przypadku potwierdzenia oraz anulowania operacji.
5.7.2.7. Data.js
Obiekt Data znajdujący się w pliku src/Core/frontend/js/src/Data.js odpowiada za
wysyłanie żądań asynchronicznych na serwer. Należy w tym celu skorzystać z metody
Data.ajaxRequest(), w której wykorzystywana jest wbudowana w bibliotekę jQuery funkcja Ajax.
Metoda przyjmuje następujące parametry:
24









address – adres, na który ma zostać wysłane żądanie. W większości przypadków żądanie
powinno być wysyłane na adres aktualnie otwartej strony. W takim wypadku jako parametr
należy przekazać wartość window.location.href.
dataType – typ danych zwracanych przez serwer jako odpowiedź na żądanie. W większości
przypadków należy przekazać wartość json.
data – dane przesyłane na serwer. W metodzie kontrolera odpowiedzialnej za obsługę
żądania dane te są dostępne w tablicy $post pod kluczem data.
request – typ żądania. Typ żądania musi się znaleźć w tablicy routingu, więcej informacji na
temat tablicy routingu można znaleźć w rozdziale 5.3.1 Tablica routingu.
obj – obiekt przekazywany do funkcji beforeSendFunction oraz completeFunction.
Dodatkowo obiekt ten jest również przekazywany do funkcji successFunction oraz
errorFunction jako składowa thisObj obiektu przekazywanego jako parametr tych funkcji.
successFunction – metoda wywoływana w przypadku otrzymania odpowiedzi na żądanie
gdy zwrócony w odpowiedzi na żądanie obiekt w składowej result zawiera ciąg znaków true.
Jako parametr funkcji przekazywany jest zwrócony w odpowiedzi obiekt. Dodatkowo do
tego obiektu dodawana jest składowa thisObj zawierająca opisywany w poprzednim
punkcie parametr obj.
errorFunction – metoda wywoływana w przypadku gdy podczas wysyłania żądania wystąpił
błąd oraz w przypadku gdy otrzymana została odpowiedź na żądanie, ale w zwróconym
obiekcie w składowej result znajduje się inna wartość niż ciąg znaków true. Jako parametr
funkcji przekazywany jest zwrócony obiekt. Dodatkowo do tego obiektu dodawana jest
składowa thisObj zawierająca opisywany w poprzednim punkcie parametr obj.
beforeSendFunction – metoda wywoływana przed wysłaniem żądania. W większości
przypadków jest to metoda wyświetlająca animację ładowania.
completeFunction – metoda wywoływana po zakończeniu przetwarzania żądania. W
większości przypadków jest to metoda ukrywająca animację ładowania.
Wykorzystanie metody Data.ajaxRequest() gwarantuje to, że struktura danych przesyłanych w
żądaniach Ajax będzie wyglądać tak jak poniżej:
{
data: data, //obiekt zawierający przesyłane dane
request: request //identyfikator żądania, znajdujący się w tablicy ajax w tablicy
routingu
}
5.7.2.8. Table.js
W pliku src/Core/frontend/js/src/Table.js znajduje się funkcja zwracająca obiekty
odpowiedzialne za generowanie interaktywnych tabel zawierających dane pobierane z serwera.
Poniżej została przedstawiona lista najważniejszych funkcjonalności jakie mogą posiadać
generowane tabele:






wyszukiwanie rekordów po wszystkich kolumnach,
filtrowanie rekordów po pojedynczych kolumnach, filtrowanie może odbywać się za
pomocą zwykłych pól tekstowych lub za pomocą list rozwijanych,
sortowanie po kolumnach,
zaznaczanie rekordów,
stronicowanie,
możliwość podpięcia dowolnej funkcji pod zdarzenie podwójnego kliknięcia w rekord
tabeli.
25
5.7.2.9. JsRenderLoader.js
Obiekt JsRenderLoader.js zawiera mechanizm umożliwiający pobranie, za pomocą
technologii AJAX, szablonów JsRender6 i wygenerowanie na podstawie tych szablonów oraz
przekazanych do nich obiektów, kodu HTML.
Pliki z szablonami JsRender powinny być przechowywane w katalogu
src/<<nazwa_modułu>>/templates/jsrender_templates/. Aby korzystać z opisywanego w tym
podrozdziale obiektu należy w pierwszym kroku go zainicjalizować za pomocą metody
JsRenderLoader.init(). Metoda ta jako parametry przyjmuje dwa obiekty zawierające referencje
do funkcji odpowiedzialnych za wyświetlenie animacji ładowania przed wysłaniem żądania
pobrania szablonu JsRender oraz za ukrycie animacji ładowanie po otrzymaniu odpowiedzi na
wysłane żądanie. Po zainicjalizowaniu obiektu, w celu pobrania szablonu i wygenerowania na jego
podstawie kodu HTML należy wywołać poniższą metodę:
JsRenderLoader.getAndRenderTemplate(templateInfo, doneFunc, additionalParam)
Metoda przyjmuje trzy parametry:



templateInfo – obiekt lub tablica obiektów reprezentujących pobierane szablony. Każdy z
obiektów powinien zawierać poniższe składowe:
o module – nazwa modułu, w którym znajduje się pobierany szablon.
o dir – ścieżka do katalogu zawierającego szablon począwszy od katalogu
src/<<nazwa_modułu>>/templates/jsrender_templates/. W przypadku gdy obiekt
nie będzie posiadać tej składowej lub gdy składowa będzie przechowywać pusty ciąg
znaków to szablon powinien znajdować się bezpośrednio w katalogu
src/<<nazwa_modułu>>/templates/jsrender_templates/.
o file – nazwa pliku z pobieranym szablonem bez rozszerzenia. Plik powinien mieć
rozszerzenie *.tmpl.
o data – opcjonalna składowa zawierająca dane potrzebne do wygenerowania kodu
HTML na podstawie pobranego szablonu.
o helper – opcjonalna składowa zawierająca dodatkowe dane wykorzystywane do
utworzenia kodu HTML na podstawie pobranego szablonu.
doneFunc – funkcja wywoływana po pobraniu szablonu i wygenerowaniu na jego
podstawie kodu HTML. Funkcja powinna przyjmować tyle parametrów ile obiektów zostało
przekazanych w parametrze templateInfo. Każdy z tych parametrów stanowi
wygenerowany na podstawie szablonu kod HTML.
additionalParam – opcjonalny parametr przekazywany jako ostatni parametr do funkcji
doneFunc.
5.7.2.10. AppException.js
W pliku src/Core/frontend/js/src/AppException.js znajduje się konstruktor obiektów
wykorzystywanych podczas wyrzucania wyjątków z różnego rodzaju błędami w kodzie JavaScript.
Mogą to być na przykład błędy związane z podaniem przez użytkownika nieprawidłowych danych
w formularzu. Z konstruktora AppException korzysta się analogicznie jak z wbudowanego w język
JavaScript konstruktora Error7. Poniżej został przedstawiony przykładowy fragment kodu
prezentujący sposób wykorzystania konstruktora AppException:
...
6
7
https://www.jsviews.com/#jsrapi
https://developer.mozilla.org/pl/docs/Web/JavaScript/Referencje/Obiekty/Error
26
try
{
var selectedRow = this.usersListObj.tableObj.getSelectedRow();
if (selectedRow === null)
{
throw new AppException('mustSelectOneRow');
}
}
catch (error)
{
AppErrorHandler.showError(error);
}
...
5.7.2.11. Utils.js
W pliku src/Core/frontend/js/src/Utils.js znajduje się funkcja zawierająca różnego rodzaju
uniwersalne metody, które mogą być wykorzystywane w różnych modułach aplikacji.
27
6. Moduł App 2.01
6.1. Wstęp
Moduł App, podobnie jak opisywany w poprzednim rozdziale moduł Core, stanowi
integralną część framework’a i jest domyślnie aktywny. Stanowi on swojego rodzaju trzon
aplikacji zawierający klasę z wszystkimi podstawowymi ustawieniami (klasa
\App\config\AppSettings), dwie strony odpowiedzialne za wyświetlenie nieoczekiwanego błędu i
błędu 404 oraz szablon layout.tpl stanowiący główny szablon aplikacji, po którym powinny
dziedziczyć wszystkie pozostałe szablony. Dodatkowo w module znajdują się style CSS związane z
elementami wymienionych szablonów oraz obiekt Translation.js odpowiedzialny za działanie
mechanizmów przełączania wersji językowych aplikacji i klasa Site.js odpowiedzialna za
inicjalizację działania aplikacji po stronie przeglądarki użytkownika.
Pierwszy krok podczas pisania aplikacji w oparciu o niniejszy framework powinna stanowić
modyfikacja tego modułu, począwszy od ustawienia odpowiedniej konfiguracji w klasie
\App\config\AppSettings, a kończąc na modyfikacji szablonów i styli modułu.
6.2. Konfiguracja aplikacji
6.2.1.
Wstęp
Ustawienia związane z działaniem aplikacji znajdują się w klasie \App\config\AppSettings.
Klasa ta dziedziczy po klasie \Core\config\Settings zawierającej dwie metody. Pierwsza metoda
Settings::get() umożliwia pobranie wartości prywatnej składowej klasy z ustawieniami. Druga
metoda Settings::exist() umożliwia sprawdzenie istnienia prywatnej składowej klasy z
ustawieniami. Dodatkowo sama klasa \App\config\AppSettings również zawiera dwie metody.
Pierwsza z nich o nazwie AppSettings::moduleIsOn() umożliwia sprawdzenie czy moduł o nazwie
przekazanej
w
parametrze
jest
aktywny.
Druga
z
nich
o
nazwie
AppSettings::setDatabaseConnectArr() umożliwia ustawienie danych do połączenia do bazy
danych.
Metoda
umożliwia
zmodyfikowanie
zmiennych
AppSettings::$sqliteDatabaseConnectArr,
AppSettings::$mysqlDatabaseConnectArr,
AppSettings::$mssqlDatabaseConnectArr oraz AppSettings::$pgsqlDatabaseConnectArr.
Pierwszym krokiem jaki należy wykonać podczas pisania aplikacji jest ustawienie wartości
składowych klasy ustawień opisanych w kolejnych podrozdziałach.
6.2.2.
APP_VERSION
Stała
przechowująca
wersję
aplikacji.
W
przypadku
gdy
stała
SHOW_APP_VERSION_IN_TITLE ma wartość true to wersja aplikacji jest wyświetlana w tytule
każdej strony aplikacji. Dodatkowo wersja aplikacji może być wyświetlona w szablonach Smarty
poprzez automatycznie tworzoną przez mechanizmy framework’a zmienną $appVersion.
6.2.3.
APP_NAME
Nazwa tworzonej w oparciu o niniejszy framework aplikacji. Nazwa może być
wykorzystywana na przykład w wiadomościach email wysyłanych przez inne moduły aplikacji.
Dodatkowo nazwa aplikacji jest przekazywana do szablonów Smarty poprzez automatycznie
tworzoną przez mechanizmy framework’a zmienną $appName.
28
6.2.4.
APP_CREATION_YEAR
Rok powstania aplikacji wykorzystywany do utworzenia i wyświetlenia w stopce ciągu
znaków: Copyright © rok_utworzenia_aplikacji – aktualny_rok lub Copyright © rok_utworzenia,
gdy rok utworzenia == aktualny rok. Do wyświetlenia zakresu lat w szablonach Smarty
wykorzystywana jest automatycznie tworzona przez framework zmienna $copyrightYears.
6.2.5.
$templateDir
Zmienna zawierająca ścieżkę lub tablicę ścieżek od katalogu modułu App (src/App/) do
katalogów z szablonami Smarty modułu App. Należy pamiętać o tym że szablony Smarty modułu
App muszą znajdować się bezpośrednio w katalogach wskazywanych przez te ścieżki, nie mogą
znaleźć się w żadnym niewskazanym bezpośrednio podkatalogu.
6.2.6.
ENVIRONMENT_TYPE
Środowisko pracy aplikacji (dev – środowisko developerskie, prod – środowisko
produkcyjne). W przypadku gdy ustawione jest środowisko developerskie to błędy PHP
wyświetlane są na ekranie przeglądarki oraz w konsoli przeglądarki wyświetlane są przechwycone
wyjątki JavaScript i błędy zwrócone jako odpowiedź na żądania asynchroniczne AJAX. Dodatkowo
ustawienie środowiska developerskiego jest konieczne do tego aby móc uruchomić mechanizm
kopiowania plików z kodem JavaScript, z kodem CSS, z czcionkami oraz z obrazkami poprzez
ustawienie wartości true stałej COPY_FRONTEND_FILES. Więcej informacji na temat tego
mechanizmu znajduje się w rozdziale 5.7.1 Przenoszenie elementów frontend’u z katalogu
modułu do katalogu public.
6.2.7.
MAIN_SITE_KEY
Identyfikator strony z tablicy routingu reprezentujący domyślną stronę startową aplikacji.
6.2.8.
FRIENDLY_LINKS
Znacznik określający to czy aplikacja korzysta z przyjaznych linków w formacie:
adres_serwera/link/ (wartość true), czy też korzysta z linków w formacie:
adres_serwera/index.php?url=link (wartość false). Należy pamiętać o tym aby w przypadku gdy
aplikacja ma korzystać z przyjaznych linków w katalogu public umieścić odpowiedni plik
web.config dla serwera IIS lub plik .htaccess dla serwera Apache. Zawartość dla pliku web.config
znajduje się w pliku web.config.standard w katalogu public aplikacji. Natomiast zawartość dla
pliku .htaccess znajduje się w pliku htaccess.standard.
6.2.9.
COPY_FRONTEND_FILES
Znacznik określający to czy pliki frontend’u (wszystkie pliki wyświetlane lub przetwarzane
przez przeglądarkę użytkownika takie jak na przykład pliki z kodem JavaScript, z kodem CSS,
obrazki oraz czcionki) mają być kopiowane z podkatalogów katalogu frontend modułów do
katalogu
public.
Pliki
kopiowane
są
według
następującej
reguły:
src/<<nazwa_modułu>>/frontend/<<katalog>>/*
do
katalogu
public<<katalog>>/<<nazwa_modułu>>/*. Operacja kopiowania przeprowadzana jest podczas
przetwarzania każdego żądania synchronicznego. Jeśli stała ma wartość true to aby pliki były
kopiowane stała ENVIRONMENT_TYPE musi mieć wartość dev. Więcej informacji na temat tego
mechanizmu można znaleźć w rozdziale 5.7.1 Przenoszenie elementów frontend’u z katalogu
modułu do katalogu public.
29
6.2.10. $copyFrontendException
Tablica zawierająca nazwy podkatalogów katalogu frontend, które nie mają być kopiowane
z
aktywnych
modułów
aplikacji
do
katalogu
public
(patrz
stała
AppSettings::COPY_FRONTEND_FILES). Więcej informacji na temat tego mechanizmu można
znaleźć w rozdziale 5.7.1 Przenoszenie elementów frontend’u z katalogu modułu do katalogu
public.
6.2.11. SESSION_KEY
Klucz wykorzystywany do tworzenia tablicy $_SESSION oraz $_COOKIE. Dzięki zastosowaniu
tego klucza można uruchomić więcej niż jedną aplikację działającą w oparciu o opisywany
framework na tej samej domenie ale na innym porcie. Konieczność zastosowania w takim
przypadku tego klucza wynika z tego że zmienne $_SESSION oraz $_COOKIE są wspólne dla danej
domeny.
6.2.12. REMEMBER_LAST_SITE
Znacznik określający to czy aplikacja ma zapamiętywać za pomocą plików COOKIES ostatnio
otwartą stronę. W sytuacji gdy wartość stałej wynosi true to w przypadku obsługi żądania
synchronicznego mającego na celu wyświetlenie jednej ze stron aplikacji w metodzie
\Core\controller\Controller::routing() w COOKIES zapisywana jest wartość z parametru url
przekazanego podczas wysyłania żądania. W przypadku gdy parametr url nie został przekazany
podczas wysyłania żądania to sprawdzane jest istnienie adresu ostatnio otwartej strony w
COOKIES. Jeśli adres istnieje to wyświetlana jest właśnie strona o tym adresie. W przeciwnym
przypadku wyświetlana jest strona reprezentowana przez identyfikator z tablicy routingu podany
w stałej AppSettings::MAIN_SITE_KEY.
6.2.13. TITLE_SITE_PREFIX
Stała przechowująca ciąg znaków, który jest dodawany na początku tytułu każdej strony.
6.2.14. TITLE_SITE_SUFIX
Stała przechowująca ciąg znaków, który jest dodawany na końcu tytułu każdej strony.
6.2.15. SHOW_APP_VERSION_IN_TITLE
Znacznik określający to czy wersja aplikacji ma zostać wyświetlona na końcu tytułu każdej
strony.
6.2.16. TRANSLATIONS_HANDLING
Znacznik określający to czy aplikacja obsługuje wiele języków. Więcej informacji na temat
tworzenia aplikacji działającej w wielu językach można znaleźć w rozdziale 7 Mechanizm
tłumaczenia witryny.
6.2.17. DEFAULT_LANGUAGE
Znacznik określający domyślny język aplikacji. Znacznik powinien się również znaleźć w
tablicy AppSettings::$availableLang. Element wymagany w przypadku gdy stała
TRANSLATIONS_HANDLING ma ustawioną wartość true.
30
6.2.18. $availableLang
Tablica zawierająca znaczniki reprezentujące dostępne wersje językowe aplikacji. Element
wymagany w przypadku gdy stała AppSettings::TRANSLATIONS_HANDLING ma ustawioną
wartość true.
6.2.19. $modules
Tablica zawierająca nazwy aktywnych modułów aplikacji z wyłączeniem modułów Core oraz
App. Moduły Core oraz App są domyślnie aktywne i nie można ich dezaktywować.
6.2.20. DATABASE_TYPE
Typ domyślnej bazy danych aplikacji. Dozwolone wartości to: sqlite, mysql, mssql oraz
pgsql. Z typem bazy danych ściśle związane są tablice zawierające informacje potrzebne do
nawiązania połączenia do bazy danych: AppSettings::$sqliteDatabaseConnectArr,
AppSettings::$mysqlDatabaseConnectArr,
AppSettings::$mssqlDatabaseConnectArr
oraz
AppSettings::$pgsqlDatabaseConnectArr. Więcej informacji na temat sposobu komunikacji z bazą
danych można znaleźć w rozdziale 5.6 Baza danych.
6.2.21. $mailData
Tablica zawierająca dane potrzebne do wysyłania wiadomości email. Dane te są
wykorzystywane w metodzie \Core\utils\Mail::sendEmail().
6.3. Widok
W
module
App
szablony
Smarty
przechowywane
są
w
katalogu
src/App/templates/templates/. Struktura plików z szablonami opiera się na szablonie layout.tpl.
Jest to główny szablon zawierający szkielet struktury html stron aplikacji. Wszystkie szablony
reprezentujące poszczególne strony aplikacji powinny dziedziczyć pośrednio lub bezpośrednio po
tym szablonie. Dziedziczenie szablonów opiera się na blokach. To znaczy w szablonie nadrzędnym
o nazwie na przykład parent.tpl definiuje się blok tak jak w kodzie poniżej:
...
<div id="bodyContent">
{block name=content}{/block}
</div>
...
Następnie tworzy się szablon podrzędny, którego kod może wyglądać następująco:
{extends file="parent.tpl"}
{block name=content}
{strip}
<p>Zawartość szablonu podrzędnego</p>
{/strip}
{/block}
W szablonie podrzędnym znajduje się zawartość bloku content, który został zdefiniowany w
szablonie nadrzędnym. Więcej informacji na temat tego w jaki sposób korzystać z mechanizmu
bloków można znaleźć w dokumentacji systemu szablonów Smarty8.
8
http://www.smarty.net/docs/en/language.function.block.tpl
31
W module App oprócz szablonu layout.tpl znajduje się również szablon strony z
nieoczekiwanym błędem o nazwie error.tpl oraz szablon strony z błędem 404 o nazwie
error404.tpl, wyświetlanym w przypadku próby przejścia pod nieprawidłowy adres strony. Poniżej
znajduje się prosty diagram przedstawiający strukturę dziedziczenia szablonów wchodzących w
skład modułu App:
Rysunek 6.1
Jako że moduł App udostępnia dwie strony (strona z nieoczekiwanym błędem oraz strona
z błędem 404) to znaleźć w nim można dwie klasy reprezentujące te strony. Klasy te o nazwach
Error404View oraz UnexpectedErrorView znajdują się w katalogu src/App/view/error/.
6.4. Elementy frontend’u
6.4.1.
Kod CSS
Style CSS zawarte w module App dotyczą albo znaczników HTML znajdujących się
bezpośrednio w szablonach tego modułu albo znaczników HTML znajdujących się w szablonach
wchodzących w skład więcej niż jednego modułu. Pliki z kodem CSS znajdują się w katalogu
src/App/frontend/css.
6.4.2.
Kod JavaScript
6.4.2.1. Wstęp
W module App w katalogu src/App/frontend/js/src/ znaleźć można dwa pliki z kodem
JavaScript. Pierwszy z nich zawiera klasę Site odpowiedzialną za inicjalizację aplikacji po stronie
klienta, opisaną szerzej w rozdziale 6.4.2.2 Site.js. Drugi z nich zawiera obiekt Translation
odpowiedzialny za działanie mechanizmu przełączania wersji językowej witryny w momencie
wystąpienia zdarzenia kliknięcia w odpowiedni przycisk znajdujący się w nagłówku strony.
6.4.2.2. Site.js
Przyjęto założenie że każda strona aplikacji pisanych w oparciu o niniejszy framework
będzie posiadać reprezentującą ją klasę napisaną w języku JavaScript. Klasa ta powinna zawierać
podstawowe zdarzenia związane z daną stroną i powinna dziedziczyć po klasie Site znajdującej się
w pliku src/App/frontend/js/src/Site.js. Dodatkowo każda z klas dziedziczących po klasie Site
powinna w swoim konstruktorze (metoda init) wywoływać konstruktor klasy Site. Na każdej ze
stron powinien być tworzony obiekt klasy reprezentującej daną stronę.
Trzymanie się ściśle tego założenia nie jest wymagane, jednakże w przypadku gdy dana
strona nie posiada reprezentującej ją klasy to na tej stronie należy utworzyć obiekt klasy Site. Ma
to na celu wywołanie konstruktora tej w klasy, w którym przeprowadzane są następujące
operacje:
32












Inicjalizacja
zmiennych
typu
bool
o
nazwach:
jQuery.browser.mozilla,
jQuery.browser.webkit, jQuery.browser.opera oraz jQuery.browser.msie dzięki którym
można zweryfikować typ przeglądarki użytkownika.
Weryfikacja czy przeglądarka użytkownika to Internet Explorer i jeśli tak to sprawdzenie
wersji tej przeglądarki. W przypadku gdy wersja jest mniejsza niż 9 to wyświetlany jest
komunikat o tym że aplikacja nie obsługuje tej wersji przeglądarki.
Inicjalizacja obiektu ErrorHandler odpowiedzialnego za wyświetlanie okien z błędami
(patrz rozdział 5.7.2.4 ErrorHandler.js).
Inicjalizacja obiektu ConfirmQuestionHandler odpowiedzialnego za wyświetlanie okien z
pytaniami potwierdzającymi (patrz rozdział 5.7.2.6 ConfirmQuestionHandler.js).
Inicjalizacja obiektu MessageHandler odpowiedzialnego za wyświetlanie okien z
komunikatami (patrz rozdział 5.7.2.5 MessageHandler.js).
Sprawdzenie czy aplikacja obsługuje wiele języków. Jeśli tak to inicjalizowany jest obiekt
Translation.
Wywołanie funkcji tooltip() dodającej zdarzenie wyświetlania okienek tooltip po
najechaniu kursorem myszy na elementy dokumentu html mające ustawiony atrybut datatitle. W okienku wyświetlany jest tekst stanowiący wartość tego atrybutu.
Wyświetlenie zawartości strony. Wyświetlanie strony z poziomu kodu JavaScript ma na
celu zagwarantowanie tego że w przypadku gdy przeglądarka użytkownika ma wyłączoną
obsługę języka JavaScript to wyświetlony zostanie tylko komunikat znajdujący się w
szablonie layout.tpl wewnątrz znacznika <noscript>.
Dodanie zdarzenia wyświetlenia menu w momencie kliknięcia w przycisk wyświetlany dla
mobilnej wersji strony.
Dodanie zdarzeń mających na celu zagwarantowanie tego że w sytuacji gdy wysyłane
żądanie AJAX zostanie przerwane poprzez kliknięcie w odnośnik do innej strony lub
poprzez przeładowanie strony to nie spowoduje to wyświetlenia informacji o wystąpieniu
nieoczekiwanego błędu.
Ustawienie odpowiedniej szerokości menu rozwijanego. Menu jest rozwijane po
najechaniu na przycisk zawierający adres email stanowiący login użytkownika.
Na koniec w przypadku gdy w aplikacji aktywny jest moduł ClientInfoRegister to
uruchamiany jest mechanizm odpowiedzialny za wysyłanie co pięć minut żądania zapisania
w bazie informacji dotyczących adresu ip oraz przeglądarki użytkownika.
33
7. Mechanizm tłumaczenia witryny
W oparciu o opisywany w niniejszym dokumencie framework można tworzyć aplikacje
internetowe działające w kilku wersjach językowych. Pierwszym krokiem w tym celu jest
ustawienie odpowiednich składowych klasy \App\config\AppSettings. Po pierwsze należy ustawić
wartość stałej TRANSLATION_HANDLING na true. Kolejny krok stanowi utworzenie tablicy
$availableLang zawierającej dostępne wersje językowe (założenie jest takie aby poszczególne
wartości tablicy stanowiły kilku literowe ciągi znaków reprezentujące dany język np. pl, en, de
itd.). Na koniec należy ustawić wartość stałej DEFAULT_LANGUAGE na wartość jednej ze
składowych tablicy $availableLang, która reprezentuje domyślny język aplikacji. W przypadku
włączenia mechanizmu tłumaczenia witryny odnośniki do poszczególnych stron są w formacie:
adres_serwera/index.php?lang=langMarker&url=link, gdzie langMarker stanowi identyfikator
wersji językowej znajdujący się w tablicy $availableLang w klasie
\App\config\AppSettings, natomiast link może mieć wartość np. 'adres',
'adres/adres2/adres3', 'adres/adres1'
Na pasku przeglądarki odnośniki mogą wyświetlać się w powyższym formacie lub też w formacie
przyjaznym użytkownikowi. W drugim przypadku w katalogu public musi się znaleźć plik
web.config zawierający kod z pliku web.config.lang (serwer IIS) lub plik .htaccess zawierający kod
z pliku htaccess.lang (serwer Apache) oraz w klasie \App\config\AppSettings stała
FRIENDLY_LINKS musi mieć wartość true. Odnośniki w takim wypadku mają format:
adres_serwera/langMarker/adres/adres2 tłumaczone na
adres_serwera/index.php?lang=langMarker&url=adres/adres2
Przy pierwszym uruchomieniu aplikacji język zależy od wersji językowej przeglądarki pod
warunkiem że język przeglądarki znajduje się na liście dostępnych w aplikacji języków (tablica
\App\config\AppSettings::$availableLang). W przypadku gdy język przeglądarki nie znajduje się
na tej liście to język aplikacji zależy od wartości stałej \App\config\DEFAULT_LANGUAGE
zawierającej identyfikator domyślnego języka. Zmiana języka odbywa się poprzez wywołanie
jednej z podstron aplikacji z innym identyfikatorem języka. W momencie wywołania podstrony
wybrany język aplikacji jest zapisywany w ciasteczkach dzięki czemu po zamknięciu przeglądarki i
późniejszym otwarciu strony zostanie ona wyświetlona w języku wybranym poprzednio przez
użytkownika.
Tłumaczenie statycznej treści witryny odbywa się w oparciu o pliki w formacie json
znajdujące się w katalogu templates/translations w katalogach zawierających kod PHP
poszczególnych modułów aplikacji. Znaleźć się tam mogą trzy pliki:



translations.json – obiekt zawierający tłumaczenia statycznej treści witryny, klucze obiektu
stanowią teksty w języku polskim, natomiast wartości stanowią obiekty, w których klucze
są identyfikatorami wersji językowych a wartości przetłumaczonym na dany język tekstem,
siteAddressTranslations.json – tłumaczenia poszczególnych odnośników witryny, struktura
obiektu jest taka sama jak obiektu w pliku translations.json,
titleTranslations.json – tłumaczenia tytułów poszczególnych podstron aplikacji, struktura
obiektu jest taka sama jak obiektu w pliku translations.json.
W momencie inicjalizacji mechanizmu tłumaczeń wymienione powyżej pliki z poszczególnych
modułów są ze sobą łączone. Zawartość plików siteAddressTranslations.json oraz
titleTranslations.json jest wykorzystywana automatycznie przez mechanizmy wbudowane w kod
framework’a. W przypadku tłumaczeń z pliku translations.json sytuacja wygląda nieco inaczej.
Mogą one być wykorzystywane przez programistę w kodzie PHP oraz w szablonach Smarty
34
poprzez statyczną metodę \Core\view\Lang::translate(), która jako parametr przyjmuje tekst w
języku polskim. W kodzie PHP wystarczy wywołać tą metodę tak jak każdą inną metodę statyczną.
Natomiast w plikach szablonów należy wywołać tą metodę na rzecz obiektu $langObj tak jak w
przykładzie poniżej:
<p id="errorTitle">{$langObj->translate('Błąd')}</p>
Tłumaczenie dynamicznej treści witryny takiej jak różnego rodzaju komunikaty lub tekst
zmieniający się dynamicznie w momencie wykonywania przez użytkownika pewnych operacji
odbywa się w kodzie JavaScript. Mechanizm związany z komunikatami opiera się o obiekt
Message znajdujący się w pliku src/Core/frontend/js/src/message/Message.js. Znajduje się tam
metoda Message::getMsg() umożliwiająca zwrócenie treści komunikatu na podstawie znacznika
komunikatu, typu komunikatu oraz opcjonalnie nazwy obiektu, w którym znajduje się komunikat.
W przypadku braku trzeciego opcjonalnego parametru komunikat jest wyszukiwany we
wszystkich obiektach o nazwach znajdujących się w tablicy msgObjects. Komunikat jest zwracany
w zdefiniowanym języku aplikacji. Struktura przykładowego obiektu zawierającego komunikaty
wykorzystywane w module User wygląda następująco:
var UserMessage =
{
errors: {
'emptyEmail': {
'pl': 'Adres email nie może być pusty.',
'en': 'E-mail address can not be empty.'
},
'wrongEmail': {
'pl': 'Niepoprawny adres email.',
'en': 'Invalid email address.'
},
'tooLongEmail': {
'pl': 'Adres email nie może być dłuższy niż {0} znaków.',
'en': 'E-mail address can not be longer than {0} characters.'
},
'emptyPassword': {
'pl': 'Hasło nie może być puste.',
'en': 'Password can not be empty.'
},
'tooShortPassword': {
'pl': 'Hasło musi składać się z minimum {0} znaków.',
'en': 'The password must contain a minimum of {0} characters.'
},
'tooLongPassword': {
'pl': 'Hasło nie może być dłuższe niż {0} znaków.',
'en': 'Password can not be longer than {0} characters.'
},
'wrongData': {
'pl': 'Adres email lub hasło są niepoprawne.',
'en': 'E-mail address or password is incorrect.'
},
'emptyFirstname': {
'pl': 'Imię nie może być puste.',
'en': 'Name can not be empty.'
},
'emptyLastname': {
'pl': 'Nazwisko nie może być puste.',
'en': 'Name can not be empty.'
},
'differencePasswords': {
'pl': 'Hasła muszą być takie same.',
'en': 'Passwords must be the same.'
},
'existingUser': {
'pl': 'Użytkownik o podanym adresie email istnieje już w systemie. Aby się
zarejestrować musisz podać inny adres.',
'en': 'User with the email address already exists in the system. To register,
you must provide a different address.'
},
'nonActiveUser': {
35
'pl': 'Twoje konto jest nieaktywne, aby się zalogować musisz najpierw kliknąć
w link aktywacyjny przesłany na adres podany podczas rejestracji.',
'en': 'Your account is inactive, you need to login first click on the
activation link sent to the address provided during registration.'
},
'emailDoesntExist': {
'pl': 'W systemie nie ma użytkownika o podanym adresie email.',
'en': 'The system does not have a user with the given email address.'
},
'emptyOldPassword': {
'pl': 'Aby zmienić dane musisz podać swoje hasło.',
'en': 'To change the data you need to enter your password.'
},
'wrongOldPassword': {
'pl': 'Podane hasło jest nieprawidłowe.',
'en': 'The password is incorrect.'
},
'tryingRemoveYourself': {
'pl': 'Nie możesz usunąć samego siebie.',
'en': 'You can not remove yourself.'
},
'nonSelectedRows': {
'pl': 'Musisz zaznaczyć minimum jeden rekord.',
'en': 'You must select at least one record.'
},
'userDoesntExist': {
'pl': 'Zostałeś usunięty z systemu przez administratora!',
'en': 'You have been removed from the system administrator!'
},
'mustSelectOneRow': {
'pl': 'Musisz zaznaczyć dokładnie jeden rekord.',
'en': 'You must select exactly one record.'
}
},
confirms: {
'modifyAccount': {
'pl': 'Operacja modyfikowania danych użytkownika przebiegła prawidłowo.',
'en': 'Operation modifying user data is dealt with correctly.'
},
'successGetUserData': {
'pl': 'Dane użytkownika zostały pobrane prawidłowo.',
'en': 'User data were collected properly.'
}
},
info: {
'noUsers': {
'pl': 'Brak użytkowników',
'en': 'No user'
}
},
questions: {
'removeUser': {
'pl': {
'title': 'Usuwanie użytkownika',
'text': 'Jesteś pewien że chcesz usunąć użytkowników o następujących
adresach email: {0}?'
},
'en': {
'title': 'Deleting a user',
'text': 'Are you sure you want to remove users with the following email
addresses: {0}?'
}
}
}
};
36
8. Moduł User 1.52
8.1. Wstęp
Opisywany w niniejszym rozdziale moduł o nazwie User odpowiada za działanie systemu
użytkowników w aplikacji tworzonej w oparciu o opisywany w niniejszej dokumentacji
framework. Moduł umożliwia rejestrowanie nowego konta użytkownika, logowanie istniejącego
użytkownika, odzyskiwanie hasła użytkownika, modyfikację danych podanych podczas rejestracji
przez użytkownika po zalogowaniu, zarządzanie innymi użytkownikami przez administratorów
systemu oraz zarządzanie typami użytkowników przez administratorów systemu. Możliwe jest
również zintegrowanie modułu User z innymi modułami aplikacji w taki sposób aby strony
dodawane przez inne moduły były dostępne tylko po zalogowaniu lub tylko dla pewnych grup
użytkowników.
8.2. Ustawienia
8.2.1.
Wstęp
Pierwszy krok, podczas pisania aplikacji wykorzystującej opisywany w niniejszym rozdziale
moduł, stanowi konfiguracja modułu. Wszystkie ustawienia modułu znajdują się w klasie
\User\config\UserSettings dziedziczącej po klasie \Core\config\Settings. W kolejnych
podrozdziałach przedstawione zostały najważniejsze składowe tej klasy.
8.2.2.
$requiredModules
Tablica zawierająca nazwę modułu, który jest potrzebny do prawidłowego działania
modułu User.
8.2.3.
SITE_AFTER_LOGIN
Stała przechowująca identyfikator strony z tablicy routingu, na którą ma nastąpić
przekierowanie po prawidłowym zalogowaniu użytkownika.
8.2.4.
ADMIN_USER_CONFIRM
Znacznik określający to czy zarejestrowanych użytkowników musi potwierdzać
administrator. Domyślnie po wykonaniu przez użytkownika operacji rejestracji nowo utworzone
konto jest nieaktywne. W przypadku gdy stała UserSettings::ADMIN_USER_CONFIG ma wartość
false to użytkownik po zarejestrowaniu konta otrzymuje wiadomość z linkiem aktywującym
konto. Natomiast w sytuacji gdy stała UserSettings::ADMIN_USER_CONFIG ma wartość true to
użytkownik po zarejestrowaniu konta dostaje wiadomość z informacją o tym że konto zostało
utworzone, ale musi być jeszcze aktywowane przez administratora. Dodatkowo wszyscy
administratorzy dostają wiadomość email zawierającą adres email nowego użytkownika. Po
aktywowaniu tego konta przez administratora wysyłana jest do użytkownika kolejna wiadomość
email z informacją o tym że konto zostało aktywowane. Konta użytkowników mogą być
aktywowane na stronie zarządzania użytkownikami.
8.2.5.
ADMIN_TYPE
Typ użytkowników, którzy mają dostęp do strony zarządzania użytkownikami oraz do
strony zarządzania typami użytkowników.
37
8.2.6.
EMAIL_MAX_LANGTH
Maksymalna długość adresu email podawanego podczas rejestracji nowego użytkownika
oraz podczas edycji danych użytkownika na stronie zarządzania użytkownikami. Należy pamiętać
że w przypadku ustawienia długości większej niż 100 znaków należy również zmodyfikować typ
kolumny email w tabeli user.
8.2.7.
PASSWORD_MIN_LENGTH
Minimalna długość hasła podawanego podczas rejestracji nowego użytkownika oraz
podczas edycji danych użytkownika na stronie zarządzania użytkownikami.
8.2.8.
PASSWORD_MAX_LENGTH
Maksymalna długość hasła podawanego podczas rejestracji nowego użytkownika oraz
podczas edycji danych użytkownika na stronie zarządzania użytkownikami. Należy pamiętać że w
przypadku ustawienia długości większej niż 100 znaków należy również zmodyfikować typ
kolumny password w tabeli user.
8.2.9.
FIRSTNAME_MAX_LENGTH
Maksymalna długość imienia podawanego podczas rejestracji nowego użytkownika oraz
podczas edycji danych użytkownika na stronie zarządzania użytkownikami. Należy pamiętać że w
przypadku ustawienia długości większej niż 100 znaków należy również zmodyfikować typ
kolumny firstname w tabeli user.
8.2.10. LASTNAME_MAX_LENGTH
Maksymalna długość nazwiska podawanego podczas rejestracji nowego użytkownika oraz
podczas edycji danych użytkownika na stronie zarządzania użytkownikami. Należy pamiętać że w
przypadku ustawienia długości większej niż 100 znaków należy również zmodyfikować typ
kolumny lastname w tabeli user.
8.2.11. USER_TYPE_NAME_MAX_LENGTH
Maksymalna długość nazwy typu użytkownika podawanej na stronie zarządzania typami
użytkowników podczas tworzenia/edycji typu. Należy pamiętać że w przypadku ustawienia
długości większej niż 100 znaków należy zmodyfikować typ kolumny name w tabeli user_type.
8.2.12. USER_TYPE_ID_MIN_VAL
Minimalna wartość identyfikatora typu użytkowników podawanego na stronie zarządzania
typami użytkowników podczas tworzenia/edycji typu.
8.2.13. USER_TYPE_ID_MAX_VAL
Maksymalna wartość identyfikatora typu użytkowników podawanego na stronie
zarządzania typami użytkowników podczas tworzenia/edycji typu.
8.2.14. EDIT_BLOCK_TIME
Czas określony w sekundach, co który odświeżana jest wartość w kolumnie date w tabeli
user_modification lub w tabeli user_type_modification w momencie gdy otwarte jest okno edycji
użytkownika lub okno edycji typu użytkowników. Tabela user_modification wykorzystywana jest
do blokowania edycji aktualnie edytowanego użytkownika przez innych użytkowników w tym
samym czasie. Natomiast tabela user_type_modification wykorzystywana jest do blokowania
edycji aktualnie edytowanego typu użytkowników. W sytuacji gdy dany użytkownik zamknie okno
38
przeglądarki nie zamykając uprzednio okna edycji użytkownika lub typu użytkowników to
możliwość edycji tego użytkownika lub typu użytkowników będzie zablokowana przez czas
podany w niniejszej stałej pomnożony przez dwa.
8.2.15. USE_RECAPTCHA
Znacznik określający to czy w formularzu rejestracji ma być wyświetlona captcha działająca
w oparciu o mechanizm ReCaptcha9.
8.2.16. PATH_TO_CAPTCHA_LIB
Ścieżka do biblioteki PHP odpowiedzialnej za działanie mechanizmu ReCaptcha.
8.2.17. RECAPTCHA_PUBLIC_KEY
Klucz publiczny potrzebny do działania mechanizmu ReCaptcha.
8.2.18. RECAPTCHA_PRIVATE_KEY
Klucz prywatny potrzebny do działania mechanizmu ReCaptcha.
8.3. Struktura klas kontrolerów modułu
Poniżej przedstawiony został diagram dziedziczenia klas kontrolerów modułu:
Rysunek 8.1
9
https://www.google.com/recaptcha/intro/index.html
39
8.4. Struktura szablonów Smarty
Poniżej znajduje się diagram przedstawiający strukturę dziedziczenia szablonów Smarty
modułu User:
Rysunek 8.2
8.5. Strony modułu
8.5.1.
Strona logowania
Strona dostępna pod adresem http://adres_aplikacji/logowanie/ (szablon login.tpl).
Zawiera formularz umożliwiający logowanie się istniejących użytkowników. Stronę opisuje
fragment tablicy routingu wskazywany przez klucz loginSite. W większości aplikacji
zintegrowanych z modułem User identyfikator tej strony powinien być podany w składowej
\App\config\AppSettings::MAIN_SITE_KEY określającej stronę, która powinna się domyślnie
wyświetlić użytkownikowi po wejściu na adres http://adres_aplikacji/.
8.5.2.
Strona rejestracji
Strona dostępna pod adresem http://adres_aplikacji/rejestracja/ (szablon register.tpl).
Zawiera formularz umożliwiający rejestrowanie się nowych użytkowników. W zależności od
wartości stałej \User\config\UserSettings::USE_RECAPTCHA w formularzu może znajdować się
element captcha.
Do zakodowania w bazie danych podanego podczas rejestracji hasła wykorzystywana jest
wbudowana w język PHP funkcja password_hash10. Natomiast do weryfikacji hasła podczas
logowania użytkownika wykorzystywana jest funkcja password_verify11.
10
11
http://php.net/manual/en/function.password-hash.php
http://php.net/manual/en/function.password-verify.php
40
8.5.3.
Strona potwierdzania konta
Strona dostępna pod adresem http://adres_aplikacji/potwierdzenie/ (szablon confirm.tpl).
Umożliwia potwierdzenie zarejestrowanego konta użytkownika. W przypadku gdy stała
\User\config\UserSettings::ADMIN_USER_CONFIRM ma wartość false to po zarejestrowaniu
konta na adres email podany podczas rejestracji wysyłana jest wiadomość zawierająca odnośnik,
z unikalnym parametrem, do strony potwierdzania konta. Przykładowy link aktywacyjny wygląda
następująco:
http://adres_aplikacji/potwierdzenie/lukasz_rydzkowski%40loco.pl%3BYpG4xEt36RzHGcwRaqo
W powyższym adresie unikalny parametr wygląda następująco:
lukasz_rydzkowski%40loco.pl%3BYpG4xEt36RzHGcwRaqo
Parametr składa się z dwóch części oddzielonych znakiem średnika. Pierwszą część stanowi adres
email podany podczas rejestracji. Drugą część stanowi ciąg dwudziestu losowych znaków zapisany
w kolumnie series w tabeli user.
8.5.4.
Strona odzyskiwania hasła
Strona dostępna pod adresem http://adres_aplikacji/odzyskiwanie_hasla (szablon
retrieval.tpl). Zawiera formularz, w którym należy wpisać adres email podany podczas rejestracji
użytkownika, w celu otrzymania wiadomości email z nowym, automatycznie wygenerowanym,
hasłem.
8.5.5.
Konto użytkownika
Strona dostępna tylko dla zalogowanych użytkowników pod adresem
http://adres_aplikacji/konto/ (szablon account.tpl). Zawiera formularz z danymi podanymi
podczas rejestracji. Formularz umożliwia modyfikację wszystkich danych użytkownika oprócz
adresu email.
8.5.6.
Strona zarządzania użytkownikami
Strona dostępna tylko dla zalogowanych użytkowników o typie podanym w stałej
\User\config\UserSettings::ADMIN_TYPE pod adresem http://adres_aplikacji/uzytkownicy/
(szablon usersList.tpl). Na stronie znajduje się tabela z listą wszystkich zarejestrowanych w
aplikacji użytkowników. Możliwe jest usuwanie użytkowników, edycja użytkowników oraz
tworzenie nowych użytkowników. W przypadku gdy usunięty zostanie aktualnie zalogowany
użytkownik to użytkownik ten zostanie wylogowany. Użytkownik zostanie również automatycznie
wylogowany w przypadku gdy zmieniony zostanie jego adres email. Wylogowanie nastąpi w
przypadku odświeżenia aktualnej strony lub przejścia na dowolną inną stronę. Dodatkowo co 60
sekund wysyłane jest żądanie AJAX mające na celu sprawdzenie czy użytkownik powinien zostać
wylogowany. W przypadku gdy jako odpowiedź na żądanie zostanie wysłana wartość ‘false’ to w
kodzie JavaScript zostanie przeprowadzana operacja przeładowania strony co spowoduje
automatyczne wylogowanie.
8.5.7.
Strona zarządzania typami użytkowników
Strona dostępna tylko dla zalogowanych użytkowników o typie podanym w stałej
\User\config\UserSettings::ADMIN_TYPE
pod
adresem
http://adres_aplikacji/typy_uzytkownikow/ (szablon usersTypesList.tpl). Na stronie znajduję się
tabela z listą wszystkich typów użytkowników. Możliwe jest usuwanie, edycja oraz tworzenie
typów.
41
8.6. Struktura kodu JavaScript
Poniżej przedstawiony został diagram obiektów oraz struktur klaso podobnych w języku
JavaScript:
Rysunek 8.3
42
8.7. Struktura bazy danych
8.7.1.
Wstęp
Poniżej przedstawiona została struktura tabel potrzebnych do działania modułu:
Rysunek 8.4
Kod sql odpowiedzialny za utworzenie tych tabel znajduje się w plikach, które można znaleźć w
katalogu src/User/doc/sql/. W kolejnych podrozdziałach przedstawione zostały informacje
dotyczące tego jakie dokładnie informacje przechowywane są w poszczególnych tabelach.
8.7.2.
Tabela user
Tabela przechowuje informacje o utworzonych w aplikacji użytkownikach. Jak już
wspomniano w poprzednich podrozdziałach użytkownicy mogą być tworzeni poprzez formularze
znajdujące się na stronie rejestracji oraz na stronie zarządzania użytkownikami. Poniżej opisane
zostały poszczególne kolumny tabeli:






email – adres email użytkownika (NVARCHAR(100), NOT NULL).
password – zakodowane hasło użytkownika (NVARCHAR(100), NOT NULL). Do
zakodowania hasła wykorzystywana jest wbudowana w język PHP funkcja password_hash.
firstname - imię użytkownika (NVARCHAR(100), NOT NULL).
lastname – nazwisko użytkownika (NVARCHAR(100), NOT NULL).
series – ciąg dwudziestu losowych znaków, który wykorzystywany jest do wygenerowania
linka aktywującego konto, więcej informacji na ten temat można znaleźć w rozdziale 8.5.3
Strona potwierdzania konta (VARCHAR(20), NOT NULL).
token – losowa dziesięciocyfrowa liczba generowana w przypadku gdy użytkownik zaloguje
się z zaznaczoną opcją zapamiętywania logowania. Ta sama liczba jest zapisywana w
43





8.7.3.
COOKIES i w przypadku ponownego otwarcia okna przeglądarki podczas uruchamiania
aplikacji wartość w COOKIES jest porównywana z wartością w bazie. Jeśli wartości są takie
same to użytkownik jest automatycznie logowany (VARCHAR(10), NULL).
create_date – data utworzenia użytkownika (DATETIME, NOT NULL).
update_date – data aktualizacji użytkownika (DATETIME, NULL).
type_id – identyfikator typu użytkownika (INT, NOT NULL).
active – znacznik określający to czy użytkownik jest aktywny, logować mogą się tylko
aktywni użytkownicy (INT, NOT NULL).
confirm_email
–
kolumna
wykorzystywana
w
przypadku
gdy
stała
\User\config\UserSettings::ADMIN_USER_CONFIRM ma wartość true. W takim wypadku
wartość w kolumnie sprawdzana jest w celu zweryfikowania tego czy w momencie
aktywowania danego użytkownika na stronie zarządzania użytkownikami należy wysłać do
użytkownika informację o tym że jego konto jest już aktywne (INT, NULL).
Tabela user_type
Tabela przechowująca typy użytkowników. Poniżej zostały opisane poszczególne kolumny
tabeli:


8.7.4.
id – identyfikator typu użytkownika (INT, NOT NULL).
name – nazwa typu użytkownika (NVARCHAR(100), NOT NULL).
Tabela user_modification
Tabela potrzebna do działania mechanizmu blokowania, na stronie zarządzania
użytkownikami, edycji użytkowników, którzy są w danym momencie edytowani przez innego
użytkownika. W momencie gdy użytkownik wyświetli okno edycji użytkownika i w opisywanej
tabeli nie istnieje rekord, który w kolumnie edited_user_email posiada wartość stanowiącą adres
email edytowanego użytkownika to tworzony jest nowy rekord. W sytuacji gdy taki rekord istnieje
to w tym rekordzie aktualizowana jest wartość w kolumnie date oraz w kolumnie modified
ustawiana jest wartość 1. Poniżej zostały opisane poszczególne kolumny tabeli:




8.7.5.
edited_user_email – adres email edytowanego użytkownika (NVARCHAR(100), NOT NULL).
user_email – adres email użytkownika, który edytuje użytkownika (NVARCHAR(100), NOT
NULL).
date – w sytuacji gdy aktualnie otwarte jest okno edycji użytkownika to czas ten jest
aktualizowany
co
ilość
sekund
podaną
w
stałej
\User\config\UserSettings::EDIT_BLOCK_TIME. W sytuacji gdy dany użytkownik zamknie
okno przeglądarki nie zamykając uprzednio okna edycji użytkownika to możliwość edycji
tego użytkownika będzie zablokowana przez czas podany w tej stałej pomnożony przez
dwa (DATETIME, NOT NULL).
modified – znacznik określający to czy aktualnie jest otwarte okno edycji użytkownika. W
momencie otwarcia okna edycji użytkownika do kolumny wstawiana jest wartość 1,
natomiast w momencie zamknięcia okna edycji do kolumny wstawiana jest wartość 0 (INT,
NOT NULL).
Tabela user_type_modification
Tabela potrzebna do działania mechanizmu blokowania, na stronie zarządzania typami
użytkowników, edycji typów użytkowników, którzy są w danym momencie edytowani przez
44
innego użytkownika. Mechanizm ten działa analogicznie do mechanizmu blokowania edycji
użytkowników. Poniżej zostały opisane poszczególne kolumny tabeli:




edited_user_type_id – identyfikator edytowanego typu użytkowników (INT, NOT NULL).
user_email – adres email użytkownika, który edytuje typ użytkowników (NVARCHAR(100),
NOT NULL).
date - w sytuacji gdy aktualnie otwarte jest okno edycji typu użytkowników to czas ten jest
aktualizowany
co
ilość
sekund
podaną
w
stałej
\User\config\UserSettings::EDIT_BLOCK_TIME. W sytuacji gdy dany użytkownik zamknie
okno przeglądarki nie zamykając uprzednio okna edycji typu użytkowników to możliwość
edycji tego typu będzie zablokowana przez czas podany w tej stałej pomnożony przez dwa
(DATETIME, NOT NULL).
modified - znacznik określający to czy aktualnie jest otwarte okno edycji typu
użytkowników. W momencie otwarcia okna edycji typu użytkownika do kolumny
wstawiana jest wartość 1, natomiast w momencie zamknięcia okna edycji do kolumny
wstawiana jest wartość 0 (INT, NOT NULL).
8.8. Integracja z innymi modułami
W celu zintegrowania innych modułów z systemem użytkowników należy wykonać kilka
kroków opisanych w kolejnych paragrafach.
Po pierwsze wszystkie klasy kontrolerów modułu muszą dziedziczyć bezpośrednio lub
pośrednio po klasie \User\controller\UserController. Klasa ta zawiera metody odpowiedzialne
między innymi za weryfikację tego czy użytkownik jest zalogowany, za weryfikację typu
użytkownika czy też za sprawdzenie czy aktualnie zalogowany użytkownik nie został usunięty z
bazy.
Kolejny krok stanowi dodanie do tablicy routingu weryfikacji tego czy użytkownik jest
zalogowany czy też nie. W tym celu należy zmodyfikować element startAction znajdujący się we
fragmencie tablicy routingu reprezentującym wybraną stronę aplikacji.
Jeśli dana strona ma być dostępna tylko dla zalogowanych użytkowników to element
startAction powinien zawierać poniższe metody:
...
'startAction'
=> array(
'method'
=> array(
'checkUser'
),
'falseResult'
=> array(
'redirectToLoginSite'
)
)
...
Powyższy fragment oznacza że w przypadku nadejścia na daną stronę aplikacji jakiegokolwiek
żądania w pierwszej kolejności wywoływana jest metoda checkUser klasy kontrolera. Metoda
checkUser znajduje się w klasie \User\controller\UserController (między innymi dlatego wszystkie
klasy kontrolerów modułu powinny dziedziczyć po tej klasie). Jeśli użytkownik nie jest aktualnie
zalogowany to metoda ta zwróci wartość false co z kolei spowoduje wywołanie metody
redirectToLoginSite, która również znajduje się w klasie \User\controller\UserController. W
przypadku gdy przetwarzane żądanie jest żądaniem synchronicznym to metoda ta przekierowuje
użytkownika na stronę logowania. W przypadku gdy przetwarzane żądanie jest żądaniem
asynchronicznym to metoda ta jako odpowiedź na żądanie zwraca znacznik błędu
userIsNotLogged oraz adres do strony logowania, na którą powinno nastąpić przekierowanie w
45
kodzie JavaScript. Dodatkowo dla stron, które mają być dostępne tylko po zalogowaniu, w tablicy
routingu konieczne jest podanie w tablicy wskazywanej przez klucz viewMethods metody
setViewParams. Metoda ta, podobnie jak metoda redirectToLoginSite, znajduje się w klasie
\User\controller\UserController. W metodzie inicjalizowane są zmienne związane z systemem
użytkowników, które przekazywane są do szablonów Smarty odpowiedzialnych za wyświetlenie
danej strony aplikacji.
Jeśli strona ma być dostępna tylko dla niezalogowanych użytkowników to element
startAction powinien zawierać poniższe metody:
...
'startAction'
=> array(
'method'
=> array(
'checkUser'
),
'trueResult'
=> array(
'redirectToMainSite'
)
)
...
W przypadku gdy metoda checkUser zwróci wartość true, co oznacza że użytkownik jest
zalogowany,
to
wywołana
zostanie
metoda
\User\controller\UserController::redirectToMainSite(). W przypadku gdy przetwarzane żądanie
jest żądaniem synchronicznym to metoda ta przekieruje użytkownika na stronę reprezentowaną
przez klucz z tablicy routingu znajdujący się w stałej UserSettings::SITE_AFTER_LOGIN. W
przypadku gdy przetwarzane żądanie jest żądaniem asynchronicznym to metoda ta jako
odpowiedź na żądanie zwróci znacznik błędu userIsLogged oraz adres strony, na którą powinno
nastąpić przekierowanie w kodzie JavaScript.
Opisane powyżej mechanizmy odpowiedzialne za przekierowanie użytkownika na
odpowiednią stronę w przypadku przetwarzania żądań asynchronicznych są obsługiwane w
bibliotece Data.js znajdującej się w pliku src/User/frontend/js/utils/Data.js. Biblioteka ta powinna
zastąpić bibliotekę Data.js z modułu Core opisaną szerzej w rozdziale 5.7.2.7 Data.js.
W sytuacji gdy strona modułu ma być dostępna zarówno dla zalogowanych jak i dla
niezalogowanych użytkowników to wystarczy, że w tablicy routingu w tablicy wskazywanej przez
klucz viewMethods znajdzie się metoda setViewParams.
Ostatnim krokiem podczas integracji modułu z systemem użytkowników jaki należy
wykonać stanowi implementacja dziedziczenia struktur klaso podobnych, reprezentujących
strony
modułu,
po
strukturze
UserSite
znajdującej
się
w
pliku
src/User/frontend/js/src/UserSite.js. Dodatkowo w konstruktorze struktury powinien zostać
wywołany konstruktor struktury UserSite. W przypadku gdy dla strony modułu nie została
utworzona struktura klaso podobna, to na tej stronie powinien zostać wywołany kod JavaScript
tworzący obiekt na podstawie struktury UserSite. Aby to zrealizować należy wstawić na stronie
poniższy kod JavaScript:
Class.create('UserSite');
Operacja ta ma na celu wywołanie konstruktora struktury UserSite, ponieważ w tym
konstruktorze wywoływana jest metoda UserExistRequest.startSendingRequest(). Metoda ta
wysyła co 60 sekund żądanie asynchroniczne, które ma na celu zweryfikowanie czy aktualnie
zalogowany użytkownik nie został usunięty z bazy lub czy też nie został zmieniony adres mailowy
tego użytkownika. Jeśli taka sytuacja miała miejsce to po otrzymaniu odpowiedzi na żądanie, w
kodzie JavaScript, przeładowywana jest strona. Przeładowanie strony w takim wypadku
spowoduje automatyczne wylogowanie użytkownika.
46
8.9. Testowanie modułu
W module User dostępna jest klasa \User\test\User, która zawiera metodę
insertRandomData(). Metoda ta wstawia do bazy y rekordów reprezentujących typy
użytkowników oraz x rekordów reprezentujących użytkowników, gdzie y oraz x to wartości
liczbowe przekazane w parametrach metody. Dane każdego z użytkowników generowane są w
sposób pseudo losowy. Warto jedynie wspomnieć że nazwy typów użytkowników są losowane
spośród słów znajdujących się w pliku src/User/test/files/words.txt, imiona użytkowników
losowane są spośród imion znajdujących się w pliku src/User/test/files/firstnames.txt, natomiast
nazwiska losowane są spośród nazwisk znajdujących się w pliku src/User/test/files/lastnames.txt.
Opisywaną metodę można wywołać z poziomu przeglądarki poprzez plik test.php znajdujący się
w katalogu public korzystając z poniższego adresu:
http://adres_serwera/test.php?test=insertUsers
9. Moduł ListSupport 1.35
Moduł ListSupport udostępnia kod ułatwiający wyświetlanie danych pobranych z bazy w
formie interaktywnej tabeli. Moduł składa się z dwóch elementów. Pierwszy z nich stanowi klasa
PHP o nazwie \ListSupport\model\ListSupport, która zawiera metody odpowiedzialne za pobranie
danych z bazy. Drugim elementem jest struktura klaso podobna o nazwie ListSupport.js,
znajdująca się w katalogu src/ListSupport/frontend/js/src/, która może zostać wykorzystana w
kodzie JavaScript odpowiedzialnym za pobranie danych z serwera oraz wygenerowaniu na
podstawie tych danych tabeli przy wykorzystaniu funkcji Table.js, o której wspomniano w
rozdziale 5.7.2.8 Table.js. Przykład wykorzystania opisywanego modułu można znaleźć w module
User na stronach zarządzania użytkownikami oraz zarządzania typami użytkowników.
10. Moduł ModuleCreator 1.15
Moduł udostępnia stronę umożliwiającą utworzenie szkieletu nowego modułu. Strona
dostępna jest pod adresem:
http://adres_serwera/nowy_modul/
47
Na stronie znajduje się formularz z jednym polem, w którym należy podać nazwę tworzonego
modułu. Poniżej została przedstawiona struktura plików i katalogów szkieletu modułu o nazwie
Test, utworzonego za pomocą tego formularza:
Rysunek 10.1
Moduł po utworzeniu udostępnia jedną testową stronę dostępną pod poniższym adresem:
http://adres_serwera/sample/
48