• No results found

Webová aplikace pro správu dat o životním prostředí

N/A
N/A
Protected

Academic year: 2022

Share "Webová aplikace pro správu dat o životním prostředí"

Copied!
54
0
0

Loading.... (view fulltext now)

Full text

(1)

Webová aplikace pro správu dat o životním prostředí

Diplomová práce

Studijní program: N2612 – Elektrotechnika a informatika Studijní obor: 1802T007 – Informační technologie

Autor práce: Bc. Patrik Odcházel Vedoucí práce: Mgr. Kamil Nešetřil, Ph.D.

(2)

Web Application For Environmental Data Management

Master thesis

Study programme: N2612 – Electrical Engineering and Informatics Study branch: 1802T007 – Information Technology

Author: Bc. Patrik Odcházel

Supervisor: Mgr. Kamil Nešetřil, Ph.D.

(3)
(4)
(5)
(6)

Poděkování

Chtěl bych poděkovat Mgr. Kamilu Nešetřilovi, Ph.D., vedoucímu diplomové práce, za jeho ochotu a trpělivost, cenné rady a připomínky při vypracování této diplomové práce.

Dále bych chtěl poděkovat mé rodině a přátelům za podporu během studia.

(7)

Abstrakt

Práce se zabývá tvorbou webové aplikace, která umožňuje prohlížení, vkládání a editaci dat. Data pocházejí z hydrogeologických měření a jsou uložena v databázi PostgreSQL. Na začátku této práce je krátce popsáno, jakým způsobem vznikají a jak jsou data ukládána. Práce řeší implementaci podpory pro uživatele a různé úrovně jejich oprávnění a také základní zobrazení dat ze síťové knihovny Zotero.

Webová aplikace byla naprogramována pomocí PHP frameworku Nette a ja- vascriptových knihoven jQuery a DataTables. Pro vzhled aplikace byl použit front- end framework Bootstrap. Komunikace s knihovnou Zotero byla realizována pomocí webového rozhraní Zotero Web API. Většina textu této práce se věnuje podrobnému popisu softwarového řešení.

Výsledkem práce je webová aplikace poskytující rozhraní pro správu dat z hyd- rogeologických měření. Byla vytvořena aplikace, která umožňuje pracovat s předem neznámou strukturou databáze a má podporu uživatelů, jejich autorizaci a autenti- zaci. V aplikaci je možné zobrazit obsah ze síťové knihovny Zotero včetně možnosti stažení přiložených souborů.

Klíčová slova

Webová aplikace, Nette, PostgreSQL, jQuery, Bootstrap, Zotero

Abstract

The master thesis deals with creating a web application that allows viewing, inser- ting and editing data. Data come from the hydrogeological measurements and are stored in a PostgreSQL database. The report includes a short introduction how the measurement data are created and stored. The thesis solves the implementation of support for users and their different levels of permission, as well as a basic view of data from the Zotero network library.

The web application was programmed using the Nette PHP framework and the jQuery and DataTables javascript libraries. The application appearance was made by Bootstrap front-end framework. Communication with the Zotero library was realized using the Zotero Web API web interface. Most of the text of this report deals with a detailed description of the software solution.

The result of the thesis is a web application providing interface for hydrogeolo- gical data management. An application was created that allows user to work with a database of unknown structure and has users support, theirs authorization, and authentication. In the application, can be viewed content from the Zotero network library, including downloadable attachments.

Key words

(8)

Obsah

Úvod 13

1 Informační systém HgIS 14

2 Síťová knihovna Zotero 16

2.1 Zotero Web API . . . 16

3 Použité technologie 18 3.1 PHP framework Nette . . . 18

3.2 PostgreSQL . . . 19

3.3 jQuery . . . 19

3.4 DataTables . . . 19

3.5 Bootstrap . . . 19

3.6 Google Cloud Platform . . . 20

4 Softwarové řešení 21 4.1 Adresářová struktura aplikace . . . 21

4.2 Konfigurace . . . 21

4.2.1 Nastavení uživatelských rolí . . . 22

4.3 Modely . . . 23

4.3.1 DatabaseManager . . . 23

4.3.2 SessionManager . . . 26

4.3.3 UserManager . . . 27

4.3.4 ZoteroManager . . . 29

4.3.5 AttachmentResponse . . . 30

4.4 Presentery . . . 31

4.4.1 BasePresenter . . . 31

4.4.2 EditPresenter . . . 32

4.4.3 AddPresenter . . . 38

4.4.4 ErrorPresenter . . . 38

4.4.5 HomepagePresenter . . . 38

4.4.6 SignPresenter . . . 38

4.4.7 UserPresenter . . . 40

4.4.8 ZoteroPresenter . . . 42

5 Shrnutí 45

(9)

Závěr 47

Literatura 48

Přílohy 50

A Obrázky 50

B Obsah přiloženého CD 52

C Ukázky kódu 53

C.1 Struktura záznamu z knihovny Zotero . . . 53

(10)

Seznam obrázků

1.1 Mapová aplikace [9] . . . 15

1.2 Schéma informačního systému HgIS [9] . . . 15

4.1 Adresářová struktura aplikace . . . 21

4.2 Struktura objektu s informacemi o sloupcích . . . 25

4.3 Struktura tabulky users . . . 27

4.4 Výpis seznamu tabulek z databáze . . . 33

4.5 Formulář pro filtrování . . . 35

4.6 Formulář pro editaci . . . 37

4.7 Dialog pro smazání záznamu . . . 37

4.8 Přihlašovací formulář . . . 39

4.9 Uživatelské menu . . . 39

4.10 Profil uživatele . . . 40

4.11 Výpis uživatelů . . . 41

4.12 Formulář pro přidání nového uživatele . . . 42

4.13 Výpis informací z knihovny Zotero . . . 44

A.1 Domovská stránka webové aplikace . . . 50

A.2 Schéma databáze . . . 51

(11)

Seznam tabulek

2.1 URI v Zotero Web API . . . 17 4.1 Zobrazené informace z knihovny Zotero . . . 43 5.1 Uživatelé a jejich role . . . 45

(12)

Seznam pojmů a zkratek

ACL Access Control List

AJAJ Asynchronous JavaScript and JSON AJAX Asynchronous JavaScript and XML

API Application Programming Interface

DOM Document Object Model, rozhraní umožňující přístup či modifikaci obsahu dokumentu

ETL Extract Transform Load

Framework Softwarové nástroje usnadňující programování a vývoj jiných soft- warových aplikací

HTML HyperText Markup Language HTTPS Hypertext Transfer Protocol Secure

ISBN International Standard Book Number KISS Keep It Short and Simple

MVC Model-View-Controler

Open-source Software s otevřeným zdrojovým kódem PHP Skriptovací programovací jazyk

SQL Structured Query Language TUL Technická univerzita v Liberci

URI Uniform Resource Identifier URL Uniform Resource Locator

(13)

Úvod

Od roku 2012 je vyvíjen informační systém HgIS, který shromažďuje data z chemic- kých analýz, ložiskových průzkumných vrtů, informace o atmosférických srážkách, teplotě vzduchu, inklinometrie a další. Z těchto měření vznikají strukturovaná, či méně strukturovaná zdrojová data, která jsou podle typu měření ukládána do růz- ných typů souborů. Ze souborů jsou následně separovány potřebné informace pomocí nástroje Pentaho Data Integration, který zajišťuje uložení do databázových tabulek.

Cílem diplomové práce je seznámení se informačním systémem HgIS a se stáva- jícím datovým modelem. Po získání základních znalostí a principů byla vytvořena vlastní webová aplikace, která využívá databáze naplněné daty. Webová aplikace umožňuje editaci a vkládání nových záznamů do databáze. Důležitým aspektem při vývoji aplikace bylo také to, že neměla být vázána na jednu konkrétní databázi, ale měla by být schopna pracovat s různými strukturami databáze, které nejsou předem známé. Vše by mělo být vytvářeno dynamicky až při připojení k databázi. V aplikaci by měla být implementována podpora pro uživatele a různé úrovně jejich oprávnění.

Webová aplikace také poskytuje základní zobrazení dat ze síťové knihovny Zotero.

K vytvoření aplikace byl použitý PHP Framework Nette a existující databáze PostgreSQL obsahující data z hydrogeologických měření.

(14)

1 Informační systém HgIS

Hydrogeologický informační systém HgIS zpracovává data z chemických analýz, lo- žiskových průzkumných vrtů nebo specializovaných měřících stanic. Z těchto dat následně poskytuje výstup ve formě tabulek, přehledů, grafů, profilů vrtů, geolo- gických řezů a map, čímž značně usnadňuje práci hydrogeologů. Informační systém umožňuje například sledování dynamiky hydrologického, hydrogeologického a hyd- rochemického režimu oblasti a vybraných geodynamických procesů. Může být využit pro sledování hladiny podzemní vody, složení půdy, množství atmosférických srážek a další. Díky unikátní architektuře je možné informační systém nastavit pro včasné varování uživatele o tom, že měřená veličina překročila stanovenou hodnotu.

