Handelswetenschappen en Bedrijfskunde Geel Bachelor in de Toegepaste Informatica Business Information Management
Uitbreiding leerplatform in Drupal 7
CAMPUS Geel
Joey Lemmens
Academiejaar 2011-2012
Voorwoord ‘Uitbreiding leerplatform in Drupal 7’ is bedoeld voor mensen die meer te weten willen komen over het project Dutch++ en het leerplatform dat hiervoor in Drupal werd ontworpen. Uiteraard is dit eindwerk ook bedoeld voor geïnteresseerden in IT. Dit eindwerk heb ik geschreven tijdens de eindfase van mijn opleiding hoger onderwijs. Het onderwerp hangt nauw samen met mijn buitenlandse stage aan de universiteit van Wenen. Graag wil ik enkele mensen bedanken die mij de voorbije drie maanden geholpen hebben. Prof. Dr. Van Uffelen, de verantwoordelijke van het Dutch++ project aan de Weense universiteit en assistente Dr. Vogl, de verantwoordelijke voor de inhoud van het project. Voor al mijn informaticavragen kon ik steeds terecht bij Mevr. De Llano, de ITverantwoordelijke. Mevr. Spruyt, docente aan de K.H. Kempen, heeft mij met raad en daad bijgestaan voor de vormgeving en inhoud van dit eindwerk.
Samenvatting Voor het project Dutch++ dat gaat over het opzetten van een online leerplatform voor studenten die meer over Nederlands te weten willen komen, heb ik samen met mijn collega, Dieter Verbeemen in Drupal een module ontwikkeld. Deze module kan cursussen en oefeningen afkomstig van een ander leerplatform, namelijk OLAT importeren. Daarna kunnen docenten de oefeningen extra functionaliteiten geven wat in het bestaande leerplatform niet mogelijk is. Het gaat om oefeningen met drag-and-drop mogelijkheden, oefeningen waar je een bepaald deel van een woord moet kunnen selecteren en oefeningen waar je een video- of audiofragment moet kunnen pauzeren op een bepaalde locatie. Studenten kunnen vervolgens de oefeningen maken en kunnen zichzelf evalueren aan de hand van ingebouwde feedbackmogelijkheden. Zo kan de student onmiddellijk het antwoord tonen, het geselecteerde antwoord laten valideren op correctheid of de hele oefening indienen waarna hij zijn antwoorden en de oplossing ziet. Uiteraard is het aan de docent te bepalen welke feedbackmogelijkheden per oefeningen beschikbaar worden gesteld. Het project Dutch++ is een driejarig project en het maken van de module is slechts de eerste fase. Het is nu aan de partnerinstituten om de oefeningen in het OLAT-systeem te maken en vervolgens allemaal te importeren in de Drupalwebsite. Daarna is het aan de docenten om de oefeningen extra functionaliteiten te geven en uiteindelijk kan heel de wereld Nederlands leren dankzij onze inbreng in het Dutch++ project.
Inhoudsopgave Voorwoord .............................................................................................................................. 2 Samenvatting .......................................................................................................................... 3 Inhoudsopgave ....................................................................................................................... 4 Lijst van figuren ..................................................................................................................... 6 Lijst van gebruikte afkortingen ............................................................................................ 7 Inleiding .................................................................................................................................. 8 1
Stageomgeving ......................................................................................................... 9
1.1 1.2 1.2
Universiteit van Wenen ............................................................................................. 9 Neerlandistiek ......................................................................................................... 10 Contactpersoon........................................................................................................ 10
2
Stageopdracht ........................................................................................................ 11
2.1 2.2 2.3 2.4 2.5
Project Dutch++ ...................................................................................................... 11 Probleemstelling...................................................................................................... 11 Opdracht .................................................................................................................. 12 Verwacht resultaat................................................................................................... 12 Fasering ................................................................................................................... 13
3
Opzetten server ..................................................................................................... 14
3.1 3.2 3.2.1 3.2.2 3.2.3 3.2.4
Virtualisatie met VirtualBox ................................................................................... 14 Configuratie Ubuntu Server .................................................................................... 14 SSH ......................................................................................................................... 14 Tomcat .................................................................................................................... 15 OLAT ...................................................................................................................... 16 Xdebug, de debugger .............................................................................................. 17
4
QTI ......................................................................................................................... 19
4.1 4.2 4.3 4.3.1 4.3.1.1
XML ........................................................................................................................ 19 Structuur in XML .................................................................................................... 19 QTI Object Parser ................................................................................................... 21 De broncode ............................................................................................................ 21 Klassen en objecten ............................................................................................. 23
5
Drupal .................................................................................................................... 27
5.1 5.2 5.2.1 5.3 5.4 5.4.1 5.4.2
Voor- en tegenstanders............................................................................................ 27 Modulair programmeren ......................................................................................... 29 Hooks ...................................................................................................................... 29 Databaseontwerp ..................................................................................................... 30 Module .................................................................................................................... 30 hook_permission() .................................................................................................. 32 hook_menu() ........................................................................................................... 33
5.4.3 5.4.4
hook_form() ............................................................................................................ 33 Aanspreking database ............................................................................................. 34
6
Drupal in actie ....................................................................................................... 35
6.1 6.2 6.3 6.3.1 6.4 6.4.1 6.4.2 6.4.3 6.5 6.6 6.6.1 6.6.2 6.6.3
Permissies en rollen ................................................................................................ 35 Uploadfomulier ....................................................................................................... 35 Oefeningen overzichtslijst....................................................................................... 36 jQuery Ajax library ................................................................................................. 36 Oefeningen .............................................................................................................. 37 Single Choice Questions ......................................................................................... 38 Multiple Choice Questions...................................................................................... 38 Fill in the Blanks ..................................................................................................... 39 Statistieken .............................................................................................................. 40 Moeilijkheden ......................................................................................................... 40 Omgaan met video en audio.................................................................................... 40 Uploaden meerdere bestanden ................................................................................ 41 Ondersteunen drag-and-drop................................................................................... 41
Besluit.................................................................................................................................... 43 Literatuurlijst ....................................................................................................................... 44 Lijst van de bijlagen ............................................................................................................ 45 Bijlage 1 – Organigram universiteit Wenen Bijlage 2 – Fasering Bijlage 3 – QTI Klassendiagram Bijlage 4 – Handleiding
Lijst van figuren Figuur 1-1 Hoofdgebouw universiteit Wenen ......................................................................... 9 Figuur 3-1 CLI van PuTTY ................................................................................................... 15 Figuur 3-2 GUI van WinSCP ................................................................................................ 15 Figuur 3-3 OLAT draaiende op Tomcat ................................................................................ 17 Figuur 3-4 Variabelen in Netbeans met behulp van Xbugger ............................................... 18 Figuur 4-1 Fill in Blanks (FIB) oefening in OLAT ............................................................... 21 Figuur 4-2 KPRIM oefening in OLAT .................................................................................. 21 Figuur 4-3 Klassendiagram QTI object parser ...................................................................... 24 Figuur 4-4 Intellisense in Netbeans ....................................................................................... 26 Figuur 5-1 Commentaarlijnen in het entity.inc bestand ........................................................ 28 Figuur 5-2 Commentaarlijnen in het common.inc bestand ................................................... 28 Figuur 5-3 Mappenstructuur van Drupal ............................................................................... 29 Figuur 5-4 Relationeel datamodel Drupal ............................................................................. 30 Figuur 5-5 Visuele weergave van permissies in Drupal ........................................................ 32 Figuur 5-6 Uploadformulier .................................................................................................. 34 Figuur 6-1 Uploadformulier met opties ................................................................................. 35 Figuur 6-2 jQuery Datatable plug-in ..................................................................................... 36 Figuur 6-3 Details van de oefening ....................................................................................... 37 Figuur 6-4 Single choice question in Drupal ......................................................................... 38 Figuur 6-5 Multiple choice question foutief ingevuld door student ...................................... 39 Figuur 6-6 Fill in blanks oefening getransformeerd naar Drag&Drop .................................. 39 Figuur 6-7 Statistiekenoverzicht ............................................................................................ 40 Figuur 6-8 Basisfunctionaliteit drag-and-drop ...................................................................... 41 Figuur 6-9 Uitgebreide functionaliteit drag-and-drop ........................................................... 42
Lijst van gebruikte afkortingen AJAX
Asynchronous JavaScript And XML
API
Application Programming Interface
CLI
Command-line Interface
CMS
Content Management System
GUI
Graphical User Interface
HTML
HyperText Markup Language
IDE
Integrated Development Environment
IP
Internet Protocol
MD5
Message Digest Algorithm 5
OLAT
Online Learning And Training
PHP
Hypertext Preprocessor
QTI
Question and Test Interoperability
SQL
Structured Query Language
SSH
Secure Shell
URL
Uniform Resource Locator
W3C
World Wide Web Consortium
WAR
Web Application Archive
XML
Extensible Markup Language
Inleiding
8
Inleiding Vanaf maart tot mei 2012, was mijn verblijfplaats Wenen: ‘the City of Music’. Deze bijnaam heeft de stad te danken aan de verschillende componisten die hier hebben verbleven. Geen muziekopleiding voor mij tijdens deze drie maanden, wel een IT-stage aan de universiteit van Wenen waar mijn collega, Dieter Verbeemen, en ik een programma hebben ontwikkeld in Drupal. Drupal is hier in het leven geroepen om twee verschillende softwaresystemen te integreren in één handig te gebruiken ‘softwaresysteem’ voor de eindgebruiker. De bedoeling van dit eindwerk is meer informatie te geven over onze opdracht, over het project, Dutch++ waaraan die opdracht gekoppeld is en over de manier waarop we tot het eindresultaat gekomen zijn. In dit eindwerk kom je eerst meer te weten over de stageomgeving om heel de stageopdracht te kunnen kaderen. Daarna wordt de stageopdracht besproken. Je krijgt meer informatie over de probleemstelling en het beoogde resultaat zodat dit te vergelijken is met het uiteindelijke resultaat. Vervolgens worden de meer technische aspecten besproken zoals het opzetten van de ontwikkelomgeving. Hier wordt besproken hoe dit werd gedaan en welke moeilijkheden er waren. De informatiebron, een QTI-bestand, is een belangrijk aspect in dit eindwerk en het is essentieel om weten wat het is en hoe het gebruikt wordt. Verder kom je ook meer te weten over het softwaresysteem Drupal en of dit een nuttig systeem is. Ten slotte zie je ook het eindresultaat. Vaak wordt het geheel geïllustreerd met stukjes code om alles begrijpelijker te maken.
1 Stageomgeving
1
9
Stageomgeving
In het academiejaar 2011 – 2012 heb ik samen met Dieter Verbeemen stage gelopen aan de universiteit van Wenen, meer specifiek op het departement Nederlandse Taal. Weinig studenten vangen een stage aan in het buitenland, maar ik zag het als een opportuniteit om dát tikkeltje meer ervaring te krijgen. Niet alleen leer je om even zelfstandig op je benen te staan, je leert ook omgaan met vreemde culturen. Waarom ik gekozen heb voor Wenen? Omdat ik op voorhand geen idee had welke stageopdracht ik kon verwachten, moest ik mijn keuze baseren op de stad. Ik kon kiezen tussen Jimma en Mekele (Ethiopië), Halmstad (Zweden), Lissabon (Portugal) en Wenen (Oostenrijk). De keuze was voor mij zeer snel gemaakt omdat Wenen heel veel te bieden heeft. Het is een wereldstad waar elke dag iets te beleven valt en daarbij biedt ze een grote schat aan cultureel erfgoed. Een goed voorbeeld hiervan is wellicht de universiteit van Wenen.
1.1
Universiteit van Wenen
De universiteit van Wenen is gesticht door hertog Rudolph IV in 1365. Rudolph leefde van 1339 tot 1365. In deze korte tijdspanne heeft hij veel opgericht, vandaar zijn bijnaam, ‘der Stifter’ (Duits voor de stichter). In zijn hebzucht om te concurreren met zijn machtige schoonvader, die immers het Koninkrijk Bohemen met zijn hoofdstad Praag tot een cultureel middelpunt van Centraal-Europa maakte, wilde hij Wenen op de kaart zetten. Zo gaf hij de opdracht om het Stephansdom te bouwen en in 1365 de Weense universiteit. Tot nog toe is deze universiteit de oudste in het Duitstalige gedeelte van de wereld en één van de grootste in Centraal-Europa. Momenteel zijn er ca. 91 000 studenten ingeschreven in 188 verschillende opleidingen waarvan 4 vooropleidingen, 56 bacheloropleidingen, 117 masteropleidingen en 11 doctoraatsopleidingen. Naast het grote aantal studenten zijn er nog 9 400 personeelsleden waarvan 6 700 academici. De academische instellingen van de universiteit zijn over meer dan zestig locaties doorheen de stad verspreid. Het hoofdgebouw bevindt zich op de Dokter-Karl-Lueger-Ring, een straat die deel uitmaakt van de Ringstraße, een cirkelvormige boulevard rond het centrum van Wenen. Op Figuur 1-1 zie je een foto van dit hoofdgebouw.
Figuur 1-1 Hoofdgebouw universiteit Wenen
In dit gebouw zetelt het management en bevinden zich de bibliotheek, enkele administratieve diensten en sommige departementen waaronder het departement van de Nederlandse Taal. Dit departement behoort tot de Faculteit van Filologische en Culturele Uitbreiding leerplatform in Drupal 7
1 Stageomgeving
10
Studies. In Bijlage 1 – Organigram universiteit Wenen vind je een organigram waarin de structuur van de universiteit verduidelijkt wordt.
1.2
Neerlandistiek
Vanaf 1992 kunnen studenten de optie ‘Nederlandistik’ studeren in combinatie met een andere studierichting. Vanaf 1997 kunnen studenten deze optie als hoofdvak nemen en sinds het academiejaar 2008 – 2009 is het een volwaardige opleiding met zelfs een masteropleiding. Het lessenpakket omvat naast taalverwerving en taalbeheersing, ook literatuur-, taal- en cultuurwetenschappen. Studenten die afstuderen spelen een belangrijke rol als culturele bemiddelaars1 tussen Duits- en Nederlandstalige gebieden. Ze vinden vaak werk in de culturele en wetenschappelijke sector of kunnen aan de slag als vertaler-tolk. Momenteel studeren zo’n 250-tal studenten deze opleiding.
1.2
Contactpersoon
Aan het hoofd van het project Dutch++, zie hoofdstuk 2.1, staat Prof. Dr. Herbert Van Uffelen. Hij was eigenlijk onze opdrachtgever en we moesten hem wekelijks op de hoogte houden. Wij werkten het meest samen met Elisa De Llano, de IT-verantwoordelijke op het departement Neerlandistiek. Elisa is afkomstig uit Spanje en studeert haar Master Fysica op de universiteit van Wenen. In haar vrije tijd is ze veel bezig met Linux en webdevelopment in PHP.
1
Dit zijn mensen die vertrouwd zijn met het internationale artistieke landschap en met de vereisten van een hedendaagse creatie (De Coster).
Uitbreiding leerplatform in Drupal 7
2 Stageopdracht
2
11
Stageopdracht
Om inzicht te krijgen in onze stageopdracht is het belangrijk om de oorsprong en de probleemstelling hiervan te kennen. Deze zaken worden in dit hoofdstuk besproken.
2.1
Project Dutch++
Dutch++ is een project opgestart door de universiteit van Wenen onder leiding van Prof. Dr. Herbert Van Uffelen. Aan dit project nemen nog vier andere instituten deel waaronder de Universiteit van Tilburg, het Instituut voor de Opleiding van Leraren in Paramaribo, de Vrije Universiteit Berlijn en de Katholieke Hogeschool Kempen. Het doel van dit project is om een online leerplatform op te starten dat de naam Dutch++ meekrijgt. Studenten van de opleiding Neerlandistiek worden via dit platform beter ondersteund in het vergaren van kennis die ze nodig hebben om hun Nederlands bij te schaven. Het platform zal enerzijds informatie en anderzijds oefeningen aanbieden. De oefeningen bestaan uit materiaal afkomstig van Nederlandstalige tekstboeken voor het aanreiken van algemene woordenschat, maar er komen ook oefeningen die zich concentreren op de verschillende varianten van het Nederlands gesproken in Vlaanderen, Nederland en Suriname. De oefeningen zullen vooral worden aangeleverd door de universiteit van Tilburg. Het platform zal ook een online gids van de Nederlandse varianten beschikbaar stellen die zeer nuttig zal zijn voor studenten maar ook voor docenten. Dutch++ zal dus niet alleen gebruikt worden door studenten maar ook door docenten. Zij kunnen dit gebruiken als bijkomend leermateriaal in de lessen of het aanbieden voor zelfstudie. Het platform is tevens gebouwd met het oog op een makkelijke uitbreiding voor andere talen. Het platform zal worden ontwikkeld door experts op het gebied van didactiek, taalkunde en informatica. Het hele project zou binnen drie jaar of tegen 2015 afgerond moeten zijn.
2.2 Probleemstelling OLAT de afkorting voor Online Learning And Training is het online leerplatform op de universiteit. Het softwaresysteem werd niet ontwikkeld door de Weense universiteit maar door de universiteit van Zurich. OLAT is een zeer uitgebreid systeem waarin je cursussen kan aanmaken die algemene informatie kunnen bevatten, maar ook oefeningen of examens, fora, blogs, agenda’s of wiki’s. Daarnaast biedt OLAT ook nog uitgebreide ondersteuning voor accountbeheer, de mogelijkheid om bestanden te delen of zelfs te chatten. Wereldwijd hebben al meer dan 150 scholen OLAT in gebruik genomen als online leerplatform. Het grote voordeel naast de vele taalinstellingen is dat OLAT volledig gratis is en het weinig resources inneemt waardoor je al met een kleine server veel gebruikers kan ondersteunen. Enkele nadelen zijn dan weer dat je enorm veel moet klikken om bijvoorbeeld een oefening te creëren, dat je vreemde vertalingen in het systeem vindt en dat er soms een onlogische gebruikersinterface is. Op het OLAT-systeem in Wenen staat al een heleboel informatie opgeslagen waaronder lesmateriaal, oefeningen, testen, etc. Maar OLAT mist het attractieve en vooral vanuit gebruikersstandpunt het interactieve aspect. Daarom werd er een website in Drupal gemaakt waarin links staan die naar het OLAT-systeem verwijzen. De student moet dan vaak twee Uitbreiding leerplatform in Drupal 7
2 Stageopdracht
12
keer inloggen: de eerste keer op de Drupalwebsite en de tweede keer op OLAT. Dit wil men vermijden door toegang te verlenen door enkel in te loggen op de Drupalwebsite. Hiervoor wordt wel een nieuwe Drupalwebsite gecreëerd die de naam Dutch++ meekrijgt. Dit is meteen de start van het Dutch++ project. Alle cursussen en oefeningen uit OLAT worden in Drupal geüpload en gepresenteerd naar de eindgebruiker. De oefeningen uit OLAT kunnen in Drupal nog extra functionaliteiten krijgen zoals drag-and-drop ondersteuning, selectieoefeningen en oefeningen met video en audio.
2.3 Opdracht Onze opdracht bestaat eigenlijk uit drie grote delen die Dieter en ik hebben verdeeld onder elkaar. Het eerste deel bestaat erin om oefeningen die in OLAT zijn geschreven, over te brengen en te tonen in Drupal. Deze oefeningen zijn opgebouwd via de QTI-standaard of Question and Test Interoperability. Deze standaard wordt ook gebruikt bij veel andere leerplatformen zoals Blackboard of Moodle wanneer het gaat over het opslaan en delen van oefeningen. Omdat Drupal nog geen functionaliteit heeft om deze QTI-bestanden te importeren, moet dit worden ontwikkeld. Hoofdstuk 4, QTI, geeft meer informatie over dit bestandstype. Voor het tweede deel van de opdracht is het de bedoeling om de cursusinformatie gemaakt in OLAT ook over te brengen naar de Drupalwebsite. De cursusinformatie bestaat voornamelijk uit HTML-bestanden en enkele XML-bestanden. Ten slotte moeten in Drupal de oefeningen uit OLAT interactiever worden. Onder interactieve oefeningen verstaat men drag-and-drop mogelijkheden, geluids- en videofragmenten, etc. Dit is in OLAT niet mogelijk en dit kan opgelost worden door deze functionaliteiten aan Drupal toe te voegen. Ik heb het eerste deel voor mijn rekening genomen en Dieter het tweede deel. Aan het derde deel hebben we samengewerkt omdat er veel nieuwe functionaliteiten in Drupal kunnen worden toegevoegd.
2.4 Verwacht resultaat Het is natuurlijk onze intentie om een zo goed mogelijk programma op te leveren zonder systeemfouten. De gebruikersinterface moet zeer eenvoudig zijn zodat men het gewenste resultaat op de snelste manier kan bereiken zonder te veel schermen gepresenteerd te krijgen. Verder moet het systeem ook flexibel zijn, zo zal er een uploadfunctionaliteit nodig zijn om cursussen op te laden. We willen hier het de gebruiker zo aangenaam mogelijk maken dus willen we het uploaden van meerdere bestanden in één keer ondersteunen. Een andere functionaliteit die het comfort van de gebruiker moet verhogen is bij het uploaden opties onmiddellijk te kunnen instellen zoals het nog niet publiceren van de cursus of oefeningen. Studenten die de oefeningen gaan maken zullen enkele uren in het systeem doorbrengen. Daarom willen we er ook voor zorgen dat het voor hen aangenaam wordt, door de oefeningen er goed te laten uitzien en goede functionaliteiten in te bouwen voor zelfevaluatie en feedback.
Uitbreiding leerplatform in Drupal 7
2 Stageopdracht
2.5
13
Fasering
In het begin kregen we telkens een deel van de opdracht via de IT-verantwoordelijke. Daarom hebben we nooit een volledige planning op voorhand kunnen opstellen, dus hebben we telkens kleine deelplanningen opgesteld, die we aanvulde op een grote planning die je kan vinden in Bijlage 2 – Fasering. Het was pas vanaf april dat we een volledige planning konden maken omdat we dan precies wisten wat we moesten doen. Er werden wekelijks of tweewekelijks kleine vergaderingen gehouden waar het geleverde werk werd geëvalueerd. Op deze vergaderingen kwamen we vaak nog extra eisen te weten omdat het Dutch++ project nog in zijn kinderschoenen stond.
Uitbreiding leerplatform in Drupal 7
3 Opzetten server
3
14
Opzetten server
De meeste softwareprojecten beginnen met het opzetten van een testomgeving, dit is een omgeving waarop je lokaal kan ontwikkelen zonder het productieplatform te hinderen. Als de software volledig getest is, wordt alles overgebracht naar het productieplatform. Onze testomgeving bestaat eenvoudig uit een server waarop OLAT en PHP staan geïnstalleerd.
3.1
Virtualisatie met VirtualBox
Om niet voortdurend tussen twee verschillende systemen te switchen hebben we ervoor gekozen om OLAT en PHP te installeren op een virtuele machine waarop Ubuntu Server 11.10 draait. De software die de virtuele machine aanstuurt is Oracle VirtualBox. Met het commando vboxheadless kan je de virtuele machine vanop afstand starten, dus zonder de applicatie te openen. Volgend stukje code illustreert hoe je vanop afstand een virtuele machine kan starten in Windows PowerShell. Start-Process 'C:\Program Files\Oracle\VirtualBox\vboxheadless' '-s Ubuntu' -WindowStyle Hidden
3.2 Configuratie Ubuntu Server De server moet natuurlijk zo geconfigureerd worden dat die van buitenaf toegankelijk is. Daarvoor is het noodzakelijk om in het bestand /etc/network/interfaces een IP-adres te configureren. Om de server vanop afstand te kunnen beheren kan je gebruik maken van telnet of rlogin. Maar omdat dit verouderde technologie is en als onveilig wordt beschouwd, maken we gebruik van SSH om een connectie te leggen tussen de host en de remote machine.
3.2.1
SSH
Secure Shell of kortweg SSH is een netwerkprotocol dat toelaat om op een veilige, geëncrypteerde manier, commando’s te versturen naar een remote machine. Vandaag de dag wordt deze technologie het meest aanbevolen en gebruikt door systeembeheerders. Omdat we lokaal werken is er geen nood aan een zeer geavanceerde installatie van SSH. Met het RSA-encryptieprotocol maken we een publieke en private sleutel aan. ssh-keygen –t rsa
De publieke sleutel wordt gebruikt om het wachtwoord te encrypteren. De private sleutel wordt dan weer gebruikt om het geëncrypteerde wachtwoord te decrypteren. Deze private sleutel moet veilig worden bewaard en aan niemand worden doorgegeven, anders zit je met een veiligheidsprobleem. In het configuratiebestand /etc/ssh/ssh_config moet public-key authenticatie worden toegelaten en moet er verwezen worden naar waar de sleutels zijn opgeslagen op de server. Om de server vanop afstand te beheren moet je een tool gebruiken die SSH ondersteunt. Wij gebruiken hiervoor PuTTY en WinSCP. Figuur 3-1 is een schermafdruk van de Command Line Interface van PuTTY. Figuur 3-2 toont de GUI van WinSCP. Het grote verschil tussen Uitbreiding leerplatform in Drupal 7
3 Opzetten server
15
deze programma’s is dat WinSCP een grafische voorstelling toont van de server in tegenstelling tot PuTTY die de informatie rechtstreeks toont. Wij gebruiken PuTTY voornamelijk voor de configuratie van het systeem. WinSCP gebruiken we om eenvoudig bestanden te bekijken en om bestanden over te brengen naar onze lokale machine.
Figuur 3-1 CLI van PuTTY
Figuur 3-2 GUI van WinSCP
3.2.2
Tomcat
Omdat OLAT een webapplicatie is, geschreven in Java, is een Tomcatserver onontbeerlijk. Tomcat is verantwoordelijk voor de communicatie tussen JavaServer Pages en de webserver. In het bestand /etc/tomcat6/tomcat-users.xml maken we een gebruiker aan zodat deze kan inloggen op de Tomcatserver.
user username="tomcat" password="tomcat" roles="manager" />
Vervolgens kan het WAR-bestand2 van OLAT gemakkelijk gedeployd worden in Tomcat. Nu moeten er nog enkele zaken geconfigureerd worden vooraleer OLAT in gebruik genomen kan worden.
2
Een WAR-bestand bevat JavaServer Pages, Java Servlets, Java klassen, XML-bestanden en HTMLbestanden die samen een webapplicatie vormen.
Uitbreiding leerplatform in Drupal 7
3 Opzetten server
3.2.3
16
OLAT
De installatie van OLAT is vrij moeilijk omdat er weinig documentatie bestaat. De vindbare documentatie is dan vaak weer verouderd. Ondanks enkele moeilijkheden zijn we er toch in geslaagd om OLAT te installeren. OLAT maakt gebruik van een database waarin vooral logbestanden en gebruikers worden bijgehouden. Wachtwoorden van gebruikers worden opgeslagen met de MD5encryptiemethode. Dit is een spijtige zaak omdat de zogenaamde hashcodes gemakkelijk te kraken zijn, maar dit terzijde. Wij hebben gekozen voor de gratis database MySQL omdat die wordt aangeraden door OLAT zelf. Na de configuratie van de MySQL database en het uitvoeren van het databasescript moeten in het configuratiebestand op Tomcat enkele parameters worden aangevuld. Zo moet je specifiëren waar de gebruikersdata, loggegevens en cursussen worden opgeslagen. Ook moet je het databasetype opgeven. Het volgend stukje code illustreert het geheel. userdata.dir = /opt/olat/olatdata archive.dir = ${userdata.dir}/deleted_archive log.dir = ${userdata.dir}/logs folder.root = ${userdata}/bcroot db.vendor = mysql
Dit configuratiebestand moet ook gekopieerd worden naar /usr/share/tomcat6/lib/ onder de naam olat.local.properties. Als je dit niet doet, dan worden de cursussen en oefeningen niet definitief opgeslagen en worden ze gewist bij het afsluiten van de server. Het heeft veel tijd en moeite gekost om dit probleem te lokaliseren. Bij het zoeken in het logboek van Tomcat zijn we uiteindelijk op een FileNotFoundException gebotst die verwees naar de /usr/share/tomcat6/lib/ map. De Tomcatgebruiker moet eigenaar worden van de map /opt/olat/olatdata en iedereen moet ook beheerdersrechten krijgen op deze map, behalve gebruikers van buitenaf. Hiervoor worden de volgende commando’s gebruikt. chown –R tomcat6:tomcat6 /opt/olat/olatdata chmod –R 775 /opt/olat/olatdata
Dit is meteen de laatste stap van de installatie. In Figuur 3-3 zie je een schermafdruk van OLAT.
Uitbreiding leerplatform in Drupal 7
3 Opzetten server
17
Figuur 3-3 OLAT draaiende op Tomcat
3.2.4
Xdebug, de debugger
Met een debugger kan je de oorzaak van een softwarebug achterhalen. Omdat PHP op de server wordt uitgevoerd en Netbeans geen eigen developmentomgeving kan opzetten zoals bijvoorbeeld Visual Studio wel kan, moet er een extra tooltje worden ingeroepen, namelijk Xdebugger. Deze debugger werkt vlekkeloos samen met Netbeans. Netbeans is een gratis, open source Integrated Development Environment of kortweg IDE voor softwareontwikkelaars. Het is een multiplatform softwarepakket waarin hoofdzakelijk Java, C, C++, Groovy en PHP kunnen ontwikkeld worden. Op het moment van schrijven heb ik de meest recente versie 7.1.1 gebruikt. Xdebug moet wel worden geconfigureerd op de server. Dankzij het volgende commando wordt er veel zelf geconfigureerd: sudo apt-get install php5-xdebug
In het xdebug.ini of php.ini bestand moeten nog enkele lijnen code worden geplaatst. Het betreft de verwijzing naar het shared object bestand, de manier waarop Xdebug contact moet maken en het IP-adres van de host. zend_extension=/usr/lib/php5/20090626+lfs/xdebug.so xdebug.remote_enable = on xdebug.remote_host = 131.130.245.134 #xdebug.remote_port = 9000 #xdebug.remote_handler = dbgp
Uitbreiding leerplatform in Drupal 7
3 Opzetten server
18
De twee laatste waarden worden ook vaak geconfigureerd in het xdebug.ini of php.ini bestand, maar eigenlijk zijn ze overbodig omdat dit de standaardwaarden zijn. Bij elke wijziging in deze bestanden mag je niet vergeten om Apache te herstarten. Netbeans zelf is standaard al correct geconfigureerd, enkel aan de browser ontbreekt er nog een add-on. Natuurlijk zijn er verschillende add-ons op de markt voor verschillende browsers. Omdat ik een grote fan ben van de webbrowser Google Chrome, gebruik ik de add-on Xdebug helper. Na het plaatsen van een breakpoint in Netbeans zal PHP stoppen en zie je de waarden van de variabelen in Netbeans zoals je kan zien in Figuur 3-4. Uiteraard kan je steeds verder in de code gaan om te zien wat er uiteindelijk gebeurt, een stap teruggaan is niet mogelijk.
Figuur 3-4 Variabelen in Netbeans met behulp van Xbugger
Uitbreiding leerplatform in Drupal 7
4 QTI
4
19
QTI
IMS3 Question & Test Interoperabilty of kortweg QTI, ontwikkeld door het IMS Global Learning Consortium, is een standaard die de structuur beschrijft van een test met bijhorende vragen. Deze standaard zorgt er natuurlijk voor dat de informatie gemakkelijk getransfereerd kan worden naar verschillende leerplatformen zoals Moodle of Blackboard. De standaard is gedefinieerd in XML om zo ultra compatibel te zijn met zowat elke programmeertaal. XML zelf is ook een standaard van het W3C om structuur te geven aan data. De meest recente versie van QTI is versie 2.1 maar die wordt door geen enkel leerplatform volledig ondersteund (QTI, 2012). Veel leerplatformen, waaronder ook OLAT, maken immers nog gebruik van de oudere standaard, namelijk versie 1.2 die dateert van januari 2002.
4.1
XML
XML staat voor EXtensible Markup Language en is zoals reeds gezegd ontworpen om structuur te geven aan data maar ook om data op te slaan of te transfereren tussen verschillende systemen. Een XML-document bestaat uit een root element en dit heeft steeds verschillende kinderen onder zich. Een element bestaat uit tags waarin heel vaak tekst zit opgeslagen. Om nog meer informatie te geven over een bepaald element kan het ook attributen bevatten. Het volgende voorbeeld maakt dit wellicht duidelijk.
XML voor Dummies Ben Vandenbosch <prijs valuta="$">25.00 SOS Piet vol. 47 Piet Huysentruyt <prijs valuta="€">39.99
Het root element in bovenstaand voorbeeld is
en dit element heeft twee kinderen. Het element heeft drie kinderen en heeft ook een attribuut dat meer informatie geeft over het boek, namelijk categorie.
4.2 Structuur in XML Op de volgende pagina zie je een vereenvoudigd voorbeeld van een QTI-bestand.
3
IMS staat voor Instructional Management Systems, maar omdat dit meer vragen oproept dan antwoorden willen ze gewoon als IMS Global Learning Consortium door het leven gaan.
Uitbreiding leerplatform in Drupal 7
4 QTI
20
<material> <mattext> <section ident="myolat_1_85268266152282" title="Titel Sectie"> - <presentation> <material> <mattext texttype="text/html"> <material> <mattext texttype="text/html"> <material> <mattext texttype="text/html">
Zoals je kan zien in bovenstaand voorbeeld zijn de belangrijkste onderdelen in een QTIbestand: het assessment element: dit bevat heel de test; de section elementen: dit is een container voor items die een gemeenschappelijk leerdoel hebben; de item elementen: die bevatten de vragen. Het assessment element komt maximaal één keer voor in een QTI-document. De section elementen kunnen dan weer meerdere keren voorkomen binnen het assessment element en ook de item elementen kunnen meerdere keren voorkomen binnen het section element. Behalve deze cruciale elementen zijn er nog veel meer elementen die kunnen voorkomen in een QTI-document. Het presentation element dat voorkomt in een item element bevat buiten de vraag ook de mogelijke antwoorden en het vragentype. Het vragentype zit verscholen in het attribuut ident in het element item. OLAT ondersteunt vier vragentypes namelijk:
Single Choice Question (SCQ) Multiple Choice Question (MCQ) Fill in Blanks (FIB) KPRIM
Uitbreiding leerplatform in Drupal 7
4 QTI
21
Waar de eerste twee niet veel duiding vragen, zijn de laatste twee misschien minder evident. Het Fill in Blanks type is een invuloefening en KPRIM is een soort oefening die haar oorsprong vindt bij medische examens. Er zijn steeds vier mogelijkheden die juist of fout kunnen zijn. Enkel wanneer alle antwoorden correct zijn ingevuld, krijg je de volledige punten. Wanneer er één antwoord fout is krijg je nog de helft en je behaalt niks wanneer twee of meer antwoorden fout zijn. In Figuur 4-1 en Figuur 4-2 zie je twee voorbeelden van oefeningen in OLAT.
Figuur 4-1 Fill in Blanks (FIB) oefening in OLAT
Figuur 4-2 KPRIM oefening in OLAT
In het item element zit ook nog informatie opgeslagen zoals welke antwoorden correct en incorrect zijn, de puntenverdeling en feedbackmogelijkheden.
4.3 QTI Object Parser Het hele opzet is om in Drupal een cursus in te laden met bijhorende QTI-bestanden. Deze QTI-bestanden moeten dus gelezen en geïnterpreteerd worden. Omdat Drupal in PHP geschreven is, wordt het QTI-bestand in PHP gelezen en verwerkt tot een object met behulp van een zogenaamde parser. Deze parser werd in Netbeans ontwikkeld.
4.3.1
De broncode
Het is de taak van de parser om een QTI-bestand in te lezen en te verwerken tot een object. Omdat QTI eigenlijk een XML-bestand is, kan je de standaard PHP-functies gebruiken om door de XML-structuur te gaan. Met de volgende code wordt een XML-bestand ingelezen. Uitbreiding leerplatform in Drupal 7
4 QTI
22
if (file_exists($filename)) { $xml = new SimpleXMLElement($filename); } else { exit('Failed to open ' . $filename); }
In de variabele $xml zit nu het volledige XML-bestand. Het is mogelijk om via de klassieke manier door de XML-structuur te navigeren zoals je kan zien in de volgende code. $sections = $xml->assessment->section; $title = $xml->assessment->section->attributes()->title;
Bovenstaand voorbeeld geeft respectievelijk een array terug van alle section elementen en de titel als attribuut in het element section. Maar het is ook mogelijk om zeer specifiek zaken te vinden in het XML-bestand met behulp van XPath. In het volgend voorbeeld wordt XPath gebruikt om de elementen respcondition op te halen waarin het kind setvar bestaat, maar zonder het element conditionvar en het bijhorend kind other. $item = $xml->assessment->section->item; $result = $item->xpath('respcondition[setvar and not(conditionvar/other)]');
Een QTI-bestand heeft een zeer uitgebreide XML-structuur. Dit wordt zeker duidelijk wanneer je te weten moet komen of de mogelijkheden van een oefening in willekeurige of sequentiële volgorde moeten komen. $randomOrder = $item->presentation->response->choice->attributes()->shuffle;
Uiteraard is het goed mogelijk dat een element uit deze ketting ontbreekt, bijvoorbeeld het element choice. Als je de code laat staan zoals nu, gaat PHP een foutmelding tonen. Dit moet kost wat kost vermeden worden, dus moest er een oplossing gevonden worden. Al vlug kwamen we op de PHP-functie isset() die gaat controleren of de variabele bestaat en niet leeg is. Maar ook deze functie schoot te kort, want zij controleert enkel het laatste element uit de hele ketting. Ik moest zelf een functie schrijven die elk element uit de ketting gaat controleren om te zien of het bestaat. Daarvoor is de volgende functie verantwoordelijk. 1 function getDataIfExists() { 2 3 $args = func_get_args(); 4 $baseObj = array_shift($args); 5 6 if (!is_object($baseObj)) { 7 return NULL; 8 } 9 10 foreach ($args as $arg) { 11 $arg = (string) $arg; 12 if (substr($arg, -2) == '()') { 13 $arg = substr($arg, 0, -2); 14 if (!method_exists($baseObj, $arg)) 15 return NULL; 16 $baseObj = $baseObj->$arg(); 17 } else { 18 if (!isset($baseObj->$arg)) 19 return NULL; 20 $baseObj = $baseObj->$arg; 21 }
Uitbreiding leerplatform in Drupal 7
4 QTI
23
22 } 23 24 return $baseObj; 25 } 26 27 getDataIfExists($item, 'attributes()', 'title');
Deze functie ontvangt een ongekend aantal parameters (lijn 3), maar de eerste parameter is steeds een object die de structuur van de XML bevat (lijn 4). Vanaf lijn 10 ga ik elke parameter controleren of het een object is. Als de parameter een methode is, bijvoorbeeld attributes(), dan controleer ik of deze methode bestaat en vervolledig ik de ketting (lijnen 12 tot 17). Als de parameter een element is dan controleer ik of het bestaat en maak ik de ketting langer (lijnen 18 tot 21). De informatie moet worden opgeslagen en hiervoor bestaan er twee manieren. Ofwel sla je de informatie op in een grote associatieve array. Hierin kan de unieke sleutel ook strings bevatten zoals te zien is in het volgende voorbeeld. $array = array( 'foo' => 'bar', 'bar' => 'foo', );
Op deze manier kan je dus meer informatie opslaan in tegenstelling tot een klassieke array. Maar het programmeert nogal oncomfortabel en om er uiteindelijk informatie uit te halen is het nogal omslachtig. 1 2 3 4 5 6 7 8
$s = 1; foreach ($item->presentation->flow->children() as $child) { $array['sections'][$s]['items'][$i]['flow'][] = array( 'textbox' => (string) $child->attributes()->ident ); } // Increase item-var when all possibilities in items are looped $i++;
Op lijn 3 zie je ook weer een lange ketting verschijnen. Dit keer niet afkomstig van het navigeren door de XML-structuur maar wel om de array structuur te geven. Daarom ben ik met klassen en objecten gaan werken. 4.3.1.1
Klassen en objecten
Een klasse kan constanten, variabelen en functies bevatten. De laatste twee worden respectievelijk attributen en methodes genoemd. In PHP wordt een klasse op de volgende manier gedefinieerd.
Uitbreiding leerplatform in Drupal 7
4 QTI
24
class MijnKlasse { // declaratie attributen private $attribuut; // declarative methode public function toonVar() { echo $this->attribuut; } }
Vooraleer de klassen in PHP worden gedefinieerd moet je wel weten welke klassen je gaat nodig hebben. Daarom start je met het maken van een klassendiagram dat een goed beeld schetst over hoe alles in elkaar zit, zoals je kan zien in onderstaande figuur.
Figuur 4-3 Klassendiagram QTI object parser
Figuur 4-3 beschrijft dat een QTI-bestand bestaat uit een test waarin verschillende secties zitten. In elke sectie zitten vervolgens één of meerdere items of vragen. Elk item heeft natuurlijk enkele keuzemogelijkheden die worden gedefinieerd in de klasse Possibility. Verder kan een item ook feedback hebben, hoewel dit niet verplicht is. De verschillende soorten vragen zitten opgeslagen in de klassen SingleChoiceQuestion, FillInQuestion, MultipleChoiceQuestion en KPRIMQuestion. Ten slotte heb je ook nog een Answer klasse die de antwoorden bijhoudt van deze drie laatste klassen. De klasse SingleChoiceQuestion houdt zelf haar antwoord bij. Bekijk Bijlage 3 – QTI Klassendiagram voor het volledige klassendiagram.
Uitbreiding leerplatform in Drupal 7
4 QTI
25
Ik bespreek heel kort de klasse Item en MultipleChoiceQuestion. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
class Item { protected $title; protected $possibilities = array(); protected $maxAttempts; public function __construct($title, $maxAttempts = '') { $this->title = $title; $this->maxAttempts = $maxAttempts; } public function setTitle($title) { $this->title = $title; } public function getTitle() { return $this->title; } public function setPossibility($possibilities) { array_push($this->possibilities, $possibilities); } }
Zoals je kan zien in Figuur 4-3 erven alle Question klassen over van de klasse Item. Dit betekent dat de Question klassen alle attributen en methodes kunnen gebruiken uit de klasse waarvan ze overerven. Dit fenomeen noemt men ook polymorfisme. De voorwaarde is wel dat de attributen de identifier protected meekrijgen in plaats van de gebruikelijke private of public. We declareren op lijn 4 een attribuut $possibilities dat een array is waarin verschillende objecten van het type Possibility kunnen. Lijn 7 bevat de constructor. Een constructor wordt opgeroepen bij het aanmaken van een object. Wanneer je een object van de klasse Item aanmaakt, moet je minimum één parameter meegeven, namelijk de titel. Optionele parameters worden gedefinieerd door een lege string te voorzien als standaardwaarde. Met de settermethode op lijn 12 kan je data in het object stockeren en met een getter op lijn 16 haal je er informatie uit. Op lijn 20 zie je ook nog een methode setPossibility die een keuzemogelijkheid binnenkrijgt als parameter. Een item object bestaat telkens uit één titel maar uit meerdere keuzemogelijkheden vandaar dat deze in een array worden gestockeerd zoals in lijn 4. De PHP functie array_push op lijn 21 zorgt dat de parameter die binnenkomt in de array wordt opgeslagen. Net als bij de klasse Item bestaat ook de klasse MultipleChoiceQuestion uit verschillende attributen en methodes. Het enige verschil is dat deze klasse de attributen en methodes van de klasse Item moet kunnen overerven. Dit gebeurt door achter de naam van de klasse het woordje extends te plaatsen en vervolgens de naam van de klasse waarvan het moet overerven. Dit wordt geïllustreerd in het volgende voorbeeld. class MultipleChoiceQuestion extends Item { }
Uitbreiding leerplatform in Drupal 7
4 QTI
26
Nog een ander voordeel waarom ik klassen en objecten boven arrays gebruik, is het kunnen gebruiken van de Intellisense functie van Netbeans. Eigenlijk is Intellisense niet meer dan een automatische aanvulling voor code zoals je kan zien in Figuur 4-4.
Figuur 4-4 Intellisense in Netbeans
Uitbreiding leerplatform in Drupal 7
5 Drupal
5
27
Drupal
Drupal is een softwarepakket, ontwikkeld door onze landgenoot Dries Buytaert, dat toelaat om eenvoudig een grote verscheidenheid aan inhoud te publiceren, te beheren en te organiseren op een website. Men noemt dit dan ook een CMS dat staat voor Content Management System. Drupal wordt voornamelijk gebruikt voor community portaalsites, intranet portaalsites binnen bedrijven, algemene websites of e-commerce applicaties. Standaard heeft Drupal al veel mogelijkheden die je zo kan gebruiken zoals een content management systeem, fora, nieuwsbrievenbeheer, uploaden en downloaden van bestanden, etc. Het is open source software, dus het staat ontwikkelaars vrij om de software aan te passen en gratis te verspreiden via de Drupal community. Dit is meteen wat wij hebben gedaan, namelijk het ontwikkelen van een module in Drupal. Doorheen dit hoofdstuk worden stukjes code van de ontworpen module genomen ter illustratie. Deze stukjes code zijn conform de regels van Drupal 7.
5.1
Voor- en tegenstanders
Elk softwaresysteem, dus ook Drupal, heeft zijn voor- en tegenstanders. Ik heb er drie maanden mee gewerkt dus kan ik ook mijn eigen mening hier verkondigen. Met honderd procent zekerheid kan ik zeggen dat ik één van die tegenstanders ben. Drupal is volledig in PHP geschreven. PHP is een ontzettend toegankelijke programmeertaal die je zeer vlug onder de knie krijgt. Op de één of de andere manier heb je dit bij Drupal niet. Drupal staat gekend om zijn heel hoge leercurve, maar na drie maanden stage stel ik me nog steeds vragen over hoe alles werkt. Dit probleem wijd ik aan de gebrekkige documentatie en ondersteuning. Drupal heeft een API maar hierop vind je nauwelijks voorbeelden of demo’s terug en dit verwacht je toch van een degelijke API. Enkele goede voorbeelden van begrijpbare API’s zijn deze van jQuery (api.jquery.com) of MSDN van Microsoft (msdn.microsoft.com/en-us/library). Verder stel ik me ook vragen bij de opbouw van Drupal, deze bestaat uit ellenlange lijnen code waartussen massa’s lijnen aan commentaar geschreven staan die eigenlijk in de API zouden moeten opgenomen zijn. In Figuur 5-1 en Figuur 5-2 zie je hier voorbeelden van. Drupal breekt natuurlijk ook met de objectgeoriënteerde manier van programmeren en gebruikt dus nauwelijks klasses waardoor herbruikbaarheid van code bemoeilijkt wordt.
Uitbreiding leerplatform in Drupal 7
5 Drupal
28
Figuur 5-1 Commentaarlijnen in het entity.inc bestand
Figuur 5-2 Commentaarlijnen in het common.inc bestand
Als je wil upgraden naar een nieuwere versie van Drupal zullen zelfgeschreven of contributed modules4 waarschijnlijk niet werken en moet je wachten tot de modules terug ondersteund worden of ze zelf gaan herschrijven, wat veel tijd kan innemen. Gelukkig kan ik weinig softwaresystemen bedenken die geen achterwaartse compatibiliteit ondersteunen. 4
Dit zijn modules die worden aangeleverd door de community van Drupal.
Uitbreiding leerplatform in Drupal 7
5 Drupal
29
Tijdens het programmeren zijn we nog enkele programmatorische problemen tegengekomen zoals het alom gekende cacheprobleem. Drupal heeft een cachesysteem ingebouwd dat niet alleen zeer veel geheugen kan innemen maar ook voor grote frustraties kan zorgen bij het programmeren. Je schrijft namelijk een stukje code waarin een fout zit, je herstelt het en toch lijkt het nog steeds niet te werken, hoewel dit wel zou moeten. Dit komt natuurlijk door de cache die je manueel moet verwijderen. Nog een frustratie is de vreemde manier om data uit een database te halen, wat zeker moeilijk wordt bij het schrijven van ingewikkelde queries, bekijk hoofdstuk 5.4.4 Aanspreking database voor een uitgewerkt voorbeeld. En zoals het spreekwoord zegt: bij Drupal zit er overal een addertje onder het gras. Als je met een debugger te werk gaat, zie je in eerste instantie de inhoud van de array niet. Als je maar één record verwacht, moet je toch een for-each instructie uitvoeren om de array die je terugkrijgt af te lopen en als je deze array twee keer zou moeten aflopen, moet je de data opnieuw uit de database halen omdat Drupal de inhoud van de array op een mysterieuze manier doet verdwijnen.
5.2
Modulair programmeren
Na de installatie van Drupal op een webserver heb je eigenlijk al veel functionaliteiten die je kan gebruiken. Dit komt omdat Drupal standaard al enkele modules activeert die in de ‘core’ zitten. De ‘core’ in Drupal is alles buiten de map sites. In Figuur 5-3 zie je de mappenstructuur van Drupal. De map sites zal later eigen ontwikkelde of gedownloade modules bevatten.
Figuur 5-3 Mappenstructuur van Drupal
De core van Drupal is modulair opgebouwd. Hij gebruikt voornamelijk hooks die aangesproken worden via een API. Bij het ontwikkelen van een module moet je natuurlijk deze hooks gaan gebruiken.
5.2.1
Hooks
Een hook is eigenlijk een PHP-functie met de naam foo_bar(), waar foo de naam van de module is en bar de naam van de hook. Elke hook heeft een aantal voorgedefinieerde Uitbreiding leerplatform in Drupal 7
5 Drupal
30
parameters en een returnwaarde. Als je Drupal wil uitbreiden, moet je gewoon een hook implementeren. Zo gaat Drupal bij de hook hook_form_alter() controleren of er nog modules zijn die vragen naar hook_form_alter. Met deze hook kan je bijvoorbeeld de labels van een formulier wijzigen, enkele checkboxen toevoegen of een gebruiker doorverwijzen naar een andere pagina. Alle hooks zijn gedocumenteerd op de Drupal API website die je kan raadplegen op api.drupal.org.
5.3
Databaseontwerp
Vooraleer ik ben gaan programmeren heb ik een databaseontwerp gemaakt. Het datamodel, te zien in Figuur 5-4, lijkt sterk op het klassendiagram van de objectparser, zie Figuur 4-3. Dit is enigszins logisch omdat de data quasi dezelfde zijn. De data die door de objectparser worden verkregen, worden immers opnieuw ingelezen in Drupal en opgeslagen in de database. Achteraf zou je je kunnen afvragen waarom ik een objectparser heb gebruikt. Het zou toch sneller en onderhoudsvriendelijker zijn om de XML-bestanden meteen in Drupal te verwerken? Onze IT-verantwoordelijke wilde het echter op deze manier.
Figuur 5-4 Relationeel datamodel Drupal
5.4 Module Een module wordt steeds in de map sites geplaatst. Elke module in Drupal heeft een unieke naam en bestaat minimum uit twee bestanden, namelijk een .info en .module bestand. Als de module de naam color meekrijgt dan noemt het .info bestand color.info. Uitbreiding leerplatform in Drupal 7
5 Drupal
31
Het .info bestand bevat algemene informatie over de module, zo heb je de naam en de omschrijving, maar ook in welke versie de module is geschreven. Je ziet ook welke module eerst geactiveerd moet worden vooraleer de andere kan werken, en nog veel meer. Het volgend stukje code bevat een deel van het forum.info bestand, een module uit de core van Drupal. name = Forum description = Provides discussion forums. dependencies[] = taxonomy dependencies[] = comment package = Core core = 7.x files[] = forum.test
Voor ik logischerwijze het .module bestand bespreek, sta ik nog even stil bij het .install bestand. Dit bestand is niet verplicht. Bij het activeren van een module zal Drupal zoeken naar dit bestand en eventueel de hooks uitvoeren. In het .install bestand wordt meestal de database vastgelegd met de hook hook_schema(). Het is dus onnodig om zelf een SQLscript te maken omdat deze hook ervoor zorgt. Het volgend stukje code toont de aanmaak van de tabel qti_section met twee kolommen, id en testid. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
function upload_schema() { $schema['qti_section'] = array( 'description' => t('Contains the sections within a test.'), 'fields' => array( 'id' => array( 'type' => 'serial', 'unsigned' => TRUE, 'size' => 'normal', 'not null' => TRUE, 'description' => t('The primary identifier for a section.'), ), 'testid' => array( 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'description' => t('FK to qti_test.id.'), ), ), 'indexes' => array( 'testid' => array('testid'), ), 'primary key' => array('id'), 'foreign keys' => array( 'fk_qti_section_to_test' => array( 'table' => 'qti_test', 'columns' => array('testid' => 'id'), ), ), ); }
Merk op dat je naast de primaire sleutel op lijn 22 ook een index op lijn 19 kan vastleggen op een kolom. Indexen versnellen aanzienlijk het zoeken naar records in de database. De index wordt hier gelegd op testid omdat we deze kolom vaak nodig zullen hebben. Verder wordt er ook een refererende sleutel, zie lijnen 23 tot 28 gelegd naar de tabel qti_test. Helaas legt Drupal deze niet zelf vast in de database en is deze regel totaal overbodig. Men raadt echter aan refererende sleutels op te nemen, al is het maar voor documentatie. Uitbreiding leerplatform in Drupal 7
5 Drupal
32
Het laatste bestand dat ik hier bespreek is het .module bestand. Dit bestand is eigenlijk de kern van de module en beschrijft hoe de module zich moet gedragen. In dit bestand zullen ook voornamelijk hooks voorkomen zoals bijvoorbeeld hook_menu() die de URLaanvragen zal afhandelen, of hook_permission() waarin nieuwe permissies worden opgenomen. Laten we de meest belangrijke hooks, die ook in onze module geïmplementeerd zijn, bespreken.
5.4.1
hook_permission()
Deze hook zorgt voor extra permissies binnen Drupal. Permissies kunnen nadien gecontroleerd worden door gebruik te maken van de functie user_access(). 1 2 3 4 5 6 7 8 9 10 11 12 13 14
function upload_permission() { return array( 'teacher' => array( 'title' => t('Administer Upload Courses OLAT module'), 'description' => t('Perform administration tasks for…'), 'restrict access' => TRUE, ), 'student' => array( 'title' => t('See Upload Courses OLAT module'), 'description' => t('Perform student tasks for the Upload…'), 'restrict access' => TRUE, ), ); }
Bovenstaande code zorgt voor een resultaat dat zichtbaar is in Figuur 5-5. Er zijn twee permissies bijgekomen, namelijk Administer Upload Courses OLAT module en See Upload Courses OLAT module. In Drupal kan je nu aan deze permissies taken koppelen. Merk tevens ook de t() functie op bijvoorbeeld lijn 4 op. Deze zorgt ervoor dat de opgegeven strings vertaald kunnen worden in een bepaalde taal.
Figuur 5-5 Visuele weergave van permissies in Drupal
De permissies mag je niet verwarren met de rollen. Op Figuur 5-5 zie je vijf rollen die hier kort besproken worden.
Anonymous user Authenticated user Administrator Teacher
Student
Elke internetgebruiker. Elke geregistreerde gebruiker. De gebruiker die standaard alle permissies heeft. Elke geregistreerde gebruiker die de extra permissie heeft om cursussen en oefeningen te beheren. Elke geregistreerde gebruiker die de extra permissie heeft om cursussen te lezen en oefeningen te maken.
Uitbreiding leerplatform in Drupal 7
5 Drupal
33
Omdat het een open project is en het voor iedereen toegankelijk moet zijn om zonder registratie oefeningen te maken, hebben we de rol student niet in gebruik genomen. Deze dient enkel als uitbreiding om bij te houden welke student, welke oefening heeft gemaakt.
5.4.2
hook_menu()
Deze hook komt vrijwel in elke module voor. Het neemt de URL-aanvragen voor zijn rekening. Het volgend stukje code toont een extract uit ons modulebestand. 1 2 3 4 5 6 7 8 9 10 11 12
function upload_menu() { $items['oefeningen/upload'] = array( 'title' => t('Upload Course'), 'page callback' => 'drupal_get_form', 'page arguments' => array('upload_zip'), 'access arguments' => array('teacher'), 'menu_name' => 'menu-course-administration', 'type' => MENU_NORMAL_ITEM, ); return $items; }
Deze hook zal altijd een associatieve array terugsturen. De keys van de array bevatten de paden en zijn waarden zijn een associatieve array van eigenschappen voor elk pad. Wanneer een gebruiker naar het pad oefeningen/upload surft, dan zal Drupal de functie drupal_get_form() oproepen die staat gespecifieerd op lijn 4. Deze functie verwacht één parameter, namelijk $form_id. Extra parameters doorsturen kan door de eigenschap page arguments op lijn 5 op te geven. Drupal zal na permissiecontrole zoeken naar de functie upload_zip in het modulebestand. De permissiecontrole gebeurt op lijn 6. Het formulier dat we gaan oproepen, mag enkel toegankelijk zijn voor gebruikers met de permissie teacher. Deze rol wordt manueel vastgelegd in Drupal. Verder geven we ook nog de eigenschappen menu_name en type mee. menu_name is verantwoordelijk voor de plaats waar de menulink zal komen. In dit geval komt de menulink in het blok menu-course-administration terecht. De eigenschap type kan de volgende waarden bevatten: MENU_NORMAL_ITEM MENU_CALLBACK
Normale menu-items worden in het menu getoond. Het pad wordt enkel opgeslagen in de database en wordt niet getoond in het menu. MENU_SUGGESTED_ACTION Deze menu-items worden gesuggereerd aan de administrator en worden niet standaard getoond in het menu. MENU_LOCAL_TASK Deze menu-items worden getoond als tabs. Wij hebben voornamelijk gebruik gemaakt van de eerste twee waarden.
5.4.3
hook_form()
Deze hook is verantwoordelijk voor het aanmaken en tonen van een formulier. Dit is meteen ook de meest gebruikte hook in onze module. De volgende code illustreert het gebruik van deze hook. Bekijk ook Figuur 5-6 die het resultaat toont van deze code. Merk op dat dit formulier wordt opgeroepen in de code die je vindt in 5.4.2 hook_menu().
Uitbreiding leerplatform in Drupal 7
5 Drupal 1 2 3 4 5 6 7 8 9 10 11
34
function upload_zip($form_state) { $form['file'] = array( '#type' => 'file', '#description' => t('Upload een bestand, enkel zip extensies worden…'), ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Uploaden'), ); return $form; }
Figuur 5-6 Uploadformulier
5.4.4
Aanspreking database
In 5.4 Module werd de hook hook_schema() besproken. Deze hook is verantwoordelijk voor het aanmaken van de database. Natuurlijk is het ook interessant om te bekijken hoe je de database kan aanspreken in Drupal 7. 1 2 3 4 5 6 7 8 9 10
function getDetailsByPossibilityid($possibilityid) { $query = db_select('qti_possibility', 'p'); $query->fields('p', array('id', 'possibility', 'is_correct', 'answer')); $query->fields('i', array('id', 'type', 'score')); $query->join('qti_item', 'i', 'p.itemid = i.id'); $query->condition('p.id', $possibilityid, '='); $resultset = $query->execute(); return $resultset; }
Ter vergelijking noteer ik in het volgende kader de normale SQL-query. SELECT p.id, p.possibility, p.is_orrect, p.answer, i.id, i.type, i.score FROM qti_possibility p INNER JOIN qti_item i ON p.itemid = i.id WHERE p.id = $possibilityid
Beide queries geven hetzelfde resultaat terug, namelijk een lijst van mogelijkheden die bij een oefening hoort. Als je Drupal 7 gebruikt, wordt de eerste manier aanbevolen. De array die je terugkrijgt op lijn 9, kan worden gelezen met een simpele for-each instructie.
Uitbreiding leerplatform in Drupal 7
6 Drupal in actie
6
35
Drupal in actie
Na veel theorie en code in de vorige hoofdstukken, krijg je in dit hoofdstuk vooral het eindresultaat te zien. In Bijlage 4 – Handleiding vind je de handleiding die voor deze module werd geschreven.
6.1
Permissies en rollen
In hoofdstuk 5.4.1 werden de gebruikte permissies en rollen besproken. De permissies zorgen er natuurlijk voor dat de rollen extra rechten krijgen in het systeem of net omgekeerd. De gebruikers worden aan één of meerdere rollen gekoppeld. In de volgende tabel staan de rollen nog eens opgesomd met wat ze mogen doen op de Drupalwebsite. Alles wat met het beheer van de cursussen te maken heeft, wordt hier niet besproken omdat dit niet tot mijn opdracht behoorde. Teacher
Student Anonymous
Uploaden van een cursus of oefening. Cursussen en oefeningen publiceren en verwijderen. Oefeningen transformeren. Feedbackmogelijkheden instellen. Statistieken van de oefeningen bekijken. Oefeningen maken. In een later stadium van het project: statistieken per gebruiker. Oefeningen maken.
Tabel 6-1 Permissies per rolhook_permission()
6.2 Uploadfomulier Alles begint bij het uploaden van een geëxporteerde cursus of oefening uit het OLATsysteem. Bij het uploaden kan een docent op voorhand kiezen of de cursus of oefening onmiddellijk gepubliceerd zal worden. Vaak zullen oefeningen nog gewijzigd moeten worden en daarom is het interessant om dit op voorhand te kunnen kiezen. Om het comfort van de gebruiker te verhogen, maakt dit formulier gebruik van ‘multi file upload’. Dit betekent dat de gebruiker meerdere bestanden kan selecteren en uploaden. In Figuur 6-1 zie je het uploadformulier.
Figuur 6-1 Uploadformulier met opties
Uitbreiding leerplatform in Drupal 7
6 Drupal in actie
36
6.3 Oefeningen overzichtslijst Na het uploaden komen alle oefeningen in een overzichtslijst, ook oefeningen die in een cursus zitten, komen hier terecht. De cursus zelf komt in een andere lijst terecht die in dit eindwerk niet wordt besproken omdat het niet tot mijn opdracht behoorde. De overzichtslijst die je kan zien in Figuur 6-2, maakt gebruik van de jQuery datatables plug-in. Deze plug-in transformeert een simpele tabel naar een tabel met zoek- en sorteermogelijkheden, met de mogelijkheid om het aantal rijen te beperken en een handige paging functionaliteit.
Figuur 6-2 jQuery Datatable plug-in
De laatste kolom van de tabel bevat de opties voor een bepaalde rij. Van links naar rechts zie je een icoon om de oefening te bekijken, een icoon om de statistieken te bekijken, een icoon om de URL van de oefening te kopiëren en een icoon dat groen ziet wanneer de oefening gepubliceerd is en rood indien omgekeerd. Om het voor de gebruiker wat aangenamer te maken hebben we nog extra functionaliteiten ingebouwd. Zo is het mogelijk om een reeks van selectievakjes aan of uit te vinken door de shifttoets ingedrukt te houden. Dankzij de handige Ajax library van jQuery wordt er een boodschap getoond wanneer men rijen verwijdert of publiceert, totdat alle rijen succesvol zijn verwerkt. Na afloop wordt de pagina vernieuwd omdat Drupal de inhoud zal cachen. Het lijkt me interessant om deze Ajax library kort te bespreken.
6.3.1
jQuery Ajax library
Met Ajax kan je gegevens overbrengen van de webpagina naar de server zonder de pagina te herladen, wat het gebruikerscomfort aanzienlijk verhoogt. Als je ooit al met Ajax hebt gewerkt, weet je dat javascript uit veel extra lijnen code kan bestaan. De jQuery Ajax library heeft vele functies maar de start, stop, success en error zijn wellicht de belangrijkste. Alles wordt natuurlijk duidelijker met een eenvoudig voorbeeld. 1 2 3 4 5 6 7
function process_ajax() { $.ajax({ beforeSend: function() { if (!confirm('Ben je zeker dat je deze records wilt verwijderen?')) { return false; } },
Uitbreiding leerplatform in Drupal 7
6 Drupal in actie 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
37
success: function() { var checkBoxArray = Array(); var i = 0; $('input[type=checkbox]:checked').each(function () { checkBoxArray[i] = $(this).val(); i++; }); if (checkBoxArray.length > 0) { $('#ajaxDiv').load('?q=ajax', { 'var': [checkBoxArray] }); } }, error: function() { alert('Er liep iets fout, probeer later opnieuw.'); } }); $.ajaxStop(function() { window.location.reload(true); }); }
Op lijn 4 controleer ik of de gebruiker toestemt om records te verwijderen. Als de gebruiker toestemt dan haal ik elke geselecteerde checkbox op door de selector :checked mee te geven op lijn 11. Omdat een gebruiker meerdere checkboxen kan aanvinken, zit je in een for-each instructie. Op lijn 12 wordt de waarde van elke aangevinkte checkbox in een array gestopt en vervolgens op lijn 16 doorgestuurd naar de gewenste ajax-pagina. Merk op dat je hier extra parameters kan doorgeven. Mocht er iets fout lopen dan vang ik dit op in lijn 19 en wanneer alle Ajax requests zijn afgehandeld, wordt de pagina vernieuwd zoals je kan zien op lijn 24. Als je de gebruiker wil notifiëren dat de Ajax request is begonnen dan toon je een melding op lijn 16 en verwijder je deze weer in de ajaxStop-functie op lijn 23. Nogmaals wil ik benadrukken dat Ajax als doel heeft om op een zeer dynamische manier informatie op te halen zonder dat de pagina wordt vernieuwd. Helaas kan Drupal hier niet zo goed mee overweg en gaat alles verloren omdat we op lijn 24 de pagina vernieuwen.
6.4 Oefeningen Het tonen van de oefeningen is wellicht het belangrijkste onderdeel van de module. Figuur 6-3 toont de details van de oefening. De informatie komt natuurlijk uit OLAT en kan hier niet meer worden aangepast. Docenten kunnen hier wel beslissen of de oefening zichtbaar is voor de studenten en of studenten hun antwoorden kunnen controleren tijdens het maken van een oefening, erna of helemaal niet. Studenten zien deze details zonder de drie laatste rijen.
Figuur 6-3 Details van de oefening
Uitbreiding leerplatform in Drupal 7
6 Drupal in actie
38
Standaard worden er drie vragentypes uit OLAT ondersteund. Deze zijn de single choice questions, de multiple choice questions en de fill in blanks. Deze zullen in de volgende hoofdstukken worden besproken.
6.4.1
Single Choice Questions
Single choice questions zijn vragen waar slechts één antwoord het juiste is. Figuur 6-4 toont hoe docenten deze vraag zien. Studenten zien deze vraag zonder de combobox. Merk op dat er twee soorten van feedbackmogelijkheden zijn, namelijk de knop ‘Toon antwoord’ en ‘Controleer antwoord’. De eerste knop toont onmiddellijk het correcte antwoord terwijl de tweede het geselecteerde antwoord gaat controleren aan de hand van Ajax.
Figuur 6-4 Single choice question in Drupal
Dit vragentype kan worden getransformeerd naar een ‘selectieoefening’ en een ‘videooefening’. Bij de ‘selectieoefening’ is het de bedoeling om een deel van een zin te selecteren met de muis. Een voorbeeldvraag hiervan kan zijn: ‘Selecteer de klemtoon in het woord groeten.’ Bij de ‘video-oefening’ moet men de video pauzeren wanneer men bijvoorbeeld het woord groeten hoort in het bijgevoegd audiofragment. Omdat mijn collega dit heeft ontwikkeld, besteed ik hier verder geen aandacht aan.
6.4.2
Multiple Choice Questions
Multiple choice questions zijn vragen waar meerdere antwoorden correct kunnen zijn. In Figuur 6-5 zie je het resultaat van de oefening die door een student is ingediend. De groene antwoorden zijn de juiste en de rode zijn fout. Verder zie je ook het resultaat na het klikken op de knop ‘Toon antwoord’.
Uitbreiding leerplatform in Drupal 7
6 Drupal in actie
39
Figuur 6-5 Multiple choice question foutief ingevuld door student
6.4.3
Fill in the Blanks
Fill in the blanks zijn simpelweg invuloefeningen. Deze invuloefeningen kunnen wel getransformeerd worden naar drag-and-drop oefeningen zoals te zien is in Figuur 6-6. Dit is meteen ook de belangrijkste functionaliteit. Koste wat het kost moest deze functionaliteit in het eindresultaat zitten. Speciaal aan deze oefening is dat de tekstvakken wijzigen naargelang de grootte van de drag-elementen en ze gaan terug naar hun oorspronkelijke vorm wanneer ze terugkeren. Het heeft mij veel tijd gekost om dit te maken omdat niet alles gedocumenteerd is op de API van jQuery. Maar dankzij deze oefening heb ik wel leren werken met de jQuery API. Op onderstaande figuur zie je ook nog een videofragment dat in OLAT wordt ingevoegd en hier wordt getoond.
Figuur 6-6 Fill in blanks oefening getransformeerd naar Drag&Drop
Uitbreiding leerplatform in Drupal 7
6 Drupal in actie
40
6.5 Statistieken Het tonen van statistieken was een overbodige functionaliteit en moest enkel gemaakt worden indien er voldoende tijd was. Uiteindelijk heeft het weinig moeite gekost om de statistieken te verzamelen. In Figuur 6-7 zie je het statistiekenoverzicht waar docenten te weten kunnen komen welke oefeningen populair zijn, hoeveel tijd studenten gemiddeld spenderen aan een oefening, de gemiddelde score en wanneer de oefening voor het laatst werd gemaakt.
Figuur 6-7 Statistiekenoverzicht
6.6 Moeilijkheden Elk project kent zijn moeilijkheden en ik ben er ook enkele tegengekomen. In dit deel bespreek ik enkele moeilijkheden waarop ik een beetje trots ben een oplossing voor gevonden te hebben.
6.6.1
Omgaan met video en audio
De eerste moeilijkheid betreft het omgaan met video- en audio-elementen. De informatie zit natuurlijk opgeslagen in het XML-bestand dat uit OLAT geëxporteerd wordt. Hier zie je een extract uit het XML-bestand waarin een audiofragment zit verstopt. <presentation> <material> <mattext texttype="text/html"> Stop het fragment op de correcte tijd<span id="olatFlashMovieViewer()" style="display: block;"><script src="/OLAT/raw/player.js"><script>BPlayer.insertPlayer ("media/01_Audiofragment.mp3","olatFlashMovie"
]]>
Het grote probleem hier is dat ik met het script niets kan aanvangen en dat het op deze manier niet in de database gestockeerd kan worden. Verder moet ik ook rekening houden met eventuele tekst die voor of na het script kan komen en moet ik het pad naar het bestand behouden. Ik heb dit opgelost door op al de plaatsen waar video- of audio-elementen kunnen voorkomen, te zoeken naar BPlayer.insertPlayer omdat dit het meeste kans geeft dat je Uitbreiding leerplatform in Drupal 7
6 Drupal in actie
41
met zo een element te maken hebt. Vervolgens kan je eenvoudig het video- of audiofragment lokaliseren. Mocht er tekst voor het eerste <span> element staan, wordt dit ook meegenomen. Tenslotte vervang ik het script door een andere videospeler, namelijk flowplayer. Deze videospeler ondersteunt de volgende videoformaten: flv, mp4, mov, m4v en f4v. Flowplayer ondersteunt ook het afspelen van mp3-audiobestanden. De oplossing voor dit probleem is natuurlijk niet perfect omdat je allereerst niet elke soort media kan ondersteunen en omdat de informatie tussen de scripts variabel is.
6.6.2
Uploaden meerdere bestanden
Een tweede moeilijkheid was de ondersteuning voor het uploaden van meerdere bestanden. Het uploaden van één bestand is zeer eenvoudig in Drupal, in tegenstelling tot het uploaden van meerdere bestanden tegelijk daar er op het moment van implementatie geen goede module voor bestond. $form['file'] = array( '#type' => 'file', '#description' => t('Upload een bestand, enkel zip extensies worden…'), );
Dankzij HTML5 heb ik dit kunnen verwezenlijken door het toevoegen van twee extra attributen, namelijk multiple en enctype zoals je kan zien in onderstaand voorbeeld.