Departement Handelswetenschappen en Bedrijfskunde Gegradueerde in Toegepaste Informatica
Ontwikkeling van een webapplicatie voor een nucleair persarchief met eZ publish
CAMPUS Geel
Christof Theys
Academiejaar 2005-2006
De houder van dit diploma is gerechtigd tot het voeren van de titel van Bachelor
2
WOORD VOORAF Dit eindwerk is het resultaat van een boeiende stageperiode en dus ook een verdienste van verschillende personen. Zonder de hulp van al deze personen zou mijn stage en eindwerk niet mogelijk zijn geweest. Ik wil dan ook al deze personen van harte bedanken. In de eerste plaats wil ik mijn externe begeleidster Marie-Laure Ruyssen bedanken. Dankzij haar heb ik deze interessante stageopdracht kunnen uitvoeren. Ik wil ook Tom Couwberghs en Hans Melis bedanken omdat ik altijd met mijn vragen bij hen terecht kon. Verder wil ik ook Arnout Ulenaers, Kris Pennemans, Mario Bens, Natasha de Bakker en mijn collega-stagiair Joris de Rieck bedanken. Zij zijn de medewerkers van het Knowledge Centre en bij hen kon ik altijd terecht als ik iets nodig had. Verder wil ik ook Kristine Mangelschots bedanken. Zij was mijn stagebegeleidster en stond mij gedurende mijn stage met raad en daad bij. Tenslotte wil ik ook nog mijn ouders en mijn vriendin bedanken voor hun steun, want zij hebben het mogelijk gemaakt dat ik deze opleiding kon volgen.
Christof Theys
3
SAMENVATTING Door de jaren heen is er in het SCK•CEN een groot persarchief ontstaan van allerlei documenten zoals krantenknipsels, nieuwsartikels, … Mijn eindwerk bestond erin om voor dit persarchief een webapplicatie te ontwikkelen zodat de werknemers van het SCK•CEN deze documenten kunnen raadplegen, want het zou een zonde zijn om zoveel informatie verloren te laten gaan. Om deze webapplicatie te ontwikkelen heb ik het content management system eZ publish gebruikt. eZ publish maakte het mogelijk van een gebruiksvriendelijke webapplicatie op te bouwen. Omdat eZ publish een groot deel beheerst van mijn eindwerk, heb ik deze in dit eindwerk ook toegelicht. Na de uitwerking van de webapplicatie moest deze nog toegevoegd worden aan de portal van het Knowledge Centre. Waarschijnlijk zal deze webapplicatie in de toekomst nog verder uitgebreid worden om de bezoeker nog meer functionaliteiten aan te bieden. Door de korte duur van mijn stage kon ik deze webapplicatie niet zo uitgebreid maken.
4
INHOUDSOPGAVE WOORD VOORAF ................................................................................................ 2 SAMENVATTING ................................................................................................. 3 INHOUDSOPGAVE............................................................................................... 4 LIJST VAN ALLE GEBRUIKTE AFBEELDINGEN ..................................................... 6 LIJST VAN ALLE GEBRUIKTE AFKORTINGEN....................................................... 7 INLEIDING ......................................................................................................... 9 1
SCK•CEN ............................................................................................ 10
1.1 1.2 1.3 1.3.1 1.3.2
Geschiedenis ...................................................................................... 10 Doelstellingen .................................................................................... 11 Knowledge Management Knowledge Centre ...................................... 11 Knowledge Management ....................................................................... 12 Knowledge Centre ................................................................................ 12
2
STAGEOPDRACHT ............................................................................... 13
3
SOFTWARE ......................................................................................... 14
3.1 3.2 3.3 3.3.1 3.3.2 3.4 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.4.10 3.4.11 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5
Apache ............................................................................................... 14 PHP .................................................................................................... 15 MySQL................................................................................................ 17 MySQL Administrator ............................................................................ 18 MySQL Query Browser .......................................................................... 18 eZ publish .......................................................................................... 19 Content Management System ................................................................ 19 Ontwikkelingsplatform .......................................................................... 19 Interne structuur van eZ publish ............................................................ 19 Content en design ................................................................................ 21 Content management ........................................................................... 21 Content class....................................................................................... 21 Content object ..................................................................................... 22 Content node en de content node tree..................................................... 23 Relationele database model van eZ publish .............................................. 24 Site management................................................................................. 25 Access control ..................................................................................... 26 Version Control Systems .................................................................... 27 Subversion.......................................................................................... 27 Problemen met file-sharing.................................................................... 28 Lock-modify-unlock .............................................................................. 29 Copy-modify-merge.............................................................................. 30 TortoiseSVN ........................................................................................ 32
5
4
STANDAARDEN................................................................................... 33
4.1 4.2 4.3 4.4 4.5
HTML.................................................................................................. 33 XML .................................................................................................... 33 XHTML................................................................................................ 34 Cascading style sheets ....................................................................... 35 Validator ............................................................................................ 35
5
UITWERKING STAGEOPDRACHT ......................................................... 36
5.1 5.2 5.3 5.4 5.4.1
Het upgraden van eZ publish ............................................................. 36 Het gebruik van extensies.................................................................. 37 Het gebruik van modules ................................................................... 38 Het aanpassen van de eZ publish klassen .......................................... 39 De news_article_2 klasse ...................................................................... 39
5.4.1.1 5.4.1.2 5.4.1.3 5.4.1.4 5.4.1.5
Kopiëren van de news_article klasse ....................................................................................40 Aanpassen van de bronnen .................................................................................................42 Aanpassen van de auteurs ..................................................................................................49 Aanpassen van de datum ....................................................................................................50 Aanpassen van de internal number ......................................................................................51
5.5.3.1 5.5.3.2
Toolbar .............................................................................................................................59 Lijst van de laatst gepubliceerde artikels...............................................................................61
5.4.2 5.4.3 5.4.4 5.4.5 5.4.6 5.5 5.5.1 5.5.2 5.5.3 5.5.4 5.6 5.6.1 5.6.2 5.6.3
De news_folder klasse .......................................................................... 53 De resource klasse ............................................................................... 53 De folder klasse ................................................................................... 54 De rss_item klasse ............................................................................... 54 De rss_feed klasse ............................................................................... 54 Opbouw webapplicatie ....................................................................... 55 Top-menu ........................................................................................... 56 Linker menu ........................................................................................ 57 Rechter menu...................................................................................... 59
Centraal gedeelte................................................................................. 63 De webpagina’s.................................................................................. 63 Home pagina ....................................................................................... 63 News database .................................................................................... 65 Links .................................................................................................. 71
BESLUIT .......................................................................................................... 73 LITERATUURLIJST ............................................................................................ 74
6
LIJST VAN ALLE GEBRUIKTE AFBEELDINGEN Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur Figuur
1-1 Logo van SCK•CEN ........................................................................... 10 3-1 Logo van Apache .............................................................................. 14 3-2 Marktaandeel van webservers............................................................. 15 3-3 Logo van PHP ................................................................................... 15 3-4 Voorbeeld van een PHP script ............................................................. 16 3-5 Lijst PHP ondersteunende databases.................................................... 17 3-6 Logo van MySQL............................................................................... 17 3-7 Schema MySQL ................................................................................ 18 3-8 Logo van eZ publish .......................................................................... 19 3-9 Interne structuur van eZ publish ......................................................... 20 3-10 Content en design ........................................................................... 21 3-11 Content class ................................................................................. 22 3-12 Content object................................................................................ 23 3-13 Relatie tussen content object en content node..................................... 23 3-14 Content node tree ........................................................................... 24 3-15 Relationeel database model .............................................................. 24 3-16 Voorbeeld webapplicatie ven verschillende siteaccessen........................ 26 3-17 Access control ................................................................................ 26 3-18 Logo van Subversion ....................................................................... 27 3-19 Client/repository structuur................................................................ 28 3-20 Het probleem van file-sharing ........................................................... 28 3-21 De lock-modify-unlock oplossing ....................................................... 29 3-22 De copy-modify-merge oplossing ...................................................... 30 3-23 De copy-modify-merge oplossing (vervolg) ......................................... 30 3-24 Logo van TortoiseSVN...................................................................... 32 3-25 Schermafdruk TortoiseSVN ............................................................... 32 4-1 Voorbeeld HTML code ........................................................................ 33 4-2 Voorbeeld XML code .......................................................................... 34 4-3 Voorbeeld XHTML code ...................................................................... 34 4-4 Voorbeeld CSS code .......................................................................... 35 5-1 Versie upgrade eZ publish.................................................................. 36 5-2 Activatie van een extensie.................................................................. 38 5-3 Extensie folder ................................................................................. 38 5-4 Module settings ................................................................................ 39 5-5 Extensie filestructuur......................................................................... 39 5-6 Tekstbestand nieuwe versie van de sources .......................................... 46 5-7 SCK-Author...................................................................................... 49 5-8 Enhanced Selection 2 in de admin interface .......................................... 50 5-9 De opbouw van een webpagina........................................................... 55 5-10 De guillotine bug............................................................................. 56 5-11 ini-file linker menu .......................................................................... 57 5-12 Boomstructuur news database .......................................................... 59 5-13 Toolbar.......................................................................................... 61 5-14 RSS Feeds ..................................................................................... 62 5-15 Lijst met de laatst gepubliceerde artikels ............................................ 63 5-16 Home pagina.................................................................................. 64 5-17 News database ............................................................................... 66 5-18 News article ................................................................................... 67 5-19 Locaties van een news article............................................................ 67 5-20 Edit news article (1) ........................................................................ 69 5-21 Edit news article (2) ........................................................................ 69 5-22 Create news article.......................................................................... 70 5-23 Zoekfunctie .................................................................................... 71 5-24 Links ............................................................................................. 72
7
LIJST VAN ALLE GEBRUIKTE AFKORTINGEN ACTINET
Network of Excellence on Actinides
API
Application Programming Interface
CLI
Command Line Interface
CMS
Content Management System
CSS
Cascading Style Sheets
CSV
Comma Separated Value
CVS
Concurrent Versions System
DBX
Database Abstraction Extension
DOM
Document Object Model
GIMP
GNU Image Manipulation Program
GPL
General Public Licence
GNOME
GNU Network Object Model Environment
GNU
GNU’s Not Unix
GUI
Graphical User Interface
HTML
HyperText Markup Language
HTTP
HyperText Transfer Protocol
IIS
Microsoft Internet Information Service
IMAP
Internet Message Access Protocol
KMKC
Knowledge Management Knowledge Centre
LDAP
Lightweight Directory Access Protocol
NEMO
Network of Excellence on Micro-Optics
NPO
Nuclear Press Office
NTLM
windows NT Lan Manager
ODBC
Open Database Connection
OS
Operating System
PDF
Adobe Portable Document Format
PHP
PHP: Hypertext Preprocessor
PHP-GTK
PHP: Hypertext Preprocessor – Gimp Toolkit
8
POP3
Post Office Protocol 3
RDBMS
Relational Database Management System
RSS
Really Simple Syndication
SAX
Simple API for XML
SCK•CEN
Studiecentrum voor Kernenergie - Centre d'étude de l'Energie Nucléaire
SNMP
Simple Network Management Protocol
SQL
Structured Query Language
STK
Studiecentrum voor de Toepassingen van de Kernenergie
URL
Uniform Resource Locator
USA
United States of America
VITO
Vlaamse Instelling voor Technologisch Onderzoek
W3C
World Wide Web Consortium
XHTML
Extensible HyperText Markup Language
XML
Extensible Markup Language
9
INLEIDING Als laatstejaars student toegepaste informatica krijgt men de kans om gedurende drie maanden de opgedane kennis in de praktijk om te zetten en hier een eindwerk rond te maken. Ik heb deze opdracht vervuld bij het bedrijf SCK•CEN te Mol. Het project bestond erin om een webapplicatie op te bouwen waarin de werknemers van het SCK•CEN allerlei documenten uit de nucleaire wereld kunnen raadplegen. Deze documenten zijn bijvoorbeeld artikels uit kranten of dagbladen. Aangezien ik me erg interesseer in de wereld van webtoepassingen en het internet in het algemeen, sprak deze opdracht mij wel aan. Omdat ik al veel in contact ben gekomen met de programmeertalen die in deze opdracht gebruikt zijn, maar nog nooit zelf heb moeten toepassen, leek het mij een hele uitdaging om deze talen te doorgronden en er een heuse webapplicatie mee op te bouwen. Hier kon ik zeker nog iets van opsteken. In dit eindwerk wil ik u wegwijs maken in het tot stand komen van dit project en de werking ervan verduidelijken. Vooraleer ik met de eigenlijke opdracht begin, zal ik u een voorstelling geven van het stagebedrijf. Hierna komt de gebruikte software aan bod. Om een grotere gebruiksvriendelijkheid te garanderen moet men bij de ontwikkeling van een webapplicatie enkele standaarden volgen. Deze worden kort aangehaald in het volgende hoofdstuk. Als laatste deel doe ik de werking en de creatie van de eigenlijke opdracht uit de doeken.
10
1
SCK•CEN
Figuur 1-1 Logo van SCK•CEN
Het bedrijf waar ik mijn stage heb voltooid is het SCK•CEN. Het SCK•CEN is het Studiecentrum voor Kernenergie (Centre d'étude de l'Energie Nucléaire). Het is een federale instelling die onderzoek verricht naar veilige en vreedzame toepassingen van kernenergie. In dit hoofdstuk is er wat meer uitleg over de geschiedenis van het SCK•CEN, de doelstellingen en de afdeling waar ik mijn stageperiode heb doorgebracht.
1.1
Geschiedenis
Aan het einde van de 19de eeuw slaagde Wilhelm Conrad Röntgen erin om een elektromagnetische straling op te wekken die krachtiger was dan het licht. Hier is het allemaal mee begonnen. Kort daarop merkte Marie Curie op dat ook sommige grondstoffen een hoge energie vrijgaven, namelijk radioactieve energie. Dit leidde tot een atoommodel dat we hedendaags nog kennen. Zodra men in 1932 het neutron ontdekt had, kwamen de kernfysica en het kernonderzoek pas echt op gang. Enkele jaren nadien brachten de Duitsers Otto Hahn en Fritz Strassmann voor het eerst een kernsplitsing tot stand. Het uranium dat hieruit voort kwam werd vooral gebruikt voor de aanmaak van radium voor medische toepassingen. In 1942 startten de USA het Manhattan project voor de ontwikkeling van de eerste atoombom. Hiervoor waren de uraniumreserves van België zeer geschikt. Op 26 september 1944 ondertekenden de USA, het Verenigd Koninkrijk en België een ‘Memorandum of Understanding’. Hierdoor kreeg België toegang tot de nucleaire ontwikkelingen in commerciële en niet-militaire toepassingen in ruil voor het alleenrecht op de uraniumvoorraden. Toen de Amerikanen enkele jaren later hun verbintenis niet nakwamen, was het de wetenschapper Pierre Ryckmans die ijverde voor een Belgische instelling die de mogelijkheden van kernenergie ging onderzoeken. In 1951 gaf Pierre Ryckmans aan een groep wetenschappers de opdracht een nieuw organisme voor de studie van de toepassingen van de kernenergie op te richten. De oprichters behoorden tot diverse kringen van de wetenschappelijke wereld, de universiteiten, de overheid en de industrie. Na overleg beslisten zij tot de oprichting van een vzw die “Studiecentrum voor de Toepassingen van de Kernenergie” of kortweg STK genoemd zou worden. Omdat er rekening moest gehouden worden met mogelijke uitbreidingen en de veiligheid voor de omwoners, moest men een terrein vinden dat voldoende groot was, een stabiel klimaat kennen en het moest op voldoende afstand van de bewoonde gebieden liggen. De uiteindelijke keuze van de locatie viel op Mol. Nadat alle terreinen aangekocht werden begon men met de bouw van de verschillende hallen, laboratoria en andere gebouwen die tot het plan behoorden. Er werd zelfs een residentiele wijk aangelegd voor de werknemers die van ver moesten komen. Nog geen
11
drie jaar nadat men gestart was met de bouw, was de eerste Belgische reactor BR1 in werking. In 1957 verscheen in het Staatsblad het Koninklijk Besluit dat het Studiecentrum voor Kernenergie oprichtte als instelling van openbaar nut met rechtspersoonlijkheid. Deze overgang had als gevolg dat het STK een naamswijziging onderging. Het STK ging vanaf nu door het leven onder de naam SCK•CEN. De nieuwe statuten maakten een gemengde financiering door de overheid en de industrie mogelijk. Hierbij werd in oktober van datzelfde jaar beslist dat het Ministerie van Economische Zaken als voogdij-instantie zou fungeren. Deze subsidie heeft een niet te onderschatten weerslag gehad op de ontwikkeling, de keuzes en de werking van het SCK•CEN doorheen de jaren. Het SCK•CEN bekwam eigen inkomsten via experimenten en prestaties voor de privé-industrie, de overheid en het pas opgerichte Euratom. In 1957 werd er begonnen aan de bouw van een nieuwe reactor, de BR2. Deze werd pas volledig operationeel in 1961. Deze reactor heeft een hoge neutronenflex om het gedrag van allerlei materialen onder hoge bestraling na te gaan. De BR2 is nog steeds de meest performante onderzoeksreactor van West-Europa. Vanaf 1970 paste het SCK•CEN zijn statuten aan om de opdrachten te verruimen buiten de nucleaire sector. Men wilde zijn ervaring en zijn potentieel beschikbaar te stellen voor niet-nucleaire activiteiten. In opdracht van de overheid, wetenschap uit binnen- en buitenland ging het centrum onderzoek verrichten op het gebied van leefmilieu, energietoepassingen, materialen, informatica, brandstofcellen en waterstofproductie via elektrolyse. Toch bleef de nadruk liggen op de nucleaire activiteiten. In 1991 werd het SCK•CEN gesplitst. De niet-nucleaire activiteiten werden overgeheveld naar het Vlaamse Gewest, dat hiervoor VITO oprichtte. VITO staat voor Vlaamse instelling voor technologisch onderzoek. Het VITO zou zich meer gaan concentreren op het onderzoek rond het leefmilieu, energie, grondstoffen en materialen terwijl het SCK•CEN zich ging concentreren op het onderzoek rond radioactief afval en ontmanteling en stralingsbescherming. Hedendaags telt het SCK•CEN ongeveer 600 medewerkers waarvan één derde houder is van een universitair diploma. De Totale omzet bedraagt 80 miljoen euro per jaar. Ongeveer de helft van de omzet is afkomstig van subsidies van de overheid. Het V haalt 40% van de omzet uit contractwerk en dienstverlening. De overige 10% wordt indirect gehaald door activiteiten voor de ontmanteling van vrijgegeven installaties.
1.2
Doelstellingen
Het doel van het SCK•CEN is onderzoeken uit te voeren op het gebied van de kernwetenschappen. Deze onderzoeken zijn vooral gericht tot de volgende criteria. • • • • •
1.3
Veiligheid van kerninstallaties Stralingsbescherming Veilige behandeling en berging van radioactief afval Strijd tegen ongecontroleerde uitbreiding van splijtbaar materiaal Strijd tegen terrorisme
Knowledge Management Knowledge Centre
De SCK•CEN bibliotheek werd opgericht in 1953 om de nucleaire literatuur over heel de wereld beschikbaar te stellen voor eigen personeel. In artikel vier van de SCK•CEN
12
statuten staat immers sinds het begin de taak tot het “verzamelen en bijhouden van de wetenschappelijke en technische documentatie” ingeschreven. De bibliotheek speelt daarnaast de rol van nationale nucleaire bibliotheek die een ruime collectie kon aanbieden voor de opkomende nucleaire bedrijven, de universiteiten en de overheid. Tot 2001 bleef de bibliotheek gemeenschappelijk met VITO. In februari verhuisde het SCK•CEN deel naar een ander gebouw. Vanaf toe heeft men het begrip bibliotheek in een heel andere context gezet. Men had enerzijds het Knowledge Centre en anderzijds het Knowledge Management. 1.3.1
Knowledge Management
Het doel van het Knowledge management team is om alle kennis binnen het SCK•CEN op een gecentraliseerde plaats aan te bieden aan alle werknemers. Hiervoor werd er een bibliotheek portal ontwikkeld door het team. Op deze manier moeten de werknemers niet tot het Knowledge Centre komen om informatie te raadplegen. Het Knowledge Management team werkt ook aan andere projecten. Enkele van deze projecten zijn: • • 1.3.2
Network of Excellence on Micro-Optics (NEMO) Network of Excellence on Actinides (ACTINET) Knowledge Centre
Het Knowledge Centre heeft de taken van wat vroeger de bibliotheek was overgenomen. Het team dat in het Knowledge Centre actief is zorgt er nog altijd voor dat de nucleaire informatie, die het Knowledge Centre bezit, beschikbaar wordt gesteld voor alle werknemers binnen het SCK•CEN. Het team behandelt alle vragen naar informatie die men aankrijgt van de werknemers. Hierbuiten verzorgen ze ook nog de normale activiteiten die binnen een bibliotheek van toepassing zijn, zoals boeken in de rekken zetten, het fotokopiëren van artikels en het afprinten van microfiches. Natuurlijk kan het Knowledge Centre niet alle informatie bevatten die beschikbaar is voor een bepaald onderwerp. In dit geval kan het team deze informatie aanvragen bij externe bibliotheken. Het Knowledge Centre bevat ook een leeszaal waar de werknemers altijd welkom zijn.
13
2
STAGEOPDRACHT
Mijn stageopdracht bestond uit het ontwikkelen van een webapplicatie voor een persarchief uit de nucleaire wereld, namelijk het ‘Nuclear Press Office’. Dit persarchief bevat vele artikels en krantenknipsels uit de nucleaire wereld. In dit archief was men jaren geleden al documenten aan het verzamelen. Het is allemaal begonnen met Mr. Legrain. Hij was de eerste persoon die deze artikels uit verschillende kranten en dagbladen begon bij te houden. Omdat men deze documenten niet verloren wil laten gaan zijn deze in een database ingegeven. Door de jaren heen is deze database uitgegroeid tot een persarchief met meer dan duizend documenten. Mijn stageopdracht bestond uit twee grote delen, namelijk enerzijds het aanpassen van de klassen waarin deze documenten werden bewaard en anderzijds de webapplicatie zelf. •
Het aanpassen van de klassen
Om een betere gebruiksvriendelijkheid te bekomen moesten de klassen van de bestaande applicatie aangepast worden aan de noden van de nieuwe webapplicatie. •
De webapplicatie
De webapplicatie zelf bestaat uit een aantal webpagina’s die ervoor zorgen dat de bezoeker van deze webapplicatie al de ingegeven documenten kan bekijken. Deze webpagina’s bevatten een aantal functionaliteiten die het de bezoeker zo gemakkelijk mogelijk moet maken, zoals een overzichtsscherm waarin de gebruiker tussen alle documenten kan navigeren, een ingebouwde toolbar voor de editor, RSS feeds, …
14
3
SOFTWARE
In dit hoofdstuk komt de software aan bod waarmee ik tijdens mijn stage in contact ben gekomen, namelijk Apache, PHP, MySQL, eZ publish en SVN. Deze software producten zijn allemaal gebaseerd op het open source principe. Open source software is software met de volgende twee kenmerken: • •
De broncode van de software is voor iedereen toegankelijk. Aan deze software is een licentie gekoppeld. Deze licentie bepaalt wat de licentienemer met de broncode mag doen.
Een veel gebruikte licentie in de open source wereld is de General Public Licence (GPL). Deze licentie zegt bijvoorbeeld dat men de software mag gebruiken voor eender welk doeleinde. De software mag ook aangepast worden, maar dan moet er op deze aangepaste versie ook een GPL komen en deze aangepaste versie moet ook voor iedereen toegankelijk zijn. Er moet ook aangegeven worden dat er wijzigingen zijn aangebracht in de versie die men heeft aangepast zodat de gebruikers weten dat dit niet de originele versie is. Het is niet altijd zo dat open source software gratis ter beschikking word gesteld. Dit wordt ook bepaald door de licentie zodat er bijvoorbeeld niemand geld kan verdienen met uw broncode.
3.1
Apache
Figuur 3-1 Logo van Apache
Apache is een organisatie die verschillende open source software projecten heeft uitgebracht. Eén daarvan is Apache HTTPD. Dit is een software programma dat men kan gebruiken om een webserver op te zetten. Dit kan zowel bij een gebruiker thuis op zijn lokale pc of op een server in een bedrijf. De Apache webserver is zowel geschikt voor kleine als voor grote, omvangrijke webapplicaties. Het is nog steeds de meest gebruikte webserver wereldwijd. De volgende figuur toont de evolutie van het marktaandeel van de verschillende webservers doorheen de laatste jaren.
15
Bron: Netcraft (http://news.netcraft.com/archives/web_server_survey.html)
Figuur 3-2 Marktaandeel van webservers
De werking hiervan is niet zo moeilijk te begrijpen. Het begint allemaal bij de persoon die een internetpagina wil bezoeken. Hij geeft hiervoor het internetadres (URL) in de webbrowser in. Deze webbrowser zal op zijn beurt een verbinding tot stand brengen met de webserver waarop de gevraagde website zich bevindt. Op deze webserver draait de Apache software die het verzoek van de webbrowser ontvangt en de gevraagde webpagina op deze webserver gaat opzoeken. Als Apache de webpagina gevonden heeft zal deze doorgegeven worden aan de webbrowser. Dit is een zeer simplistische werking van Apache om een beetje inzicht te krijgen hoe deze software te werk gaat.
3.2
PHP
Figuur 3-3 Logo van PHP
PHP is een vaak gebruikte scripting taal die vooral geschikt is voor web development. Het is zeer gemakkelijk om PHP te integreren in een HTML gebaseerde webpagina. De volgende figuur toont een HTML-pagina waarin een PHP script is geïntegreerd.
16
Figuur 3-4 Voorbeeld van een PHP script
Hier kun je zien hoe verschillend dit is dan een script geschreven in een andere taal zoals C of Perl. In plaats van een programma te schrijven met veel commando’s om HTML te laten zien, kun je een HTML script schrijven met ingebouwde code waarmee je vele dingen kunt doen (in dit geval een stukje tekst op het scherm tonen). Je kunt zien hoe de PHP code is omgeven door een start en stop tag. Met deze tags kun je gemakkelijk overschakelen van HTML naar PHP code en omgekeerd. Er zijn ongeveer drie grote gebieden waarin PHP scripts gebruikt worden. •
Server-side scripting.
Dit is het meest gebruikte principe van PHP. Om PHP op deze manier aan het werken te krijgen zijn er drie dingen nodig. Een PHP parser, een webserver en een webbrowser. De PHP parser gaat de PHP code controleren en deze omzetten naar geldige HTML. De webserver gaat dan de gevraagde webpagina doorsturen naar de webbrowser die dan op zijn beurt de webpagina aan de gebruiker toont. Het omzetten van de PHP code gebeurt op de webserver. Daarom noemt men dit server-side scripting. •
Command line scripting.
Om PHP op deze manier te doen werken is er geen webserver of webbrowser nodig. Er is alleen een PHP parser nodig die de PHP scripts gaat uitvoeren. De PHP scripts gaan hier met behulp van een command line interface (CLI) uitgevoerd worden. Dit is vooral handig wanneer men de scripts regelmatig dient uit te voeren, bijvoorbeeld via cron (Een programma voor Linux of Unix systemen waarmee men scripts of commando’s op een vooraf ingestelde tijd/datum kan uitvoeren) of Taak Planner op Windows. •
Het ontwikkelen van client-side GUI applicaties.
PHP is misschien niet de meest geschikte taal om graphical user interface (GUI) applicaties in te ontwikkelen, maar als iemand een zeer uitgebreide kennis heeft van PHP en gebruik wil maken van de meer geavanceerde mogelijkheden dan kan hij gebruik maken van PHP-GTK om zulke applicaties te ontwerpen. PHP-GTK is een extensie van PHP waarmee men de grafische programma’s met gebruiksvriendelijke vensters, menu’s en dergelijke kan ontwerpen. PHP is bruikbaar op alle grote besturingssystemen, waaronder Linux, vele Unix varianten ( bijvoorbeeld Solaris), Microsoft Windows en anderen. Tegenwoordig wordt PHP ook door de meeste webservers ondersteund, waaronder Apache, Microsoft Internet Information Service (IIS) de meest gebruikte zijn (zie Figuur 3-2 Marktaandeel
17
van webservers). Om met PHP aan de slag te kunnen is men dus niet platform afhankelijk. Onder platform verstaan we de basis waarop software ontwikkeld wordt. Enkele bekende platformen zijn bijvoorbeeld Java, Linux, Windows, LAMP, ... Met PHP ben je ook niet gebonden aan het weergeven van HTML alleen. Het biedt ook de mogelijkheid om afbeeldingen, PDF bestanden of zelfs Flash films te genereren. Men kan elke soort tekst, zoals XHTML of elk ander XML bestand weergeven. PHP heeft ook zeer handige tekstverwerkingsmogelijkheden. Voor het inlezen en gebruiken van XML documenten ondersteunt PHP de SAX en DOM standaarden. Men kan ook de XSLT extensie gebruiken om XML documenten te transformeren. Een van de sterkste punten van PHP is waarschijnlijk dat het ondersteuning biedt voor een groot scala aan databases. Het schrijven van een database gekoppelde web pagina is ook niet zo moeilijk. Hieronder ziet u een lijst met de databases die PHP momenteel ondersteund. Adabas D
Ingres
Oracle (OCI7 and OCI8)
dBase
InterBase
Ovrimos
Empress
FrontBase
PostgreSQL
FilePro (read-only)
MySQL
Solid
Hyperwave
Direct MS-SQL
Sybase
IBM DB2
MySQL
Velocis
Informix
ODBC
Unix DBM
Figuur 3-5 Lijst PHP ondersteunende databases
Er is ook een database abstractie extensie (DBX) die men in staat stelt van elke database die deze DBX ondersteunt te gebruiken. Buiten DBX ondersteunt PHP ook de Open Database Connection Standaard (ODBC), zodat men elke database die deze ODBC ondersteunt ook kan gebruiken. PHP heeft ook ondersteuning voor communicatie met andere systemen via protocollen als LDAP, IMAP, SNMP, POP3, HTTP en nog vele anderen. Men kan ook simpelweg een netwerk socket openen en communiceren via een willekeurig protocol. Een netwerk socket is een combinatie van een IP adres en een poort. Deze heeft men nodig als men met een server wil communiceren.
3.3
MySQL
Figuur 3-6 Logo van MySQL
18
MySQL is een relationeel database management systeem (RDBMS). Het is een zeer krachtige client/server toepassing. Dit betekent dat de gegevens op de server worden bijgehouden in een databank. Via de client kan men dan de gegevens raadplegen. In deze databank kan men dan informatie opslaan, wijzigen of verwijderen. De client communiceert met de databank via SQL. De volgende figuur geeft een schematische voorstelling van hoe MySQL werkt.
Figuur 3-7 Schema MySQL
Een gebruiker wil informatie ophalen uit de databank. Hij gaat dus een connectie openen met de MySQL server. De gebruiker zegt dan tegen de MySQL server welke informatie hij wil. De MySQL server gaat dan de informatie ophalen in de databank en geeft deze door aan de gebruiker. Om het gebruikersgemak te verhogen zijn er verschillende tools uitgebracht. De tools die ik heb gebruikt zijn de MySQL Administrator en de MySQL Query Browser. 3.3.1
MySQL Administrator
De MySQL Administrator is een tool waarmee men de administratieve operaties kan uitvoeren op een MySQL server in een grafische omgeving. Hieronder verstaan we het configureren, monitoren, het starten en stoppen van een MySQL server, het beheer van de users en verbindingen, back-ups maken, … Men kan ook alle taken gewoon via een command line interface uitvoeren. Hier komen de voordelen van de MySQL Administrator tool naar voren. • • •
3.3.2
De grafische user interface maakt het meer intuïtief. Het geeft een beter overzicht van de instellingen die cruciaal zijn voor de performantie, betrouwbaarheid en veiligheid van MySQL servers. De grafische weergave van de performantie maakt het makkelijker om de instellingen te verbeteren. MySQL Query Browser
De MySQL Query Browser is een tool om MySQL queries uit te voeren in een grafische omgeving. Daar waar de MySQL Administrator tool gebruikt wordt om de administratieve taken uit te voeren, zal de MySQL Query Browser de meer data gerichte taken uitvoeren. Deze taken kunnen het uitvoeren van queries op de MySQL server betekenen, maar ook het analyseren van de data die zich op de MySQL server bevindt. Hoewel men deze queries ook via een command line interface kan uitvoeren, heeft de MySQL Query Browser toch het voordeel dat men hier de queries op een grafische manier kan uitvoeren. Dit geeft als voordeel dat men een betere kijk heeft op wat men allemaal aan het doen is op de MySQL server.
19
3.4
eZ publish
Figuur 3-8 Logo van eZ publish
eZ publish is een content management systeem en ontwikkelingsframework met functionaliteiten voor webpagina’s en intranets. eZ publish biedt standaard al een aantal functionaliteiten aan zoals versiebeheer, ondersteuning voor meerdere talen, e-commerce functionaliteiten, … 3.4.1
Content Management System
Een Content Management System (CMS) is een webapplicatie die het mogelijk om gegevens op het internet te publiceren. Deze toepassing is niet alleen voor ervaren personen bedoelt, ook de personen met een mindere technische kennis kunnen zonder problemen kunnen werken met een CMS. Een CMS bestaat minstens uit de volgende onderdelen. • • •
Een publiek gedeelte waar de gegevens door de bezoekers kunnen worden bekeken. Een (afgeschermde) administrator gedeelte waar de gegevens kunnen worden ingevoerd, verwijderd of aangepast. Een database waar de gegevens in bewaard worden.
Buiten deze onderdelen zijn er nog een hele resem aan andere onderdelen die men kan integreren in een CMS. 3.4.2
Ontwikkelingsplatform
eZ publish is een LAMP-gebaseerde webapplicatie. Dit wil zeggen dat eZ publish geschreven is voor het Linux platform, de Apache webserver en het database management systeem MySQL. Op de Apache webserver dient wel een module voor de scripting taal PHP actief te zijn. Deze module is nodig omdat eZ publish in PHP geschreven is. Het is ook niet noodzakelijk dat men eZ publish op een Linux platform integreert. Omdat Apache ook beschikbaar is voor een Microsoft Windows omgeving, kan men Windows ook als besturingssysteem gebruiken. Men is ook niet verplicht om MySQL als database management systeem te kiezen. eZ publish ondersteunt ook PostgreSQL. 3.4.3
Interne structuur van eZ publish
In dit deel wordt de interne structuur van eZ publish beschreven. De interne structuur bestaat uit drie grote delen: • • •
de libraries de kernel de modules
In de onderstaande figuur wordt getoond hoe deze delen met elkaar zijn verbonden.
20
Figuur 3-9 Interne structuur van eZ publish
•
De libraries
De libraries of klassenbibliotheken zijn de bouwstenen van het eZ publish systeem. Het zijn herbruikbare PHP klassen die onafhankelijk zijn van de kernel. Het systeem kan deze klassen oproepen wanneer deze nodig zijn. Men kan deze klassen terugvinden in het ‘lib’ mapje van de eZ publish root directory. Een voorbeeld van een klasse is eZXML. Met deze klasse is het mogelijk om met gegevens in het XML formaat te werken. •
De kernel
De kernel is de kern van het systeem. Het behandelt alle functionaliteiten van lage niveaus. Deze functionaliteiten zijn bijvoorbeeld content handling, access controle, version controle, workflows, … •
De modules
Een module biedt een HTTP interface aan die kan gebruikt worden om met het systeem te communiceren. Sommige modules bieden een interface aan voor de kernel, andere zijn minder afhankelijk van de kernel. Standaard worden in eZ publish al enkele modules voorzien, bijvoorbeeld de content module. Deze module maakt het mogelijk dat men een webbrowser kan gebruiken om de content te beheren. Een module kan men onderverdelen in views en fetch functies. o
Views
In een view kan men een template oproepen. Deze template bevat de HTML code die de weergave in de webbrowser bepaalt. Door het werken met views blijft de logica gescheiden van de lay-out. Bijvoorbeeld, de ‘search’ view van de ‘content’ module geeft de weergave van de ingebouwde search functie in eZ publish weer in de webbrowser.
o
Fetch functies
21
Fetch functies kan men gebruiken om gegevens vanuit een template op te halen. Deze gegevens kan men dan in de template gebruiken. Deze fetch functie kan men uitvoeren door het ‘fetch’ commando te gebruiken in de template. 3.4.4
Content en design
In eZ publish worden de content en het design van een webpagina volledig gescheiden gehouden. Hierdoor kan men op een content object meerdere opmaken toepassen. Een groot voordeel van dit systeem is dat de content niet kan veranderen als men in de opmaak een klein foutje maakt. In de volgende figuur wordt dit systeem getoond.
Figuur 3-10 Content en design
De content is de data die men op het scherm wil tonen. Dit kunnen gegevens uit de database zijn, maar ook gewone tekst of afbeeldingen. Het design in eZ publish wordt bepaald door templates toe te voegen aan de webapplicatie. Deze templates zijn opgebouwd uit HTML, CSS, afbeeldingen die geen deel uitmaken van de content, … Deze templates bepalen hoe de content in de webbrowser getoond wordt. 3.4.5
Content management
De rol van een content management systeem is om de content goed te organiseren, ongeacht van welk type deze content is of van welke structuur het heeft. Het hoofddoel is een systeem dat de gebruiker toelaat om gestructureerd met de content om te gaan. In tegenstelling tot sommige andere content management systemen is men in eZ publish niet verplicht om met een vooraf gedefinieerd content model te werken. De gebruiker is totaal vrij in het model dat hij wenst te ontwerpen. Maar als men het wenst, kan men toch gebruik maken van een standaard ingebouwd content model. 3.4.6
Content class
Een content class is eigenlijk een data structuur. Het is opgebouwd uit attributen. Deze attributen kan men bijvoorbeeld zien als een naam, of een omschrijving. De klasse zelf kan men eigenlijk als de definitie van de content bekijken. De volgende figuur maakt dit allemaal wat duidelijker.
22
Figuur 3-11 Content class
In dit voorbeeld heeft men de klasse ‘Article’ gekozen. Deze klasse stelt een artikel voor met een titel (=Title), een korte intro (=Intro) en de inhoud van het artikel (=Body). Dit zijn de attributen van deze klasse. Het is de blauwdruk van een artikel. In eZ publish zijn er een aantal klassen standaard ingebouwd. Deze kan men naar hartelust aanpassen of zelfs nieuwe klassen aanmaken. Men is hierin vrij om te doen wat het beste is voor de toepassing die men ontwerpt. Ook bij de attributen heeft men een ruime keuze tussen standaard geïntegreerde datatypes. Standaard zijn er in eZ publish een aantal voorgedefinieerde datatypes zoals een string, integer, afbeelding, … Men is niet verplicht een datatype hiervan te gebruiken. Men kan ook zelf datatypes creëren en gebruiken binnen de toepassing. 3.4.7
Content object
Een content object is een instantie van een content class. Daar waar de content class enkel de content definieert, bevat een content object de eigenlijke data. Van een content class kunnen meerdere content objects geïnstantieerd worden. De volgende figuur zal dit verduidelijken.
23
Figuur 3-12 Content object
Ook binnen een content object bestaan er attributen. Deze komen overeen met de attributen die in een content class worden gebruikt. Het grote verschil is dat deze attributen een waarde hebben. 3.4.8
Content node en de content node tree
Wanneer men binnen de toepassing een nieuw content object aanmaakt, heeft dit object nog geen eigenlijke locatie. De content objects moeten op de een of andere manier georganiseerd kunnen worden. Hier gaat men een content node gebruiken. Een content object kan op meerdere locaties voorkomen. Elk van deze locaties stelt een node voor. Elke node verwijst naar slechts één content object. De volgende figuur toont een node en het overeenkomstige object. Hier kan men zien dat de node met ID:2, het object met ID:30 voorstelt.
Figuur 3-13 Relatie tussen content object en content node
De content node tree is een hiërarchische structuur van content nodes. Elke locatie binnen deze structuur is een content node. Omdat men met content nodes werkt, kan een content object op meerdere plaatsen binnen deze structuur voorkomen. De volgende figuur verduidelijkt dit een beetje.
24
Figuur 3-14 Content node tree
De eenvoudigste vorm van een content node tree bestaat uit maar één content node. Deze node noemt men de root node. Deze root node heeft als ID:1. De root node is een virtuele node en bevat geen enkel content object. De nodes die direct onder de root node liggen noemt men de top level nodes. Deze top level nodes bevatten wel content objects. Standaard zit er in eZ publish al een aantal top level nodes gedefinieerd, bijvoorbeeld de Content node, Users node, … Zoals men kan zien in de bovenstaande figuur hangen de verschillende content nodes aan elkaar vast. Elke content node (behalve de root node) heeft twee verwijzingen. De eerste verwijzing gebeurt naar het object. De tweede verwijzing duidt de parent node van deze content node aan. De parent node is de direct bovenliggende node van deze content node. Hierdoor kan men de positie van de content node binnen de content node tree exact bepalen. 3.4.9
Relationele database model van eZ publish
Het relationele database model van eZ publish is veel te uitgebreid om hier in enkele regels toe te lichten. Daarom zal ik enkel de hoofdtabellen toelichten. In de volgende figuur worden de relaties tussen de verschillende tabellen getoond.
Figuur 3-15 Relationeel database model
25
In deze figuur kan men de verschillende klassen terug zien, namelijk de content class, de content object en de content node. De relatie tussen deze klassen wordt hier verduidelijkt. Een object is een instantie van een class. Daarom ligt er tussen deze tabellen een één op veel relatie. Deze relatie zorgt ervoor dat er meerdere objecten per class kunnen geïnstantieerd worden, maar dat een object maar kan instantiëren in één class. De class tabel wordt in eZ publish ezcontentclass genoemd. De object tabel kreeg de benaming ezcontentobject. De content class bestaat ook uit meerdere attributen. Dit kan men ook zien door de één op veel relatie die tussen de class tabel en de class attribute tabel bestaat. Omdat een object ook attributen kan bevatten, ligt er ook een één op veel relatie tussen de object tabel en de object attribute tabel. Deze attribuut tabellen worden respectievelijk ezcontentclass_attribute en ezcontentobject_attribute genoemd binnen eZ publish. Doordat er een één op veel relatie ligt tussen de class en de object tabel, trekt deze relatie zich ook door naar de attributen. Hierdoor ontstaat er een één op veel relatie tussen de class attribute tabel en de object attribute tabel. Omdat er binnen een class meerdere objecten kunnen geïnstantieerd worden, kan een class attribute ook door meerdere object attributes geïnstantieerd zijn. Omdat een object ook gelinkt kan zijn aan meerdere nodes, ligt hier ook een één op veel relatie tussen. Omdat de node ook naar een andere node verwijst, ligt er aan de node tabel ook een recursieve relatie. Deze relatie is er omdat een node ook naar zijn parent node verwijst. Deze relatie is ook een één op veel relatie omdat een node meerdere child nodes kan hebben. De node tabel noemt in eZ publish eznode_assignment. In eZ publish is er ook een soort van versiebeheer ingebouwd. Elke keer men een object editeerd, creëert men een nieuwe versie van dit object. Het is altijd die nieuwste versie die aangepast wordt. De oudere versies zullen onaangepast blijven. Zo kan men in eZ publish de wijzigingen van elk object bijhouden. Men kan dus ook een oudere versie van het object terug oproepen indien dit nodig is. Hier is de version tabel voor geïntegreerd in eZ publish. 3.4.10
Site management
Met slechts één enkele eZ publish installatie kan men meerdere interfaces op dezelfde content bouwen. Dit is mogelijk omdat men in eZ publish gebruikt maakt van het siteaccess systeem. Met dit systeem kan men meerdere configuraties vastleggen, gebaseerd op enkele regels. Deze regels bepalen welke instellingen er op welke siteaccess gelden. Deze regels kan men terugvinden in de site.ini configuratie file. Een voorbeeld van één van deze instellingen is op welke poort van de server deze siteaccess zich bevind. De configuratiefile zelf bevindt zich in <eZ publish>/settings/override/site.ini.append.php. Wanneer er een siteaccess actief is, worden de default instellingen overschreven door de instellingen die voor deze siteaccess zijn vastgelegd. Men kan bijvoorbeeld voor elke siteaccess een ander design instellen of zelfs een andere database. Een typische eZ publish installatie bestaat uit twee siteaccessen: een publieke interface voor de bezoekers en een admin interface voor de administrators. Deze twee siteaccessen gebruiken dezelfde database. Het grote verschil tussen deze twee siteaccessen is dat ze beide een verschillende design gebruiken en het doel waarvoor ze dienen. Het volgende voorbeeld toont deze typische eZ publish webapplicatie.
26
Figuur 3-16 Voorbeeld webapplicatie ven verschillende siteaccessen
3.4.11
Access control
De bedoeling van dit deel is om eens te kijken hoe eZ publish omgaat met permissies. In eZ publish is er een systeem ingebouwd dat toelaat om de rechten van een bepaalde gebruiker of gebruikersgroep op de content of bepaalde functies te limiteren. Dit systeem is gebaseerd op de volgende elementen. • • • •
User (gebruiker) User Group (gebruikersgroep) Policy (rechten) Role (rollen)
In de volgende figuur kan men de relaties tussen deze elementen bekijken.
Figuur 3-17 Access control
27
Het begint allemaal bij de gebruiker. Een gebruiker kan lid zijn van een gebruikersgroep. De gebruiker is de persoon die de webapplicatie bezoekt. Omdat de gewone gebruiker niet alle functies tot zijn beschikking mag hebben zoals bijvoorbeeld het aanpassen of wissen van gegevens, moet men rechten aan deze gebruiker toekennen. Meestal kent men de rechten aan een gebruikersgroep toe en voegt men deze gebruiker toe aan deze groep. Dan is het eenvoudiger als men later een andere gebruiker dezelfde rechten moet geven. Deze gebruiker zal dan gewoon aan deze gebruikersgroep toegevoegd moeten worden. Een recht is een regel die toegang geeft tot een bepaalde functie of alle functies binnen een module. Als laatste zijn er de rollen. Een rol is een verzameling van rechten. In een rol kan men een aanduiden op welk deel van de webapplicatie de rechten gelden.
3.5
Version Control Systems
Een version control system (VCS) is een systeem dat verschillende versies van dezelfde data bijhoud. Het wordt het meest gebruikt in engineering en software ontwikkelingsbedrijven om de voortgang van digitale data (bijvoorbeeld de broncode, elektronische modellen of kritische informatie), dat in een team ontwikkeld wordt, te beheren. De veranderingen aan deze verschillende versies worden aangeduid met versienummers. Als men bijvoorbeeld een document met versienummer één aanpast en terug naar het systeem zet, krijgt dit document versienummer twee. Het eerste document zal ook bewaard blijven. Als men een deel van een document wil hebben dat al enkele versies oud is, kan men dit gewoon gaan ophalen uit het systeem. Het gebruik van een versie controle systeem wordt meer en meer als noodzakelijk beschouwd door bedrijven voor hun ontwikkelingsprojecten. 3.5.1
Subversion
Figuur 3-18 Logo van Subversion
Subversion is een version controle system. De kern van dit systeem is een repository. Een repository is een gecentraliseerde plaats waar men alle data opslaat (bijvoorbeeld een file server in het netwerk). Men kan dit het beste vergelijken met een boomstructuur zoals in de volgende figuur.
28
Figuur 3-19 Client/repository structuur
Deze structuur heeft als voordeel dat de data maar op één plaats staat. Als men dan wijzigingen wilt aanbrengen moet men dit maar één maal doen, in tegenstelling tot de vele malen als iedere client die data lokaal heeft staan. Maar dat de data gecentraliseerd is, kan ook problemen met zich meebrengen. 3.5.2
Problemen met file-sharing
Alle version controle systems hebben te maken met hetzelfde fundamentele probleem. Hoe kan het systeem de gebruikers toelaten om al hun data beschikbaar te stellen, maar proberen te voorkomen dat de ene gebruiker de aangepaste data van de andere gebruiker zomaar overschrijft zonder dat hij zelf rekening heeft gehouden met deze wijzigingen. Dit wordt duidelijk in de volgende figuur.
Figuur 3-20 Het probleem van file-sharing
In deze figuur zijn er twee gebruikers, Harry en Sally genaamd, die hetzelfde bestand A in de repository willen aanpassen. Eerst gaan beide gebruikers het bestand A vanuit de repository ophalen. Daarna brengen beide gebruikers hun wijzigingen aan. Harry is eerst klaar met het editeren en hij schrijft het bestand A’ terug weg naar de repository. Sally heeft even later ook gedaan met het editeren van haar versie en schrijft het bestand A’’ ook weg naar de repository. Hierbij zal ze de wijzigingen van Harry (bestand A’) overschrijven zodat deze gegevens verloren gaan. Dit is een situatie die
29
we eigenlijk willen vermijden. Om deze situatie op te lossen kan men de volgende technieken toepassen. 3.5.3
Lock-modify-unlock
Vele version controle systems gebruiken een lock-modify-unlock model om het probleem op te lossen. Dit principe is gebaseerd op een gebruik van locks. Hierdoor laat de repository slechts één persoon tegelijk toe die een bestand wil editeren. In de onderstaande figuur wordt dit principe getoond.
Figuur 3-21 De lock-modify-unlock oplossing
Harry wil het bestand A’ editeren. Hij zal eerst een lock op het bestand A’ moeten zetten voor hij dit bestand A’ kan ophalen. Als hij het bestand A’ gelockt heeft, kan hij het ophalen. Terwijl Harry bestand A’ aan het editeren is, wil Sally ook wijzigingen in bestand A’ aanbrengen. Sally zal dit bestand A’ niet kunnen locken omdat Harry dit bestand A’ heeft gelockt. Hierdoor zal Sally het bestand A’ niet kunnen ophalen. Wanneer Harry zijn wijzigingen heeft aangebracht, kan hij het terug in de repository zetten. Hierna heft hij de lock op bestand A’ op. Vanaf nu kan Sally een lock zetten op bestand A’ om er wijzigingen in aan te brengen. Aan dit principe zijn ook enkele nadelen verbonden. •
•
•
Het locken van een bestand kan administratieve problemen geven. Harry kan bijvoorbeeld een bestand locken maar vergeten dat hij een lock op dit bestand heeft gezet. Sally zal dit bestand niet kunnen editeren omdat er nog een lock actief is op het bestand. Deze situatie creëert een hoop onnodige vertraging en tijdverspilling. Het locken van een bestand kan een onnodige serialisatie veroorzaken. Als Harry het begin van een tekstbestand aan het aanpassen is en Sally wil een wijziging aanbrengen aan het einde van dit tekstbestand. Sally zal dit niet kunnen doen omdat Harry dit bestand gelockt heeft, ondanks dat beiden niet dezelfde gegevens willen aanpassen. Het locken van een bestand kan een vals gevoel van veiligheid creëren. Harry kan bijvoorbeeld bestand A locken en editeren, terwijl Sally op dezelfde moment
30
bestand B lockt en editeert. Dit zou een mogelijke situatie zijn, maar stel dat bestand A en bestand B afhankelijk zijn van elkaar. Als er dan wijzigingen gaan gebeuren in deze bestanden kan dit een incompatibiliteit tussen deze bestanden veroorzaken. Het systeem kon deze situatie ook niet vermijden. 3.5.4
Copy-modify-merge
Om de problemen van file-sharing en het lock-modify-unlock model te vermijden gebruiken Subversion, CVS en andere version controle systems een copy-modify-merge model. In dit systeem zullen de verschillende gebruikers, die één dezelfde bestand willen aanpassen, parallel werken. Dit betekent dat elk van hen een kopie van het originele bestand lokaal zal bijhouden en daar zijn wijzigingen in maakt. Uiteindelijk zullen de verschillende lokale versies van het bestand samengevoegd worden tot één nieuw bestand in de repository. Dit kan men allemaal volgen in de onderstaande afbeeldingen.
Figuur 3-22 De copy-modify-merge oplossing
Figuur 3-23 De copy-modify-merge oplossing (vervolg)
31
Harry en Sally willen beide bestand A aanpassen. Beide gebruikers gaan bestand A uit de repository lezen en een lokale kopie bijhouden (Harry heeft kopie A’ en Sally kopie A’’). Sally heeft haar kopie A’’ eerst af en schrijft het terug naar de repository. Kopie A’’ zal in de repository komen te staan. Harry heeft zijn aanpassingen daarna ook gedaan en wil het bestand A’ terug naar de repository schrijven. Dit zal niet lukken want de repository ziet dat Harry geen kopie heeft van de laatst gepubliceerde versie van het bestand. De repository geeft Harry een kopie van het laatst gepubliceerde bestand A’’. Harry heeft nu twee versies van het bestand lokaal staan (A’ en A’’). Deze twee versies zullen samengevoegd worden tot één bestand A’’. Hierna kan Harry het bestand A’’ terug naar de repository schrijven. Nu zitten de wijzigingen die Harry en Sally hebben aangebracht samen in één versie van het bestand. De copy-modify-merge oplossing mag dan een beetje chaotisch klinken, in werkelijkheid werkt deze oplossing zeer vlot. De verschillende gebruikers moeten nooit op elkaar wachten omdat ze parallel aan hetzelfde bestand werken. Zelfs al werken deze verschillende gebruikers aan hetzelfde bestand, de wijzigingen die ze maken zullen meestal elkaar niet overlappen. Is dit toch het geval, dan zal er nog minder tijd verloren gaan om dit conflict op te lossen dan de tijd die er verloren gaat door gebruik te maken van een systeem met locks. Om de bestanden op de repository aan te spreken maakt men gebruik van een aantal commando’s. De meest gebruikte commando’s zijn check-out, commit en update. •
Check-out
De check-out van een bestand in de repository zorgt ervoor dat men een lokale versie van dat bestand verkrijgt. In deze lokale versie kan men dan de aanpassingen doen die men wenst. •
Commit
Met het committen van een bestand bedoelen we het schrijven van dit bestand naar de repository. Hierdoor zullen de andere personen die aan het project werken de wijzigingen ook krijgen omdat Subversion de commando’s aanbiedt om het bestand uit de repository met het lokale bestand te mergen. De commit wordt soms ook check-in genoemd. •
Update
Als men het lokale bestand wil updaten met de versie uit de repository, dan kan men het lokale bestand updaten. Hierdoor zullen de wijzigingen die aan het bestand op de repository zijn gedaan door andere gebruikers gemerged worden met het lokale bestand. Het lokale bestand is dan ook up-to-date.
32
3.5.5
TortoiseSVN
Figuur 3-24 Logo van TortoiseSVN
TortoiseSVN is een subversion client. Deze tool laat je werken vanuit een Windows Explorer. In tegenstelling tot een command-line client is deze grafische client voor de meeste mensen gemakkelijker te gebruiken. De reden hiervoor is dat de meeste mensen niet zo vertrouwd zijn met een command-line interface. Op de volgende figuur is een schermafdruk van TortoiseSVN te zien.
Figuur 3-25 Schermafdruk TortoiseSVN
Zoals u in de bovenstaande figuur kunt zien is TortoiseSVN geïntegreerd in de Windows Explorer. Als men met de rechter muistoets op een bestand klikt, dan krijgt men buiten de standaard Windows werkbalk ook de TortoiseSVN opties te zien. Als men al eens een commit heeft uitgevoerd, krijgt men op de icoontjes van deze bestanden de status van deze bestanden te zien. Zo kan men zien of er aan een bestand een wijziging is gebeurd sinds de laatste commit.
33
4
STANDAARDEN
Een webtoepassing kan door vele gebruikers bekeken worden. Er bestaat een kans dat zij niet allemaal dezelfde webbrowser hebben. Deze verschillende webbrowsers interpreteren de broncode van de webtoepassing allemaal op een verschillende manier. Hierdoor kan men best enkele standaarden volgen. Hierdoor zal de webtoepassing beter ondersteund worden door deze verschillende webbrowsers en zal de gebruiksvriendelijkheid in een positieve zin evolueren.
4.1
HTML
HTML (HyperText Markup Language) is nog steeds de meest gekende opmaak taal voor onder andere webbrowsers vandaag. Dit wil zeggen dat het de webbrowser door middel van HTML tags gaat vertellen hoe de webpagina moet worden weergegeven op het scherm. HTML is eenvoudig om aan te leren, terwijl men er ook ingewikkelde dingen mee kunt doen, maar met de basisfuncties kan men al een leuke website bouwen. In de loop der jaren is het aantal tags enorm uitgebreid. De volgende figuur toont een zeer eenvoudig voorbeeld van HTML code.
Figuur 4-1 Voorbeeld HTML code
4.2
XML
XML (Extensible Markup Language) is een opmaaktaal voor documenten die gestructureerde informatie bevatten. Deze informatie bevat zowel de inhoud (bijvoorbeeld tekst of afbeeldingen) als een indicatie van de rol dat die inhoud heeft (bijvoorbeeld inhoud van een header heeft een andere betekenis dan die van een footer). XML kan men een klein beetje vergelijken met HTML. Het werkt ook met tags. Maar daar waar HTML vaste tags gebruikt, is men in XML vrij om de tags te benoemen hoe men wil. In XML moeten de tags wel well-formed zijn. Hiermee bedoelen we dat de tags onder andere in lower case moeten geschreven worden en dat de tags op een correcte manier moeten afgesloten worden. XML wordt wel niet rechtstreeks gebruikt om de opmaak van webpagina’s te verzorgen. Het is een vaak gebruikte opmaaktaal om bijvoorbeeld gegevens uit te wisselen of om RSS feeds weer te geven. De volgende figuur toont een eenvoudig voorbeeld van XML code.
34
Figuur 4-2 Voorbeeld XML code
4.3
XHTML
XHTML betekent eXtensible HyperText Markup Language en is de opvolger van HTML. Uiteindelijk zal XHTML de oudere HTML opmaak taal gaan vervangen. XHTML lijkt wel heel erg op HTML. Men kan XHTML vooral zien als een strengere en schonere versie van HTML. Hierdoor verkrijgt men een veel betere codering van de broncode door de striktere regels die men opgelegd krijgt. Hierdoor zullen meer webbrowsers deze opmaak taal ondersteunen en zullen er minder fouten optreden bij het omzetten van de broncode. Hieronder worden enkele van deze regels toegelicht. • • • • •
Alle tags en attributen van deze tags moeten in kleine letters geschreven worden. Er mogen geneste tags gebruikt worden, maar men moet deze in de juiste volgorde sluiten. Alle tags moeten gesloten worden. Alle waarden van attributen moeten tussen dubbele quotes staan. Het gebruik van een Doctype is verplicht. De doctype wordt door webbrowsers en validators gebruikt om na te gaan welke syntax voor het XHTML document gebruikt moet worden.
Omdat men in de toekomst op het web meer en meer gebruik gaat maken van XML, is XHTML de eenvoudigste manier om naar XML om te schakelen. De volgende figuur toont een zeer eenvoudig voorbeeld van XHTML code.
Figuur 4-3 Voorbeeld XHTML code
35
4.4
Cascading style sheets
Cascading style sheets of CSS is een taal die men gebruikt om de grafische presentatie van een opmaak taal te verzorgen, zoals een HTML of een XHTML document. In de opmaaktaal zelf kan men ook verschillende effecten toevoegen op zijn document, maar deze zijn zeer beperkt. Met CSS heeft men veel meer mogelijkheden. Een groot voordeel is dat de CSS code niet in de eigenlijke broncode van de opmaak taal moet zitten, hierdoor kan men alle opmaak centraliseren. De CSS code kan men in een stylesheet zetten, en deze dan includen in de broncode. Zo staan alle opmaakelementen bij elkaar. Wilt men een andere stijl op zijn website? Dan hoeft men alleen de stylesheet aan te passen. Aan de broncode zelf hoeft men niet te komen. De volgende figuur toont een voorbeeld van de code die men in een CSS stylesheet kan terugvinden.
Figuur 4-4 Voorbeeld CSS code
4.5
Validator
Om uw aangemaakte webpagina’s na te kijken of ze beantwoorden aan deze standaarden, bestaan er validators. Deze validator zorgt ervoor dat de fouten op uw webpagina’s zichtbaar worden zodat men ze kan repareren. Want niet elke webbrowser interpreteert een opmaaktaal op dezelfde manier. Een webpagina die in webbrowser X werkt, kan bijvoorbeeld maar half zo goed getoond worden door webbrowser Y. Daarom kan men best deze standaarden opvolgen. Met deze standaarden gaat niet elke webbrowser deze webpagina perfect weergeven, maar er zal toch een verbetering zijn. Om mijn website te valideren, heb ik gekozen voor de W3C (World Wide Web Consortium) validator. Dit is een online validator die iedereen gratis kan gebruiken. Met deze validator kon ik mijn XHTML en CSS code controleren.
36
5
UITWERKING STAGEOPDRACHT
Mijn stageopdracht bestond uit het maken van een webapplicatie waar men nieuwsartikels uit de nucleaire wereld kon samenbrengen. Omdat men deze artikels al vele jaren geleden is beginnen verzamelen, was er al een eZ publish site aangemaakt die al deze artikels bevatte. Het eerste deel van mijn stageopdracht bestond er in om deze eZ publish installatie up te graden naar een nieuwere versie. Daarna heb ik de klassen binnen deze eZ publish site aangepast om beter in de nieuwe webapplicatie te passen. Als laatste ben ik begonnen met het ontwikkelen van de webtoepassing zelf.
5.1
Het upgraden van eZ publish
De documenten die door de jaren heen zijn ingegeven, waren ingegeven in een eZ publish module die was aangemaakt met als doel deze documenten te verzamelen. Toen men deze module aanmaakte, was de laatste stabiele versie van eZ publish versie 3.3.1. De versie waarin ik de webapplicatie diende te maken is versie 3.6.7. Het upgraden van eZ publish was nodig omdat men dan over de laatste functionaliteiten beschikte die in eZ publish aanwezig waren. Er waren ook oudere functionaliteiten binnen eZ publish die men verbeterd had om een betere gebruiksvriendelijkheid te kunnen bieden aan de gebruiker. Het upgraden van eZ publish was een beetje chaotisch in het begin. Dit was mede omdat er verschillende updates beschikbaar waren. Langs de ene kant heeft men de kleinere versie updates. Dit is bijvoorbeeld een update van versie 3.3.1 naar 3.3.2. Langs de andere kant had men ook nog de grotere updates. Deze waren bijvoorbeeld een update van versie 3.3.5 naar 3.4.0. Deze grotere updates waren iets ingewikkelder omdat men dan verschillende extra stappen moest uitvoeren, zoals bijvoorbeeld enkele PHP scripts uitvoeren, om tot de nieuwe versie te komen. De weg waarop men eZ publish kan upgraden is uitgelegd in de eZ publish documentatie op de website. Maar om een overzicht te geven hoe deze weg eruit kan zien, is hier de weg die ik moest volgen om tot de huidige versie te komen.
Figuur 5-1 Versie upgrade eZ publish
37
Om van een oude naar een nieuwe versie up te graden moet men enkele stappen ondergaan. Hier volgen de stappen die men moet uitvoeren om een kleine upgrade te doen. •
Het downloaden van de nieuwe eZ publish distributie
Men dient eerst de nieuwe versie te downloaden van de eZ publish website. Deze versie bevat dan alle wijzigingen die er in de nieuwe versie van kracht zijn. Dit kunnen bijvoorbeeld aangepaste script files zijn of een nieuwe functie die geïntegreerd werd. •
Het overschrijven van de oude bestanden
Nadat men de nieuwe versie gedownload heeft, moet men de oude eZ publish vervangen door deze nieuwe versie. Men kan dit bijvoorbeeld doen door de nieuwe eZ publish versie over de oude versie te kopiëren. De oudere files zullen dan vervangen worden door de nieuwere. •
Het uitvoeren van een script om de database up to date te brengen
Als laatste stap dient men dan nog een SQL script uit te voeren die de wijzigingen in de database uitvoert. Het kan bijvoorbeeld zijn dat er geen wijzigingen in de database structuur worden uitgevoerd. In dit geval zal alleen de versie, die bewaard wordt in de database, naar de nieuwe versie worden aangepast. Als er een tabel bij aangemaakt moet worden, dan zal dit in het script gebeuren. Deze scriptfiles bevinden zich in de nieuwe versie die men gedownload heeft, in de map <eZpublish folder>/update/database/mysql/
. Als men een grote upgrade dient uit te voeren moet men de stappen van een kleine upgrade eerst uitvoeren. Bij een grote upgrade moet men nadien nog enkele PHP scripts uitvoeren. Een grote upgrade wordt uitgevoerd wanneer men een grote wijziging in eZ publish wilt uitvoeren. Onder een grote wijziging verstaan we bijvoorbeeld een eZ publish mechanisme dat aangepast moet worden zoals de versiebeheer of een verandering in de structuur van eZ publish.
5.2
Het gebruik van extensies
Omdat eZ publish regelmatig van versie verandert, kan men niet zomaar in de broncode de functies gaan bijschrijven die men wenst te gebruiken. De nieuwe code zou overschreven worden tijdens de volgende upgrade van eZ publish. Om nieuwe onderdelen aan te maken in eZ publish gebruikt men extensies. Alles wat men in een extensie programmeert, zal de bestaande code dus niet overschrijven, maar zal wel in de plaats van deze code uitgevoerd worden. Al de extensies die men aanmaakt moeten in de extensie map gezet worden. Eenmaal dit gebeurt is, moet men deze extensie activeren in de site.ini file.
38
Figuur 5-2 Activatie van een extensie
De extensies die u in dit voorbeeld kan zien zijn de extensies die ik in mijn webapplicatie gebruikt heb. De namen die men hier ziet staan zijn de namen van de extensie zelf. Deze zijn identiek aan de namen van de extensie folders die zich in het extensie mapje bevinden. De structuur van deze folders kan men in de volgende figuur zien.
Figuur 5-3 Extensie folder
5.3
Het gebruik van modules
Wat een module is, hebben we eerder al besproken in het hoofdstuk eZ publish. Maar hoe moet zo’n nieuwe module aangemaakt worden? Als men een nieuwe module wil aanmaken, moet men eerst een nieuwe extensie activeren. Hierin kan men dan de module aanmaken. Om het aanmaken van een module uit te leggen, maak ik gebruik van de module fetchrssfeeds. Wat deze module eigenlijk doet, komt later nog aan bod. Om deze module aan te maken heb ik eerst de extensie fetchrssexports geactiveerd. In deze extensie vindt men twee mappen terug, namelijk het mapje modules en het mapje settings. In het mapje settings zit de module.ini file en hierin wordt er bepaald welke extensies er gebruikt worden en welke modules er in deze extensie zitten. Dit kan u in de volgende figuur zien.
39
Figuur 5-4 Module settings
In het modules mapje zitten de verschillende modules die in deze extensie geactiveerd zijn, elk in hun eigen mapje. In dit geval zal dit het mapje fetchrssfeeds zijn. Hierin zitten de bestanden van deze module. Dit word weergegeven in de volgende figuur.
Figuur 5-5 Extensie filestructuur
5.4
Het aanpassen van de eZ publish klassen
Omdat sommige van de klassen, die men in de oudere versie van eZ publish aangemaakt had niet meer up to date zijn, moesten deze klassen aangepast worden om aan de noden van de nieuwe webapplicatie te voldoen. Het kon zijn dat deze klassen nog niet bestonden. In dit geval was het nodig dat we deze klassen gingen aanmaken. In de nieuwe webapplicatie worden de volgende klassen gebruikt. • • • • • •
news_article_2 news_folder resource folder rss_feed rss_item
We gaan nu deze verschillende klassen één voor één uit de doeken doen en zien hoe we deze omgevormd hebben naar de uiteindelijke vorm. 5.4.1
De news_article_2 klasse
De news_article klasse die in de oudere versie beschikbaar was, diende aangepast te worden aan de nieuwe webapplicatie. Deze klasse werd gewijzigd omdat we de webapplicatie een zo groot mogelijke gebruiksvriendelijkheid wilden geven. In deze klasse konden we niet zomaar de attributen gaan aanpassen of verwijderen. Er bestaan meer dan duizend objecten van deze klasse. Als we een attribuut in de news_article klasse gaan verwijderen, zal al de informatie die in het overeenkomstige attribuut van de objecten zit verloren gaan. Het kan niet de bedoeling zijn dat informatie die al zo
40
lang is bijgehouden nu verloren gaat. Daarom heb ik een nieuwe news_article_2 klasse aangemaakt waarin de nieuwe attributen zijn ingegeven. Het aanmaken van een nieuwe klasse is relatief eenvoudig in eZ publish. Men kan deze aanmaken via de admin interface. 5.4.1.1
Kopiëren van de news_article klasse
Nadat deze klasse aangemaakt was, moesten de objecten nog van de news_article klasse naar de news_article_2 klasse gekopieerd worden. Het kopiëren van deze objecten gebeurt via een PHP script dat ik heb geschreven. We gaan nu eens bekijken hoe dit script is opgebouwd. // include the necessary classes and libs include_once( 'kernel/classes/ezcontentobject.php' ); include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); include_once( 'kernel/classes/ezcontentobjectattribute.php' ); include_once( 'kernel/classes/ezcontentclass.php' ); include_once( 'lib/ezutils/classes/ezini.php' ); include_once( 'lib/ezutils/classes/ezoperationhandler.php'); // Get the creatorID $ini =& eZINI::instance( 'site.ini' ); $creatorID =& $ini->variable( 'UserSettings', 'UserCreatorID' ); // Get the classIdentifier $migrationIni =& eZINI::instance( 'migrationsettings.ini' ); $classIdentifier=&$migrationIni->variable( 'MigrationSettings','ClassID' ); $sectionID =& $migrationIni->variable( 'MigrationSettings', 'SectionID' ); We gaan eerst de nodige klassen en bibliotheken invoegen die we in het script nodig hebben. Daarna halen we de gegevens op die we nodig hebben om een nieuw object aan te maken. Deze gegevens worden opgehaald uit verschillende ini-files die zich in de eZ publish settings map bevinden. // fetch the news articles $params = array( 'ClassFilterType' => 'include', 'ClassFilterArray' => array('news_article') ); $articles =& eZContentObjectTreeNode::subTree( $params ,2 ); Hierna gaan we alle nodes van de klasse news_article ophalen in de content node tree die zich onder de node met node_id:2 bevinden. Al deze artikels worden in een array opgevangen. foreach ( $articles as $article ) { $dataMap = $article->dataMap(); $parentNodeID = $article->attribute( 'parent_node_id' ); $articleNodeID = $article->attribute( 'node_id' ); // Title if( array_key_exists( 'title', $dataMap ) ) { $titleAttribute =& $dataMap['title']; $titleContent =& $titleAttribute->content(); }
41
… Nu gaat men deze artikels één voor één aflopen om de gegevens te kunnen kopiëren. Dit doen we met behulp van een foreach lus. Van elk artikel gaat men de datamap ophalen. In deze datamap bevinden zich de verschillende attributen van het artikel, namelijk title, subtitle, source, … Voor elk artikel (of object) moeten we ook de parent en de node_id kennen. Als we deze gegevens hebben gaan we van elk attribuut de gegevens ophalen uit de datamap en deze in variabelen steken. Ik heb hier maar één attribuut aangehaald, attribuut title, omdat dit op een dezelfde wijze voor alle andere attributen gedaan word. Omdat we zeker geen foutmeldingen willen krijgen als het attribuut niet bestaat, doen we eerst een controle. Indien het attribuut bestaat, halen we de content van het attribuut uit de datamap op. Deze stockeren we dan in een variabele. Indien het title attribuut niet bestaat, slaan we dit attribuut gewoon over en gaan we naar het volgende attribuut. $contentClass=&eZContentClass::fetchByIdentifier($classIdentifier); $contentObject=&$contentClass->instantiate($creatorID, $sectionID); Als we alle attributen hebben opgehaald en deze in variabelen hebben bewaard, moeten we voor de klasse news_article_2 een nieuw object aanmaken en deze attributen hier in de juiste vorm opslaan. We gaan een object van de news_article_2 klasse instantiëren. // Create node assignment $nodeAssignment =& eZNodeAssignment::create( array( 'contentobject_id' => $contentObject->attribute( 'id' ), 'contentobject_version' => $contentObject attribute( 'current_version' ), 'is_main' => 1, 'parent_node' => $parentNodeID ) );
->
$nodeAssignment->store(); $version =& $contentObject->version( 1 ); $version->setAttribute( 'status', EZ_VERSION_STATUS_DRAFT ); $version->store(); Nadat we dit object geïnstantieerd hebben, gaan we een node assignment aanmaken. In deze node assignment gaan we de id, de versie, of het de main_node is en de node_id van de parent meegeven. De main_node is de eigenlijke locatie van de node. Al de andere nodes verwijzen naar deze main_node. Deze node assignment wordt dan bewaard en daarna gaan we de versie van dit object bepalen en bewaren. // Get object attributes, and set their values and store them. $dataMap =& $version->dataMap(); // set title if( array_key_exists( 'title', $dataMap ) ) { $dataMap['title']->setAttribute( 'data_text', $titleContent ); $dataMap['title']->store(); } … //publish new object $operationResult=eZOperationHandler::execute('content','publish', array( 'object_id' => $contentObject->attribute( 'id' ),
42
'version' )
=>
$contentObject->attribute('current_version') );
} Nadat we de versie en de node assignment hebben bepaald, gaan we de datamap van dit nieuwe object ophalen. Als dit gebeurd is, gaan we voor elk attribuut dat bestaat, de waarden uit de variabelen (die we eerder hebben opgehaald) in deze datamap zetten. Daarna bewaren we het attribuut in de datamap. Als alle attributen opgevuld zijn, moeten we het object nog publiceren. Hierna is het object van de news_article_2 klasse aangemaakt. Na het publiceren wordt de foreach lus afgesloten en gaan we naar het volgende artikel in de array. 5.4.1.2
Aanpassen van de bronnen
Het voorgaande script toonde hoe de artikels gekopieerd worden van de news_article naar de news_article_2 klasse. Maar dit is nog niet alles dat er veranderd moet worden. De resources staan nog in een tekstveld. De bedoeling is dat we de bronnen (sources) die in de news_article klasse staan, in een apart deel van de webapplicatie moeten komen te staan. Hier heeft men dan een beter overzicht van welke bronnen er allemaal zijn en kan men ze makkelijker beheren. Voor deze bronnen is er een aparte klasse aangemaakt, namelijk de resource klasse. De bedoeling is om de naam van deze bronnen, die in tekstvorm bij het artikel zijn bewaard, te vervangen door de node ID van de bron. Eerst heb ik een Resource folder aangemaakt waarin alle bronnen konden worden samengevoegd. De code om de bronnen in deze folder te kopiëren ziet u hieronder. include_once( … ); // Get the creatorID $ini =& eZINI::instance( 'site.ini' ); $creatorID =& $ini->variable( 'UserSettings', 'UserCreatorID' ); $resources = array(); $params = array( 'ClassFilterType' => 'include', 'ClassFilterArray' => array('news_article') ); $articles =& eZContentObjectTreeNode::subTree( $params ,2 ); foreach ( $articles as $article ) { $dataMap =& $article->dataMap(); De code om de verschillende klassen toe te voegen heb ik ingekort omdat dit toch altijd op dezelfde manier gebeurt. Na het invoegen van deze klassen gaan we de creatorID ophalen. Hierna wordt de $resources array gedeclareerd. Deze zal de node ID’s van de artikels bevatten waarin de huidige bron voorkomt. Hierna gaat men alle artikels ophalen en deze één voor één afgaan. Voor elk artikel haalt men de datamap op. if( array_key_exists( 'source', $dataMap ) ) { $sourceAttribute =& $dataMap['source']; $sourceContent =& $sourceAttribute->content(); $sourceHash = md5( $sourceContent ); if ( !array_key_exists( $sourceHash, $resources ) )
43
{ $resources[$sourceHash] = array( 'name' => $sourceContent, 'articles' => array($article->attribute('node_id')) ); } else { $resources[$sourceHash]['articles'][]=$article->attribute 'node_id' ); } }
(
} Hier gaat men controleren of het source attribuut bestaat. Als dit bestaat, gaan we de inhoud van dit attribuut in een variabele steken. We maken van deze variabele ook een md5 gecodeerde hash. Deze hash is uniek en is een 32 tekens lang hexadecimaal nummer. Hij kan zeer goed dienen als key van de $resources array. Als deze key nog niet bestaat in de $resources array, gaat men in de $resources array een nieuwe array aanmaken met de attributen “name” en “articles”. Het “name” attribuut krijgt de inhoud van het “source” attribuut van het artikel. Het “articles” attribuut is een array op zichzelf en krijgt als waarde de node ID van het huidige artikel. Indien deze key al in de $resources array bestond, gaat men gewoon de node ID van het huidige artikel in het “articles” attribuut van de $resources array bijvoegen. Nadat de $resources array is gevuld met de verschillende bronnen uit de artikels, gaan we elke bron afgaan. foreach ( $resources as $key => $resource ) { $resourceClass =& eZContentClass::fetchByIdentifier( 'resource'); $resourceObject =& $resourceClass->instantiate( $creatorID, 1 ); $resourceObject->store(); $nodeAssignment =& eZNodeAssignment::create( array( 'contentobject_id' => $resourceObject->attribute('id'), 'contentobject_version' => $resourceObject -> attribute( 'current_version' ), 'is_main' => 1, 'parent_node' => 8689 ) ); $nodeAssignment->store(); Voor elke bron in de array gaan we een nieuw object aanmaken van de klasse resource. Daarna instantiëren we de node. Deze nodes krijgen als parent ID de ID mee van de Resources folder (8689). Hierna bewaren we deze node. $version =& $resourceObject->version( 1 ); $version->setAttribute( 'status', EZ_VERSION_STATUS_DRAFT ); $version->store(); // Get object attributes, and set their values and store them. $dataMap =& $version->dataMap(); Daarna gaan we de versie van het object instellen en de datamap ophalen. // set source if( array_key_exists( 'name', $dataMap ) ) { $dataMap['name']->setAttribute( 'data_text' , $resource['name'] );
44
$dataMap['name']->store(); } // set article if( array_key_exists( 'articles', $dataMap ) ) { $dataMap['articles']->setAttribute( 'data_text' $resource['articles'] ) ); $dataMap['articles']->store(); }
,
implode(
',',
Dan worden de attributen van het nieuwe object opgevuld met de waarden van de huidige bron. Het attribuut “name” krijgt de naam van de bron. In het attribuut “article” gaan we de inhoud van de “articles” array bewaren. De functie implode zorgt ervoor dat we deze “articles” array gaan opslaan als een string, waar de verschillende waarden die in de array zitten met een “,” zullen gescheiden worden. //publish new object $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $resourceObject->attribute( 'id' ), 'version' => $resourceObject->attribute('current_version') ) ); } Als laatste wordt het object gepubliceerd. Nu deze bronnen in de Resources folder zitten, kunnen we er nog wat verder in snoeien. Er zijn nogal wat bronnen met een verschillende naam, maar die toch dezelfde bron zijn. Hiervoor heb ik deze bronnen naar een CSV bestand (Comma Separated Value) geëxporteerd. De keuze is op een CVS bestand gevallen, nadat ik de verschillende opties met deze medewerker overlopen had. Hierdoor kon ik deze bronnen laten nakijken door een medewerker van het Knowledge Centre die me dan kon vertellen welke bronnen er moesten blijven en welke samengevoegd moesten worden. Ik heb een bestand van het CSV formaat gekozen omdat men dit bestand in vele bewerkingssoftware kan openen, bijvoorbeeld Microsoft Excel. De gegevens die in het bestand staan zullen automatisch in rijen en kolommen gezet worden. In dit bestand zullen de volgende attributen opgenomen worden: de node ID van deze bron, de naam en de node ID’s van de artikels waarin deze bron voorkomt. De code die ervoor zorgt dat de bronnen in het bestand wordt weggeschreven ziet u hieronder. include_once( … ); $fh = fopen( '/home/ctheys/exportSources.csv', 'w' ); if ( $fh ) { … fclose( $fh ); } In deze code gaat het bestand exportSources.csv geopend worden door middel van de functie fopen. De extra parameter w die men meegeeft staat voor de mode waarin dit bestand geopend wordt. De mode w staat voor alleen schrijven. Dit is wat we nodig hebben want we moeten hier alleen maar de bronnen wegschrijven naar een bestand. Deze mode zorgt er ook voor als het bestand dat men meegeeft niet bestaat, dat dit aangemaakt wordt. Als het bestand bestaat, dan word de code (die hier voorgesteld
45
wordt door …) uitgevoerd. Als de code is uitgevoerd, gaat men het bestand sluiten door middel van de functie fclose. De code die daarna uitgevoerd wordt is de volgende. $params = array( 'ClassFilterType' => 'include', 'ClassFilterArray' => array( 'resource' ), 'SortBy' => array( 'name', true ) ); $resources =& eZContentObjectTreeNode::subTree( $params,2 ); foreach ( $resources as $resource ) { $dataMap =& $resource->dataMap(); $nodeID = $resource->attribute( 'node_id' ); $nameAttribute =& $dataMap['name']; $sourceName =& $nameAttribute->content(); $articleAttribute =& $dataMap['articles']; $sourceArticles =& $articleAttribute->content(); fwrite(
$fh, '"' . $nodeID . '";"' $sourceArticles . '"' . "\n" );
.
$sourceName
.
'";"'
.
} Eerst gaat men hier alle nodes van de klasse resource ophalen en in de array $resources bewaren. Deze zijn gesorteerd op naam, van A tot Z. Daarna gaat men elke resource uit deze array $resources afgaan. Van elke resource die in deze array zit, gaat men de datamap en de node_id ophalen. Daarna gaat men de attributen “name” en “articles” ophalen uit deze datamap. Als laatste schrijven we deze resource weg in het CSV bestand met de functie fwrite. Een regel in dit CSV bestand is bijvoorbeeld “1000”;”Bronnaam”;”1001,1002,1003”. De “\n” aan het einde van deze regel dient om naar een nieuwe lijn te gaan. Als men deze lijn bijvoorbeeld in Microsoft Excel gaat openen krijgt men het volgende te zien.
1000 Bronnaam 1001,1002,1003 Nu alle bronnen in het CSV bestand staan, kan ik dit bestand doorgeven aan een van de werknemers van het Knowledge Centre die dit bestand ging controleren. Toen ik de lijst terug kreeg, kon ik de bronnen in de Resource folder aanpassen. De lijst die ik terug kreeg was in de vorm van een tekst bestand.
46
Figuur 5-6 Tekstbestand nieuwe versie van de sources
Omdat de meeste code van dit script hetzelfde is opgebouwd, ga ik alleen het belangrijkste deel tonen. $sourceNodeIDsArray = array(); // Get the article nodes from a text-file $fh = fopen( '/home/ctheys/Sources_nieuw.txt', 'r' ); if ( $fh ) { $newResourceList = array(); $newResourceArray = array(); while ( !feof( $fh ) ) { $readLine = fgets( $fh ); $newResourceList[] = $readLine; } fclose( $fh ); … Dit deel van het script gaat de bronnen uit een tekstbestand lezen en deze in een array stoppen. Men gaat hier opnieuw de fopen functie gebruiken om een bestand te openen. Deze keer staat het bestand in de read only mode. Als het bestand bestaat gaan we twee arrays declareren, één array om de regels uit het tekstbestand in op te slaan en een andere array om de verschillende node ID’s uit de eerste array in op te vangen. Na deze declaratie gaat men elke regel uit het tekstbestand afgaan tot men aan het einde van het tekstbestand zit. Ondertussen gaat men elke regel aan de eerste array toevoegen. Wanneer men aan het einde is van het tekstbestand, gaat het tekstbestand gesloten worden. foreach ( $newResourceList as $newResource ) { $newResourceArray = explode( "\t", $newResource ); $sourceNodeIDsList[] = str_replace( $newResourceArray[2] ); } }
'"',
'',
Nu gaat men elke regel uit dat tekstbestand afgaan. Elke regel die in de eerste array zat is een string. Via de explode functie gaat men elke string omvormen tot een array. Het scheidingsteken waarop gezocht zal worden is “\t” of een tab. Daarna gaat men de
47
dubbele quotes uit de tweede array vervangen door een lege string. Dit is hetzelfde als de dubbele quotes verwijderen. foreach( $sourceNodeIDsList as $sourceNodeIDs ) { $sourceNodeIDsArray = explode( ';', $sourceNodeIDs ); $articleArray = array(); Nu gaat men alle node lijsten één voor één afgaan. In de array $sourceNodeIDsArray gaat men alle nodes uit de huidige lijst ingeven met behulp van de explode functie. Men gaat ook de array $articleArray declareren. Deze array gaat alle nodes bevatten waarin deze bron voorkomt. if( count( $sourceNodeIDsArray ) > 0) { foreach( $sourceNodeIDsArray as $sourceNodeID ) { // Fetch each source $sourceNode =& eZContentObjectTreeNode::fetch( $sourceNodeID ); if( !is_null( $sourceNode ) && is_object( $sourceNode ) ) { $sourceData =& $sourceNode->dataMap(); $articleContent =& $sourceData['articles']->content(); $articleArray = array_merge( $articleArray, explode( ',', $articleContent ) ); } } } Als er nodes in de array $sourceNodeIDsArray zitten, dan gaat men deze één voor één afgaan. Voor elk van deze nodes gaat men dan de bron fetchen. Als deze bron bestaat en hij een object is, dan gaat men de datamap van deze bron ophalen. Men gaat de inhoud van het “articles” attribuut ophalen en toevoegen aan de $articleArray. // Add the article list in the first source of the array $addArticlesToSource =& eZContentObjectTreeNode::fetch( $sourceNodeIDsArray[0] ); $addArticlesToSourceData =& $addArticlesToSource->dataMap(); // set articles if( array_key_exists( 'articles', $addArticlesToSourceData ) ) { $addArticlesToSourceData['articles']->setAttribute( 'data_text' implode( ',', $articleArray ) ); $addArticlesToSourceData['articles']->store(); }
,
Omdat de eerste node ID uit de lijst de bron is waarin alle andere bronnen moeten toegevoegd worden, zal deze bron gefetched worden. Men gaat van deze bron de datamap ophalen en daarna de lijst van node ID’s van de verschillende artikels toevoegen aan het “articles” attribuut. Deze lijst wordt terug als een string ingegeven. for( $i=1; $i < count( $sourceNodeIDsArray ); $i++ ) { $node = eZContentObjectTreeNode::fetch( $sourceNodeIDsArray[$i] );
48
$object = $node->object(); $object->remove(); $object->purge(); unset( $node, $object ); } } Omdat we alleen de eerste bron uit de lijst moeten houden, mogen alle andere bronnen verwijderd worden. Nu hebben we bij elke bron de node ID’s van de artikels waarin deze bron voorkomt. Om af te sluiten dienen we de artikels aan te passen zodat de juiste bron in elk artikel zit. Dit moeten we nog doen want in de artikels zitten nog altijd in de oude bronnen. $resources = array(); $sourceContent = array(); $params = array( 'ClassFilterType' => 'include', 'ClassFilterArray' => array('resource') ); $resources =& eZContentObjectTreeNode::subTree( $params ,2 ); foreach ( $resources as $resource ) { $dataMap =& $resource->dataMap(); // Name if( array_key_exists( 'name', $dataMap ) ) { $nameAttribute =& $dataMap['name']; $nameContent =& $nameAttribute->content(); } // Articles if( array_key_exists( 'articles', $dataMap ) ) { $articleAttribute =& $dataMap['articles']; $articleContent =& $articleAttribute->content(); } $sourceHash = md5( $nameContent ); $sourceContent[$sourceHash] = array( 'name' => $nameContent, 'articles' => $articleContent ); } In de bovenstaande code gaan we alle resources ophalen. Deze resources gaan we één voor één afgaan. We gaan de naam en de lijst van de node ID’s van de artikels bewaren in variabelen. Hierna gaan we een array $sourceContent aanmaken waarin we deze variabelen gaan steken. Zo zal deze array alle bronnen bevatten, waarvan de naam moet aangepast worden, met zijn attributen. $articleNodeIDs = array(); foreach ( $sourceContent as $key => $source ) { $articleNodeIDString = $source['articles'];
49
$articleNodeIDs = explode( ',', $articleNodeIDString ); foreach ( $articleNodeIDs as $articleNodeID ) { // Fetch the article of the source that need to change $article =& eZContentObjectTreeNode::fetch( $articleNodeID ); $articleDataMap = $article->dataMap(); // Source if( array_key_exists( 'source', $articleDataMap ) ) { $sourceAttribute =& $articleDataMap['source']; $sourceContent =& $sourceAttribute->content(); // Set the new source name $articleDataMap['source']->setAttribute( $sourceContent ); $articleDataMap['source']->store();
'data_text'
,
} } } Hier gaat men elk van de bronnen in de $sourceContent array afgaan. Elk van deze bronnen heeft een lijst waarin de node ID’s van de artikels zit die moeten aangepast worden. Deze artikels gaan we dan opvragen en in een array steken. Men gaat dan de lijst van node ID’s één voor één afgaan en voor elk van deze node ID’s gaat men het artikel fetchen. Van dit artikel halen we dan de datamap op en geven we het artikel de nieuwe node ID van deze bron. Nu zijn al de bronnen in de artikels aangepast aan de nieuwe wensen. 5.4.1.3
Aanpassen van de auteurs
De auteurs van de oude news_article klasse zijn in één tekstveld ingegeven. Om een betere functionaliteit te bieden heb ik voor deze auteurs een nieuw datatype “sckauthor” geïntegreerd in de eZ publish module. Dit datatype bevindt zich in de extensie “sckauthor”. Dit datatype was al ontwikkeld door de programmeurs van het Knowledge Centre en ik heb de mogelijkheid gekregen om dit datatype te integreren in mijn webapplicatie. In dit nieuwe datatype kan men meerdere auteurs ingeven voor één artikel. Men moet voor elke auteur de voornaam, familienaam en een email adres ingeven.
Figuur 5-7 SCK-Author
Er was wel een probleem met dit datatype. Men is altijd verplicht van een voornaam, familienaam en email adres in te geven voor een auteur. Stel nu dat het artikel is uitgegeven door een nieuws provider? Omdat ik het sckauthor datatype niet mocht
50
aanpassen, heb ik ervoor geopteerd in de klasse news_article_2 een extra attribuut “news_provider” aan te maken. Hierin kan men dan deze nieuws provider ingeven. 5.4.1.4
Aanpassen van de datum
In de oude news_article klasse werden de dag, maand en jaar in een datatype Date bewaard. Bij de nieuwe webapplicatie willen we dit anders aanpakken. Om een zo groot mogelijke gebruiksvriendelijk en functionaliteit te bekomen •
Dag
De dag zal een integer veld worden. De reden hiervoor is dat 31 waarden in een dropdownlist veel te veel is. Dan is het sneller om een getal in te typen. •
Maand
De maand zal wel in een dropdownlist komen. Hiervoor gebruiken we de extensie enhancedselection2. Deze extensie is ontwikkeld door de programmeurs van het Knowledge Centre en mocht worden geïntegreerd in mijn webapplicatie.
Figuur 5-8 Enhanced Selection 2 in de admin interface
•
Jaar
Het jaar zal om en dezelfde reden als de dag in een integer veld komen. Er kunnen artikels zijn die 30 jaar oud zijn, of zelfs ouder. Dit zou een te uitgebreide dropdownlist geven. Daarom opteren we voor een tekstveld. Het overzetten van de inhoud van deze attributen is gebeurd terwijl we de news_article klasse kopieerden. Hieronder ziet u de code die hiervoor zorgde. … // get Date if( array_key_exists( 'date', $dataMap ) ) { $dateAttribute =& $dataMap['date']; $dateContent =& $dateAttribute->content();
51
} … // set Date -> day if( array_key_exists( 'day', $dataMap ) ) { $dataMap['day']->setAttribute( 'data_int', attribute( 'day' ) ); $dataMap['day']->store(); }
$dateContent->
// set Date -> month if( array_key_exists( 'month', $dataMap ) ) { $month = $dateContent->attribute( 'month' ); $monthArray = array( $month ); $dataMap['month']->setContent( $monthArray ); $dataMap['month']->store(); } // set Date -> year if( array_key_exists( 'year', $dataMap ) ) { $dataMap['year']->setAttribute( 'data_int', attribute( 'year' ) ); $dataMap['year']->store(); } …
$dateContent->
Deze code werkt volgens hetzelfde principe als de voorgaande voorbeelden. Men gaat voor elk artikel de content van het attribuut opslaan in een variabele. Deze variabele gaat men dan wegschrijven in het attribuut van de nieuwe klasse. 5.4.1.5
Aanpassen van de internal number
In de oude news_article klasse was de internal number een tekstveld met een nummer in. In de nieuwe klasse heb ik ervoor geopteerd om gebruik te maken van het sckidentifier datatype. Dit datatype bestond al en was aangemaakt door de informatici binnen het Knowledge Centre. Ik mocht van dit datatype gebruik maken. In dit datatype zat nog één klein foutje dus moesten we hierop iets verzinnen. Als men een nieuw news_artikel aanmaakt, wordt de internal number met één verhoogd en krijgt dit news_article deze nummer. Elk news_article heeft een uniek internal number. Dit is het principe dat dit datatype volgt. Er was een klein foutje met het uitdelen van deze nummer wanneer men een nieuw artikel aanmaakte, maar alvorens het gepubliceerd werd, was het mogelijk om deze bewerking te annuleren door op de discard knop te klikken. Op dat moment was er een draft aangemaakt en was de internal number met één verhoogd. Als men deze draft discard (of verwijderd) bleef deze internal number met één verhoogd. Daarom heb ik de volgende functie moeten toevoegen aan het sckidentifier datatype. … function deleteStoredObjectAttribute( &$objectAttribute, $version = null ) { $contentclass_attribute = $objectAttribute->attribute( 'contentclass_attribute' ); $classnumber = $contentclass_attribute->attribute('data_int3') - 1; $dataInt = (int)$objectAttribute->attribute( 'data_int' );
52
if ( $version === null or $version === 1 ) { if ( $classnumber == $dataInt ) { $contentclass_attribute->setAttribute( $classnumber ); $contentclass_attribute->store(); } } } …
'data_int3',
Als een object bewaard is (een draft), is deze nog niet permanent bewaard. Om een object permanent te bewaren moet men dit object publiceren. Deze functie wordt opgeroepen wanneer een bewaard object (draft) verwijderd wordt. Men gaat hier de inhoud van de internal number opvragen en met één verlagen. Deze waarde steekt men in de variabele $classnumber. Men gaat ook de huidige internal number opvragen van het object. Als er geen versie van een object is of de versie is gelijk aan één, dan gaat men controleren of deze $classnumber overeenkomt met $dataInt. Als ze gelijk zijn, dan gaan we in het huidige object de internal number vervangen met $classnumber. Deze $classnumber is de huidige internal number met één verlaagd. Nu deze wijzigingen gebeurt zijn, is de news_article_2 klasse klaar om te gebruiken in de nieuwe webapplicatie. Hieronder ziet u een overzicht van de attributen van de nieuwe news_article_2 klasse. Name
Identifier
Datatype
Options
Title
title
Text line
Required Searchable
Subtitle
subtitle
Text line
Searchable
Author(s)
author
SCK-CEN Authors
Searchable
News Provider
news_provider
Text line
Searchable
Source
source
Text line
Searchable
Day
day
Integer
Searchable
Month
month
Enhanced Selection 2
Searchable
Year
year
Integer
Searchable
Level
level
Enhanced Selection 2
Searchable
Abstract
abstract
XML block
Required Searchable
Keywords
keywords
Keywords
Required Searchable
Attachment
attachment
File
Searchable
Internal Number
internal_number
SCK-CEN Identifier
Required
53
Searchable Country
country
Country Selection
Searchable
Language
language
Enhanced Selection 2
Required Searchable
Display Externally
display_externally
Checkbox
Searchable
5.4.2
De news_folder klasse
De news_folder klasse bestond al en er moesten geen wijzigingen aan gebeuren. De news_folder klasse wordt gebruikt om de news_articles en/of andere news_folders in onder te brengen. Deze klasse bevat de volgende attributen. Name
Identifier
Datatype
Options
Name
name
Text line
Required Searchable
Description
description
Text line
Searchable
This folder can contain articles
this_folder_can_contain_articles
Checkbox
Searchable
5.4.3
De resource klasse
Deze klasse bestond nog niet en moest nog worden aangemaakt. De resource klasse is een klasse waarin alle sources zitten. Een source is de bron van een artikel. De resource klasse bevat de volgende attributen. Name
Identifier
Datatype
Options
Name
name
Text line
Required Searchable
Articles
articles
Text line
Searchable
Show as resource
show_as_resource
Checkbox
Searchable
URL
url
URL
Text
text
Text line
Searchable
54
5.4.4
De folder klasse
De folder klasse is een klasse die standaard in eZ publish zit. Deze klasse is zoals de naam al zegt een klasse van een folder. Er waren voor deze klasse geen aanpassingen nodig. De folder klasse bevat de volgende attributen. Name
Identifier
Datatype
Options
Name
name
Text line
Required Searchable
Description
description
XML block
Searchable
5.4.5
De rss_item klasse
Deze klasse was nog niet aanwezig in de oude applicatie en moest dus nog worden aangemaakt. De rss_item klasse stelt een artikel voor dat op een andere website gepubliceerd is. Deze artikels worden opgehaald via een RSS import script. Alle artikels die van een verschillende RSS feed komen, worden door de rss_item klasse voorgesteld. De rss_item klasse bevat de volgende attributen. Name
Identifier
Datatype
Options
Title
title
Text line
Required Searchable
Description
description
Text block
Required Searchable
URL
url
URL
Required
5.4.6
De rss_feed klasse
Deze klasse moest ook nog worden aangemaakt. De rss_feed klasse is bedoeld om de verschillende RSS feeds van andere websites te verzamelen. Een RSS feed bevat verschillende rss_items. De rss_feed klasse bevat de volgende attributen. Name
Identifier
Datatype
Options
Title
title
Text line
Required Searchable
Description
description
Text block
Required Searchable
55
5.5
Opbouw webapplicatie
Nu de klassen aangepast zijn om in deze webapplicatie te gebruiken, kunnen we aan de opbouw beginnen. De opbouw van deze webapplicatie gebeurt via de CSS codeer taal. Met CSS kunnen we de vormgeving van webpagina’s bepalen. De opbouw van de verschillende webpagina’s gebeurt als volgt.
Figuur 5-9 De opbouw van een webpagina
Helemaal bovenaan op de pagina heeft men de header. Hierin komt de banner van het Nuclear Press Office te staan. Onder de header bevindt zich het top-menu. In dit menu kan men navigeren tussen de verschillende delen van de webapplicatie. Onder het topmenu zien we de centrale container. Deze container bevat een linker menu, een centraal gedeelte en een rechter menu. Onder deze centrale container ziet u de footer. Deze lay-out heb ik verkregen door CSS stylesheets toe te voegen aan deze webapplicatie. Het werken met stylesheets verloopt in de meeste gevallen niet zonder problemen. De reden hiervoor is dat elke webbrowser deze CSS code anders interpreteert. Een website die bijvoorbeeld perfect werkt in Mozilla Firefox, kan totaal verkeerd getoond worden in Microsoft Internet Explorer. In deze twee webbrowsers heb ik mijn webapplicatie getest. De reden dat ik voor deze twee webbrowsers gekozen heb is omdat de meeste internet gebruikers met één van deze webbrowsers op het internet surft. De kans dat de webapplicatie goed zal getoond worden in andere webbrowsers, als deze werkt in Mozilla Firefox en Microsoft Internet Explorer, is zeer groot. Ik ben ook met een aantal problemen in aanraking gekomen. De twee grootste problemen die ik ben tegengekomen waren de peekaboo IE6 bug en de IE/WIN Guillotine bug. •
De peekaboo bug
De peekaboo bug is een bug die in Internet Explorer 6 voorkomt wanneer men gebruikt maakt van floats. Men kan deze bug makkelijk herkennen door de inhoud van de webpagina, die op een mysterieuze wijze verdwenen is. De pagina herladen blijkt niet echt te helpen. Als men op de webpagina begint te scrollen, verschijnt de inhoud ineens. Dit is wel zeer onhandig als men op een internet pagina aan het surfen is. Een oplossing voor deze bug is om aan alle elementen met de eigenschap float, een vaste breedte of hoogte toe te kennen. Zorg er ook voor dat de clearing div niet in aanraking komt met de div’s die deze floats bevatten. •
De guillotine bug
56
De guillotine bug is een bug die ook voorkomt in Internet Explorer. Deze bug komt voor wanneer men bijvoorbeeld twee div’s heeft. Een container div en een floated div die zich in de container div bevind. De volgende figuur maakt dit een beetje duidelijker.
Figuur 5-10 De guillotine bug
Als de inhoud van de floated div te groot is om in de container div te passen, gaat deze floated div zich buiten de container div begeven. Dit doet zich alleen maar voor als de floated div niet gecleared is. Als we deze lay-out in Internet Explorer gaan bekijken, zal de container div zich aanpassen aan de floated div. Maar, als men dan in de container div op een link gaat staan, wordt de floated div afgekapt. Deze bug kan opgelost worden door gebruik te maken van de zogenaamde holyhack. In een normale webbrowser is de HTML tag de hoogst mogelijke tag die men kan gebruiken. Maar Internet Explorer gelooft dat er nog een tag rond deze HTML tag zit. Hierdoor kunnen we in CSS code opgeven die Internet Explorer wel ziet staan, maar de andere webbrowsers niet. Dit noemt men de holyhack. De belangrijkste delen die lay-out voorkomen worden hieronder toegelicht. 5.5.1
Top-menu
Het menu dat zich boven het centrale gedeelte bevindt, doet dienst als navigatie. Door hier het menu item aan te klikken waar men heen wenst te gaan kan men de verschillende delen van de webapplicatie bezoeken. Deze menu is als volgt opgebouwd. {cache-block} {def $menuitems=fetch('content','list',hash( 'parent_node_id', 2, 'sort_by', array( 'priority', true() ) )) $displayitems=ezini( 'DisplayTopMenuItem', 'settopmenuitems.ini' )} {foreach $menuitems as $menuitem} {if eq( $displayitems|contains( $menuitem.name ), true() )} - {$menuitem.name|wash()}
{/if} {/foreach}
{/cache-block}
'ItemList',
57
In het top-menu van de webapplicatie gaan we de verschillende delen tonen waar de gebruiker mag heen navigeren. We gaan de verschillende menu-items fetchen. Hierna halen we de items op uit een ini-file die we gaan tonen. De items die in deze ini-file staan zullen we dus in de navigatie laten zien. Daarna gaan we deze items op het scherm tonen. 5.5.2
Linker menu
In het linker menu krijgen we een boomstructuur te zien van de news database. In deze boomstructuur krijgt de gebruiker de verschillende news_folders te zien die zich in de news database bevinden. Hij kan dan doorheen deze mappen browsen om de inhoud van deze news_folders te zien. Omdat deze boomstructuur niet op elke webpagina beschikbaar moet zijn, gaan we deze tonen aan de hand van webpagina waarop men zich bevind. De controle hierop gebeurt door middel van reguliere expressies. Een reguliere expressie is eigenlijk een tekstpatroon. De reguliere expressies die ik gebruik staan in de volgende ini-file.
Figuur 5-11 ini-file linker menu
Omdat er in eZ publish standaard nog geen functie aanwezig was waarmee men met reguliere expressies kon werken, moest ik er iets op verzinnen zodat deze functie wel beschikbaar was in de templates. In PHP is er een functie die preg_match noemt. Deze functie doet precies wat ik nodig heb. Hiervoor heb ik de extensie “regexp” aangemaakt die deze functie beschikbaar stelt in de templates. De preg_match functie wordt gebruikt om een onderwerp met een reguliere expressie te vergelijken. Als er een overeenkomst is, dan geeft deze functie de resultaten terug. Om deze preg_match functie meer universeler in gebruik te maken, heb ik de mogelijkheid ingebouwd om tussen de Preg_match en preg_match_all functies in PHP te kiezen. Deze functies doen eigenlijk hetzelfde, met de grote uitzondering dat de preg_match_all functie blijft doorzoeken terwijl als men bij de preg_match functie een match vind, deze preg_match functie stopt met zoeken. Om de keuze tussen deze twee functies aan te geven dient men gewoon een extra parameter mee te geven. Als men geen parameter meegeeft, zal standaard de preg_match functie gebruikt worden. De volgende code toont hoe dit gebeurt is. $pattern = $namedParameters['pattern']; $subject = $namedParameters['subject'];
58
$all = $namedParameters['all']; if( empty( $pattern ) || empty( $subject ) ) { $tpl->error( 'RegExpOperator::preg_match', not set.' ); return false; }
'Required
parameters
are
if( $all === true ) { $result = preg_match_all( $pattern, $subject, $matches ); } else { $result = preg_match( $pattern, $subject, $matches ); } $operatorValue = array( 'result' => $result, 'matches' => $matches ); Eerst gaat men hier de parameters, die met de functie meegegeven zijn, opvragen. De $pattern variabele bevat de reguliere expressie. De $subject variabele bevat het onderwerp dat men met de reguliere expressie wil vergelijken. De laatste variabele $all geeft aan welke van de twee preg_match functies er gebruikt moet worden. Standaard zal deze variabele op “false” staan. Eerst gaat men controleren of de $subject en de $pattern variabelen wel zijn ingegeven. Is dit niet zo, dan gaat men een foutmelding genereren en de functie afbreken. Zijn deze wel correct ingegeven, dan gaat de juiste preg_match functie uitgevoerd worden. Hierna gaat men het resultaat van deze functie in de $operatorValue steken. Deze $operatorValue wordt terug gestuurd naar waar men deze functie oproept. De code die ervoor zorgt dat het linker menu al dan niet getoond wordt, ziet er als volgt uit. {* Code to enable or disable the left menu *} {def $regexps=ezini( 'DisplayLeftMenu','SiteList','setleftmenu.ini' )} {foreach $regexps as $regexp} {def $reg=$regexp|explode( ';' ) $value1=preg_match( $reg[0], $module_result.uri )} {if $value1.result|ge(1)} {if $reg[1]|eq( 'enable' )} {set $status="no_right_column"} {/if} {break} {/if} {undef $reg $value1} {/foreach} Men gaat eerst de reguliere expressies uit de ini-file halen. Deze reguliere expressies bevatten de webpagina’s waar dit menu getoond of niet getoond mag worden. We gaan deze reguliere expressies één voor één controleren met de url van de huidige webpagina waarop men zich bevind. Als er een match gevonden in door de preg_match functie, gaan we kijken of dit menu al dan niet getoond mag worden.
59
De code van de boomstructuur zelf ga ik u besparen. Deze code is opgebouwd uit HTML, CSS en javascripts. In de admin interface van deze webapplicatie maakt men ook gebruik van een boomstructuur. Ik heb deze boomstructuur in mijn webapplicatie geintegreerd, mits de nodige aanpassingen. Deze aanpassingen waren nodig omdat de boomstructuur meerdere functies had die in mijn webapplicatie totaal overbodig zijn. In mijn webapplicatie ziet deze boomstructuur er als volgt uit.
Figuur 5-12 Boomstructuur news database
5.5.3
Rechter menu
Het rechter menu bestaat uit twee delen, namelijk de toolbar en een lijst met de tien laatst ingegeven artikels. Deze twee delen worden hieronder toegelicht. 5.5.3.1
Toolbar
De toolbar is een apart toolbox waarin de verschillende functies staan die de editor kon uitvoeren. Het spreekt voor zich dat alleen de gebruikers met de juiste rechten deze toolbar te zien krijgen. De code die hiervoor zorgt kunt u hieronder zien. {def
$roles=ezini( 'DisplayRightMenuUser', 'setrightmenu.ini' ) $userroles=$current_user.roles}
'AccessList',
{foreach $userroles as $userrole} {if and( $roles|contains( $userrole.name ), is_object( $node ) )} … {break} {/if} {/foreach} De rollen die deze toolbox te zien krijgen zijn opgenomen in een ini-file. Hierdoor kan men deze altijd wijzigen. Als eerste gaat men in deze code de rollen uit de ini-file halen en de rollen van de huidige gebruiker opvragen. Daarna gaat men deze één voor één vergelijken en als een match gevonden word, dan gaat men de toolbox tonen, anders niet. Ik ga hieronder de create functie beschrijven. Omdat de edit, delete en move functies volgens hetzelfde principe zijn opgebouwd, ga ik u deze code besparen. De die men hier ziet is in een form ingegeven. Als men op de “create” knop klikt zal dit form verzonden worden en zal men naar de webpagina “action.php” geredirect worden. Men binnen het form controleren of er een object kan aangemaakt worden. De objecten die kunnen worden aangemaakt gaat men bewaren in de array $classlist. Als er een folder aangemakt moet worden, moeten de verborgen velden NodeID en ContentNodeID in de form gezet worden. Men gaat ook nog het verborgen tekstveld ContentObjectID in de form zetten om de object ID mee te geven als parameter als de form verzonden word. Naast deze verborgen velden gaat er een dropdownlijst getoond worden met de klassen waarvan men een object kan aanmaken. De geselecteerde klasse zal ook als parameter meegegeven worden als het formulier verzonden word. De volgende figuur is een mogelijkheid van hoe de toolbar er kan uitzien.
61
Figuur 5-13 Toolbar
5.5.3.2
Lijst van de laatst gepubliceerde artikels
Deze toolbox zorgt ervoor dat elke gebruiker die de webapplicatie bezoekt een overzicht krijgt van de (in dit geval) tien laatst gepubliceerde artikels. De code die hiervoor zorgt is als volgt. Men gaat het typische oranje RSS icoontje te zien krijgen dat men in vele webapplicaties gebruikt word. Wat RSS feeds juist zijn gaan we straks bekijken. Als men op dit icoontje klikt, wordt men doorverwezen naar een andere siteaccess waar de RSS feeds zich bevinden. De reden dat ik deze RSS feeds op een andere siteaccess ga
62
tonen zijn de rechten. Om deze RSS feeds gewoon te bekijken was het niet nodig om deze op een andere siteaccess te tonen. Als men deze RSS feeds met een RSS reader gaat lezen, kon men de RSS feeds niet bekijken. Een RSS reader is een softwaretoepassing waar men de locatie van de RSS feeds van verschillende webapplicaties kan ingeven. De RSS reader gaat de RSS feeds dan ophalen bij deze webapplicatie. Omdat we in de siteaccess waar mijn webapplicatie zich bevind gebruik maken van NTLM authenticatie voor de gebruikers, kan deze RSS reader de RSS feeds niet ophalen. Daarom heb ik een andere siteaccess aangemaakt zonder NTLM authenticatie om deze RSS feeds te tonen. De volgende schermafdruk toont de RSS Feeds op deze siteaccess.
Figuur 5-14 RSS Feeds
Het NTLM (Windows NT Lan Manager) protocol zorgt ervoor dat de gebruikers binnen het bedrijf automatisch aangemeld worden met de persoonlijke gegevens waar men zich op iedere computer binnen het bedrijf kan aanmelden. Omdat we NTLM authenticatie gebruiken, moet de gebruiker niet telkens aanmelden als hij de webapplicatie wilt bezoeken. De lijst van de tien laatst gepubliceerde artikels zal er als volgt uitzien.
63
Figuur 5-15 Lijst met de laatst gepubliceerde artikels
5.5.4
Centraal gedeelte
In het centrale gedeelte gaan we de verschillende templates tonen. Welke templates we gaan tonen hangt af van in welk deel van de webapplicatie men zich bevind. Standaard zijn er al templates voor deze delen van de webapplicatie beschikbaar, maar omdat deze niet echt gebruiksvriendelijk zijn, gaan we zelf templates definiëren en deze in de plaats van deze standaard templates tonen. We maken hierbij gebruik van het override systeem.
5.6
De webpagina’s
In dit laatste deel gaan we de webpagina’s zelf eens bekijken. Ik ga hier aan de hand van schermafdrukken duidelijk maken hoe deze webapplicatie in mekaar zit. 5.6.1
Home pagina
De Home pagina is de eerst webpagina waar de bezoeker terecht komt als hij de webapplicatie bezoekt.
64
Figuur 5-16 Home pagina
Op deze webpagina bevindt zich een welkomsttekst. De toolbar aan de rechterzijde is hier zichtbaar omdat ik als editor ben aangemeld toen ik deze schermafdruk nam. Onderaan ziet men de verschillende RSS Feeds die afkomstig zijn van andere websites. RSS is de afkorting van Really Simple Syndication. RSS bestanden (of RSS Feeds) worden gebruikt gegevens van een website in een ander formaat te zetten zodat andere websites deze gegevens automatisch in hun omgeving kunnen tonen. Men kan ook de RSS Feeds van een website op die website zelf gaan bekijken. Dit kan men doen door naar de webpagina met de RSS Feeds op te browsen of met een RSS lezer. Er zijn vele RSS lezers verkrijgbaar op het internet, voor sommigen moet men betalen en voor anderen niet. Hieronder staat de code die ervoor zorgt dat ik deze RSS Feeds op het scherm te zien. We gaan hier eerst alle RSS Feeds ophalen die zich in de Feed folder bevinden. Daarna gaan we voor elk van deze Feeds de vijf recentste RSS items ophalen en deze in een tabel tonen. De naam van de RSS items zal maximaal 25 karakters lang zijn op het scherm. Hiervoor zorgt de functie shorten. Deze zal de langere namen afkappen en “…” op het einde plaatsen. 5.6.2
News database
De news database is het gedeelte van de webapplicatie waarin alle news folders en de news artikels zich bevinden. Men kan hier ook news folders en news artikels aanmaken, wijzigen, … De volgende schermafdruk toont ons hoe deze news database eruit ziet.
66
Figuur 5-17 News database
Zoals u kunt zien krijgt men in dit gedeelte van de webapplicatie het linker menu te zien. Hierin kan de gebruiker door de news folders heen navigeren. Als men op een news folder klikt krijgt men de inhoud te zien in het centrale gedeelte. Dit kunnen zowel andere news folders zijn als news artikels. Men gaat deze news folders en news artikels eerst fetchen en daarna op het scherm tonen. Als er geen news articles in de news folder zitten, dan krijgt men hier ook een melding van. Er kunnen natuurlijk alleen maar news artikels zitten in de news folder waarvan het attribuut “this_folder_can_contain_articles” op true staat. Als men op een news artikel klikt, krijgt men een detailview van dit news artikel. Dit kunt u zien in de volgende schermafdruk.
67
Figuur 5-18 News article
In het detailview van een news artikel krijgt u de verschillende attributen van dit artikel te zien. Het email adres van de auteur is niet zomaar in tekstvorm weergegeven in deze lijst van attributen. Ik heb van deze email eerst een afbeelding gemaakt en deze daarna ingevoegd. De reden hiervoor is dat er programma’s zijn die het internet afzoeken naar email adressen. Deze programma’s kunnen dit emailadres dan voor slechte doeleinden gebruiken of gewoon spam mails sturen naar dit emailadres. Als het emailadres omgevormd is in een afbeelding, dan zien deze programma’s het emailadres niet. Onder deze attributen krijgt men ook nog een overzicht met de verschillende locaties. Dit overzicht ziet er als volgt uit.
Figuur 5-19 Locaties van een news article
Deze locaties zijn opgebouwd uit de verschillende mappen waarin dit news article zich bevind. Men kan op elk deel van deze locatie klikken. Als men bijvoorbeeld op een map klikt, dan gaat men naar de overzichtspagina van deze map. Dit locatie overzicht is op de volgende manier opgebouwd.
{foreach $node.object.assigned_nodes as $assignedNode sequence array( 'bglight', 'bgdark' ) as $sequence}
68
{def $path_string=$assignedNode.path_string|explode( '/' ) $path_id_string=$assignedNode.path_identification_string| explode( '/' ) $path_string_help=array()} {foreach $path_string|extract( 3 ) as $key => $item} {if ne( $key|sum(1), count( $path_string|extract(3) ) )} {set $path_string_help = $path_string_help|append( $item )} {/if} {/foreach} {foreach $path_string_help as $key => $item} {delimiter}
)|ezurl}>
alt=""
/>
{undef $path_string $path_id_string $path_string_help} |
{/foreach}
We gaan eerst alle assigned_nodes ophalen van het object. Dit zijn de locaties waar het news artikel zich bevind. Voor elke locatie gaan we twee attributen ophalen, de “path_string” en de “path_identification_string”. De “path_string” is de locatie van die artikel, aangegeven met de node_id’s. De “path_identification_string” is de locatie van dit artikel, aangegeven met de namen van de folders waarin het zich bevind. Deze variabelen gaan we gebruiken om de locatie op het scherm te tonen. We gaan de verschillende delen van deze twee variabelen in een array stoppen. Omdat deze twee arrays niet evenveel attributen bevatten moeten we dit even aanpassen. De “path_string” bepaalde de locatie vanaf de root folder, terwijl de “path_identification_string” dit niet zo deed. Als we deze arrays even groot hebben gemaakt, is het een koud kunstje om deze op het scherm te laten zien. Men kan in de news database ook news artikels of news folders editeren met behulp van de toolbar. Het is logisch dat alleen de personen met de juiste rechten dit kan. Als men een news artikel wil editeren, komt men op het volgende scherm terecht.
69
Figuur 5-20 Edit news article (1)
Figuur 5-21 Edit news article (2)
Op deze edit pagina krijgt men alle attributen te zien die in het news artikel waren ingegeven. Bovenaan krijgt men een lijst van alle locaties van dit artikel. Men kan hier een nieuwe locatie toevoegen of verwijderen. Er is ook de optie om de main node te bepalen. Daaronder krijgt men alle invoervelden van het artikel te zien. De twee
70
invoervelden die het meest opvallen zijn de invoervelden van de auteur(s) en het abstract. Bij de auteur kan men één of meerdere auteurs ingeven. Men moet gewoon de velden van de voornaam, familienaam en email juist invullen. Als men daarna op “Add Author” klikt komt de auteur bij in de lijst te staan. Men kan een auteur ook uit deze lijst verwijderen als men dat wil. Boven het invoerveld van het abstract ziet men een hele menubalk. Door deze menubalk kan men de opmaak van de tekst die in het tekstveld staat makkelijk aanpassen. Er is ook een optie om deze menubalk uit te schakelen. De oorzaak van dit opmaakmenu is de module ezdhtml. Deze module zet het opmaakmenu rond alle invoervelden waarvan het attribuut een XML Block is. Deze module mag men niet zomaar integreren in een webapplicatie. De informatici van het Knowledge Centre hebben deze module niet zelf ontwikkeld. Om deze module te mogen gebruiken hebben zij hier een licentie voor aangevraagd. De kosten aan werkuren die ze erin zouden steken om een module als deze te ontwerpen zouden toch hoger liggen dan de licentie zelf. Daarom heeft men geopteerd om deze licentie aan te vragen. Als men de wijzigingen heeft aangebracht aan dit artikel, dan moet men alleen maar op “Store” klikken. Het bestand zal dan gepubliceerd worden. Als men verplicht invoerveld vergeet in te vullen of een verkeerde waarde in een invoerveld ingeeft, zal men een foutmelding krijgen. Men kan ook een news article of een news folder aanmaken. Hiervoor moet men in de toolbar eerst het juiste item selecteren in de dropdownlist. Als men op de “create” knop klikt in de toolbar komt men op het volgende scherm terecht.
Figuur 5-22 Create news article
Hier moet men de locatie van het nieuwe news article aanduiden. Dit gebeurt door in de boomstructuur op de juiste folder te klikken. Het news article zal dan in deze folder geplaatst worden als het gepubliceerd word. Het aanmaken van een news folder gebeurt ook op deze wijze. Men zal hier ook eerst een locatie moeten aanduiden om daarna naar de pagina te gaan waar men de attributen kan ingeven. Deze pagina is ook de pagina waar men terecht komt als men aan news article of een news folder wilt
71
editeren, alleen zijn hier nog geen attributen ingevuld (zie figuur 5-19 en 5-20 edit news article, in geval van een news artikel). In de news database zit ook een zoekfunctie ingebouwd. Hiermee kan men naar artikels gaan zoeken. De volgende schermafdruk toont deze zoekfunctie.
Figuur 5-23 Zoekfunctie
De zoekcriteria waarop men kan gaan zoeken zijn de titel, de source, de auteur, en keywords van een artikel. De resultaten van de zoekopdracht zullen weergegeven worden in een lijst onder de zoekcriteria. Als men op één van deze artikels klikt, wordt men automatisch naar de detailpagina van dit artikel doorverwezen. 5.6.3
Links
In het Links gedeelte van de webapplicatie zitten alle bronnen verzameld.
72
Figuur 5-24 Links
De bronnen zijn onderverdeeld in verschillende categorieën. Dit gedeelte bevat ook de functionaliteiten voor het aanmaken, editeren en verwijderen van een bron. Als men een bron wil aanmaken, moet men ook eerst de locatie van deze nieuwe bron bepalen. Pas daarna krijgt men het scherm te zien waar men de attributen kan gaan ingeven.
73
BESLUIT De opbouw van een webapplicatie kan op verschillende manieren gebeuren. Nu dat ik kennis gemaakt heb met een Content Management Systeem kan ik geen betere manier bedenken om een webapplicatie op te bouwen. De mogelijkheden dat zo een systeem, zoals eZ publish heeft is enorm. Ik ben me ervan bewust dat ik op deze korte tijdspanne dat ik stage heb gedaan, ik maar een klein deel van deze mogelijkheden heb gebruikt om mijn eindwerk uit te voeren. Omdat ik maar drie maanden de tijd heb gekregen om deze webapplicatie te ontwikkelen, is deze niet helemaal af geraakt. Men zal deze in de toekomst nog verder ontwikkelen en misschien zelfs verbeteringen aanbrengen. Ik heb tijdens mijn stage enorm veel bijgeleerd, niet alleen de nieuwe programmeertalen, maar ook over hoe het er in een groot bedrijf aan toe gaat. Het was zeker een positieve ervaring om in het SCK•CEN stage te mogen doen.
74
LITERATUURLIJST VERWIMP, L. en VERLEDENS, A., 2002. 1952-2002 SCK•CEN studiecentrum voor kernenergie Centre d’Etude de L’Energie Nucléaire. 57 p. CONVERSE T., PARK J., 2000. PHP 4, het complete handbook. 1e druk, Schoonhoven, Academic Service, 625 p. BORGERMANS P., WOOD, T., FORSYTH, P., BAUER, M., DIEDING, B., PIRT, B., 2004. Learning eZ publish 3. Building Content Management Solutions, Packt publishing, 372 p. MOULDING, P., 2000. PHP, the black book, 1e druk, New York, Coriolis group, 880 p. SCK•CEN, 1999. Klaar voor de 21ste eeuw. 32 p. The Apache Software Foundation, 1999. http://www.apache.org/ The PHP Group, 2001. http://www.php.net/ SVN, 2005. Subversion Project Home. http://subversion.tigris.org/ TortoiseSVN. 2005. A Subversion client for Windows. http://tortoisesvn.tigris.org/ MySQL, 1995. http://www.mysql.com Position is everything, 2002. http://www.positioniseverything.net Content management System eZ publish (Open Source CMS) , 2006. http://ez.no/ MijnHomepage.nl – Het startpunt voor webmasters, 2000. http://www.mijnhomepage.nl/