Data pro informační systém jsou na počátku uložena v různých typech soubo- rů. Laboratotní řídicí a informační systém Labsystém, provádějící chemické ana- lýzy, exportuje data ve formátu DBF. Informace týkající se chemismu a geologie poskytuje Česká geologická služba ve formátu MDB (Microsoft Access). Z ložisko- vých průzkumných vrtů vytváří měřící software soubory ve formátu DOC (Microsoft Word). Soubory s atmosférickými srážkami a teplotami vzduchu jsou stahovány pro- střednictvím protokolu FTP ve formátu TXT. Další informace jsou uložené v ručně vytvořených souborech XLS (Microsoft Excel).

Z předchozího odstavce je zřejmé, že struktura dat a způsob uložení je velmi různorodé, proto se k uložení do databáze PostgreSQL používá nástroj Pentaho Data Integration neboli Kettle. Tento nástroj je zodpovědný za procesy extrakce, transformace a uložení dat do databáze. Z anglického Extract, Transform, Load se tento typ softwaru označuje zkratkou ETL. Před uložením dat probíhá jejich čištění, výpočty veličin, agregace, atd. V databázi je vytvořeno několik tabulek, které uchovávají např. tyto informace:

• pozorované objekty (studny, vrty, dokumentační body se souřadnicemi);

• popis geologických objektů (vrtné profily a jejich interpretace - stratigrafie);

• definice pozorovaných veličin (jednotky, chemický vzorec);

• standardy (sanační a legislativní limity);

• definice hloubkových intervalů;

• měření vázané k hloubkovému intervalu nebo ke konkrétní hloubce;

• vzorky (metody vzorkování, podmínky).

(15)

Data z databáze PostgreSQL jsou vizualizována pomocí několika specialních ná- strojů. Jedním z nich je software EnviroInstite, který se zabývá vizualizací podzemní vody. Vytváření reportů např. o průzkumných vrtech ve formátu XLS, DOC, PDF zajišťuje software Pentaho Business Analytics. Prohlížení naměřených hodnot je možné ve webové aplikaci, která přehledně zobrazuje jednotlivá místa měření na mapovém podkladu. Náhled mapové aplikace je na obrázku 1.1. [9]

Obrázek 1.1: Mapová aplikace [9]

Přehledné schéma celého informačního systému znázorňuje obrázek 1.2.

Obrázek 1.2: Schéma informačního systému HgIS [9]

(16)

2 Síťová knihovna Zotero

Síťová knihovna Zotero je bezplatný open-source citační manager, který umožňuje spravovat bibliografická data a související dokumenty. Uživatel si může přehledně ukládat bibliografické záznamy různých dokumentů do své vlastní knihovny. Zotero je k dispozici jako samostatná aplikace nebo jako rozšíření pro webové prohlížeče.

Po instalaci je při procházení webu možné ukládat bibliografické záznamy včetně plného textu dokumentu přímo do knihovny Zotero. Informace o autorovi, názvu díla, ISBN, roku vydání a další informace potřebné pro tvorbu citací jsou vyplněny automaticky podle typu dokumentu.

Uložené záznamy je možné třídit do složek, ručně upravovat a přidávat poznám- ky, přílohy či odkazy. K záznamu lze přidávat také štítky, počet a jejich text je čistě na uživateli. Rychlé vyhledávání zobrazuje záznamy, které odpovídají frázi zada- né do vyhledávacího pole přímo v aplikaci. Zotero nabízí také přidání záznamu do knihovny pouze na základě ISBN, všechny údaje jsou následně automaticky vyplně- ny. Pokud je třeba, je možné přidat záznam manuálně vyplněním všech potřebných informací.

Zotero používá Citation Style Language pro vytváření citací v mnoha různých bibliografických stylech. K dispozici je celkem přes 8500 bibliografických stylů, pří- padně si uživatel může vytvořit svůj vlastní styl citací. [10]

2.1 Zotero Web API

Pro práci s knihovnou Zotero je k dispozici webové rozhraní (API), se kterým se komunikuje prostřednictvím HTTPS požadavků se specifickými parametry. Web API má základní URL https://api.zotero.org.

Přístup k veřejným knihovnám nevyžaduje žádný API klíč. Pro získání informací z neveřejných knihoven je třeba mít vygenerovaný API klíč, který se předává jako parametr v požadavku. Tento klíč je možné vygenerovat v uživatelském nastavení Zotero pod záložkou Feeds/API.

Požadavky na získání záznamů konkrétního uživatele nebo skupiny začínají ces- tou /users/<IDuživatele> případně /groups/<IDskupiny>. ID uživatele je uvedeno v uživatelském nastavení Zotero pod záložkou Feeds/API. ID skupiny je možné zjis- tit při otevření knihovny pod odkazem na přihlášení k odběru RSS kanálu. Web API nabízí několik URI, pomocí kterých je možné získat potřebné informace o zá- znamech. Výběr několika základních URI a jejich popis zobrazuje tabulka 2.1.

Formát získaných záznamů se nastavuje parametrem format. Tento parametr

(17)

URI Popis

/items Seznam všech záznamů v knihovně

/items/<iKey> Pouze konkrétní záznam z knihovny /items/<iKey>/tags Seznam štítků u konkrétního záznamu /collections Seznam všech složek v knihovně

/collections/<cKey>/items Seznam všech záznamů z konkrétní složky Tabulka 2.1: URI v Zotero Web API

může nabývat mimo jiné těchto hodnot:

• atom - pro čtečky formátu Atom;

• bib - vrací formátovanou bibliografii jako XHTML;

• json - vrací pole JSON se záznamy.

S parametrem format je spojený další parametr include, který definuje, zda od- pověď bude obsahovat formátovanou referenci, citaci nebo všechna zadaná data u konkrétního záznamu. Mezi parametry, které ještě stojí za zmínku, bych zařadil limit, který musí být v rozsahu 1-100 a udává počet vrácených záznamů. Znamená to tedy, že Zotero API na jeden požadavek vždy vrátí maximálně 100 záznamů. Pro získání dalších záznamů se používá parametr start, kterým se určije index prvního vráceného záznamu. [11]

Zobrazení citací z knihovny Zotero by měla umožňovat také webová služba Bib- base. Po propojení s knihovnou by mělo dojít k vytvoření seznamu literatury, který je následně možné vložit do vlastních webových stránek. Seznam by měl být dy- namicky generován a tudíž stále aktuální. Bohužel při testování se mi vyskytovala chyba na straně webové aplikace Bibbase, která měla problém s načtením položek z knihovny Zotero a tudíž jsem tento způsob neměl možnost vyzkoušet.

(18)

3 Použité technologie

Pro vytvoření webové aplikace byl v první řadě použit PHP framework Nette a da- tabáze PostgreSQL obsahující data. Programování aplikace probíhalo ve vývojovém prostředí NetBeans IDE. Pro testování webové aplikace na vlastním počítači jsem použil aplikaci WampServer [2]. Jedná se o nástroj pro vývoj webových aplikací, který zajišťuje běh webového serveru Apache a podporuje jazyk PHP. S efektivním odstraněním chyb pomohl nástroj Tracy Debugger společně s aplikací FireLogger, která je rozšířením pro webový prohlížeč Chrome. Databáze PostgreSQL byla nain- stalována nejprve lokálně a následně byl vytvořen virtuální server s nainstalovanou databází PostgreSQL pomocí služby Google Cloud Platform.

3.1 PHP framework Nette

PHP framework Nette je open source nástroj pro tvorbu webových aplikací ve skrip- tovacím programovacím jazyce PHP. Framework Nette 2.3 vyžaduje PHP ve ver- zi 5.6 nebo vyšší a je kompatibilní také s aktuálně nejnovější verzí 7.1. Předností frameworku Nette je mimo jiné, že se snaží snižovat bezpečnostní rizika aplikace ošetřením proti těmto typům útoků:

• XSS – metoda, kdy je do neošetřeného vstupu aplikace podstrčen vlastní ja- vascriptový kód, který může stránky zablokovat, změnit vzhled, případně zís- kat citlivá data od uživatelů;

• Cross-Site Request Forgery – přihlášený uživatel navštíví stránku, která skrytě útočí na webovou aplikaci a následně je vykonána akce bez vědomí uživatele;

• Invalid UTF-8, control codes, URL attack – různé druhy útoků zaměřených na podstrčení škodlivého vstupu;

• Session hijacking, session stealing, session fixation – útoky založené na zci- zení nebo podstrčení session, čímž může útočník například získat přístup do aplikace.

Nette framework podporuje moderní technologie AJAX/AJAJ a Dependency Injection neboli vkládání závislostí. Je založen na principu DRY pro redukci počtu duplicitních informací a na principu KISS pro co nejjednodušší návrh aplikace. Vý- sledná aplikace je architektury MVC (Model-View-Controller), která odděluje kódy obsluhy (Controller), aplikační logiky (Model) a uživatelského rozhraní (View). [8]

(19)

Vývoj aplikace ve frameworku Nette vede k přehlednosti a znovupoužitelnosti kódu, který je možné snadno upravovat a doplňovat do něj další funkce. Některé komponenty, které využívá informačního systém HgIS, jsou také napsány pomocí Nette frameworku, a proto je jednou ze zásad pro vypracování použití tohoto ná- stroje. Pro programování jsem použil vývojové prostředí NetBeans IDE 8.1 a PHP framework Nette 2.3.

