TABUN_CMS System zarządzania treścią dla dedykowanej grupy użytkowników
Spis treści TABUN_CMS...1 Informacje wstępne...3 Cele wdrożenia systemu...3 Wykorzystane technologie...3 Ocena działania systemu...3 Wygląd i funkcjonalności aplikacji...4 Moduły aplikacji...5 Dodatkowe możliwości użytkownika zalogowanego...8 Użytkownik bez dodatkowych uprawnień (grupa obserwator -domyślna)...12 Użytkownik dodany do grupy klubowicz...12 Użytkownik dodany do grupy moderator...13 Użytkownik dodany do grupy administrator...14 Budowa aplikacji...16 Wykaz tabel...16 Tabela users...16 Tabela groups...17 Tabela articles...18 Tabela comments...19 Tabela windows...19 Tabela window_properties...20 Tabela window_defaults...21 Relacje między tabelami...22 Skrypty PHP...23 Funkcje i triggery zwiazane z automatycznym dodawaniem danych:...23 Funkcje i triggery zwiazanezabezpieczeniem przed nadpisywaniem danych:...24 2
Informacje wstępne Tabun_CMS to System Zarządzania Treścią stworzony dla Ośrodka Rekreacji i Rehabilitacji Konnej Tabun. System został wdrożony w czerwcu 2008 roku. Cele wdrożenia systemu 1. Uproszczenie procesu dodawania i zarządzania treścią na stronie 2. Podzielenie użytkowników na grupy o różnych uprawnieniach 3. Umożliwienie użytkownikom, w zależności od nadanych uprawnień, na dodawanie i moderację treści strony 4. Zwiększenie widoczności strony w wyszukiwarkach internetowych Wykorzystane technologie Strona napisana jest w języku PHP. Za przechowywanie informacji oraz ich spójność odpowiada baza danych PostgreSQL. Dodatkowe efekty zostały uzyskane przy wykorzystaniu technologii AJAX: skryptów własnych oraz bibliotek Prototype, Scriptaculous, Prototype UI. Ocena działania systemu Po półrocznym okresie od wdrożenia systemu można stwierdzić, że administracja serwisem stała się intuicyjna i wygodna. Nie udało się jednak niestety zwiększyć interakcji z użytkownikami serwisu, którzy, poza jednostkowymi przypadkami, poprzestali na zarejestrowaniu się w serwisie. W pełni został natomiast osiągnięty cel 4 strona jest widoczna jako pierwsza przy wyszukiwaniu dla większości fraz pod które była optymalizowana. 3
Wygląd i funkcjonalności aplikacji Aplikacja ma modularną budowę. Poszczególne moduły ładowane są jako niezależne okna generowane przez skrypt Javascript. Moduły można dowolnie modyfikować (rozmieścić na stronie,zmienić rozmiar, oraz wygląd) a ich ustawienie dla zarejestrowanych użytkowników jest zapisywane i automatycznie ładowane przy kolejnych odwiedzinach. Dla użytkowników ze starszymi przeglądarkami bądź nie korzystających z możliwości modyfikowania okien została przygotowana statyczna wersja serwisu. Tło dla aplikacji stanowi fotografia. W systemie dostępny jest skrypt cyklicznej zmiany fotografii tła. Funkcjonalnie treści na stronie są Moduły aplikacji 1. Nagłówek strony podstawowe informacje teleadresowe; 2. Menu strony: Rejestracja; Działy strony lista wszystkich dostępnych działów; Nowości, Informacje, Nasze Konie, Byli z Nami, Galerie, Forum, Archiwum bezpośrednie łącza do wybranych działów; 4
Ciekawe Linki, Kalendarium Imprez, Pobieralnia bezpośrednie łącza do wybranych artykułów. 3. Logowanie / Zarządzanie danymi użytkownika panel umożliwiający rejestrację nowym użytkownikom, logowanie użytkownikom już zarejestrowanym, oraz zarządzanie wyglądem aplikacji i swoimi danymi osobistymi już zalogowanym użytkownikom; 4. Nowości wyciąg artykułów z działu Nowości; 5. Ostatnio dodane wyciąg artykułów z pozostałych działów; 6. Galerie graficzne łącza do ostatnich galerii w formie pokazu slajdów ; 7. Stopka - informacje na temat autorów oraz sposobu modyfikacji wyglądu aplikacji w formie pokazu slajdów. Dodatkowe możliwości użytkownika zalogowanego Użytkownik zalogowany ma możliwość: przejścia na tryb bez okienek zmienienia ustawień okienek. 5
Edytowania swoich danych. W menu ma do dyspozycji dodatkowe łącza: Nowy artykuł okno dodawania nowych treści na stronie (dla użytkowników bez dodatkowych uprawnień na życzenie administratora systemu wyłączone); Użytkownicy lista osób zarejestrowanych z podstawowymi danymi. 6
Użytkownik bez dodatkowych uprawnień (grupa obserwator -domyślna) Użytkownik dodany do grupy klubowicz Dodatkowe możliwości: Pisanie komentarzy do artykułów; 7
Dodawanie artykułów do działu Forum. Użytkownik dodany do grupy moderator Dodatkowe możliwości: Dodawanie artykułu do dowolnej kategorii Rozbudowany panel edytora tekstu Możliwość usuwania komentarzy Możliwość edycji artykułów 8
Użytkownik dodany do grupy administrator 9
Dodatkowe możliwości: Panel administratora umożliwiający edycję i usuwanie artykułów, usuwanie komentarzy, dodawanie, edycję i usuwanie działów, edycję danych i usuwanie użytkowników. 10
Budowa aplikacji Wykaz tabel Dane aplikacji zapisywane są w tabelach: users, articles, comments, groups, sections, windows, window_properties. Tabela users Tabela users zawiera informacje o użytkownikach aplikacji. Jest tworzona za pomocą kodu przedstawionym poniżej: DROP TABLE users; CREATE TABLE users ( id serial, group_id int4 DEFAULT '3', nick varchar(20) UNIQUE, pass varchar(20) NOT NULL, mail varchar(30) NOT NULL, firstname varchar(20) DEFAULT NULL, surname varchar(20) DEFAULT NULL, enabled BOOL DEFAULT, theme varchar(30) NOT NULL DEFAULT 'mac_os_x', js BOOL DEFAULT, date timestamp, PRIMARY KEY (id), CONSTRAINT key_group FOREIGN KEY (group_id) REFERENCES groups(id) ); Kolejne kroki przy tworzeniu tabeli: 1. Usunięcie poprzedniej tabeli users (jeżeli tak znajdowała się w bazie). 2. Stworzenie nowej tabeli users która zawiera następujące kolumny: id identyfikator użytkownika tworzony funkcją auto-increment, zapobiega to powstaniu duplikatu; group_id identyfikator grupy użytkownika; nick nazwa użytkownika (unikatowa); pass hasło użytkownika; mail email użytkownika; firstname imię użytkownika; surname nazwisko użytkownika; enabled informacja czy konto użytkownika jest aktywne; theme nazwa stylu wyświetlania aplikacji przez użytkownika; date data utworzenia konta. 11
3. Ustawienie dodatkowych właściwości tabeli: klucz główny którym jest id użytkownika (id); klucz obcy do pobrania numeru grupy. Tabela groups Tabela groups zawiera informacje o grupach i ich uprawnieniach. Jest tworzona za pomocą kodu przedstawionym poniżej: DROP TABLE groups; CREATE TABLE groups ( id serial, name varchar(20) DEFAULT NULL, write_article BOOL DEFAULT FALSE, write_comment BOOL DEFAULT FALSE, edit_article BOOL DEFAULT FALSE, edit_comment BOOL DEFAULT FALSE, edit_users BOOL DEFAULT FALSE, PRIMARY KEY (ID) ); Kolejne kroki przy tworzeniu tabeli: 1. Usunięcie poprzedniej tabeli groups (jeżeli tak znajdowała się w bazie). 2. Stworzenie nowej tabeli groups która zawiera następujące kolumny: id identyfikator grupy tworzony funkcją auto-increment, zapobiega to powstaniu duplikatu; name nazwa grupy; write_article ustawianie prawa do pisania artykułów; write_comment ustawianie prawa do pisania komentarzy; edit_article ustawianie prawa do edycji artykułów; edit_comment ustawianie prawa do edycji komentarzy; edit_users ustawianie prawa do edycji użytkowników. 3. Ustawienie dodatkowych właściwości: klucz główny którym jest id grupy (id); Domyślnie ustawione są cztery grupy użytkowników jednak jest możliwość stworzenia większej ilości grup poprzez nadanie odpowiednich wartości w kolumnach. Tabela poniżej przedstawia 4 grupy użytkowników jakie obecnie występują w systemie wraz z prawami jakie mają (wartość prawo nadane, wartość FALSE prawo zabronione). Grupa write_article write_comment edit_article edit_comment edit_users 12
Administrator Moderator FALSE Klubowicz FALSE FALSE FALSE Obserwator FALSE FALSE FALSE FALSE FALSE Tabela articles Tabela articles zawiera wszystkie artykuły oraz dane pomocnicze. Jest tworzona za pomocą kodu przedstawionym poniżej: DROP TABLE articles; CREATE TABLE articles ( id serial, user_id int4 NOT NULL, title varchar(255) NOT NULL, tagline varchar(255) DEFAULT ' ', section varchar(255) NOT NULL, content text NOT NULL, date timestamp, flag int4, PRIMARY KEY (ID), CONSTRAINT key_user FOREIGN KEY (user_id) REFERENCES users(id), CONSTRAINT key_section FOREIGN KEY (section) REFERENCES sections(name), UNIQUE (title, section) ); Kolejne kroki przy tworzeniu tabeli: 1. Usunięcie poprzedniej tabeli articles (jeżeli tak znajdowała się w bazie). 2. Stworzenie nowej tabeli articles która zawiera następujące kolumny: id identyfikator artykułu tworzony funkcją auto-increment, zapobiega to powstaniu duplikatu; user_id id użytkownika który napisał artykuł; title tytuł artykułu; tagline skrót artykułu; section nazwa kategorii do której należy artykuł; content treść artykułu; date data publikacji artykułu; flag parametr potrzebny przy edycji artykułu aby zapobiegać edycji jednego artykułu przez dwie osoby. 3. Ustawienia dodatkowych wartości: 13
klucz główny którym jest id artykułu (id); dwa klucze obce: jeden do pobrania id użytkownika, który napisał artykuł, drugi do pobrania nazwy kategorii do której został przydzielony artykuł; stworzenie unikalnej pary tytuł, kategoria. Tabela comments Tabela comments zawiera wszystkie komentarze dodane do artykułów przez użytkowników. Jest tworzona za pomocą kodu przedstawionym poniżej: DROP TABLE comments; CREATE TABLE comments ( id serial, article_id int4 NOT NULL, user_id int4 NOT NULL, content TEXT NOT NULL, date timestamp, PRIMARY KEY (id), CONSTRAINT key_article FOREIGN KEY (article_id) REFERENCES articles(id), CONSTRAINT key_user FOREIGN KEY (user_id) REFERENCES users(id) ); Kolejne kroki przy tworzeniu tabeli: 1. Usunięcie poprzedniej tabeli comments (jeżeli tak znajdowała się w bazie). 2. Stworzenie nowej tabeli comments która zawiera następujące kolumny: id identyfikator komentarza tworzony funkcją auto-increment, zapobiega to powstaniu duplikatu; article_id id artykułu w którym napisano komentarz; user_id id użytkownika który napisał komentarz; content treść komentarza; date data publikacji komentarza. 3. Ustawienia dodatkowych wartości: klucz główny którym jest id komentarza (id); dwa klucze obce: jeden do pobrania id użytkownika, który napisał artykuł, drugi do pobrania id artykułu w którym napisano artykuł. Tabela windows Tabela windows zawiera treści okien aplikacji. Jest tworzona za pomocą kodu przedstawionym poniżej: 14
DROP TABLE "windows" CASCADE; CREATE TABLE "windows" ( window_name varchar(60) NOT NULL, header varchar(120) NOT NULL DEFAULT 'naglowek', content text NOT NULL DEFAULT 'adres strony', footer varchar(120) NOT NULL DEFAULT 'stopka', PRIMARY KEY (window_name) ); Kolejne kroki przy tworzeniu tabeli: 1. Usunięcie poprzedniej tabeli windows (jeżeli tak znajdowała się w bazie). 2. Stworzenie nowej tabeli windows która zawiera następujące kolumny: window_name nazwa okna; header nazwa okna wyświetlana w nagłówku (np. Logowanie); content zawartość okna; footer stopka okna. 3. Ustawienia dodatkowych wartości: klucz główny którym jest nazwa okna (window_name). Tabela window_properties Tabela window_properties zawiera właściwości poszczególnych okien aplikacji. Jest tworzona za pomocą kodu przedstawionym poniżej: DROP TABLE window_properties; CREATE TABLE window_properties ( window_name varchar(60) NOT NULL, user_id int4 NOT NULL, pos_top int4 NOT NULL, pos_left int4 NOT NULL, width int4 NOT NULL, height int4 NOT NULL, active BOOL NOT NULL, PRIMARY KEY (window_name,user_id), CONSTRAINT key_user FOREIGN KEY (user_id) REFERENCES users(id), CONSTRAINT key_window FOREIGN KEY (window_name) REFERENCES windows(window_name) ); Kolejne kroki przy tworzeniu tabeli: 1. Usunięcie poprzedniej tabeli window_properties (jeżeli tak znajdowała się w bazie). 15
2. Stworzenie nowej tabeli window_properties która zawiera następujące kolumny: window_name nzwa okna; pos_top położenie okna (współrzędna pionowa); pos_left położenie okna (współrzędna pozioma); width szerokość okna; height wyokość okna; active włączenie/wyłączenie okna. 3. Ustawienia dodatkowych wartości: klucz główny którym jest nazwa okna (window_name) i id użytkownika (user_id); dwa klucze obce: jeden do pobrania id użytkownika, a drugi do pobrania nazwy okna. Tabela window_defaults Tabela window_defaults zawiera właściwości wyświetlania wszystkich okien aplikacji. Jest tworzona za pomocą kodu przedstawionym poniżej: DROP TABLE windows_defaults; CREATE TABLE windows_defaults ( user_id int4 NOT NULL, parameter varchar(120) NOT NULL, value varchar(120) NOT NULL, CONSTRAINT key_user FOREIGN KEY (user_id) REFERENCES users(id) ); 1. Usunięcie poprzedniej tabeli window_defaults (jeżeli tak znajdowała się w bazie). 2. Stworzenie nowej tabeli window_defaults która zawiera następujące kolumny: user_id id użytkownika; parameter parametr; value wartość; 3. Ustawienia dodatkowych wartości: klucz obcy do pobrania id użytkownika; 16
Relacje między tabelami Na poniższym diagramie zostały przedstawione zależności pomiędzy poszczególnymi tabelami. Diagram ten został stworzony w programie DBDesigner. Skrypty PHP Funkcje i triggery zwiazane z automatycznym dodawaniem danych: Podczas dodawania okna w tabeli 'windows trigger zapisuje do tabeli window_properties domyślne właściwości okna. CREATE OR REPLACE function add_window_properties() RETURNS trigger AS ' BEGIN FOR user IN SELECT id FROM users LOOP 17
EXECUTE ''INSERT INTO window_properties (window_name,user_id,pos_top,pos_left,width,height,active) VALUES (NEW.window_name,user.id,50,50,500,500,)'' END LOOP; END; 'LANGUAGE 'plpgsql'; CREATE TRIGGER add_properties AFTER INSERT ON windows FOR EACH ROW EXECUTE PROCEDURE add_window_properties(); Funkcje i triggery związane z zabezpieczeniem przed nadpisywaniem danych: Aplikacja przy wykonywaniu polecenia SELECT w celu edycji na tabeli articles bądź comments zwiększa jednocześnie o 1 wartość znajdująca się w kolumnie flag i zapisuje w ukrytym polu formularza (przy poleceniu SELECT wydawanym jedynie w celu wyświetlenia artykułu nie zwiększamy wartość flagi). Następnie przy poleceniu UPDATE wartość flagi jest sprawdzana przez trigger i porównywana z wysyłana przez formularz. Jeżeli wartości się różnią, oznacza to, że w międzyczasie ktoś inny rozpoczął edycje tego samego artykułu/ komentarza i trigger zablokuje zapis. Jest to podstawowe rozwiązanie problemu konkurencyjności, mające tę wadę, że do edycji jest dopuszczona nie pierwsza, a ostatnia rozpoczynająca edycje osoba. Jednak uznaliśmy, że w przypadku naszego sytemu jest to rozwiązanie wystarczające. CREATE function check_flag() RETURNS trigger AS ' BEGIN IF NEW.flag!= OLD.flag THEN RAISE NOTICE ''Operacja nie została wykonana. Ktoś inny rozpoczął w międzyczasie edycje tego dokumentu. Spróbuj ponownie.''; RETURN NULL; ELSE RETURN NEW; END IF; END; 'LANGUAGE 'plpgsql'; CREATE TRIGGER articles_check_flag BEFORE UPDATE ON articles FOR EACH ROW EXECUTE PROCEDURE check_flag(); CREATE TRIGGER comments_check_flag BEFORE UPDATE ON comments FOR EACH ROW EXECUTE PROCEDURE check_flag(); 18