Dokumentový sklad v.1
Dokumentový sklad
z
První verze (2002): z
z
Petr Lampa
Ukládání diplomových prací a ročníkových projektů v PDF a PostScriptu Požadavky: z z z
z
Řešení: z
z
Dokumentový sklad v.2 z
Druhá verze (2003): z
Cíle: z z z z z z
z
Strukturovaný dokumentový sklad pro ukládání dokumentů fakulty Organizace ve formě stromu Ukládání metadat k dokumentům Přístupová a majitelství adresářů/souborů Možnost ukládat verze dokumentů Jednoduchá správa Web prohlížečem (použití sekretariáty)
Koncepce: z
Stejné rozhraní by se hodilo pro prohlížení DP a do budoucna také pro odevzdávání projektů v předmětech
Archivace dokumentů Malá četnost prohlížení Žádná indexace Fixní systém práv (student pouze uložit/číst svou práci), ostatní všechno číst Pevná struktura pojmenování (/báze/ROK/BP/id.pdf)
Koncepce skladu v.2 z
Co je společné? z z
z
z
Uživatelské rozhraní Zpracování úplného jména dokumentu, validace a kontroly Některé operace (download, upload, rm)
Co je různé? z z z
Systém pojmenování dokumentů/adresářů Co je povoleno (přístupová práva) Vazba na tabulky v informačním systému
1
Koncepce skladu v.2 z
Řešení: z
Ukládání do systému souborů (důležitý návrh pojmenování) z z z
velké BLOBy v databází silně komplikují archivaci/restore na funkčnosti skladu bezprostředně nezávisí funkčnost IS fulltext v databázi sice funguje, ale:
problém stemizace velká zátěž databáze při indexaci problém konverze formátů (PDF)
Pojmenování z z z
z z
z
/rp/
//.pdf (ps) /dr/{/}<soubor> /ci///{/}/<soubor> /course///{/}<soubor> …
První komponenta určuje typ skladu, čili třídu generovaného objektu
Koncepce skladu v.2 z z
z
z z
Použít objektově orientovaný návrh Společné vlastnosti implementovat jako bázovou třídu Specifické mutace funkčnosti různých částí skladu implementovat odvozenými třídami Integrace různých typů skladu do jednoho stromu Omezení: typ je dán nejvyšším adresářem
Implementace class doc_file { function doc_create($name, $path) {
// factory method $classname = "doc_folder_${name}“; if (!class_exists($classname)) { $src = "$docs_handlers/docs_${name}.php"; if (file_exists($src)) include_once($src); } return new $classname($path); } function doc_file($path) { … }
// constructor
2
Metody z
z
doc_title(), doc_access($mode), doc_realpath(), doc_path(), doc_remove(), doc_upload() doc_attrs() – seznam atributů, které podporuje daný typ skladu:
array("type" => array("title"=>"Typ", "sort"=>true, "show"=>true, "order"=>"10", "type"=>"icon"), "title" => array("title"=>"Název", "sort"=>true, "show"=>true, "order"=>"20", "type"=>"link", "filter"=>32), ... );
Uživatelské rozhraní z
docs_show($dir, $attrs) z z z
z
Univerzální metoda, nezávislá na typu skladu. Styl zobrazení, zobrazené prvky, povolené operace dány polem parametrů. Zobrazí ovládací prvky (HTML form, vstupní pole), detekuje jejich použití, kontroluje validitu a volá patřičné metody. Podle definovaných atributů generuje patřičné filtry sloupců, odkazy pro řazení, titulky, obsahy sloupců, atd.
Metody z
z
doc_getdir() – vygeneruje pole obsahující obsah adresáře, ke každému souboru všechny atributy doc_oper() – zpracování požadavku z uživatelského rozhraní (download, upload, mkdir)
Hlavní problémy z
Koncepce jedné třídy reprezentující dokument se ukázala jako příliš omezující: z
z
z
z
Při zpracování operací je třeba pracovat s komponentami v cestě diskrétně (kontrola práv, nadřazený adresář). Parsování a validaci cesty musela být implementována v každé odvozené třídě znovu. Pro nové typy skladů bylo třeba zavést přechody mezi různými typy skladů (obdoba mount v Unixu). Uživatelské rozhraní musí u některých operací pracovat současně s dvěma soubory.
3
Dokumentový sklad v.3 z
Cíle: z z z
z
Odstranit omezení rozšiřovatelnosti. Oddělit třídu zabalující uživatelské rozhraní od třídy popisující dokument. Implementovat do bázové třídy dokumentu více funkčnosti tak, aby byl návrh odvozených tříd jednodušší (a bezpečnější). Při implementaci využít principy používané v systémech souborů (místo kompletního parsování jména použít zpracování po komponentách jména).
doc_file function doc_parse($path) { $cur =& new doc_folder(&$this->repos, null, '/'); $this->folders[0] = &$cur; $this->dirs = explode('/', $path); for ($i = 1; $i < count($this->dirs); $i++) { if (!$cur->doc_access(AUTH_WALK)) *ERR if (!$cur->doc_valid_name($this->dirs[$i], false)) *ERR if (!$cur->doc_lookup(&$this->repos, $this->dirs[$i], $i, &$this->folders[$i])) *ERR $cur = &$this->folders[$i]; }
Nová struktura tříd z z
z
class doc_folder – komponenta v cestě class doc_file – dokument (obsahuje pole objektů doc_folder) class doc_repos – zabalení uživatelského rozhraní a společných dat
doc_folder
z
function doc_lookup($name, $level, &$cur) { if ($level != 1 || !ctype_alpha($name)) *ERR $classname = "doc_folder_${name}"; if (!class_exists($classname)) { $src = "$docs_handlers/docs_${name}.php"; if (file_exists($src)) include_once($src); if (!class_exists($classname)) *ERR } $cur = new $classname(&$this, $name); } ctype_digit() – PHP 4.3.x!
4
Výsledek z z
z
Prodloužení kódu, nicméně logičtější struktura a snadnější zápis. Složitější na pochopení – v některých metodách reprezentuje $this aktuální komponentu, jinde nadřazenou komponentu. Ukázalo se jako nezbytné v některých operacích reprezentovat dokument instancí a v jiných reprezentovat instancí nadřazeného adresáře a holým jménem (neregulérní struktura).
Implementované typy z z
z z z
z
ci – soubory k termínům (jedna úroveň) course – soubory k předmětům (seznam předmětů z IS, seznam virtuálních podadresářů, dále dr) dr – strukturovaný adresář s právy a metadaty ftp – FTP klient product, proj, pub – soubory k VaV (báze z IS, dále z dr) rp – diplomky
Výsledek z
Lze přecházet z jednoho typu skladu do druhého libovolně: z
/pubs → zpracováno bázovou třídou, vznikne instance třídy doc_pub z
/132 → zpracováno doc_pub, vznikne instance třídy doc_dr
z
/adresář…/soubor → zpracováno doc_dr
Aplikovaná třída zajišťuje správnou kontrolu validity jména, testování přístupových práv a také povolený repertoár operací.
Použití z z
Použití částí skladu je zabudováno do různých částí IS FIT, s omezením na podstrom Prohlížeč celého skladu:
$docs_params = array( … ); $repos = new doc_repos($pathinfo, $self, $path_type, $docs_params); $ok = $repos->doc_oper($vars, &$file); is_header(); if ($ok) $repos->docs_show(&$file, $vars); else $repos->docs_print_error(); is_footer();
5
Fulltext z
z
z
z
Prohlížeč skladu generuje regulární HTML dokument s odkazy na soubory/podadresáře. Sklad lze indexovat libovolným nástrojem indexace Web prostoru. Problémy: omezení na část prostoru, aplikace přístupových práv, prohledávání podle typu. Mnogosearch – open source engine, index v MySQL jako blob, zvládá vícejazyčné mutace, tvary slov, tagování prostoru podle kritérií.
Sklad v.3.1 + AJAX z
z
z
z
Operace copy/rename vyžadují jako parametr cílový adresář nebo jméno. Web je na aplikaci rozhraní typu NC příliš těžkopádný – odeslání odpovědi na formulář, vygenerování a přenos celého HTML dokumentu trvá příliš dlouho. Je nutno doplnit jednoduchý průchod adresářovou strukturou pro výběr cílového adresáře. Ideální na aplikaci AJAXu (Asynchronous JavaScript and XML)
By-product - FTP klient z z z z
z
Vznikl jako ověření koncepce v.3 za jedno odpoledne. Kompletně včetně implementace protokolu FTP v PHP. Skutečně se uplatnila nová hierarchie tříd. Jediná komplikace bylo doplnění operace rename, bylo třeba reimplementovat protokol FTP tak, aby byl lokální na úrovni instance, ne na úrovni doc_repos (je třeba otevřít dvě nezávislé spojení pro zpracování zdroje a cíle). Kupodivu se stal nejpoužívanějším typem skladu.
Složitost modifikace z
z
Doplnit XML výstup pro doc_getdir() – triviální, bude se hodit i pro jiné aplikace. Dynamicky naplněný HTML <SELECT> podle obsahu poslední komponenty cesty zadané v textovém poli: z
z
Dovoluje zadat rychle část nebo celou cestu v textovém poli a pak teprve vygenerovat obsah. Zároveň dovoluje průchod stromem bez zadávání, jen myší.
6
Princip z
z
Událost onchange seznamu volá JavaScript funkci xml_getdir(): xmlreq = new XMLHttpRequest(); xmlreq.open('GET', URL, true); xmlreq.onreadystatechange = xml_finish; Stránka zůstává v prohlížeči zobrazena, požadavek GET se uloží jako samostatný strom a pak xml_finish():
PHP jako objektový jazyk z
z
z
dir = xmlreq.responseXML.getElementsByTagName("dir"); for (var i = 0; i < dir.length; i++) { el = document.createElement("option"); el.value = dir[i].getAttribute("name"); el.appendChild(document.createTextNode( dir[i].getAttribute('name'))); idselect.appendChild(el); }
Raději PHP5 z z z z z z z
Implicitně se předávají a přiřazují objekty referencí (pro kopii clone) Není kompatibilní s PHP4 – přebytečné reference hlásí jako chybu Omezení viditelnosti (public, private) Konstruktor, destruktor Statické metody a atributy Abstraktní třídy a interface Deklarace tříd parametrů (typová kontrola)
PHP4 lze použít, ale:
z z
PHP nemá ukazatel, vše je implicitně předáváno hodnotou, čili vzniká kopie instance objektu (výjimka je $this). Což nevadí, dokud není třeba něco vracet z metody nebo sdílet jednu instanci pro společná data. Pak je třeba použít referenci - & Katastrofa – je třeba bedlivě hlídat, kde referenci napsat a kde ne. Nestačí jen v deklaraci funkce, ale je třeba také při přiřazení a volání.
Final note z
Jak správně zacházet s URL (STD 66): z
vygenerovat správně htmlspecialchars(něco) nestačí!
z
rawurlencode() nebo urlencode()?
z
z
z
prefixuje pouze <, >, &, “, ale URL jen A-Z,0-9,-,_,.,~ ani jedno – určeno pro zakódování pouze částí!
z z
<scheme>://[<user>[:<pass>]@]?[ =]{&=}[#]
urlencode() je na , , nahrazuje ‘ ‘ za + rawurlencode() je určeno na , nahrazuje ‘ ‘ za %20, ale taky / za %2F, ~ za %7E (je třeba obnovit)
7
Final note z
z
Generované URL je třeba obecně rozparsovat na jednotlivé části, parametry CGI na jednotlivé dvojice (jméno, hodnota) a na každou část aplikovat jiný způsob zakódování. Problém URL oddělovače &: z z z
v URL je naprosto legální není legální v HTML! (uvozuje entity) nahrazovat v URL vždy &
8