3.2 PostgreSQL

PostgreSQL je výkonný open source objektově-relační databázový systém, zkráce- ně nazývaný Postgres. Databáze se používají pro ukládání a ke zpětnému získávání dat. Vhodné jsou především pro velké objemy dat, které je třeba často aktualizo- vat a načítat. Databáze umožňuje uspořádané ukládání dat, jejich rychlé načtení a komplexní analýzu. [6, s. 1]

Data z hydrogeologických měření jsou do databázového systému uložena pomocí celkem 15 tabulek. Struktura databáze byla již vytvořena a pracují s ní i další aplikace, například mapová aplikace pro zobrazení údajů o měření přímo na mapě.

Pro testování aplikace jsem si nainstaloval na vlastní počítač databázi Postgre- SQL ve verzi 9.5.4, která je dostupná na webových stránkách [17].

3.3 jQuery

Malá a rychlá javascriptová knihovna jQuery, která má mnoho užitečných funkcí.

Obsahuje funkce pro práci s HTML dokumenty - procházení a změna DOM elemen- tů. Dále funkce pro zpracování událostí nebo například provádění animací a efektů.

Nabízí také funkce pro práci s AJAX, které usnadňují programování a zvyšují pře- hlednost díky kratšímu zápisu zdrojového kódu.

Ve webové aplikaci používám knihovnu jQuery ve verzi 1.12.3, která je dostupná na webových stránkách [14].

3.4 DataTables

DataTables je plugin pro výše zmíněnou javascriptovou knihovnu jQuery. Toto rozší- ření nabízí funkce pro práci s databázovými tabulkami. Možné je využít stránkování vypsaných záznamů, řazení podle jednotlivých sloupců a také vyhledávání řetězců v obsahu tabulky. V aplikaci používám tento plugin ve verzi 1.10.9, který je dostupný na webových stránkách [13].

3.5 Bootstrap

(20)

soben velikosti displeje zařízení, na kterém je otevřena. Prohlížení webové aplikace je tak mnohem přehlednější. Moderní design je použitý na všechny prvky, které se v aplikaci nacházejí. Twitter Bootstrap ovlivňuje vzhled ovládacích prvků, formu- lářů a tabulek. Framework Bootstrap používám ve verzi 3.3.6, který je dostupný z webové stránky [19].

3.6 Google Cloud Platform

Sada nástrojů a služeb pro tzv. cloudový hosting Google Cloud Platform nabízí mož- nost spuštění virtuálních serverů, které běží přímo v datových centrech společnosti Google. Při spouštění virtuálního serveru je možné zvolit datové centrum, ve kterém má server běžet. K dispozici jsou datová centra rozmístěná v Americe, západní Ev- ropě a východní Asii. Dále je možné zvolit konfiguraci serveru. Od základní s jedním sdílením procesorem a 0,6 GB operační paměti až po virtuální server, který disponu- je výkonem 64 virtuálních procesorů a 416 GB operační paměti. Pro uložení dat je možné zvolit mezi standardním mechanickým pevným diskem nebo rychlejším SSD.

[4]

Pro otestování práce s externí databází jsem si pomocí Google Cloud Platform nejprve vytvořil virtuální server, na který jsem nainstaloval poslední verzi Postgre- SQL 9.6.2 z knihovny serverových aplikací Bitnami. Z databáze dodané vedoucím práce jsem si z příkazové řádky programem pg_dump vytvořil zálohu dat včetně struktury tabulek. Schéma testovací databáze je v příloze na obrázku A.2. Prostřed- nictvím Google Cloud Platform jsem se připojil k vytvořenému virtuálnímu serveru s databází PostgreSQL, na který jsem pomocí konzole obnovil zálohu a tím vytvořil kopii původní databáze, kterou jsem následně použil při vývoji webové aplikace.

(21)

4 Softwarové řešení

4.1 Adresářová struktura aplikace

Webová aplikace napsaná pomocí Nette frameworku má architekturu MVC stručně popsanou v kapitole 3.1. Tomu odpovídá i adresářová struktura, která je rozdělena do několika složek. Adresářová struktura s popisy jednotlivých adresářů je zobrazena na obrázku 4.1.

Obrázek 4.1: Adresářová struktura aplikace

4.2 Konfigurace

V adresáři config se nachází soubor s názvem config.local.neon, který obsahuje infor- mace pro připojení k databázím. Pro databázi označenou jako default s daty z hyd- rogeologických měření spuštěnou na virtuálním serveru Google Cloud Platform jsou

(22)

Informace o uživatelích a jejich rolích jsem se rozhodl uložit do jiné databáze.

Důvodem je především to, že při programování webové aplikace jsem předpokládal připojování k databázím s různou, předem neznámou strukturou. Proto je třeba, aby informace o uživatelích byly uložené zvlášť, mimo databázi, která obsahuje zob- razovaná data. Pro otestování vzájemné nezávislosti jsem vytvořil druhou databázi PostgreSQL označenou jako users, která běží na jiném serveru a údaje pro připojení jsou následující:

dsn: "pgsql :host =35.187.171.98; port =5432; dbname = postgres "

U konfigurace databáze se také může nastavit zobrazení informací o tom, jaké SQL dotazy byly v databázi provedeny. Informace se vypíší do lišty Tracy Debug- geru, která je zobrazena ve vývojářském režimu. Pro tuto funkci je třeba nastavit parametry debugger a explain na hodnotu true. Vývojářský režim je možné povolit ve spouštěcím souboru bootstrap.php, který slouží k načtení celého frameworku Nette a pro nastavení aplikace. Stačí změnit hodnotu parametru funkce $configurator-

>setDebugMode(FALSE) na hodnotu TRUE.

V sekci parameters se ještě nastavuje schéma databáze, se kterým má aplikace pracovat. Parametr schemaDefault s hodnotou mare pro databázi default a parametr schemaUsers s hodnotou public pro databázi s uživateli. Také se zde zadává ID skupiny a API klíč do knihovny Zotero, které jsem popsal v kapitole 2.1.

schemaDefault: mare schemaUsers: public zoteroGroup: 34313 ZoteroAPIKey: API_KLIC

Adresář config obsahuje ještě soubor config.neon, ve kterém se nastavuje napří- klad délka platnosti proměnných session a také se zde registrují služby pro použití v presenterech.

4.2.1 Nastavení uživatelských rolí

Nastavení oprávnění pro uživatelské role je možné provést v souboru Authoriza- torFactory.php ve složce security. Framework Nette disponuje třídou Nette\Security

\Permission, která poskytuje ACL vrstvu pro řízení práv a přístupu. Princip spočívá v definici seznamu uživatelských rolí, zdrojů a oprávnění. Seznam určuje, k jakému zdroji může uživatelská role přistupovat a jaké operace s ním může provádět.

V souboru AuthorizatorFactory.php je definována třída AuthorizatorFactory, ve které jsem vytvořil konstanty s těmito uživatelskými rolemi:

• admin – všechna oprávnění, včetně správy uživatelů,

• editor – editace a přidávání záznamů,

• user – prohlížení záznamů,

• guest – nepřihlášený uživatel;

(23)

Role guest je ve frameworku Nette výchozí role pro nepřihlášeného uživatele a musí vždy existovat. Po vytvoření instance třídy Nette\Security\Permission se do ní přidají role metodou addRole. Uživatelské role mohou mít rodiče, od kterého automaticky dědí všechna oprávnění. Přidání uživatelské role user s rodičem guest se zapíše tímto způsobem:

$acl->addRole('user ', 'guest ');

V aplikaci jsem nadefinoval, že role user a editor dědí oprávnění od role guest, aby měly oprávnění k přihlášení/odhlášení z webové aplikace. Zdroje se přidávají metodou addResource a mohou mít také definovaného rodiče. Pokud má uživatel přístup ke zdroji Front, který je rodičem zdroje Front:Homepage, bude mít uživatel automaticky přístup i k tomuto zdroji Front:Homepage. Definici zdrojů umožňuje tento zápis:

$acl->addResource('Front : Homepage ', 'Front ');

Zdroje jsem definoval pro každý presenter, abych mohl nastavit přístup k jed- notlivým částem aplikace. SignPresenter, HomepagePresenter, EditPresenter a Add- Presenter mají společného rodiče Front. Zdroje pro ZoteroPresenter a UserPresenter jsou definované bez rodičů. Všechny zmíněné presentery jsou popsány v kapitole 4.4.

Oprávnění se přidává metodou allow, které se předá název role, název zdroje a případně název akce. Pokud se má například uživatelské roli user přidat oprávnění pro EditPresenter, ale pouze pro akci renderDefault a renderTable, provede se zápis tímto způsobem:

$acl->allow('user ', 'Front :Edit ', ['default ', 'table ']);

