Vysoká škola ekonomická v Praze Fakulta informatiky a statistiky Vyšší odborná škola informačních služeb v Praze
Pavel Přibyl Návrh a implementace rezervačního systému vhodného pro transfuzní stanice Bakalářská práce
2009
Poděkování Děkuji vedoucímu práce Ing. Davidu Viochnovi za pomoc a podporu během tvorby práce, za vstřícný a přátelský přístup při řešení nejrůznějších problémů. Zároveň děkuji RNDr. Romanu Ondruškovi ze společnosti SUN Microsystems za přínosné konzultace v otázkách uživatelského rozhraní. a přátelům za podporu a trpělivost.
V neposlední řadě děkuji rodině
Prohlášení Prohlašuji, že jsem bakalářskou práci na téma „Návrh a implementace rezervačního systému vhodného pro transfuzní stanice“ zpracoval samostatně a použil pouze zdrojů, které cituji a uvádím v seznamu použité literatury.
V Praze dne 1.5.2009
Abstrakt Cílem práce je návrh a implementace on-line rezervačního systému vhodného pro transfuzní stanice. Vzhledem ke specifickým požadavkům na systém je třeba vytvořit vlastní řešení, nelze tedy použít stávající univerzální komerční aplikace. Praktickou část tvoří samotná aplikace, resp. její zdrojový kód. Ten je vytvořen s použitím technologií PHP, MySQL, XHTML, CSS a JavaScript. Teoretická část popisuje způsob využití těchto technologií, specifikaci požadavků a návrh systému. Pro modelování systému jsou využity UML diagramy. Výsledkem práce je funkční webová aplikace s dokumentací. Tato aplikace je využitelná pro praktické nasazení v transfuzních stanicích.
Abstract Objective of this work is to design and implement on-line reservation system suitable for use in transfusion station. Due to the specific requirements for the system it is necessary to create own solution, it is not possible to use universal commercial applications. Practical part of this work is the web application itself, respectively its source code. It is created with the use of following technologies: PHP, MySQL, XHTML, CSS and JavaScript. The theoretical part describes how the technologies are used, the requirement specification and system design. For modelling of the system are used UML diagrams. Result of this work is functional web application with documentation. The application is usable for practical use in transfusion station.
1. Obsah 1. Obsah ............................................................................................................................6 2. Úvod..............................................................................................................................8 2.1. Rezervační systém pro transfuzní stanici...............................................................9 3. Použité metody a technologie .....................................................................................10 3.1. PHP ......................................................................................................................10 3.1.1. Způsob využití...............................................................................................10 3.1.2. Přednosti jazyka ............................................................................................11 3.1.3. Objektově orientované programování v PHP ...............................................11 3.2. XHTML ...............................................................................................................12 3.3. CSS.......................................................................................................................12 3.4. JavaScript .............................................................................................................13 3.4.1. AJAX ............................................................................................................13 4. Návrh systému.............................................................................................................14 4.1. Specifikace požadavků.........................................................................................14 4.1.1. Funkcionalita.................................................................................................14 4.1.2. Uživatelé .......................................................................................................15 4.1.3. Základní postupy a pravidla používání .........................................................16 4.1.4. Data ...............................................................................................................17 4.2. Případy užití .........................................................................................................18 4.2.1. Doplňující charakteristiky.............................................................................19 4.3. Modely .................................................................................................................20 4.3.1. Přihlášení uživatele do systému (Diagram aktivit) .......................................20 4.3.2. Zápis rezervace (Diagram aktivit).................................................................21 4.3.3. Diagram tříd ..................................................................................................22 4.3.4. Sekvenční diagram ........................................................................................24 4.3.5. Stavový diagram............................................................................................25 4.3.6. Diagram nasazení ..........................................................................................26 4.3.7. ERA diagram.................................................................................................27
-6-
5. Implementace ..............................................................................................................28 5.1. Serverová část aplikace ........................................................................................28 5.1.1. Pomocné třídy ...............................................................................................29 5.1.2. Přihlášení uživatele .......................................................................................30 5.1.3. Vytvoření rozvrhů .........................................................................................30 5.1.4. Generování tabulek rozvrhů..........................................................................32 5.1.5. Časové razítko...............................................................................................33 5.1.6. Zaznamenávání rezervace .............................................................................34 5.1.7. Nastavení systému.........................................................................................35 5.1.8. Použité návrhové vzory.................................................................................36 5.1.9. Zabezpečení...................................................................................................37 5.2. Klientská část aplikace.........................................................................................39 5.2.1. Uživatelské rozhraní......................................................................................39 5.2.2. Ovládací prvky ..............................................................................................41 5.2.3. Asynchronní dotazy ......................................................................................43 5.3. Testování aplikace................................................................................................45 6. Závěr ...........................................................................................................................46 6.1. Zhodnocení splnění požadavků............................................................................46 6.2. Budoucnost systému ............................................................................................47 7. Seznam použitých zdrojů ............................................................................................48 8. Seznam obrázků ..........................................................................................................50 9. Seznam příloh..............................................................................................................51
-7-
2. Úvod Cílem této práce je vytvořit „engine“, neboli funkční jádro on-line rezervačního systému tak, aby vyhovoval specifickým požadavkům pro nasazení v transfuzní stanici. Základem práce proto bude návrh databáze a aplikační části systému. Následujícím krokem bude implementace, tj. vytvoření webové aplikace v jazyce PHP s využitím MySQL databáze. Přestože těžištěm bude serverová část aplikace, tedy samotná aplikační logika, součástí práce bude i vytvoření vhodného uživatelského rozhraní. Pro tyto účely bude využit jazyk XHTML, styly CSS a jazyk JavaScript. Výsledná aplikace by měla být snadno modifikovatelná. Uživatel, resp. správce systému bude schopen upravit její parametry tak, aby odpovídaly konkrétním potřebám stanice. Díky tomu by pak aplikace měla být snadno rozšiřitelná do více transfuzních stanic, bez nutnosti zasahovat do jejího zdrojového kódu. Tato práce je vytvářena ve spolupráci se společností Baxter BioScience, působící v oblasti zpracování krevní plazmy. V případě úspěšného dokončení bude rezervační systém nabídnut k využívání v
transfuzních stanicích, se kterými společnost
spolupracuje.
-8-
2.1. Rezervační systém pro transfuzní stanici Hlavní význam rezervačních systémů spočívá v možnosti zaznamenávat, uchovávat a zpracovávat údaje o rezervacích jednotlivých uživatelů. Nejčastější využití pak nacházejí v oblasti dopravy (rezervace jízdenek), sportu (rezervace sportovišť, např. tenisových kurtů), kultury (vstupenky) apod. Systémy pak mohou být navrhovány „na míru“, tj. účelně pro konkrétní nasazení, nebo univerzálně, s možností využití na více místech. I tato univerzální řešení se však vždy zaměřují na konkrétní oblast. Zatímco např. pro sportovní zařízení existuje řada již hotových rezervačních systémů, jejich nasazení v transfuzní stanici je poměrně nepraktické. Systém pro transfuzní stanici musí mimo jiné počítat s řadou omezení, která jsou spojena s darováním krve a krevní plazmy. Například se jedná o stanovení intervalu mezi dvěma rezervacemi, během kterého nelze rezervace provádět. Zatímco systém pro rezervaci tenisových kurtů zcela jistě umožňuje rezervovat si kurt na dvě hodiny ihned po sobě, v případě transfuzní stanice musí být uživatelův výběr omezen. Dostupné univerzální rezervační systémy pak často zahrnují i řešení finančních otázek, tedy například výpočet ceny v závislosti na čase rezervace, možnosti platby online apod. Pro nasazení v podmínkách transfuzní stanice je však tato funkcionalita nadbytečná, resp. nežádoucí. Z těchto důvodů se tedy jeví jako výhodnější vytvořit systém nový, který bude již od začátku koncipován právě s přihlédnutím k těmto specifickým požadavkům.
-9-
3. Použité metody a technologie Serverová část aplikace bude vytvořena s využitím objektově orientovaného programování v jazyce PHP. Samotnému vývoji bude předcházet návrh a modelování systému s využitím UML jazyka. Klientská část bude tvořena XHTML webovými stránkami, tvořenými v souladu se standardy W3C [23]. Funkcionalita bude podpořena použitím skriptovacího jazyka JavaScript a technologie AJAX. Grafická úprava a rozložení prvků stránky budou zajištěny využitím kaskádových stylů CSS.
3.1. PHP PHP je open-source programovací jazyk, určený především pro tvorbu webových stránek a aplikací. Za více než deset let své existence se PHP vyvinulo z „okrajového“ jazyka, který byl využíván pro přidání dynamické funkcionality webovým stránkám, na výkonný nástroj pro vývoj rozsáhlých aplikací. Jeho popularita je způsobena zejména snadností použití, rychlým osvojením základních funkcí, široké podpoře (jak ze strany významných vývojářů a poskytovatelů webových hostinců, tak i ze strany početné komunity) a v neposlední řadě jeho cenou. Je totiž zcela zdarma.
3.1.1. Způsob využití PHP bylo navrženo (a dodnes je nejčastěji využíváno) pro spouštění a běh skriptů generujících webový obsah, nejčastěji tedy HTML kódu. Výstupem těchto skriptů však může být například i XML dokument, grafika, PDF soubor, flashová animace apod. K uživateli, resp. na klientskou část aplikace, je pak přenesen již jen výsledek činnosti skriptu. Uživatel tak nemá možnost prohlédnout si zdrojový kód původního skriptu. PHP skripty lze spouštět i bez běžícího serveru, z příkazové řádky. Tento přístup bývá využíván spíše pro administrační účely, ladění skriptů a hledání chyb. S pomocí PHP lze vytvořit rovněž i aplikace s grafickým uživatelským rozhraním, které běží na straně klienta. Pro tyto účely je třeba nainstalovat grafické rozšíření GTK+, například PHP-GTK
- 10 -
3.1.2. Přednosti jazyka Jednou z důležitých vlastností je nezávislost na použité platformě. Všechny zmíněné způsoby využití lze bez rozdílu provozovat na operačních systémech Windows, MacOS, a různých UNIXových distribucích. Předností PHP je pak široké spektrum podporovaných databází, se kterými může spolupracovat. Umožňuje tak obsluhu všech významných databázových systémů: MySQL, PostgreSQL, Oracle, Sybase, a ODBC, ale i řadu dalších (např. SQLite). Díky zmiňované široké podpoře již existuje nepřeberné množství zdrojů, kterých mohou uživatelé využívat. Jedná se jak o řadu teoretických zdrojů (návody, doporučení, tipy a triky), tak o volně dostupná hotová řešení. Mezi tyto pak patří nejrůznější knihovny s využitelnými funkcemi, připravené třídy nebo tzv. frameworky softwarové struktury obsahující nástroje pro usnadnění a urychlení vývoje aplikací.
3.1.3. Objektově orientované programování v PHP Podpora OOP se v jazyce PHP objevila až s verzí 4. Jednalo se o zatím pouze o základní principy. Programátor mohl mimo jiné definovat a využívat vlastní třídy, jejich atributy a metody. Stále však chyběla podpora pro některé způsoby užití. Např. zcela
chyběla
podpora
modifikátorů
přístupu,
známých
z jiných
objektově
orientovaných či hybridních jazyků. Dále chyběla možnost použití abstraktních tříd. Všechny tyto nedostatky však odstranila verze PHP 5. Peter Lavin [10] popisuje původní nedůvěru ze strany programátorů a tvůrců webových aplikací k využívání objektových principů v PHP. Zejména právě slabá podpora ve verzi 4 jen utvrzovala názor některých, že PHP by mělo zůstat čistě skriptovacím jazykem a využívat procedurální postupy. V současné době je však využití OOP prakticky samozřejmostí. Jedním z důvodů jsou jistě zmiňovaná vylepšení ve verzi 5, ale hlavně přijetí samotné podstaty tohoto způsobu programování. To zajišťuje snadnou modifikovatelnost aplikací, znuvupoužitelnost konkrétních řešení, snazší a intuitivnější návaznost na UML modely atd. Především však PHP jakožto hybridní jazyk umožňuje stále používat oba způsoby programování. Programátor tak může využívat čistě procedurální přístup, objektový přístup, nebo vhodnou kombinaci obojího.
- 11 -
3.2. XHTML XHTML je jazyk pro tvorbu hypertextových dokumentů. Oproti klasickému HTML značkovacímu jazyku je patrné propojení určitých principů a pravidel pro zápis kódu s jazykem XML. Vývoj a definici pravidel a standardů zajišťuje konsorcium W3C. Validní dokument tak musí obsahovat odkaz na použitou definici DTD. Může být použita standardní definice W3C, uživatel si však může vytvořit vlastní DTD a používat tak při psaní dokumentu vlastní značky (tagy) a jejich strukturu. Oproti HTML se liší i některá pravidla pro zápis kódu. Zatímco HTML umožňuje použití neuzavřených nepárových tagů (např. , , ), v XHTML musí být i tyto tagy uzavírány. A to buď odpovídajícím uzavíracím tagem (, , ), nebo pomocí zkráceného zápisu, např. . Další pravidla, mimo jiné zákaz křížení tagů nebo povinnost udávat hodnoty atributů v uvozovkách, jsou obsaženy v dokumentaci W3C [23]. Dodržováním standardů pro zápis validních dokumentů by mělo být zajištěno korektní zobrazení stránek ve všech moderních prohlížečích.
3.3. CSS Použití kaskádových stylů (CSS, cascading style sheet) umožňuje upravovat vzhled stránek napsaných v (X)HTML. Je možné zapisovat kaskádové styly přímo do zdrojového kódu stránky, případně do atributu style jednotlivých tagů. Nejčastěji se však používá způsob zápisu CSS do odděleného souboru, čímž se výsledný kód značně zpřehlední. Pomocí kaskádových stylů lze měnit způsob zobrazení jednotlivých (X)HTML elementů, případně lze definovat vlastní třídy a přiřazovat jim konkrétní vlastnosti. Různé elementy se pak mohou přihlašovat k těmto třídám pomocí atributu class. Zobrazení jednotlivých elementů lze rovněž upravovat přes jejich atribut id. Styly umožňují definovat nejrůznější možnosti zobrazení. Kromě ovlivnění barvy textu, použitého fontu, nebo obrázku pozadí bývají kaskádové styly často využívány i pro určení rozložení jednotlivých prvků na stránce a definování celkové struktury zobrazeného dokumentu. Rovněž lze měnit použité styly v závislosti na konkrétním zobrazovacím médiu. Lze tedy jinak formátovat dokument pro zobrazení na monitoru a jinak pro tisk. - 12 -
3.4. JavaScript Hlavní předností skriptovacího jazyka JavaScript je to, že je interpretován až na straně klienta, tedy v internetovém prohlížeči. Tím umožňuje přenést část zátěže ze serveru a prohlížeč se stává tzv. „tlustým“ klientem. Ten neslouží již pouze k zobrazení výstupů, ale sám se podílí na vykonávání částí kódu aplikace. Skripty v jazyce JavaScript (zkráceně označovány jako „javascripty“) tak mohou například kontrolovat údaje odeslané z webového formuláře nebo ovládat nejrůznější interaktivní prvky (tlačítka, zaškrtávací políčka, textové vstupy). Javascripty umí přistupovat k jednotlivým elementům HTML kódu, měnit vlastnosti jejich atributů nebo kaskádových stylů. To přispívá ke značnému zvýšení interakce stránek a přiblížení dojmu klasické „desktopové“ aplikace. Nevýhodou využití tohoto jazyka je zejména fakt, že uživatel může podporu JavaScriptu ve svém prohlížeči vypnout. Často je tak činěno z bezpečnostních důvodů. Stránky pak mohou zcela přestat fungovat, nebo fungují s určitými omezeními. Dalším problémem je odlišná podpora v internetových prohlížečích. Je proto třeba kód optimalizovat pro různá prostředí a aplikaci testovat nejen na různých prohlížečích, ale i na různých verzích jednoho typu prohlížeče (skripty se mohou chovat jinak v Internet Exploreru 6 a jinak v Internet Exploreru 7). Základní postupy při psaní javascriptů jsou popsány v odborných textech a učebnicích [1][13][17][21]. Otázky spojené s kompatibilitou v různých prohlížečích a řešením konkrétních problémů bývají probírány na odborných webových serverech a v internetových diskusích [8].
3.4.1. AJAX Jedním z nejčastějších způsobů využití javascriptů je v současné době technologie AJAX a metody asynchronní komunikace se serverem. Zatímco původní přístup pro tvorbu dynamických webových stránek a aplikací vyžadoval po odeslání jakéhokoliv dotazu na server znovunačtení celé stránky, s využitím AJAXu prohlížeč odesílá a přijímá pouze části stránky, které je potřeba změnit.
- 13 -
4. Návrh systému 4.1. Specifikace požadavků Zadavatelem požadavků byl ing. David Viochna, MSc. ze společnosti Baxter BioScience spol. s r.o. Tato společnost se zabývá produkcí derivátů vyráběných z krevní plazmy. Zároveň je i výrobcem technologií pro odběr a separaci krve. Díky tomu, že společnost spolupracuje s řadou tuzemských transfuzních stanic, bylo možné shromáždit a vyhodnotit požadavky z většího množství konkrétních pracovišť.
4.1.1. Funkcionalita Systém bude podporovat procesy spojené s rezervací termínů odběru plazmy v transfuzní stanici. Kromě evidence uživatelových rezervací bude systém generovat základní statistické přehledy (počet rezervací, využití jednotlivých separátorů apod.). Systém bude umístěn na veřejně dostupném webovém serveru, uživatelé k němu budou přistupovat přes internet prostřednictvím libovolného internetového prohlížeče. Doba kdy je možné do systému přistupovat nebude nijak omezena. Klient – dárce krevní plazmy – bude své rezervace zadávat sám, prostřednictvím grafického uživatelského rozhraní. Pro tento účel bude muset mít zřízen uživatelský účet s jedinečnými přihlašovacími údaji. Bude však podporována i možnost zapsání dárcovy rezervace zaměstnancem transfuzní stanice (na základě osobní žádosti, nebo po telefonické dohodě). Aplikace bude navržena univerzálně, s nastavitelnými parametry, aby mohla být snadno nasazena do různých stanic. Případné modifikace, opravy a rozšíření systému bude možné aplikovat i během aktivního provozu, bez hrozby ztráty dat.
- 14 -
4.1.2. Uživatelé Aplikace bude mít 3 kategorie uživatel: •
Klient (dárce) – bude mít možnost zapsat (případně i zrušit) vlastní rezervaci, zobrazovat přehledy a statistiky svých rezervací a upravit vlastní nastavení
•
Recepce – zaměstnanec transfuzní stanice. Bude mít přístup k pokročilejšímu nastavení, možnost vytvářet uživatelské účty, zakládat a rušit rezervace jiných uživatelů
•
Správce – Mimo možností, které má „Recepce“, bude mít možnost nastavit základní parametry systému, určovat otevírací dobu a rozvrhy jednotlivých separátorů Uživatelé mohou mít různě vysokou úroveň zkušenosti práce s informačními
technologiemi. Zatímco zaměstnanci stanice budou při instalaci systému proškoleni v jeho využívání, klienti se s ním setkají poprvé až během užívání. Proto je nezbytné, aby ovládání bylo intuitivní a přehledné, zároveň musí mít uživatel vždy k dispozici nápovědu. Přestože se u aplikace tohoto typu nepředpokládá úmyslné zneužití, je třeba vytvořit bezpečnostní opatření, která by znemožnila byť i neúmyslné ohrožení bezpečnosti, zneužití osobních údajů uživatelů, případně ztrátu dat. Za tímto účelem bude aplikace obsahovat mimo jiné tato bezpečnostní opatření: •
Přihlášení pomocí e-mailu a hesla. Toto heslo nebude nikde zaznamenáno. Při ztrátě nebo zapomenutí si bude klient muset vygenerovat heslo nové. Systém bude odhlašovat neaktivní uživatele po uplynutí časového intervalu
•
Kontrola odesílaných dat. Jelikož je aplikace založena na interakci s uživatelem, je nutné kontrolovat všechny uživatelovy vstupy – např. data odeslaná pomocí formulářů, ale i parametry předávané v URL adrese
•
Evidence pouze nejnutnějších osobních údajů. Vzhledem k povaze systému postačí zaznamenávat pouze základní osobní údaje – jméno, příjmení, e-mail, případně i telefonní číslo
- 15 -
4.1.3. Základní postupy a pravidla používání V systému se budou uplatňovat následující pravidla a postupy: A, Provádění rezervací •
Klient se může zapsat pouze na budoucí termíny
•
Systém bude zobrazovat počet volných separátorů. Uživatel si může rezervovat pouze termíny s alespoň jedním volným separátorem. Systém musí zabránit konfliktu při zapisování dvou uživatelů na jeden separátor ve stejný čas
•
Mezi dvěma rezervacemi jednoho klienta musí být (nastavitelný) interval, během kterého nelze zapsat další rezervace
•
Uživatel si bude moci rezervovat termín i na delší dobu dopředu. Délka této doby bude limitovaná podle potřeb a požadavků transfuzní stanice
B, Vytváření a správa uživatelských účtů •
Klienti si sami nebudou moci vytvářet uživatelské účty. Ty jim budou vytvořeny zaměstnancem transfuzní stanice
•
Jako přihlašovací údaje bude sloužit e-mailová adresa a heslo. Uživatel si bude moci sám změnit pouze heslo, adresu nikoliv. Tu to možnost bude mít pouze správce systému
•
Klient si sám nebude moci změnit osobní údaje (jméno a příjmení)
C, Nastavení parametrů systému •
Bude možné nastavit otevírací dobu celé stanice, stejně jako individuální rozvrh pro jednotlivé separátory
•
Kromě běžného rozvrhu bude možné nastavit mimořádný rozvrh, např. během státních svátků, dovolených a mimořádných událostí
•
Aplikace bude umožňovat nastavení jména a loga stanice, uvítací zprávy a kontaktů
•
Tato nastavení bude moci provádět pouze uživatel s administrátorskými právy
- 16 -
4.1.4. Data Množství dat procházejících systémem do značné míry závisí na velikosti stanice, ve které bude systém nasazen, resp. na počtu dárců kteří ji navštěvují. Informace o rezervacích totiž představují největší část zpracovávaných dat. Další data budou tvořit informace o rozvrzích jednotlivých separátorů, a to jak pravidelných, tak mimořádných. Předpokládané hodnoty: Průměrný počet separátorů v jedné stanici ............... 8-10 Uživatelů v databázi ................................................. 1000 Průměrný počet rezervací 1 uživatele ...................... 1 za 3 týdny Omezení počtu rezervací .......................................... maximálně 35 za rok Pokud by každý dárce důsledně dodržoval počet 35 rezervací ročně, přibývalo by do databáze rezervací 35 000 záznamů ročně. Tato situace je však pouze čistě teoretická, takže hodnota je brána spíše jako horní limit. Podobným způsobem lze určit limitní hodnotu pro počet uložených rozvrhů separátorů. Pokud by na každý den v roce připadal mimořádný rozvrh stanice a každý separátor by měl unikátní rozvrh, tvořilo by data o rozvrzích 365 x 8 = 2920 záznamů. Na druhou stranu pokud by platil po celý rok stejný rozvrh pro všechny separátory, postačilo by pro zápis takové situace pouze 7 záznamů (na každý den v týdnu by připadal jeden rozvrh).
- 17 -
4.2. Případy užití Následující diagram popisuje možnosti, které bude systém uživatelům poskytovat.
Obr. 4.1. - Use case diagram
- 18 -
4.2.1. Doplňující charakteristiky Upřesnění vybraných případů užití: A, Přihlášení do systému •
Podmínky (preconditions): Uživatel musí mít zřízený vlastní účet
•
Související případ užití: Vytvořit nový účet (aktér: Recepce, Správce)
•
Postup (action steps): Uživatel vyplní přihlašovací údaje a odešle formulář
•
Úspěšné zakončení: Uživatel je přihlášen do systému
Související diagram aktivit na straně 20 B, Zapsat vlastní rezervaci •
Podmínky (preconditions): 1, Uživatel musí být přihlášený 2, Rozvrh jednotlivých separátorů je nastaven a alespoň jeden termín je volný
•
Související případ užití: Nastavit systém (aktér: Správce)
•
Postup (action steps): 1, Uživatel vybere volný termín ze zobrazeného rozvrhu (tabulky) 2, Potvrdí ověřující dialog
•
Úspěšné zakončení: Rezervace je zapsána do databáze a uživateli je poslán e-mail
Související diagram aktivit na straně 21 C, Zapsat cizí rezervaci •
Podmínky (preconditions): 1, Uživatel musí být přihlášený jako Recepce nebo Správce 2, Rozvrh jednotlivých separátorů je nastaven a alespoň jeden termín je volný 3, V systému je založený alespoň jeden účet typu Klient
•
Související případ užití: Nastavit systém (aktér: Správce)
•
Postup (action steps): 1, Uživatel vybere volný termín ze zobrazeného rozvrhu (tabulky) 2, Ze zobrazeného seznamu vybere konkrétního uživatele
•
Úspěšné zakončení: Rezervace je zapsána a uživateli je poslán e-mail
Související diagram aktivit na straně 21 - 19 -
4.3. Modely 4.3.1. Přihlášení uživatele do systému (Diagram aktivit)
Popis jednotlivých tříd: Rozvrh: Abstraktní třída, obsahující atributy a metody, které od ní přebírají její potomci. Každý rozvrh tak obsahuje údaje o aktuálním dni a datu, stejně jako údaje potřebné pro jeho zobrazení v tabulce. DenniRozvrh: Představuje rozvrh stanice pro konkrétní den. Je vyhodnocován na základě rozvrhů jednotlivých separátorů. Každému uživateli se může zobrazovat jinak (správci se zobrazují jiné údaje než dárci. Ten vidí pouze své rezervace, nikoliv rezervace jiných dárců apod.). Nejdůležitější metody této třídy pro samotné zobrazení jsou pak zobrazJakoTabulku() a zobrazVTabulce(). Umožňují vytvářet buď souhrnný přehled rozvrhů na více dnů, nebo detailní rozvrh pro jeden konkrétní den s podrobným zobrazením rozvrhů separátorů. RozvrhSeparatoru: Obsahuje údaje o otevírací době konkrétního separátoru. Umožňuje zobrazení v detailním denním přehledu díky metodě zobrazVTabulce(). Uživatel: Kromě základních údajů o uživateli (jméno, příjmení, úroveň apod.) obsahuje i údaje o jeho rezervacích. Všechny tyto údaje načítá z databáze, případně do databáze zapisuje. K tomu slouží příslušné metody třídy. Separator: Představuje údaje o jednotlivých separátorech. Díky statickým atributům třídy
pocetSeparatoru
a
vsechnySeparatory
umožňuje
systému
přistupovat
k jednotlivým separátorům bez nutnosti přistupovat do databáze. K té se přistupuje pouze při inicializaci rozvrhu, kdy třída Separator načte všechny údaje pomocí svých statických metod. Tento postup je zobrazen v sekvenčním diagramu na straně 24. Rezervace: Instance této třídy představují jednotlivé uživatelovy rezervace. Ty jsou primárně vytvářeny na základě uživatelovy aktivity (výběr termínu) a následně jejich data uložena do databáze. Třída umožňuje komunikaci s DB i pomocí statické metody.
- 23 -
4.3.4. Sekvenční diagram
Obr. 4.5. - sekvenční diagram Tento diagram popisuje spolupráci jednotlivých tříd. Na základě uživatelova požadavku na zobrazení rozvrhu jsou načteny rozvrhy separátorů. Z nich je vytvořen rozvrh daného dne a vygenerován XHTML kód. Díky němu pak může uživatel vybrat požadovaný termín a zapsat tak svou rezervaci. O úspěchu či neúspěchu zápisu je pak informován na základě hodnoty zapsano, která může nabývat hodnot true/false.
- 24 -
4.3.5. Stavový diagram
Obr. 4.6. - stavový diagram
- 25 -
4.3.6. Diagram nasazení
Obr. 4.7. - diagram nasazení Popis nasazení: •
Serverovou část aplikace budou tvořit PHP skripty. Na aplikačním serveru proto musí být nainstalován PHP parser. Skripty budou ke svému chodu vyžadovat PHP verze 5 a vyšší. Pro připojení k databázi bude sloužit standardní knihovna php_mysql. Jednou z dalších možností by bylo použít vylepšené php_mysqli, ale to během testovacího provozu vykazovalo nečekané chyby (pád aplikace, odpojování od serveru).
•
Bude použit MySQL databázový server. Data budou uložena s UTF-8 kódováním.
•
Klientská část aplikace poběží ve webovém prohlížeči. Úlohu „tenkého“ klienta budou plnit vygenerované XHTML stránky. Část aplikační logiky však budou vykonávat přímo na straně uživatele skripty v Javascriptu, čímž budou plnit roli „tlustého“ klienta.
- 26 -
4.3.7. ERA diagram Navrhovaná struktura databáze: Pozn.: tabulky se zaoblenými rohy představují slabé (popisné) entity
Obr. 4.8. - ERA diagram
- 27 -
5. Implementace Tato část práce obsahuje způsoby řešení jednotlivých funkcí aplikace v již hotovém programu. Cílem je poukázat na některá konkrétní řešení na úrovni zdrojového kódu. Dále popsat a zdůvodnit strukturu a chování použitých objektů.
5.1. Serverová část aplikace Základním souborem je index.php. Kód v tomto souboru je zpracován po zadání URL adresy aplikace. Rozložení stránky je pak definováno v souboru dokument.php, který se načítá po inicializaci tříd a proměnných, potřebných pro chod aplikace. Na základě uživatelových akcí se k základnímu kódu obsaženému v tomto souboru připojují konkrétní skripty pomocí PHP funkce include. Požadovaná akce se předává v proměnné $akce jako součást URL adresy. Akce je poté vyhodnocena a pomocí řídící struktury switch. Příklad kódu: if (isset($_GET['akce']))
$akce = $_GET['akce'];
switch ($akce) { case "iuzivatel": include '/zobrazeni/akce/iuzivatel.php'; break; case … //další možné akce default: include '/zobrazeni/akce/tyden.php'; break;
Pro práci s třídami je využita funkce _autoload, představená v PHP 5. Bez ní vždy musela být požadovaná třída buď přímo součástí skriptu, který ji chtěl využít, nebo k němu musela být alespoň připojena pomocí funkce include_once (případně require_once). Použití funkce autoload: function __autoload($nazev_tridy) { require_once $nazev_tridy . '.php'; }
Např. pokud je třeba vytvořit novou instanci třídy ‘Tabulka’ pomocí příkazu new Tabulka, připojí se kód souboru Tabulka.php. Kód třídy se tedy připojí až když
je skutečně vyžadován, čímž se zefektivňuje chod aplikace a zpřehledňuje kód. - 28 -
5.1.1. Pomocné třídy Kromě základních tříd, zhotovených na základě návrhu systému (viz diagram tříd na straně 22), obsahuje program řadu tzv. pomocných tříd, které slouží k vykonávání specifických úkolů. Tabulka usnadňuje tvorbu jednoduchých tabulek. Lze v ní nastavit jednotlivé parametry požadované tabulky, jako např. počet sloupců, šířku (v pixelech nebo procentech), styl vykreslování sudých a lichých řádků. Díky metodě addRow lze přidávat jednotlivé řádky tabulky jako pole hodnot. Metoda displayTable() pak na základě nastavených parametrů vygeneruje HTML kód tabulky. Příklad použití – tabulka pro výpis jména a příjmení uživatel v databázi: $vysledek = … //vysledek dotazu na DB uzivatel $tabulka = new Tabulka; $tabulka->numCols = 4; $tabulka->headings = array ("Příjmení","jméno"); while ($radek = mysql_fetch_array($vysledek)) { $tabulka->addRow($radek); } $tabulka->displayTable();
Formular na rozdíl od Tabulky neslouží přímo ke generování kódu, ale k zaznamenávání hodnot a chyb, získané při vyhodnocování formulářů. Každý skript pracující s formuláři využívá instanci této třídy. V případě nalezení jakékoliv chyby (nevyplnění povinné položky, špatný formát e-mailu apod.) zaznamená údaje o této chybě k příslušné položce formuláře. Příklad použití – obsluha přihlašovacího formuláře: Část kontrolního skriptu: if(!$heslo){ $formular->nastavChybu("heslo", "* heslo nebylo zadáno"); }
Část skriptu se zobrazením formuláře: echo $formular->error("heslo");
Pokud je helso správně zadáno, nezobrazí se nic. Jakmile však heslo není zadána, zobrazí se příslušné oznámení chyby. Další pomocné třídy jsou zmíněny přímo v následujících kapitolách.
- 29 -
5.1.2. Přihlášení uživatele Klíčovou roli při přihlašování hrají pomocné třídy Process, Session a Databaze. Uživatel prostřednictvím formuláře odešle metodou POST své přihlašovací údaje. Třída Process (resp. její instance) vyhodnocuje právě data odeslaná prostřednictvím formulářů a předává je k dalšímu zpracováním. Ověření jejich správnosti pak probíhá s využitím třídy Databaze, která v tomto případě zajišťuje přístup do tabulky s uživatelskými údaji v databázi. Instance třídy Session pak umožňuje vytvářet session proměné, uchovávající informace o přihlášeném uživateli. Na rozdíl od běžných proměnných zůstávají hodnoty session uložené v globálním poli $_SESSION. Jednotlivé skripty mohou k těmto hodnotám přistupovat nezávisle, tj. nemusí si je explicitně předávat např. jako parametry v URL adrese. Systém v tuto chvíli ověří, že jsou v pořádku nastavené sessions a obsahují informace o uživateli. Již pak nezobrazuje přihlašovací formulář, ale úvodní stranu aplikace.
5.1.3. Vytvoření rozvrhů Jednou z nejdůležitějších funkcí aplikace je vytvoření rozvrhů na základě nastavené otevírací doby. Spolupráce s databází Záznamům v tabulce separator odpovídá záznam v tabulce rozvrh. Jsou propojeny přes atribut id_separatoru. Takto lze nastavit pro každý separátor individuální rozvrh na každý den v týdnu (hodnota vyjadřující číslo dne v týdnu je uložena v atributu den). Pokud je v určitý den stejný rozvrh pro všechny separátory, použije se pouze jeden záznam v tabulce rozvrh a do id_separatoru se vloží hodnota 0. Toto slouží pro snížení nároků na databázi. Např. v případě 10 separátorů při stejné otevírací době od pondělí do pátku postačí pouze 5 záznamů. Pro případ mimořádných událostí (státní svátky, prázdniny apod.) je zavedena tabulka udalosti. Tam se zaznamenává nejen popis události, ale zejména od kdy do kdy trvá. Pokud je rozvrh spojen s konkrétní událostí, je id této události uloženo do atributu id_udalosti. U těchto rozvrhů pak není nastavena hodnota den (resp. je nastavena na NULL), neboť se nejedná o rozvrh pro konkrétní den v týdnu, ale pro celé období trvání události.
- 30 -
Příklad: Udalosti id_udalosti popis zacatek 10 Vánoce 2009-12-23 11 Silvestr 2009-12-31
id 1 2 3 4 5
den 1 2 2 NULL NULL
otevreno 1 1 1 0 1
konec 2009-12-25 2009-12-31
Rozvrh od do 08:00 18:00 08:00 18:00 10:00 14:00 NULL NULL 08:00 12:00
Separator id_separatoru nazev 1 Jednička 2 Dvojka
id_separatoru 0 1 2 0 1
id_udalosti NULL NULL NULL 10 11
Tabulka 5.1. až 5.3. – Příklady údajů v databázových tabulkách Rozbor záznamů v tabulce Rozvrh: •
V pondělí (den=1) mají všechny separátory otevřeno od 8 do 18 hodin
•
V úterý (den=2) má separátor „Jednička“ otevřeno od 8 do 18, „Dvojka“ od 10 do 14
•
Na Vánoce je zavřeno (od 23.12 do 25.12.2009)
•
Na Silvestra má separátor „Jednička“ rozvrh pouze od 8 do 12
SQL dotazy: Třída DenniRozvrh ve své metodě nactiDenniRozvrh nejprve kontroluje, zda na daný den připadá nějaký rozvrh, nebo jestli je ten den zavřeno. K tomu využívá atribut třídy cisloDne a proměnnou datumDBformat, které vytvoří ze zadaného data: $this->cisloDne = date("N", $datum);
První SQL dotaz je pak formulován takto: SELECT otevreno, id_separatoru, id_udalosti, popis FROM rozvrh LEFT JOIN udalosti USING(id_udalosti) WHERE den=".$this->cisloDne." OR (zacatek<='$dateDBformat' AND konec>='$dateDBformat ')
Výsledek tohoto dotazu pak určuje způsob načítání rozvrhů jednotlivých separátorů. Pokud ani jeden ze řádků výsledku neobsahuje otevreno=1, není tento den otevřeno a není třeba načítat další data. Pokud hodnota id_udalosti není nulová, jedná se o mimořádný rozvrh. Rozvrhy separátorů jsou pak načítány i s informacemi o mimořádné události. - 31 -
5.1.4. Generování tabulek rozvrhů Systém
generuje tyto
tabulky na základě
nastavení
otevírací
doby,
zaznamenaných rezervací, uživatelovy úrovně a dalších kritérií. Jednotlivé buňky odpovídají časovým úsekům. Záleží pak na stavu konkrétní buňky, jaké akce s ní mohou být spojeny. Pro tento účel je vytvořena třída Bunka. Ta může nabývat dvou stavů – aktivní/neaktivní. S neaktivními buňkami nemohou být spojeny žádné akce. Většinou tyto buňky představují dobu kdy je zavřeno, jsou vyčerpány všechny volné separátory apod. Pomocí aktivních buněk pak může uživatel provádět požadované akce, nejčastěji tedy zapsat rezervaci. Buňky dále mohou být několika typů - ty pak odpovídají právě důvodu jejich (ne)aktivity. Tyto typy mají význam zejména pro samotné zobrazení buňky (např. buňka typu „obsazená“ bude zobrazena s červeným pozadím), rozhodují o použitém popisku (tooltipu) a samotném textu, který bude buňka obsahovat. Podle typu se pak také rozhoduje o použitém obslužném javascriptu. Třída Rozvrh a její dva potomci – DenniRozvrh a RozvrhSeparatoru – slouží jednak k uchovávání informací o otevírací době, ale mají i funkce pro generování a zobrazování těchto interaktivních tabulek. Instance třídy DenniRozvrh umožňují dvojí zobrazení – „v tabulce“ a nebo „jako tabulku“. Zobrazení v tabulce slouží při zobrazení rozvrhů pro více dnů najednou, např. v rámci jednoho týdne. Denní rozvrhy pak představují jednotlivé řádky. Příklad: Dva denní rozvrhy. Čísla představují počet separátorů (volné/celkem). Pondělí 1.1.2009 Úterý 2.1.2009
10:00 1/2 Zavřeno
11:00 0/2 Zavřeno
12:00 1/2 6/6
tabulka 5.4. – rozvrhy v tabulce Pokud je denní rozvrh zobrazen jako tabulka, představují řádky jednotlivé separátory. Příklad: Zobrazení denního rozvrhu jako tabulky. X představuje obsazený separátor. Pondělí 1.1.2009 Separátor 1 Separátor 2
10:00
11:00 X O
12:00 X X
tabulka 5.5. – rozvrh jako tabulka
- 32 -
X O
Pro zobrazení tabulky jsou pak důležité 3 metody: •
vytvorHlavicku() – vygeneruje záhlaví tabulky s nadpisem a časy, kterým odpovídají jednotlivé buňky.
•
vytvorRadek($nadpis) – vytvoří nový řádek, na jeho úvod napíše požadovaný nadpis a řádek vyplní jednotlivými buňkami. O způsobu vyplnění rozhoduje další funkce: naplnBunku ($zacatekBunky). Tuto metodu pak překrývají oba potomci třídy Rozvrh. Na základě informace o čase, kterému buňka odpovídá, vybere vhodný typ buňky.
•
vytvorZapati() – slouží k vygenerování XHTML tagů pro uzavření tabulky
Samotné generování řádku v metodě vytvorRadek probíhá následujícím způsobem: 1. Na základě nastavení systému se určí počáteční a koncový čas. 2. Interval mezi těmito časy se vydělí dálkou jednoho odběru. Tím se zjistí, kolik buněk je třeba na jeden řádek vložit. 3. Pomocí cyklu for vkládá jednotlivé buňky na řádek, funkce naplnBunku rozhoduje o použitém typu buňky.
5.1.5. Časové razítko Pro vyjádření času se v programu využívá tzv. časové razítko (timestamp, resp. Unix timestamp). Čas je vyjádřen celým číslem, které představuje počet vteřin od půlnoci 1.ledna 1970, tedy tzv. koordinovaného světového času (UTC). PHP nabízí řadu funkcí pro převod data a času na časové razítko (např. strtotime, mktime) a opačně (date). Jelikož je čas vyjádřen jako celé číslo, je možné s ním provádět různé matematické operace. Např. délku intervalu lze vyčíslit tak, že se odečte časové razítko, představující začátek intervalu, od razítka konce. Výsledek pak lze např. vydělit číslem 3600 a získat tak délku intervalu v hodinách. Jelikož žádné dvě razítka představující různé časy nemohou být shodná, je toto číslo využito i jako jednoznačný identifikátor každé buňky v tabulce rozvrhu. Do atributu id HTML tagu
je proto vložena hodnota „b_[hodnota časového razítka]”. Dle standardů W3C nesmí identifikátor id začínat číslicí, proto obsahuje ještě předponu b_ (buňka). Tento identifikátor je pak základem pro komunikaci s obslužnými javascripty, které umožňují vybírat prvky na stránce právě na základě atributu id. - 33 -
Problém s exponenciálním tvarem Během testovacího provozu aplikace se na některých serverech vyskytovala zvláštní chyba. V případě některých buněk rozvrhu nebyl javascript schopen z časového razítka určit datum a zobrazoval nesmyslné hodnoty. Ukázalo se, že příčinou byl automatický převod některých čísel na exponenciální tvar. PHP totiž automaticky převádělo velká čísla končící na pět a více nul na jejich vyjádření pomocí vhodné mocniny deseti. Např. časové razítko představující 30.3.2009 10:00 je rovno 1238400000. PHP však tento tvar převedlo na 1,2384E+9. Tuto hodnotu javascript vyhodnotil jako textový řetězec a nebyl schopný z něj určit časový údaj. Pro zabránění této nechtěné konverzi na exponenciální tvar byla použita funkce intval. Ta vrací přesnou celočíselnou hodnotu zadané proměnné. Pokud je tedy potřeba uložit časové razítko, použije se konstrukce: $cas = intval($cas);
5.1.6. Zaznamenávání rezervace Pokud uživatel potvrdí požadovaný termín v tabulce rozvrhu, vytvoří se nová instance třídy Rezervace.
Parametry konstruktoru této třídy jsou: časové razítko
představující vybraný termín, id separátoru a uživatel, pro kterého bude rezervace zapsána (objekt typu Uzivatel). Tato instance pak zavolá svojí metodu zapisDoDB, která spustí následující SQL dotaz na databázi: INSERT INTO rezervace (id_uzivatele, datum_cas, id_separatoru) VALUES (".$this->uzivatel->getId().", '$this->casDBformat', $this->separator)
Systém však ještě kontroluje, zda nebyla mezitím obsazena zbývající volná místa. Uživatelské rozhraní totiž zobrazí aktuální počet volných separátorů pouze při aktualizaci stránky s rozvrhem. Může se tedy stát, že mezitím poslední volné místo bylo obsazeno a uživatel o tom neví, neboť si stránku neobnovil. Pro řešení těchto konfliktů slouží metoda jeMozneZapsat, která před samotným zapsáním do databáze ověří, zda ještě nějaké volné místo opravdu zbývá.
- 34 -
5.1.7. Nastavení systému Jelikož základním požadavkem na aplikaci je její snadná modifikovatelnost, je převážná většina jejích parametrů nastavitelná. Parametry aplikace jsou umístěny v souborech konstanty.php a db_config.php v adresáři /config. Mezi tyto parametry patří: •
nastavení
přístupu
k databázi
–
údaje
jsou
uloženy
v konstantách
DB_SERVER, DB_LOGIN, DB_HESLO a DB_DATABAZE. Tyto konstanty pak vstupují do všech skriptů, které se připojují k databázi a v případě změny některého z údajů postačí pouze změnit hodnotu příslušné konstanty. •
názvy databázových tabulek - tyto nejsou v SQL dotazech pevně nastaveny, ale rovněž využívají konstanty (např. TBL_REZERVACE=’rezervace’). V praxi může nastat situace, kdy by docházelo ke konfliktu názvů tabulek v jedné databázi. Aby při změně názvu tabulky nebylo nutné měnit všechny SQL dotazy v programu, jsou tímto způsobem soustředěny na jedno místo.
•
ostatní - nastavení doby platnosti cookies, doba neaktivity po které je uživatel automaticky odhlášen apod. Parametry tohoto typu je tedy možné upravit pouze editací souborů, ve kterých
jsou definovány. Není možné je měnit prostřednictvím uživatelského prostředí aplikace. Naproti tomu parametry konkrétní transfuzní stanice jsou uloženy v databázi, v tabulce nastaveni. Uživatelské prostředí umožňuje jejich nastavení pomocí formuláře v administrátorské sekci systému. Uživatel musí být přihlášen jako správce, aby k nim měl přístup. Tyto parametry jsou: název stanice, nadpis stránky, obrázek s logem, kontaktní informace, délka jednoho odběru, výhled (na kolik dní dopředu se má rozvrh zobrazovat), interval mezi dvěma rezervacemi. Pro uchovávání hodnot těchto parametrů slouží při běhu programu třída NastaveniSystemu. Ta při spuštění aplikace načte hodnoty z databáze a pak je dává k dispozici jako statické atributy. Například soubor pro zobrazení úvodní strany tak pro zobrazení názvu stanice využívá následující kód:
- 35 -
5.1.8. Použité návrhové vzory A, Jedináček (Singleton) Použití tohoto vzoru zajišťuje, že bude vytvořena pouze jedna instance určité třídy. Tuto vlastnost využívá třída Databaze, u které by vytvoření více instancí bylo nežádoucí. Vzniklo by tím více současných připojení k databázi, což PHP nepodporuje a skript by skončil s chybou. Základní myšlenkou tohoto návrhového vzoru je znepřístupnění konstruktoru třídy nastavením modifikátoru jeho přístupu na private. V případě, že program potřebuje instanci této třídy, nevytváří novou (new Databaze), ale volá její statickou metodu getInstance (Databaze::getInstance() ). Tato metoda je definována takto: public static function getInstance(){ if(self::$instance == NULL ){ self::$instance = new Databaze; } return self::$instance; }
Ve statickém atributu je tedy uchována jediná instance. Při prvním volání této metody je vytvořena a uložena, při dalších volání metoda pouze vrací odkaz na již existující instanci. B, MVC Vzor Model-View-Controller (Model-Pohled-Ovladač) byl použit pro obsluhu administrátorské části aplikace. Spočívá v tom, že od sebe odděluje skripty na zobrazovací (generují výstupní kód), datové modely (obsahují metody pro přístup k databázi a uchovávají hodnoty ve svých atributech) a skripty s obslužnou logikou. Jednotlivé skripty jsou rozděleny do příslušných adresářů a každý plní svoji odpovídající funkci. Příklad využití: PravidelnyRozvrhOvladac vytvoří nový objekt (model) PravidelnyRozvrh. Ten pomocí příslušných metod načte data z databáze a je předán příslušnému „pohledu“ PravidelnyRozvrhNastaveni. Ten zobrazí data z tohoto modelu jako tabulku a umožní nastavit příslušné hodnoty. Ty jsou pak opět zpracovány ovladačem a uloženy do databáze.
- 36 -
5.1.9. Zabezpečení V této kapitole jsou popsány způsoby řešení bezpečnostních prvků. Jedná se o nejčastěji řešené bezpečnostní otázky. Přesto, že je řešení poměrně snadné, bývají níže popsané situace často podceňovány, což může vést k řadě problémů. Nejčastěji únik informací o uživatelích, případně i ztráta dat. Způsoby řešení jsou popsány v řadě publikací, ale i na nejrůznějších diskusních fórech a návodech pro PHP programátory. Postupy použité v aplikaci jsou popsány v [19]. A, Uložení hesla Heslo je hlavním prvkem při ověřování totožnosti uživatele při jeho přihlašování do systému. Zadané heslo je porovnáno s údajem v databázi. Tam se však neukládá přesné znění hesla, nýbrž jen jeho zápis, zašifrovaný pomocí MD5 algoritmu. Díky tomu ani správce systému s přístupem do databáze nezná hesla uložených uživatel. Jelikož heslo není nikde přímo zaznamenáno, nemůže být v případě ztráty znovu sděleno uživateli, ale musí mu být vygenerováno heslo nové. V PHP existuje pro vytvoření zmiňovaného zápisu (označovaný jako otisk, případně hash) funkce md5. Při přihlašování se tedy neporovnávají přímo hesla, ale jejich otisky. B, PHP injection Situace, při které dojde k vložení cizího skriptu do běžící aplikace, bývá označována jako PHP injection. Nejčastěji se tak stává v případech, kdy se k běžícímu skriptu připojují jiné pomocí funkcí include a require. Jedná se i o situaci, která je popsána v samém úvodu kapitoly „Implementace“. Na základě parametru $akce přijatém v URL adrese aplikace připojuje související skript. Kdyby byl skript napsán pouze formou include '/$akce', představoval by značné riziko. Pokud by útočník zadal vlastní URL adresu, mohl by vložit vlastní škodlivý skript. Např. tímto způsobem: index.php?akce= http://domena.cz/skodlivyskript.php
- 37 -
C, SQL injection V URL adrese jsou obsaženy hodnoty, které jsou následně použity v SQL dotazech. Např. pro vyhledání uživatele v databázi může být předáno jeho id v parametru $id. URL adresa pak vzpada např. takto: index.php?akce= vyhledejuzivatele&id=13 Skript pro vyhledávání pak může obsahovat SQL dotaz: $dotaz = “SELECT FROM uzivatele WHERE id_uzivatele = $id“
Útočník by však mohl změnit hodnotu parametru id v URL například na: index.php?akce= vyhledejuzivatele&id=13;DROP TABLE uzivatele Výsledný SQL dotaz by tedy byl: SELECT FROM uzivatele WHERE id_uzivatele = 13; DROP TABLE uzivatele
Jako ochranu proti SQL injection je využita PHP funkce mysql_real_escape_string. Ta vrací pouze takový textový řetězec, který je vhodný pro použití v SQL dotazu. Pokud takový řetězec není možné vytvořit, vrací false.
- 38 -
5.2. Klientská část aplikace Tato kapitola popisuje část aplikace běžící na straně klienta, tj. v internetovém prohlížeči. Kromě popisu uživatelského rozhraní vysvětluje princip fungování asynchronních dotazů a vybraných javascriptů.
5.2.1. Uživatelské rozhraní
Obr. 5.1. – úvodní strana (pohled správce) Hlavním prvkem aplikace jsou interaktivní tabulky s rozvrhy (na obrázku 5.1. označeny číslem 5). Ty jsou proto zobrazeny na úvodní straně a uživatel k nim má přístup ihned po přihlášení. Rozmístění ovládacích prvků odpovídá rozložení v jiných internetových aplikacích (např. Google Docs, e-mailové webové klienty apod.). Respektuje tak zásady použitelnosti internetových aplikací [4] (s.171-191) . Uznávaný odborník Jakob Nielsen na toto téma uvádí zásadu pro design webových stránek. „Uživatel stráví většinu času na jiných stránkách. Své zkušenosti a očekávání si tak utváří tam a není žádoucí nutit ho měnit jeho zaběhlé principy“ [14].
- 39 -
Přihlášený uživatel tak vidí své jméno v pravém horním rohu, kde se nacházejí i volby pro úpravu účtu, případně odhlášení (číslo 1). Jednotlivé sekce systému jsou přístupné přes menu s ikonkami (číslo 3). Položky v menu se liší podle úrovně přihlášeného uživatele. Nejčastěji využívané funkce, v tomto případě „Zobrazit denní rozvrh“ a „Přidat uživatele“, jsou zobrazeny v levém horním rohu (číslo 4). Tedy v místě, odkud většina uživatel začíná prohlížet stránku. Název stanice, logo, úvodní zpráva a kontakty na stanici (číslo 2) mohou být nastaveny v administrátorské sekci. Tyto údaje jsou zobrazeny po celou dobu, mění se pouze obsah části stránky pod nimi. Administrátor má možnost sledovat všechny uživatele, kteří jsou přihlášení k systému. K tomu slouží spodní část stránky (číslo 6). Jména jsou zobrazena jako odkazy, po kliknutí na jméno uživatele se otevře jeho profil. Ukázky dalších částí uživatelského rozhraní jsou v příloze A, popis ovládání a návod k obsluze je k dispozici na přiloženém CD.
B, Tlačítka – pro označení tlačítek rovněž slouží standardní XHTML tagy, konkrétně . Mimoto jako interaktivní tlačítka vystupují i jednotlivé buňky tabulky s rozvrhem. Základem je atribut onclick, ve kterém je definovaná příslušná funkce z obslužného javascriptu. Ukázka použití: Pokud je v určitý čas volný alespoň jeden separátor, je příslušná buňka v tabulce s rozvrhem zobrazena zeleně a plní roli tlačítka. Po stisknutí se uživateli rezervuje vybraný termín. Buňka tabulky, resp. XHTML tag
má definovány atributy id a onlclick například takto:
Funkce rezervuj(prvek) je definována v obslužném javascriptu ‘rozvrh.js’. Při zavolání této funkce je jí předán odkaz na vybranou buňku. Její id rozdělí pomocí funkce split na jednotlivé části a použije je jako parametry pro další funkce. Jednou se součástí id je i časové razítko, které odpovídá vybranému datu a času. Podle W3C standardu [23] nesmí atribut id začínat číslicí, proto na začátku obsahuje předponu „b_“. Krom toho, že funkce rezervuj předává parametry pro funkce, spojené se samotným zápisem rezervace do databáze (více v kapitole „Asynchronní dotazy“), předává odkaz na buňku funkci oznac(predmet). Ta zvýrazní vybranou buňku oranžovou barvou, díky možnosti javascriptu měnit atributy CSS stylu. predmet.style.backgroundColor = "#FFCC66";
Tímto způsobem je zajištěna zpětná vazba pro uživatele, který tak vidí, že vybrána je opravdu požadovaná buňka. - 41 -
C, Skrytá okna – jsou zobrazována pouze v případě, že se od uživatele čeká ještě nějaká doplňující akce. Nejčastěji se jedná o potvrzující dialogy s možnostmi Ano/Ne. Pomocí skrytého okna je řešen mimo jiné i seznam uživatel, který se zobrazí v případě zápisu cizí rezervace správcem systému (resp. uživatelem s právy pro zápis cizích rezervací).
Obr. 5.2. – okno se seznamem uživatelů Tato okna jsou řešena pomocí HTML oddílů
, které mají standardně nastavený CSS atribut display=none. Díky tomu jsou přítomné v HTML kódu (a může tak k nim přistupovat javascript) , nejsou ale zobrazené na výstupní stránce. Po zavolání spouštěcí funkce, resp. po provedení akce se kterou je spojeno zviditelnění skrytého okna, nastaví javascript hodnotu atributu display na „block“ a okno se zobrazí. Pro zajištění pozice okna na středu stránky je nastaven CSS atribut position na hodnotu „aboslute“. Pomocí hodnot atributů x a y je pak učena přesná poloha okna. Jelikož okna musí být v popředí, tj. překrývat veškerý obsah pod nimi, je nastavena hodnota z-index na 10. Standardní hodnota u ostatních prvků je 0. Hodnota 10 je tedy použita spíše pro jistotu. Teoreticky by stačila hodnota 1. Jelikož tyto vlastnosti musí mít všechna skrytá okna, jsou v rámci CSS definovány v třídě .neviditelny. Každý oddíl má tedy definovaný HTML atribut class=“neviditelny“, čímž získává požadované hodnoty CSS atributů.
- 42 -
5.2.3. Asynchronní dotazy Jak již bylo pospáno v úvodní kapitole „AJAX“, spočívá asynchronní dotazování mimo jiné v komunikaci klienta se serverem bez nutnosti znovu načítat celý obsah stránky. Těchto dotazů může být vykonáno i více najednou, což je podstatný rozdíl oproti dřívějšímu přístupu v tvorbě webových aplikací. Ve vytvořeném rezervačním systému je využito asynchronní dotazování pro tyto aktivity: a, zaznamenání/zrušení rezervace – javascript přejímá z vybrané buňky časové razítko, které odpovídá datu a času rezervace. To je odesláno v asynchronním dotazu na server, kde PHP skript vykoná SQL dotaz na tabulku s rezervacemi. Výsledek dotazu je pak předán zpět javascriptu, který změní pouze určitou část stránky. Konkrétně text v tzv. „informačním oddílu“. Ten je do této chvíle skrytý, v případě úspěchu je zobrazen se zeleným pozadím a informuje o úspěšném vykonání dotazu. b, zobrazení seznamu uživatelů – javascript opět pomocí dotazu na server (potažmo na databázi) získá jména registrovaných uživatelů, zviditelní skryté okno a vloží do něj tento seznam. c, listování tabulkami s rozvrhy – uživatel má možnost zobrazovat rozvrhy na další týdny pomocí příslušných tlačítek. I při této aktivitě se však mění pouze tabulky s rozvrhy, zbytek stránky zůstává beze změny. d, mazání záznamů – pokud je zobrazen tabulkový výpis hodnot (např. seznam uživatel, výpis rezervací, přehled separátorů apod.), má uživatel možnost odstranit záznam pomocí tlačítka na příslušném řádku. V tom případě je opět vykonán dotaz, který pomocí id získaného javascriptem odstraní tento záznam z databáze. Po úspěšném vykonání dotazu je odstraněn příslušný řádek z tabulky. e, změna vybraného separátoru – uživateli je po potvrzení rezervace přidělen první volný separátor. Správce mu však může přidělit separátor jiný. Tato akce s skládá hned ze dvou asynch. dotazů. V prvním se správci zobrazí okno se separátory, které jsou pro vybraný čas také dostupné. Po vybrání požadovaného separátoru se vykoná dotaz na úpravu údaje v databázi rezervací a je překreslena tabulka s detailním rozvrhem.
- 43 -
Ukázka kódu: Funkce pro vykonávání asychronních dotazů jsou umístěny v souboru javascript/asynchronni.js. Pro zahájení přenosu je třeba vytvořit požadavek, tzv. request object. Jelikož Internet Explorer využívá jiný druh požadavku než ostatní prohlížeče, je třeba v této fázi rozlišit, o jaký prohlížeč se jedná. Použité řešení je popsáno v [18] (str. 20-22) req = initRequest(); function initRequest() { if (window.XMLHttpRequest) { if (navigator.userAgent.indexOf('MSIE') != -1) { isIE = true; } return new XMLHttpRequest(); } else if (window.ActiveXObject) { isIE = true; return new ActiveXObject("Microsoft.XMLHTTP"); } else { return false; } }
Dále je definován cílový PHP skript, zadáním jeho URL adresy. Do URL lze samozřejmě přidávat parametry dotazu. V tomto příkladu předáváme id vybrané buňky. var url = "automatickeDoplneni.php?bunkaId=" + id_bunky; req.open("GET", url, true);
Je určena funkce, kterou má javascript vykonat, jakmile dostane odpověď na odeslaný dotaz. Kód v příkladu nejprve najde na stránce prvek s id=”jmena” (jedná se o jedno ze skrytých oken) a upraví jeho XHTML kód podle odpovědi serveru na zaslaný požadavek. req.onreadystatechange = callback1; function callback1() { jmena = document.getElementById("jmena"); jmena.innerHTML = req.responseText; }
Nakonec je požadavek odeslán. req.send(null);
- 44 -
5.3. Testování aplikace Výsledná aplikace byla po dokončení spuštěna na veřejně přístupném serveru a testována jak z hlediska funkcionality, tak z přehlednosti a použitelnosti uživatelského rozhraní. Cílem bylo odhalit případné chyby v programu a otestovat, zda uživatelské rozhraní bude pro uživatele intuitivní a přehledné. Testu se zúčastnilo 9 osob. Jedním z nich byl zadavatel požadavků a vedoucí práce, dále pak dvě zaměstnankyně transfuzní stanice, zbytek byli náhodně vybraní dobrovolníci, kteří se systémem před samotným testováním nepřišli do styku. Testování probíhalo na platformách: Windows XP; Windows Vista; Ubuntu 8.04; Solaris 10. Internetové prohlížeče použité při testování: Internet Explorer 6, 7 a 8; Mozzila Firefox 3, Opera 9, Konqueror (Ubuntu verze). Během testování nebyly nalezeny žádné vážné nedostatky, které by zabraňovaly používání aplikace. Menší chyby byly odstraněny ihned po odhalení a do konečné verze programu se nedostaly. Testování uživatelského rozhraní probíhalo formou tzv. „usability testu“. Uživateli byly zadány různé úkoly (např. vytvořit nový uživatelský účet, nastavit pokročilý rozvrh, zrušit rezervaci jiného uživatele apod.). Zatímco tyto akce vykonával, musel nahlas komentovat veškeré své počínání, včetně svých názorů na to, jak s ním aplikace komunikuje a jak reaguje na jeho podněty. Na základě výsledků těchto testů bylo uživatelské rozhraní upraveno. Mělo by tak splňovat podmínku snadného a intuitivního ovládání.
- 45 -
6. Závěr 6.1. Zhodnocení splnění požadavků Cíl práce, tj. vytvoření funkčního jádra rezervačního systému, se podařilo splnit. Během práce se navíc podařilo aplikaci vylepšit natolik, že může být bez nutnosti větších úprav používána jako plnohodnotný rezervační systém. Tento systém tedy již ve stávající podobě splňuje všechny požadavky, které byly definovány v úvodní specifikaci, případně které byly upřesněny během konzultací se zadavatelem. Díky objektově orientovanému přístupu lze aplikaci dále snadno rozšiřovat a modifikovat přidáním nových tříd, případně přidáním nových metod do tříd stávajících. Jedním z hlavních požadavků bylo snadné nastavení parametrů rezervačního systému. I tento požadavek se podařilo úspěšně splnit. Správce systému má možnost upravovat základní nastavení, definovat libovolnou otevírací dobu stanice (s možností přiřadit specifický rozvrh jednotlivým separátorům) a ovlivňovat pravidelnou otevírací dobu v případě mimořádných událostí. Design uživatelského rozhraní vychází za současných standardů. Při vývoji byl kladen důraz na intuitivnost a snadné osvojení ovládání. Systém tak nevyžaduje po uživateli vysokou úroveň práce s informačními technologiemi. Součástí aplikace je i podrobný návod. Dostupnost a použitelnost ovládacích prvků není negativně ovlivněna použitým internetovým prohlížečem. Díky použití technologie AJAX je zajištěn rychlejší a plynulejší chod aplikace. Uživatel není nucen čekat na znovunačtení celé stránky po každé své akci. Mění se pouze části, které s touto akcí souvisejí. Systém respektuje zásady bezpečnosti internetových aplikací. Předchází útokům typu PHP injection a SQL injection. Hlavním zabezpečovacím prvkem pro identifikaci uživatelů je heslo, jehož přesné znění není nikde zaznamenáváno. Pouze jako zašifrovaný otisk.
- 46 -
V současné době je systém úspěšně implementován a testován na dvou veřejně přístupných testovacích serverech. Rovněž byl spuštěn zkušební provoz v nově otevírané transfuzní stanici v Praze.
6.2. Budoucnost systému O tento rezervační systém již projevily zájem dvě další transfuzní stanice v České republice a velmi pravděpodobně zde opravdu bude provozován. Pro budoucnost systému nyní bude nejdůležitější následující „ostrý“ provoz a zpětná vazba od uživatelů. V případě úspěšného provozu systému může být v budoucnosti systém rozšiřován o další funkce. Díky snadné modifikovatelnosti není vyloučeno ani využití v jiném prostředí. To ale rozhodně není prioritou. Tou i nadále zůstává zaměření na transfuzní stanice.
- 47 -
7. Seznam použitých zdrojů 1. ADAMS, Cameron, EDWARDS, James. The JavaScript Anthology. USA : SitePoint, 2006. 592 s. ISBN 978-0-975-24026-7 2. ALLEN, Rob, LO, Nick, BROWN, Steven. ZEND Framework In action. [ZEND Framework v akci] USA : Manning Publications, 2009. 623 s. ISBN 1933988320 3. ARLOW, Jim, NEUSTADT , Ila. UML a unifikovaný proces vývoje aplikací : objektově orientovaná analýza a návrh prakticky. překl. Bogdan Kiszka. 2. aktualiz. vyd. Brno : Computer Press, 2007. 567 s. 4. BUTOW, Eric. User Interface Design for Mere Mortals. [Návrh uživatelského rozhraní pro běžné smrtelníky] : Addison-Wesley Professional, 2007. 312 s. ISBN 978-0-321-44773-9 5. DRUSKA, Peter. CSS a XHTML : tvorba dokonalých webových stránek krok za krokem. 1.vyd.. Praha : Grada, 2006. 200 s. ISBN 80-247-1382-9 (brož.) 6. GRIFFITHS, Patrick. HTML Dog : The Best-Practice Guide to XHTML and CSS. [Průvodce nejlepšími praktikami XHTML a CSS] New Riders, 2006. 368 s. ISBN 978-0-321-31139-9 7. HOFFMAN, Sharon L. Beyond RPG: To PHP or Not to PHP [PHP - ano či ne]. System iNEWS . 2008, is.344 [cit. 2008-11-14], s. 8-10. ISSN 1933-1738 8. Interval.cz : webdesign a e-komerce denně [online]. 2002 [cit. 2009-02-22]. Dostupný z WWW: . ISSN 1212-8651 9. KUČEROVÁ, Helena. Projektování informačních systémů : Sylaby ke kurzu. Praha: Vyšší odborná škola informačních služeb, 2007. 114 s. Dostupný z WWW: 10. LAVIN, Peter. Object-Oriented PHP. [Objektově orientované PHP] 2006. 216 s. ISBN 978-1-593-27077-3 11. MCLAUGHLIN, Brett, POLLICE, Gary, WEST, David. Head First ObjectOriented Analysis and Design. [Objektově orientovaná analýza a návrh] USA : O'Reilly Media. Inc, 2006. 752 s. ISBN 978-0-596-00867-3 - 48 -
12. MILES, Russel, HAMILTON, Kim. Learning UML 2.0. USA : O'Reilly Media, Inc., 2006. 288 s. ISBN 978-0-596-00982-3 13. MORRISON, Michael. Head First JavaScript. USA:O'Reilly Media, Inc, 2007. 656 s. ISBN 978-0-596-52774-7 14. NIELSEN, Jacob. Useit.com : Jakob Nielsen's Website [online]. 1995-2009 [cit. 2009-03-19]. Dostupný z WWW: . ISSN 1548-555 15. PECINOVSKÝ, Rudolf. Myslíme objektově v jazyku Java : kompletní učebnice pro začátečníky. 2., aktualiz. a rozš. vyd.. Praha : Grada, 2009. 570 s. ISBN 978-80-247-2653-3 16. REIERSÖL, Dagfinn, BAKER, Marcus, SHIFLETT, Chris. PHP in Action : Objects, Design, Agility. [PHP v akci: objekty, návrh, rychlost], 2007. 552 s. ISBN 978-1-932394-75-7 17. RESIG, John. JavaScript a Ajax : moderní programování webových aplikací. překl. Ondřej Baše, Ondřej Žižka. Vyd. 1. Brno : Computer Press, 2007. 360 s. ISBN 978-80-251-1824-5 (brož.) 18. RIORDAN, Rebecca. Head First Ajax. USA : O\'Reilly Media, Inc., 2008. 528 s. ISBN 978-0-596-51578-2 19. SEIDEN, Alan. Configure a Safe Environment for PHP Web App [Nastavení bezpečného prostředí pro PHP webové aplikace]. System iNEWS. 2007, is. 338 [cit. 2008-11-14], s. 36-40. ISSN 1933-1738 20. SCHWARTZ, Baron. High Performance MySQL [Vysoce výkonné MySQL]. 2nd edition. USA:O'Reilly Media, Inc., 2008. 712 s. ISBN 978-0-596-10171-8 21. SUEHRING, Steve. JavaScript : krok za krokem. překl. Jakub Zemánek. Vyd. 1. Brno: Computer Press, 2008. 335 s. ISBN 978-80-251-2241-9 (brož.) 22. VRÁNA, Jakub. PHP Triky : Weblog o elegantním programování v PHP pro mírně pokročilé [online]. 2005 [cit. 2009-03-19]. Dostupný z WWW: 23. XHTML™ 1.0 : The Extensible HyperText Markup Language. 2002 [cit. 200904-15]. Dostupný z WWW:
Obr. A.7. – Denní rozvrh v tabulce (pohled uživatele)
Obr. A.8. – Detailní denní rozvrh s vyznačením rezervací
B. Obsah přiloženého CD Adresář (soubor)
Obsah
/TXT
Text bakalářské práce ve formátu .doc a .pdf
/OBR
Obrázky, použité v bakalářské práci (v původním rozlišení)
/INSTALL
Zdrojové soubory aplikace
/MANUAL
Uživatelská příručky pro uživatele a pro správce systému
readme.txt
Obsah CD
C. Návod na instalaci aplikace Požadavky Server s podporou PHP verze 5 a vyšší MySQL databáze verze 4.1 a vyšší Libovolný internetový prohlížeč s podporou JavaScript: např. Internet Explorer (doporučená verze 7 a vyšší), Mozzila Firefox, Opera
Instalace 1. Nakopírujte adresář registrace z instalačního balíčku na Váš webový server. 2. Upravte nastavení databáze v souboru /config/db_config.php 3. Na Vaší databázi spusťte dotazy, uložené v souboru /config/databaze.sql 4. Nastavte přístupová práva pro zápis do adresáře /obr Toto nastavení je důležité kvůli možnosti uploadování vlastních obrázků na server 5. V případě instalace na lokální server (localhost) je nutné mít správně nakonfigurovaný mailserver. V opačném případě systém hlásí chybu funkce mail() při pokusu odeslat e-mail. Pro testovací účely lze zabránit odesílání e-mailů nastavením konstant EMAIL_VITEJTE a EMAIL_ZMENA na „false“ (v souboru config/konstanty.php)
První spuštění Pokud jste adresář registrace nakopírovali do kořenového adresáře Vašeho serveru, bude adresa např. http://registrace.vasedomena.cz
Přihlášení Po zadání této adresy budete vyzváni k zadání přihlašovacích údajů. Pro první přístup do systému použijte tyto hodnoty: • e-mail: [email protected] • heslo: admin Tyto hodnoty si po prvním nastavení změňte v menu „Můj účet“. Pozn. Nejprve doporučuji změnit heslo, potom teprve jméno a e-mail. Po změnění emailu budete ze systému odhlášeni a budete se muset přihlásit pomocí nového emailu.
Celou verzi návodu naleznete na přiloženém CD.
D. Příklady rezervačních systémů TASW (typový aplikační software) BIZZY (Smarcoms) http://www.smarcoms.cz Parametrizovatelný
systém
vhodný
zejména
pro
zejména
pro
sportovní centra.
BOOKER (Nower systems s.r.o.) http://www.nower.cz Parametrizovatelný
systém
vhodný
sportovní centra. QBIS (Hired Help) http://www.hiredhelp.biz Parametrizovatelný systém. Navržený pro plánování pomoci a služeb pro handicapované osoby. IASW (individuální aplikační software) Hotelein http://hotelein.cz Rezervační systém pro rezervaci hotelových pokojů.
Palace Cinemas http://www.palacecinemas.cz Rezervační systém pro rezervaci vstupenek do kina. Vytvořený pro společnost Palace Cinemas.