STRIX
StrixDocumentManagementForProgrammers: Revision 7
docman-import.php

Strix Document Management s naglaskom na import dokumenata

O dokumentu

Nove verzije ovog dokumenta bi se mogle naci na strix wikiju.

Verzija 1: Matko Anđelinić, Srpanj 2005., Inicijalna verzija

Opis tablica

Tablica "document"

Glavna tablica. Zapisi i za dokumente i foldere.

id integer jedinstveni id dokumenta
title character varying(256) naslov dokumenta (ne nuzno isto sto i filename)
description text opis - text/html polje s opisom dokumenta
activation_time timestamp without time zone vrijeme aktivacije dokumenta
expiration_time timestamp without time zone vrijema isteka dokumenta
creation_time timestamp without time zone vrijeme dokumenta (glavno datumsko polje na dokumentu)
lang_id integer jezik u tablici lang
allow_discussion boolean t/f - dopusteno otvaranje diskusije o dokumentu na forumu
author_id integer zastarjelo polje za autora. pogledaj tablicu document_author
parent_folder_id integer id parent foldera (zapis u istoj tablici)
folder boolean t/f - radi li se o folderu ili o dokumentu
locked boolean nije u upotrebi
approved boolean dokument je odobren - ako je false dokument se pojavljuje u "waiting for approval" popisu
keywords text kljucne rijeci
edit_time timestamp without time zone zadnje vrijeme promjene zapisa
edit_user integer korisnik koji je napravio zadnju promjenu (tablica users)
source text free text polje - atribut "izvor dokumenta"

PRIMARY KEY (id)

Tablica "document_revision"

Tablica koja veze verziju dokumenta s filenameom na filesystemu servera. Filename
je samo filename i ne ukljucuje path (ni relativni ni apsolutni).

document_id integer id dokumenta
version_num smallint redni broj verzija (nije vezan ni za jednu sekvencu)
filename character varying(256) naziv dokumenta na filesystemu (bez patha, samo filename)
filesize integer veličina fajla u bajtovima
edit_time timestamp without time zone vrijeme promjene
editor_id integer user koji je napravio promjenu
last_author integer polje last author (mijenja se preko sucelja)

PRIMARY KEY (document_id, version_num)

Napomena 1: Verzioniranje ide redom 1, 2, ....

Napomena 2: Iako folderi ne mogu imati verzije, za njih je svejedno potrebno
imati zapis u ovoj tablici s version_num=0, te proizvoljnim vrijednostima u
ostalim poljima.

Napomena 3: Lokacija dokumenta na disku se racuna ovako:

$docman_dir/$document_id/$version_num/$filename

gdje je

  • $docman_dir - konfiguracijska varijabla iz etc/.conf.php
  • $document_id - id dokumenta (public.document.id ili public.document_revision.id)
  • $version_num - redni broj verzije dokumenta (public.document_revision.version_num)
  • $filename - vrijednost u polju public.document_revision.filename

Tablica "document_author"

Vise zapisa po dokumentu. Informacija o autorima dokumenta koja se moze unositi
i mijenjati preko sucelja. Po defaultu bi trebao biti barem jedan zapis s npr.
osobom koja je uploadala dokument.

document_id integer id dokumenta
version_num smallint verzija
author_id integer autor iz tablice users

PRIMARY KEY (document_id, version_num, author_id)
FOREIGN KEY (document_id, version_num) referencira "document_revision"

Ostale tablice

atributi
komentari

Dozvole

Koristi se STRIX-ov sustav dozvola - ACL. Oznaka za dokumente u ACL-u je 'file'.

Tablice acl_user i acl_group

Opis ACL-a nije u scopeu ovog dokumenta pa se nece opisivati. Vazno je da postoje
te tablice, te zgodna plpgsql funkcija:

acl_userObjectAddPerm(user_id, 'file', document_id, perm)

Za dokumente perm moze biti:

  • 'PERM_READ' ili integer vrijednost 1
  • 'PERM_SUGGEST' ili integer vrijednost 2
  • 'PERM_AUTHOR' ili integer vrijednost 4
  • 'PERM_OWN' ili integer vrijednost -1 ili 8

Automatska, defaultna dodjela dozvola

Uploaderu se, na razini baze (triggerom) automatski dodjeljuje OWN pravo. Bez
obzira na sučelje kojim je zapis zavrsio u bazi. Uploader je osoba upisana
u polju author_id prilikom inserta recorda u tablicu document.

Za one koji zele znati vise, za to je zaduzen sljedeci zapis u tablici
acl_users_default:

 acl_id |                              default_sql
--------+-----------------------------------------------------------------------
 file   | SELECT 'file', NEW.id, author_id, -1 FROM document WHERE id = NEW.id

Dodatno, preporuka je da se OWN pravo dodijeli i svim osobama navedenim kao autori
dokumenta u tablici document_author.

SELECT acl_userObjectAddPerm($user_id, 'file', $document_id, 'PERM_OWN');

Mali primjer importa dokumenta koristenjem PHP libraryja

Zamislimo slucaj da imamo na filesystemu dokument /data/tmp/dokument.doc kojeg
zelimo importati u novi folder "Novi folder" koji bi se nalazio ispod postojeceg
foldera XXXX sa id-jem 9.

Stanje sadrzaja foldera XXXX prije pokretanja skripte za import:

	plivaweb=# select id, title, folder, depth, ord from getDocumentTree(9);
	 id |   title   | folder | depth | ord
	----+-----------+--------+-------+-----
	 12 | Bayer.zip | f      |     0 |   1
	 13 | Lilly.zip | f      |     0 |   2
	(2 rows)