V souboru AuthorizatorFactory.php jsem nastavil, že uživatelé s rolí admin mají oprávnění ke všem zdrojům, včetně správy uživatelů. Role editor disponuje oprávně- ním k editaci a přidávání nových záznamů do databázových tabulek. Uživatelé s rolí user mohou záznamy pouze prohlížet a nepřihlášení uživatelé mají přístup pouze na stránku s přihlašovacím formulářem. Zobrazení dat ze síťové knihovny Zotero mají povolené všechny role, kromě guest.

4.3 Modely

Jedná se o třídy, které se starají o aplikační logiku. Níže popsané komponenty jsem naprogramoval tak, že obsahují metody pro práci s databází, správu a přihlašování uživatelů, obsluhu proměnných session a komunikaci se síťovou knihovnou Zotero.

4.3.1 DatabaseManager

V adresáři model se nachází soubor DatabaseManager.php, ve kterém je definová- na stejnojmenná třída. Tato třída obsahuje metody pro práci s databází. Připojení k databázi je navázáno pomocí třídy Nette\Database\Connection. Základní funkci-

(24)

Metoda getTables

Bezparametrická metoda getTables vrací pole objektů s informacemi o tabulkách.

Každý objekt v poli má tyto vlastnosti:

• fullName – název tabulky včetně schématu (např. mare.screens);

• name – název tabulky;

• view – nabývá hodnot true/false podle toho, zda se jedná o pohled.

Informace o tabulkách jsou získány voláním metody getSupplementalDriver a následně getTables na instanci třídy Connection.

$this->connection->getSupplementalDriver() ->getTables();

Metoda getTablesCount

Bezparametrická metoda getTablesCount vrací pole objektů s informacemi o ta- bulkách doplněné o vlastnost count s hodnotou, která odpovídá počtu záznamů v tabulce.

Metoda getColumns

Metoda getColumns přijímá jako parametr název tabulky, pro kterou je potřeba získat informace o sloupcích. Vrací pole objektů s několika vlastnostmi, ze kterých jsou důležité především tyto:

• name – název sloupce;

• nativetype – datový typ hodnot ve sloupci;

• primary – nabývá hodnot true/false podle toho, zda je sloupec primární klíčem;

• autoincrement – nabývá hodnot true/false podle toho, zda je hodnota ve sloup- ci doplňována automaticky;

• nullable – nabývá hodnot true/false podle toho, zda hodnota ve sloupci musí být vyplněna;

Ukázka toho, jak vypadá struktura objektu s informaci o sloupcích je zobrazena na obrázku 4.2. Podobně jako u předchozí metody getTables se informace o sloupcích získají voláním metody getSupplementalDriver a následně getColumns na instanci třídy Connection.

$this->connection->getSupplementalDriver() ->getColumns();

(25)

Obrázek 4.2: Struktura objektu s informacemi o sloupcích

Metoda createFilterSql

Metoda createFilterSql přijímá jako první parametr název tabulky a jako druhý parametr filtry, které byly nastaveny ve filtrovacím formuláři. Filtry jsou předány jako objekt typu Nette\Utils\ArrayHash. Metoda na základě těchto vstupů sestaví SQL dotaz pro výběr dat z databáze.

Princip je takový, že jsou pomocí názvu tabulky zjištěny informace o sloupcích.

K tomu je využita metoda getColumns popsaná v kapitole 4.3.1. Poté jsou postupně procházeny všechny sloupce a je kontrolováno, zda pro ně byla nastavena nějaká hodnota ve filtrovacím formuláři. Pokud ano, je do SQL dotazu přidána podmínka WHERE, případně AND, která vybere odpovídající záznamy. Z databáze je vybráno maximálně prvních 3000 záznamů, které odpovídají zadaným hodnotám.

Metoda getData

Metoda getData má opět dva parametry - název tabulky a filtry nastavené ve fil- trovacím formuláři. Pokud je zjištěno, že nejsou žádné filtry nastaveny, vytvoří se SQL dotaz, který provede výběr prvních 3000 záznamů z uvedené tabulky. V opač- ném případě je zavolána metoda createFilterSql popsaná v kapitole 4.3.1 a následně proveden sestavený SQL dotaz. Metoda vrací záznamy z databáze jako pole objektů typu Nette\Database\Row.

Metoda getPrimaryKey

Metoda getPrimaryKey přijímá jako parametr název tabulky a vrací název sloupce, který je jejím primárním klíčem. Nejprve jsou pomocí metody getColumns zjištěny informace o sloupcích. Sloupce jsou poté postupně procházeny a hledá se, ve kterém je nastavený parametr primary na hodnotu TRUE.

Metoda getRecordById

Metoda getRecordById má dva parametry - název tabulky, ve které je umístěn a id záznamu, který je třeba získat. Zápis tohoto příkazu v Nette je na jeden řádek:

(26)

Metoda vrací záznam jako instanci třídy Nette\Database\Table\ActiveRow, kte- rá umožňuje se získaným záznamem provádět různé operace, například ho editovat nebo smazat.

Metoda insertRecord

Metoda insertRecord přijímá dva parametry - název tabulky a hodnoty zadané do formuláře pro nový záznam. Do databáze je záznam vložen pomocí jednoho příkazu:

$this->database->table($tableName)->insert($values);

Metoda getForeignKeys

Metoda getForeignKeys vrací informace o cizích klíčích v tabulce, jejíž název je předaný jako parametr. Uvnitř metody je zapsaný SQL dotaz, který pracuje s infor- mačním schématem databáze. V tomto schématu jsou uloženy metadata o objektech definovaných v databázi [16]. SQL příkaz provede výběr všech cizích klíčů pro kon- krétní tabulku a výsledek vrací jako pole objektů. Každý objekt obsahuje údaje o tom, jaký sloupec v této tabulce je cizím klíčem, z jaké tabulky je cizí klíč a jaký název má sloupec s cizím klíčem v této tabulce.

Metoda getColumnData

Metoda getColumnData přijímá dva parametry - název tabulky a název sloupce.

Tyto parametry jsou dosazeny do SQL dotazu, který vybere všechny hodnoty, které se ve sloupci nacházejí a abecedně je seřadí. Po vykonání SQL dotazu je zavolá metoda fetchPairs, která výsledek vrátí jako pole.

4.3.2 SessionManager

Druhým souborem v adresáři model je soubor s názvem SessionManager.php. Je v něm definována třída SessionManager, která se stará o práci s proměnnými session.

Do těchto proměnných se ukládají informace, které je potřeba uchovávat na straně serveru.

Pro práci s proměnnými session je použita třída Nette\Http\Session, jejíž in- stance je předána v konstruktoru. Ve třídě SessionManager jsou vytvořeny dvě sekce session proměnných:

• form - hodnoty z filtrovacího formuláře;

• table - název tabulky, pro kterou bylo provedeno filtrování.

Jsou zde také vytvořeny metody, které jsou nezbytné pro práci s proměnnými session. Jedná se o metody pro nastavení těchto proměnných, o metody pro získání hodnot z proměnných a také o metody, které proměnné session vymažou.

(27)

4.3.3 UserManager

V souboru s názvem UserManager.php jsem vytvořil třídu UserManager a něko- lik metod pro správu uživatelů. Třída UserManager implementuje rozhraní Net- te\Security\IAuthenticator a definuje vlastní metodu pro autentizaci uživatelů au- thenticate. Třída pracuje s databází, která je definována v souboru config.local.neon, a ve které jsou uloženy informace o uživatelích. Připojení k databázi je navázáno po- mocí třídy Nette\Database\Connection. Základní funkcionalitu pro práci s databází zajišťuje třída Nette\Database\Context. Instance těchto tříd jsou předány společ- ně s názvem schématu v konstruktoru třídy UserManager, která s nimi následně pracuje.

Tabulku s daty o uživatelích jsem navrhl tak, aby uchovávala tyto informace:

• id – jednoznačný identifikátor;

• username – jméno uživatele;

• password – otisk hesla;

• role – uživatelská role.

Schéma tabulky users je zobrazeno na obrázku 4.3. Primárním klíčem je sloupec id datového typu integer, který má výchozí hodnotu nastavenou pomocí sekven- ce user_id_seq. Sekvence zajistí, že následující hodnota id bude vždy o 1 větší.

V databázi jsem sekvenci vytvořil tímto SQL příkazem:

CREATE SEQUENCE user_id_seq;.

Ve framewroku Nette se pro šifrování hesel používá hashovací funkce Bcrypt a otisk hesla bude mít vždy délku 60 znaků. Uživatelská role má datový typ char o maximální délce 20 znaků. Uživatelské jméno má datový typ char o maximální délce 30 znaků a musí být v tabulce unikátní.

Obrázek 4.3: Struktura tabulky users

Název tabulky a jednotlivých sloupců se nastavuje jako hodnota konstant na začátku třídy UserManager. Pokud by se tedy názvy sloupců změnily, není problém upravit pouze konstanty a celá třída bude bez problémů fungovat.

(28)

Metoda authenticate

Přihlašování uživatelů má na starosti metoda authenticate, která přijímá jako pa- rametr pole s uživatelským jménem a heslem. Princip ověření uživatele je takový, že se metoda nejprve pokusí v databázi najít uživatelské jméno a pokud existuje, je zkontrolováno heslo pomocí metody verify ze třídy Nette\Security\Passwords. Po- kud je uživatelské jméno nebo heslo zadáno špatně, je vytvořena výjimka, kterou zpracovává presenter. Při správně zadaných přihlašovacích údajích se ještě zkont- roluje, zda se nezměnila hashovací funkce a není třeba vytvořit nový otisk hesla uložený v databázi.

Metoda vrací identitu uživatele jako instanci třídy Nette\Security\Identity. Iden- tita obsahuje ID uživatele, jeho roli, uživatelské jméno a případně i další uživatelské informace, které by byly v databázi uloženy. Framework Nette ukládá identitu do proměnné session a využívá ji k autorizačním procesům. V presenterech je poté mož- né pracovat s identitou uživatele přes proměnnou $this->user a v šablonách přes

$user->getIdentity(). Pokud administrátor změní roli přihlášeného uživatele, zůsta- ne v session nastavená původní hodnota a změna se projeví až při novém přihlášení uživatele.

Metoda addUser

Metoda addUser přijímá jako parametry uživatelské jméno, heslo a roli, které ná- sledně ukládá do databáze uživatelů příkazem insert. Před vložením do databáze je ještě z hesla vytvořen otisk pomocí metody hash ze třídy Nette\Security\Passwords.

Metoda getUserById

Metoda getUserById vrací z databáze záznam s ID, které bylo předáno jako para- metr. Záznam je jako instance třídy Nette\Database\Table\ActiveRow.

Metoda editUser

Metoda editUser slouží pro editaci uživatelů. Jako parametry přijímá id uživatele a hodnoty zadané do formuláře pro editaci. Na začátku metody je zavolána metoda getUserById a je zkontrolováno, zda uživatel s předaným id v databázi existuje. Ke změně hesla dojde pouze v případě, že je ve formuláři vyplněné. Stejně jako u před- chozí metody addUser se před uložením vytvoří jeho otisk. Změny v databázi jsou provedeny metodou update třídy ActiveRow, které jsou předány data z formuláře pro editaci.

Metoda deleteUser

Metoda deleteUser přijímá jako parametr ID uživatele a nejprve je zavolána metoda getUserById. Pokud uživatel v databázi existuje, je na záznamu provedena metoda delete třídy ActiveRow, která smaže odpovídající řádek v databázi.

(29)

Metoda getUsers

Zavoláním metody getUsers jsou z databáze vráceny všechny záznamy s uživateli jako pole instancí třídy ActiweRow.

Metoda getPrimaryKey

Metoda getPrimaryKey vrací název sloupce, který je primárním klíčem v tabulce s uživateli.

4.3.4 ZoteroManager

V adresáři model se nachází soubor ZoteroManager.php, ve kterém je definována stejnojmenná třída. V této třídě jsem naprogramoval několik metod pro práci se sí- ťovou knihovnou Zotero popsanou v kapitole 2. Do konstruktoru třídy jsou předány proměnné s ID skupiny a s vygenerovaným klíčem pro komunikaci se Zotero API.

Pro odesílání požadavků protokolem HTTPS jsem použil knihovnu Guzzle [3], kte- rou jsem do projektu doinstaloval pomocí manageru závislostí pro PHP – aplikace Composer [1].

Metoda sendRequest

Metoda sendRequest přijímá jako požadavek číslo prvního záznamu, který má být vrácen a odesílá HTTP požadavek pomocí instance třídy GuzzleHttp\Client a její metody request. Požadavek je odeslán dotazovací metodou HTTP protokolu GET na URI https://api.zotero.org/groups/ID_skupiny/items s následujícími parametry:

• format = ’json’,

• include = ’data’,

• start = $start,

• limit = ’100’,

• order = ’dateAdded’,

• sort = ’desc’,

• key = Zotero API klíč

K parametrům popsaným v kapitele 2.1 jsou přidány ještě parametry pro seřazení záznamů podle data přidání do knihovny od nejnovějšího po nejstarší a také API klíč, který musí obsahovat každý požadavek odeslaný na Zotero API.

Metoda getRecords

Na začátku metody getRecords je zavolána metoda sendRequest, která vrátí nejvýše prvních 100 záznamů ve formátu JSON. Před dalším zpracováním je zkontrolován status HTTP odpovědi, který musí mít kód 200. Tento kód potvrzuje, že HTTP

(30)

aplikace obdržela všechny záznamy. Pomocí PHP funkce json_decode jsou výsledky každého požadavku převedeny z formátu JSON na pole. To je hlavně z důvodu, že poté je možné spojit výsledky do jednoho pole pomocí PHP funkce array_merge.

Zotero API vrací stejným způsobem záznamy článků, knih, ale také jejich příloh a poznámek. Struktura záznamu je zobrazena v příloze C.1. Rozhodl jsem se, že ze získaných záznamů nejprve odeberu všechny položky, které jsou typu attachment nebo note. K tomu jsem navrhl metodu getItems. Vznikne tak pole pouze se záznamy knih a článků, které se mají zobrazit uživateli. Samotné přílohy se získají voláním metody getAttachment. Každá příloha má v poli data prvek parentItem, jehož hod- notou je klíč záznamu, ke kterému příloha náleží. Jako nejlepší způsob spojení příloh s jejich rodiči jsem vymyslel, že informace o přílohách připojím do pole k odpovída- jícím záznamům. U záznamů s přílohami se v poli data vytvoří ještě prvek links a attachments. Do links se pak přidají přílohy, které mají v poli data nastavený prvek linkMode na hodnotu linked_url. Do attachments se přidají informace o ostatních přílohách, kterými jsou soubory převážně ve formátu pdf.

Metoda getItems

Metoda getItems přijímá jako parametr vícerozměrné pole se všemi záznamy z knihov- ny Zotero. Metoda prochází celé pole a vymaže z nich záznamy, které mají nastavený v poli data prvek itemType na hodnotu attachment nebo note.

Metoda getAttachments

Metoda getAttachments pracuje na podobném principu jako předchozí metoda ge- tItems. Ze všech záznamů v poli nechá pouze ty, které mají v poli data nastavený prvek itemType na hodnotu attachment.

Metoda downloadAttachment

Metoda downloadAttachment přijímá jako parametr identifikátor záznamu, který je přiloženým souborem. Pro zobrazení nebo stažení souboru je třeba odeslat HTTP požadavek na Zotero API pomocí instance třídy GuzzleHttp\Client a její metody request. Požadavek je odeslán dotazovací metodou HTTP protokolu GET na toto URI:

• https://api.zotero.org/groups/ID skupiny/items/ID záznamu/file/view.

Jako parametr je předán pouze klíč k Zotero API. Metodě copy_to_string z třídy GuzzleHttp\Psr7 je předán obsah odpovědi, kterým je objekt typu GuzzleHttp\Psr7

\Stream. Obsah souboru je tedy vrácen jako řetězec.

4.3.5 AttachmentResponse

V adresáři model se nachází soubor AttachmentResponse.php, ve kterém je defino- vána stejnojmenná třída implementující rozhraní Nette\Application\IResponse. Ve

(31)

třídě jsem definoval vlastní metodu send, která dokáže zpracovat obsah souboru a odeslat ho uživateli jako HTTP odpověď. Framework Nette totiž sice obsahuje třídu FileResponse, ale ta pracuje pouze se soubory uloženými přímo na serveru a jako parametr vyžaduje cestu k odesílanému souboru. To by znamenalo, že by se na serveru musel vytvořit dočasný soubor, odeslat uživateli a následně tento soubor smazat. Toto řešení mi přišlo zbytečně složité, a proto jsem se rozhodl napsat tuto třídu, které stačí předat pouze obsah souboru. V konstruktoru třídy jsou předány tyto informace:

• obsah souboru;

• jméno souboru;

• informace o tom, zda se má soubor otevřít v prohlížeči nebo nabídnout ke stažení;

• typ obsahu souboru.

Pokud není typ obsahu souboru předán, je nastaven na application/octet-stream, což je binární soubor. V metodě send se k odpovědi nastavuje typ obsahu a do HTTP hlavičky parametr Content-Disposition, který má buď hodnotu inline, pokud se má soubor v prohlížeči uživatele zobrazit.

Content-Disposition: inline

Jestliže se má soubor nabídnout ke stažení, bude mít hodnotu následující:

Content-Disposition: attachment; filename=" jmenosouboru "

Dále se do hlavičky nastavuje ještě velikost souboru získaná PHP funkcí strlen, která spočítá počet znaků jeho obsahu.

4.4 Presentery

V presenterech probíhá zpracování požadavků od uživatele a na jejich základě je volána aplikační logika z modelu. Po vyhodnocení jsou výsledná data odeslána do šablon, které je zobrazí.

4.4.1 BasePresenter

V souboru BasePresenter.php jsou tři podobné metody BootstrapRenderer, Bootstra- pRendererEdit a BootstrapRendererLogin. Tyto metody se starají o to, aby formulá- ře byly vykresleny se stylem frameworku Bootstrap. Jednotlivým prvkům formuláře jsou nastaveny třídy, které odpovídají syntaxi Bootstrapu. Formulářové prvky jsou poté při zobrazení v aplikaci vykresleny s Bootstrap kaskádovými styly a vlast- nostmi. Toto řešení je velmi výhodné, protože v Nette je možné vytvářet formuláře