Skripta za import:

	<?php
	
		include_once("sysinc/stdlib.php");
		include_once "docman.php";
		
		// globalna varijabla koja (ako je true) libraryju govori da 
		// pobrise OWN dozvole koje su automatski dodijeljene uploaderu (author_id)
		// preko triggera u bazi
		$PD_no_automatic_perms = false; 
		
		$parent_folder = 9; 
		$document_path = "/data/tmp/dokument.doc";
		
		$in = array (
		     "title" => "Novi folder"
		   , "description" => ""
		   , "creation_time" => strftime("%Y-%m-%d")
		   , "lang_id" => "1"
		   , "allow_discussion" => "t"
		   , "author_id" => "4"
		   , "approved" => "t"
		   , "keywords" => "testni folder, document import"
		   , "edit_time" => ""
		   , "edit_user" => ""
		   , "source" => ""
		   , "folder" => "t"
		);
		$folder = PlivawebDocuments::createFolder($parent_folder, $in);
		
		if (PlivawebDocumentsError::isError($folder)) die ($folder->text);
		
		//ako smo ovdje u varijabli $folder imamo id novokreiranog foldera
		
		$in = array (
		     "title" => "Moj dokument"
		   , "description" => "Dokument koji sam uploadao"
		   , "creation_time" => strftime("%Y-%m-%d")
		   , "lang_id" => 1 
		   , "allow_discussion" => "t"
		   , "author_id" => 3 
		   , "approved" => "t"
		   , "keywords" => ""
		   , "edit_time" => strftime("%Y-%m-%d")
		   , "edit_user" => 3
		   , "source" => ""
		
		   , "attributes" => array()
		
		   , "local_file_name" => $document_path
		
		);
		
		$did = PlivawebDocuments::addDocument($folder, $in);
		if (PlivawebDocumentsError::isError($did)) die ($did->text);
		
		echo "Document created";

	?>

Pokrenuta skripta:

$ php4 docmanimport-example.php plivaweb

Stanje sadrzaja foldera XXXX poslije pokretanja skripte za import:

	plivaweb=# select id, title, folder, depth, ord from getDocumentTree(9);
	  id  |    title     | folder | depth | ord
	------+--------------+--------+-------+-----
	 4949 | Novi folder  | t      |     0 |   3
	 4950 | Moj dokument | f      |     1 |   4
	   12 | Bayer.zip    | f      |     0 |   6
	   13 | Lilly.zip    | f      |     0 |   7
	(4 rows)

Napomena 1: PHP library u inc/docman.php nije ni blizu kompletan i 100% fail safe,
ali je dobar start za nekoga tko zeli importati dokumente kroz skriptu.

Napomena 2: Nema razloga da se ne napise skripta u nekom drugom jeziku koja
bi direktno pisala po document* tablicama pridrzavajuci se gore opisanih pravila.

Dodatak: Funkcije za dohvat podataka

Postoji niz funkcija za rukovanje (dohvacanje podataka). One su mahom rekurzivne.
Popis tih plpgsql funkcija, zajedno s implementacijom moze se naci u
tables2/docman.sql.

Najcesce koristena takva funkcija je getDocumentTree(folder_id integer) koja
vraca popis zapisa iz document tablicom skupa s dvije dodatne kolone depth (dubina,
razina) te ord (redoslijed po kriteriju folder, title)

Npr.

plivaweb=# select id, title, folder, depth, ord from getDocumentTree(26);
 id  |               title                | folder | depth | ord
-----+------------------------------------+--------+-------+-----
  27 | forms                              | t      |     0 |   1
  28 | AC form                            | f      |     1 |   2
 426 | ChemClient Izjava                  | f      |     1 |   3
 427 | Formular za publikacije            | f      |     1 |   4
 417 | HTS_form.pdf                       | f      |     1 |   5
 418 | New_PL_form.pdf                    | f      |     1 |   6
 419 | New_PL_form.xls                    | f      |     1 |   7
 422 | PK&M form                          | f      |     1 |   8
  29 | Publications Form                  | f      |     1 |   9
 428 | Rjesenje GO                        | f      |     1 |  10
 429 | Zahtjev za nabavu                  | f      |     1 |  11
  33 | instructions                       | t      |     0 |  12
  35 | LabNotebooks law.pdf               | f      |     1 |  13
 421 | Pravilnik za pisanje lab. dnevnika | f      |     1 |  14
 420 | Upute o kretanju NII.pdf           | f      |     1 |  15
  30 | instruments                        | t      |     0 |  16
  31 | instruments_development.xls        | f      |     1 |  17
  32 | instruments_research.xls           | f      |     1 |  18
  37 | presentations                      | t      |     0 |  19
(19 rows)

Preporuka je, ne koristiti ovu funkciju bas za svaku moguci dohvat dokumenata,
jer dodavanje WHERE uvjeta nad ovakav upit nece nimalo ubrzati dohvat podataka.
Ako bi se dodao Where uvjet, svejedno bi se za svaki upit izgenerirao kompletan
result set nakon cega se tek radi filtriranje. Bolje rjesenje je da se za svaku
specificnu upotrebu pri kojoj je bitna efikasnost pise svoja rekurzivna funkcija.

Napomena: Iako to nije slucaj sa funkcijama u tables2/docman.sql, zgodno je
dodati STABLE u definiciji takve funkcije sto bi moglo bitno ubrzati te funkcije
u nekim slucajevima. (Npr. u sucajevima kada se u jednom upitu radi visestruko
pozivanje iste funkcije s istim parametrima).