(32)

přímo při vytváření formuláře. Od abstraktní třídy BasePresenter jsou odvozeny všechny ostatní presentery.

Ve třídě BasePresenter je přepsána metoda checkRequirements, která je již stan- dardně obsažena ve třídě Nette\Application\UI\Presenter. Tato metoda kontroluje, zda má uživatel autorizaci pro přístup k presenteru. Každý presenter musí mít na- stavenou hodnotu anotace @resource, která ho jednoznačně identifikuje. Metoda checkRequirements zjistí hodnotu anotace @resource a poté zkontroluje pomocí me- tody isAllowed z třídy Nette\Security\User, zda má uživatel oprávnění k tomuto zdroji. Pokud je zjištěno, že uživatel oprávnění nemá a že není přihlášen, je pře- směrován na přihlašovací stránku. V případě, že uživatel byl přihlášen, je vytvořena vyjímka a zobrazena stránka s chybovým kódem 403 - neautorizovaný přístup.

4.4.2 EditPresenter

EditPresenter se nachází v souboru EditPresenter.php. Jeho úkolem je zobrazení a editace záznamů z databáze. V konstruktoru třídy EditPresenter se předávají instance tříd DatabaseManager a SessionManager, aby mohly být použity jejich metody. Konstruktor tedy vypadá následovně:

public function __construct(Model\DatabaseManager $dm, Model\SessionManager $sm) {

$this->dm = $dm;

$this->sm = $sm;

}

Kdekoliv v presenteru je pak možné používat metody těchto modelů, např.:

$tables = $this->dm->getTablesCount();

Šablony tohoto presenteru jsou uloženy ve složce templates\Edit.

Metoda beforeRender

Metoda beforeRender se provede vždy před vykreslením šablony. Kontroluje se zde, zda jméno tabulky nastavené v session je stejné jako jméno tabulky předané v URL parametru. Do session se totiž jméno tabulky ukládá ve chvíli, kdy je odeslán fil- trovací formulář. V případě, že se jméno tabulky v session a v URL parametru neshoduje, jsou vymazány session s daty z filtrovacího formuláře a také session se jménem tabulky. Tím je zajištěno, že nemohou být aplikovány nastavené filtry na jinou tabulku.

Výpis informací o tabulkách

Pro výpis informací o tabulkách se používá metoda renderDefault, která se zavolá při kliknutí na tlačítko Databáze v menu aplikace. Tato metoda předává do šablony default.latte informace o tabulkách v připojené databázi, které jsou získány z třídy DatabaseManager pomocí metody getTablesCount, popsané v kapitole 4.3.1. Pro předání dat do šablony se v Nette používá tento zápis:

(33)

$this->template->tables = $tables;

V šabloně je poté přístupná proměnná $tables, se kterou je možné dál praco- vat. Informace jsou v šabloně vypsány do tabulky se stylem Bootstrap, na kterou je javascriptově aplikován plugin DataTables zmíněný v kapitole 3.4. Uživatel vidí výsledek zobrazený na obrázku 4.4.

Obrázek 4.4: Výpis seznamu tabulek z databáze

Název tabulky funguje jako odkaz na metodu renderTable, která vypisuje zázna- my z tabulky. V šabloně se tento odkaz vygeneruje pomocí makra n:href s tímto zápisem:

<a n:href="Edit:table $table ['name ']">{$table['name ']} </a>

Pro přidání nového záznamu je k dispozici tlačítko s nápisem Přidat záznam, které se zobrazuje pouze u tabulek, které nejsou typu view nebo-li pohled. Pokud je tabulka pohledem, není možné editovat její záznamy, přidávat nové záznamy nebo je mazat, ale pouze je prohlížet. Kliknutím na tlačítko Přidat záznam je zavolána metoda addRecord z presenteru AddPresenter, který je popsaný v kapitole 4.4.3.

Výpis záznamů z tabulky

Výpis záznamů z tabulky zajišťuje metoda renderTable, která přijímá jako parametr

(34)

název sloupce, který je primární klíčem tabulky. Z proměnné session jsou načteny filtry z filtrovacího formuláře. Filtry společně s názvem tabulky jsou odeslány jako parametry metody getData, která vrátí odpovídající záznamy z databáze. Popis této metody je v kapitole 4.3.1.

Získaná data jsou odeslána do šablony s názvem table.latte, kde jsou vypsány do tabulky s aplikovaným javascriptovým rozšířením DataTables. Díky tomuto rozšíření je možné řadit záznamy v tabulce podle jednotlivých sloupců, používat stránkování a měnit počet vypsaných záznamů na stránce. Také je možné vyhledávat řetězce v obsahu vypsané tabulky. Tyto funkce jsou velmi rychlé, ale fungují pouze na vypsaná data a nikoliv na celou databázovou tabulku. Pokud bylo vypsáno pouze prvních 3000 záznamů, budou fungovat pouze na tyto záznamy. Pro vyhledávání ve všech záznamech, které tabulka obsahuje, je nutné zadat hledané hodnoty do formuláře pro filtrování. Tento formulář popisuje následující kapitola.

Filtrovací formulář

Pro vytvoření formuláře pro filtrování slouží metoda createComponentFormFilter, jedná se o tzv. továrničku. Filtrovací formulář je touto metodou dynamicky gene- rován pro každou tabulku z databáze. Z URL parametru je zjištěn název tabulky a pomocí něj názvy a datové typy sloupců. Poté je ve formuláři pro každý sloupec vytvořeno vstupní textové pole. Také jsou ze session načteny filtry, které jsou po- užity jako výchozí hodnoty do formuláře. V případě, že žádné filtry nebyly dosud nastaveny, zůstane formulář prázdný.

Na vstupy formuláře jsou použity podmínky, podle toho, jakého datového typu jsou sloupce v databázi. Z informací o sloupcích se kontroluje hodnota parametru na- tivetype, ze které se vezmou první tři písmena. Ta stačí k tomu, aby bylo rozeznáno, zda se jedná o sloupec typu INTEGER, FLOAT, DATE, BOOLEAN. U datových typů TIME a TIMESTAMP se porovnává celá hodnota parametru. Následně se po- mocí konstrukce switch case na formulářová pole přidají správné podmínky metodou addCondition a pravidla metodou addRule. Například zápis, aby do formulářového pole mohlo být zadáno pouze číslo se provede tímto způsobem:

$form[$column['name ']]

->addCondition(Form::FILLED)

->addRule(Form::INTEGER, 'Hodnota musi byt cele cislo ');

V případě, že sloupec obsahuje datum, čas nebo datum i čas (časové razítko), je využito regulárních výrazů, které definují formát, v jakém musí být hodnota zadaná.

Například pro pole s časem byl pro kontrolu použit tento zápis:

$form[$column['name ']]

->setAttribute(" placeholder ", "hh:mm:ss") ->addCondition(Form::FILLED)

->addRule(Form::PATTERN, "Cas musi byt ve formatu hh:mm:ss", "

(([01]\ d|2[0 -3]) :([0 -5]\d):([0 -5]\d))");

V případě, že by se uživatel pokusil zadat například řetězec místo číselné hod- noty, bude na to upozorněn pomocí vyskakovacího okna. Výčet datových typů je k nahlédnutí v dokumentaci k databázi PostgreSQL. [15]

(35)

Na konci vytváření formuláře je zavolána metoda bootstrapRenderer z BasePre- senteru, která formulářovým prvkům přidá styly z front-end frameworku Bootstrap.

V šabloně table.latte je formulář vykreslen zavoláním tohoto příkazu:

{control formFilter}

Formulář je vykreslen pod panelem s nápisem Filtrování, jak je možné vidět na obrázku 4.5. Tento panel navíc funguje jako přepínač, který volá javascriptovou funkci napsanou v šabloně. Pomocí této funkce se formulář může zobrazit nebo skrýt tak, aby na stránce nezabíral místo, když není používaný. Ve chvíli, kdy jsou nastavené nějaké filtry, objeví se na formuláři tlačítko pro jejich zrušení. Jedním kliknutím je tak možné je vynulovat a nechat si zobrazit všechny data.

Obrázek 4.5: Formulář pro filtrování

Po odeslání filtrovacího formuláře kliknutím na tlačítko Filtruj se zavolá metoda filterFormSucceeded, která nastaví hodnoty pro filtrování do proměnné session a zavolá metodu renderTable, aby došlo k překreslení výpisu. Tato metoda je popsaná v kapitole 4.4.2.

Editační formulář

Editaci záznamů je možné provádět po kliknutí na tlačítko se symbolem tužky v prv-

(36)

u tabulek, které nemají sloupec s primárním klíčem. Tlačítko je zobrazené pouze uživatelům oprávněným k editaci.

Formulář pro editaci záznamů je vytvořen pomocí metody createComponentFor- mEdit a šablony editRecordById.latte. V metodě createComponentFormEdit se při vytváření formuláře pro každý sloupec tabulky kontroluje, zda není typu autoin- crement. To by znamenalo, že hodnotu do tohoto sloupce doplňuje databáze auto- maticky, nejčastěji se tato vlastnost nastavuje u primárních klíčů, a proto jsem se rozhodl, že hodnoty ve sloupcích s vlastností autoincrement nebude možné editovat.

V editačním formuláři se proto tyto sloupce vůbec nezobrazují.

Při vytváření formuláře se metodou getForeignKeys popsanou v kapitole 4.3.1 zjistí informace o cizích klíčích. Cizím klíčem se definuje vztah mezi dvěma tabul- kami a musí nabývat pouze hodnot, které jsou primárním klíčem v jiné tabulce. Ve formuláři se u sloupců, které jsou cizím klíčem z jiné tabulky, místo textového pole zobrazí nabídka s výběrem možností, tzv. select. Hodnoty do tohoto rozbalovacího seznamu jsou získány voláním funkce getColumnData, která je popsaná v kapitole 4.3.1. Metodě je předán název tabulky a název sloupce, který je cizím klíčem. Poté se zkontroluje, zda může být hodnota ve sloupci nevyplněná a pokud ano, tak se na začátek získaného pole hodnot přidá ještě prázdná hodnota pomocí PHP meto- dy array_unshift. Zda je v databázi u sloupce nastavena vlastnost NOT NULL na hodnotu TRUE, se zjistí z pole s informacemi o sloupcím z prvku nullable, který je popsaný v kapitole 4.3.1.

Do formuláře se rozbalovací seznam přidá metodou addSelect a naplnění hodno- tami se provede metodou setItems, které se předají hodnoty a jako druhý parametr hodnota FALSE. Díky hodnotě FALSE se v rozbalovacím seznamu jako klíč použijí přímo hodnoty a není vytvářen umělý klíč. Tento postup je užitečný z hlediska před- vyplnění údajů do formuláře při editaci. V seznamu se totiž tyto údaje vyhledávají podle klíče a nikoliv jeho hodnoty.

Toto řešení pomocí rozbalovacího seznamu zajišťuje, že uživatel nemůže zadat hodnotu cizího klíče, která by v odpovídající tabulce neexistovala. Pro zadání hod- not pro zbylé sloupce jsou do formuláře přidána textová pole, u kterých se nastavuje, zda jsou povinná opět na základě vlastnosti nullable. Na konci vytváření formuláře je zavolána metoda bootstrapRendererEdit z BasePresenteru, která formulářovým prvkům přidá styly z front-end frameworku Bootstrap. Editační formulář je vykres- len v Bootstrap dialogovém okně Modal, které je definováno jako tzv. Nette snippet v základní šabloně @layout.latte. Vzhled editačního formuláře, jehož součástí je také tlačítko pro smazání záznamu, můžete vidět na obrázku 4.6.

Po kliknutí na tlačítko se symbolem tužky je vyvolána akce editRecordById s parametrem id záznamu. Funkce actionEditRecordById se pokusí nalézt záznam v databázi a pokud se jí to podaří, vyvolá zobrazení editačního formuláře s vyplně- nými údaji záznamu. Tyto údaje je možné upravit a po kliknutí na tlačítko Uložit jsou zaneseny do databáze. Pro zadané údaje probíhá validační kontrola, zda jsou správného datového typu. Princip je stejný jako u formuláře pro filtrování popsa- ného v kapitole 4.4.2. Po odeslání formuláře dojde k nahrazení všech nevyplněných hodnot, které jsou ve tvaru prázdných řetězců na hodnotu NULL. Pokud by se apli- kace pokusila uložit do databáze hodnotu prázdného řetězce do sloupce s datovým

(37)

Obrázek 4.6: Formulář pro editaci

typem například INTEGER, došlo by k chybě.

Editovaný záznam je také možné z databáze úplně odstranit. K tomu slouží červené tlačítko s nápisem Smazat, u kterého se ještě objeví potvrzovací dialog, aby nedošlo k nechtěnému smazání záznamu. Detail tohoto dialogu znázorňuje obrázek 4.7.

Obrázek 4.7: Dialog pro smazání záznamu

Potvrzovací dialog je vytvořen pomocí javascriptové knihovny Bootstrap Con-

(38)

pokud se jí to podaří, záznam odstraní.

4.4.3 AddPresenter

Třída AddPresenter se nachází v souboru AddPresenter.php a je určena pro vkládání nových záznamů, které je přístupné přes tlačítko Přidat záznam ve výpisu tabulek, popsaného v kapitole 4.4.2. Kliknutím na tlačítko je zavolána metoda actionAddRe- cord, která provede vykreslení formuláře pro přidání záznamu. Formulář pro zadání údajů je vypsán v Bootstrap dialogovém okně Modal a funguje na stejném principu jako editační formulář popsaný v kapitole 4.4.2.

Po odeslání formuláře dojde k volání funkce addFormSucceeded, která uloží nový záznam do databázové tabulky.

4.4.4 ErrorPresenter

V souboru ErrorPresenter.php se nachází stejnojmenná třída, která se stará o zob- razení chybových hlášení. Pokud dojde k nějaké chybě, je podle stavového kódu pro- tokolu HTTP zavolána odpovídající šablona uložená v adresáři templates/Error/.

Každá šablona obsahuje krátký popis, k jaké chybě došlo. Zároveň je také informa- ce o vzniklé chybě, včetně časového údaje, uložena do souboru s chybovými logy access.log ve složce s názvem log.

4.4.5 HomepagePresenter

V souboru HomepagePresenter.php je definována třída HomepagePresenter, která nemá žádnou funkcionalitu. Této třídě je pouze anotací @resource nastaven zdroj na hodnotu Front:Homepage a je spojena se šablonou default.latte ve složce Home- page. V této šabloně je definován vzhled domovské stránky, na které se vykresluje rozcestník do celkem čtyř zdrojů. Vzhled domovské stránky je zobrazen v příloze na obrázku A.1. Uživatel je na tuto stránku přesměrován po přihlášení nebo po kliknutí na nápis HgIS Admin v horním menu aplikace.

4.4.6 SignPresenter

V souboru SignPresenter.php je definována třída SignPresenter, která má na staros- ti přihlašování uživatelů a zobrazení jejich profilu. Šablony tohoto presenteru jsou uloženy ve složce s názvem Sign. Uživatel se může do webové aplikace přihlásit pomocí přihlašovacího formuláře, který je popsán samostatně v této kapitole. For- mulář vytváří metoda createComponentSignForm, která volá metodu create třídy SignFormFactory a formulář předává do šablony in.latte.

Přihlašovací formulář

Ve složce s názvem forms se nachází soubor SignFormFactory.php a je v něm defi- novaná stejnojmenná třída. V této třídě je metoda create, která vytváří přihlašovací

(39)

formulář. Ve formuláři je povinné pole pro uživatelské jméno a heslo a také zaškr- távací políčko s nápisem Zůstat přihlášen. Vzhled formuláře zobrazuje obrázek 4.8.

Obrázek 4.8: Přihlašovací formulář

Po odeslání formuláře se nejprve metodou setExpiration třídy Nette\Security

\User nastaví, za jak dlouho bude uživatel odhlášen v případě neaktivity. V do- kumentaci Nette je uvedeno, že se tato metoda má volat ještě před samotnou au- tentizací. Není-li zaškrtnuté políčko Zůstat přihlášen, bude uživatel automaticky odhlášen po 30 minutách neaktivity nebo při zavření prohlížeče. Pokud políčko bu- de zaškrtnuté, nastaví se čas expirace přihlášení na 14 dní a uživatel zůstane při- hlášen i po zavření prohlížeče. Metodou login třídy Nette\Security\User se zavolá autentikátor, kterým je třída UserManager a její metoda authenticate popsaná v ka- pitole 4.3.3. Při zadání neexistujícího uživatelského jména, je odchycena výjimka Nette\Security\AuthenticationException s kódem 1, případně s kódem 2, pokud je zadáno špatné heslo. Na základě těchto chybových kódů je konstrukcí switch case zobrazena chyba u odpovídajícího pole přihlašovacího formuláře.

V případě, že je uživatel v pořádku přihlášen, zobrazí se jeho uživatelské jméno v pravé části horního menu aplikace. Po kliknutí na uživatelské jméno se uživateli zobrazí vysouvací menu s možností zobrazit si svůj profil nebo se odhlásit. Menu pro přihlášené uživatele je zobrazeno na obrázku 4.9.

Obrázek 4.9: Uživatelské menu

(40)

Metoda renderProfile

Metoda renderProfile se zavolá při zobrazení profilu uživatele a je v ní kontrolováno, zda je uživatel přihlášen. V případě, že by uživatel nebyl přihlášen, je přesměrován na stránku s přihlašovacím formulářem. S touto metodou je spojena šablona profi- le.latte, ve které je definován vzhled stránky s profilem. Zobrazuje se zde uživatelské jméno a role. Pokud by informace o uživateli byly rozšířeny, nebyl by problém ša- blonu upravit a zobrazovat další data. Ukázka toho, jak vypadá stránka s profilem je na obrázku 4.10.

Obrázek 4.10: Profil uživatele

Metoda actionOut

Metoda actionOut je zavolána při kliknutí v uživatelském menu na položku Odhláše- ní. Na instanci uživatele je zavolána metoda logout třídy Nette\Security\User, která provede jeho odhlášení z webové aplikace. Odkaz na metodu actionOut je zapsán v základní šabloně @layout.latte pomocí Latte makra n:href:

<a n:href="Sign:out">Odhlaseni</a>

4.4.7 UserPresenter

V souboru UserPresenter.php je definována třída UserPresenter, která má na staros- ti správu uživatelů. Metody tohoto presenteru se starají o zpracování požadavků na přidání, editaci a mazání uživatelů. Presenter také získává data o uživatelích a pře- dává je pro zobrazení do šablon, které jsou uloženy ve složce s názvem User. Přístup k tomuto presenteru mají pouze uživatelé s rolí admin, kteří do správy uživatelů mohou přejít přes položku Uživatelé v horním menu aplikace.

Metoda renderDefault

V metodě renderDefault se nejprve získají data o uživatelích pomocí metody ge- tUsers ze třídy UserManager, která je popsaná v kapitole 4.3.3. Poté se ze stejné třídy zavolá ještě metoda getPrimaryKey, aby byl získán název sloupce s primárním klíčem v tabulce s uživateli. Informace o uživatelích jsou společně s názvem sloupce

(41)

s primárním klíčem předány do šablony default.latte. V šabloně je vykresleno tlačít- ko pro přidání nového uživatele a informace o uživatelích jsou vypsány do tabulky se stylem Bootstrap, na kterou je javascriptově aplikován plugin DataTables zmíněný v kapitole 3.4. Výsledný vzhled výstupu znázorňuje obrázek 4.11.

Obrázek 4.11: Výpis uživatelů

Při kliknutí na tlačítko pro přidání nového uživatele je vykreslena šablona ze sou- boru newUser.latte, ve které se volá metoda presenteru createComponentNewUser- Form. V této metodě je pouze vytvořen formulář pro přidání nového uživatele.

Formulář pro přidání nového uživatele

Ve složce s názvem forms se nachází soubor NewUserFormFactory.php a je v něm definovaná stejnojmenná třída. V této třídě je metoda create, která vytváří formulář pro přidání nového uživatele. Na začátku této třídy je do pole uložen seznam všech rolí, kterými mohou uživatelé disponovat. Pole s rolemi je poté předáno do vstupního pole select – nabídky s výběrem možností. Ve formuláři je textové pole pro zadání uživatelského jména, které musí mít délku v rozmezí 4 až 30 znaků. Heslo zadané do pole typu password musí mít délku v rozmezí 6 až 30 znaků. Všechny položky formuláře jsou povinné a musí být vyplněné.

Po odeslání formuláře se zkusí provést metoda addUser popsaná v kapitole 4.3.3.

Pokud by v databázi již existovalo zadané uživatelské jméno, je odchycena výjim- ka Nette\Database\UniqueConstraintViolationException a formuláři je nastavena chyba u textového pole s uživatelským jménem. Vzhled formuláře včetně zobrazené chyby je znázorněn na obrázku 4.12.

(42)

Obrázek 4.12: Formulář pro přidání nového uživatele

Formulář pro editace uživatele

Ve složce s názvem forms se nachází soubor EditUserFormFactory.php, který vytvá- ří formulář pro editaci uživatele. Tento formulář je podobný formuláři pro přidání nového uživatele, a proto zde popíši pouze rozdíly, kterými se od sebe liší. V edi- tačním formuláři je pole s heslem nepovinné. Vyplňuje se pouze, když je uživateli potřeba změnit heslo. Dalším rozdílem je, že do formuláře bylo přidáno tlačítko pro smazání uživatele, které je doplněno potvrzovacím dialogem. Při odeslání formuláře jsou informace o tomto tlačítku odstraněny z předaných hodnot a je zavolána me- toda editUser popsaná v kapitole 4.3.3. Metodě se předají hodnoty z formuláře a ID uživatele získané z parametru presenteru. Stejně jako při vytváření nového uživatele je odchycena výjimka, pokud by uživatelské jméno v databázi již existovalo.

4.4.8 ZoteroPresenter

V souboru ZoteroPresenter.php je definována třída ZoteroPresenter, která uživateli zprostředkovává data ze síťové knihovny Zotero popsané v kapitole 2. Presenter předává data ke zobrazení do šablon, které jsou uloženy ve složce s názvem Zotero.

Přístup k zobrazeným datům mají uživatelé přes položku Zotero v horním menu aplikace.

Metoda renderDefault

Metoda renderDefault se provede při kliknutí na odkaz Zotero v horním menu apli- kace. Nejprve jsou získány data voláním metody getRecords z třídy ZoteroManager.

Jakým způsobem tato metoda pracuje je popsáno v kapitole 4.3.4. Data jsou pře- dána do šablony s názvem default.latte. Struktura jednotlivých záznamů je poněkud složitější, jak je možno vidět v příloze C.1. Oproti této struktuře mají záznamy ještě navíc přidány v poli data prvky links a attachments.

Záznamy jsou vypsány do tabulky se stylem Bootstrap, na kterou je aplikován javascriptový plugin DataTables. Díky tomuto pluginu je možné záznamy řadit a

(43)

Název sloupce Popis Umístění

Id identifikátor záznamu $item[’data’][’key’]

Název název\titul záznamu $item[’data’][’title’]

Autor autor knihy $item[’meta’][’creatorSummary’]

Upraveno datum poslední modifikace $item[’data’][’dateModified’]

Přílohy přílohy a odkazy $item[’data’][’attachments’]

$item[’data’][’links’]

Tabulka 4.1: Zobrazené informace z knihovny Zotero

provádět rychlé vyhledávání. Tabulka 4.1 obsahuje seznam zobrazených informací z knihovny Zotero včetně jejich popisu a umístění, ze kterého jsou data čerpána.

V šabloně jsou řádky do tabulky vypisovány makrem foreach, které iteruje nad každým záznamem. Datum poslední modifikace je předán PHP funkci date_create.

Ta se stará o to, aby byl datum do tabulky vypsán ve správném formátu.

Při výpisu příloh se musí zkontrolovat, zda právě vypisovaný záznam obsahuje prvek $item[’data’][’attachments’], pokud ano, začne se iterovat makrem foreach nad každou položkou. Do tabulky se zobrazují malé ikony knihy, které symbolizující sou- bor s přílohou. Po najetí kurzorem myši na tuto ikonu se zobrazí název přílohy. Ikona funguje jako odkaz na akci ZoteroPresenteru getAttachment. Této metodě se pře- dává klíč přílohy, což je její jednoznačný identifikátor, dále jméno souboru z $atta- chment[’data’][’filename’] a typ obsahu souboru z $attachment[’data’][’contentType’].

Pokud záznam obsahuje prvek $item[’data’][’links’], začne se iterovat makrem foreach nad každou jeho položkou. Do tabulky se zobrazují malé ikony zeměkoule s odkazem získaným z $link[’data’][’url’]. Po najetí kurzorem myši na tuto ikonu se zobrazí název odkazu. Při kliknutí na ikonu se odkaz otevře v nové záložce webového prohlížeče.

Výpis informací ze síťové knihovny Zotero znázorňuje obrázek 4.13.

Metoda getAttachment

Metoda getAttachment je vykonána po kliknutí na ikonu přílohy. Na základě předa- ného identifikátoru přílohy volá metodu downloadAttachment třídy ZoteroManager, která je popsána v kapitole 4.3.4. Získaný obsah souboru se předává konstrukto- ru třídy AttachmentResponse popsané v kapitole 4.3.5. Tato metoda vrací HTTP odpověď, která je uživateli odeslána metodou sendResponse zavolanou ve třídě Zo- teroPresenter. Metoda sendResponse je ve frameworku Nette součástí třídy Net- te\Application\UI\Presenter.

Konstruktoru třídy AttachmentResponse se předává jako třetí parametr hodnota FALSE, to znamená, že se webový prohlížeč má pokusit přílohu zobrazit. U příloh

References

Related documents

Důležitou součástí, by také měla být zpětná vazba od zaměstnance a na toto se jeví jako nejlepší metoda hodnotícího pohovoru, kde může pracovník volně vyjád it své

Veškeré komponenty aplikace, jako jsou tlačítka tabulky apod., jsou řešeny za pomoci Community Tools.. Tyto objekty jsou vytvořeny v souboru template.html a tvoří hlavní

Při opakování začal slova říkat správně a pak lépe dokázal přiřadit písmenko na začátek nebo na konec slova. Poslední probírané učivo

[r]

[r]

[r]

Mým úkolem bylo najít a analyzovat existující aplikace určené pro evidenci servisních zásahů vozidel, navrhnout webovou aplikaci včetně funkcí které bude

Pro tvorbu aplikace editoru byla využita verze 5.6, která podporuje export projektu pro Windows i WebGL.. V editoru je otevřená scéna reprezentována prvky uspořádanými v