Utseendemaler

Brendan Johan Lee
Department of Informatics
University of Oslo, Norway
brendajl@simula.no

9. mars 2011

Sammendrag

Dette er en tutorialbasert introduksjon til utvikling av utseendemaler i Drupal 6. Tutorialen er skrevet for bruk i INF5270 kurset på IFI. Alt som beskrives i denne teksten skal være mulig å gjøre på de utdelte nettstedene, men for å følge denne teksten og løse oblig 3 anbefaler jeg bruk av lokal Drupal-installasjon på egen maskin. For å lage egne utseendemaler eller endre på eksisterende utseendemaler må man endre en rekke filer og teste resultatet etterhvert som man jobber. Dere har dessverre ikke kommandolinje-tilgang på nettstedene på diw noe som betyr at dere må laste opp utseendemaler fra en nettside. Å måtte stadig pakke sammen filene i tar.gz-format, for deretter å laste dem opp og teste er ikke en optimal måte å løse denne obligen på. Jeg anbefaler derfor at hver gruppe sørger for at dere har minst en lokal Drupal-installasjon på egen maskin som dere kan jobbe på.

Drupal er lettest å ha med å gjøre i GNU/Linux, og jeg anbefaler derfor alle (uavhengig av om man kjører GNU/Linux, Windows eller Mac-OS) bruker det utdelte vmware-bildet. Dermed vil ikke Drupal-installasjonen gå ut over ytelsen på maskinen, og man kan “leke og herje” så mye man vil uten å risikere å ødelegge maskinen.

Vi har allerede gått kjapt gjennom Drupal-installasjon på en tidligere forelesning, men dersom det her noen som har behov for hjelp med dette, kan vi gjøre dette på neste gruppetime.

Teksten vil ta utgangspunkt i egne Drupal-installasjoner og man vil dermed finne tekst av typen “åpne filen og endre …” gjennomgående i denne teksten.

1 Krav til Drupal-nettstedet

Vi kommer til å benytte oss av devel, Theme Developer-modulene samt Drupal for firebug-modulen som ble presentert på forrige forelesning, og for å følge dette dokumentet må dere sørge for at disse er installert og aktivert på nettstedet dere jobber mot.

Legg merke til at alle stiene brukt i dette dokumentet vil gjøre utseendemalen tilgjengelig for alle Drupal-nettsteder som kjøres av Drupal-installasjonen. Om man ønsker at de bare skal være tilgjengelig for ett nettsted bytter man ut sites/all med sites/<navnpånettsted>.

2 Utseendemaler - en introduksjon

Vi har til nå i kurset sett hvordan man skaper, strukturerer, vedlikeholder og presenterer innhold på et Drupal-nettstedet. Det som nå gjenstår er hvordan vi skal formatere innholdet, men andre ord hvordan vi skal designe nettstedet visuelt. Drupal har, som vi har sett, et helt klart og tydelig skille mellom utseende og innhold.

Det som skiller om et Drupal-nettsted som ser ut som et “typisk Drupal-nettsted” eller ei, er hvor dyktig man har vær til å lage egen utseendemal, eller hvorvidt man i det hele tatt har lagd utseendemal.

Men hva er egentlig en utseendemal? I Drupal er en utseendemal en samling av bilder, CSS og vanligvis HTML/PHP som bestemmer hvordan nettstedet og innholdet på nettstedet ser ut. Det er fullt mulig, dog ikke veldig vanlig, å lage utseendemaler til Drupal som bare benytter seg av CSS.

[dangerous l bend]

I denne teksten tar vi for oss utseendemal-motoren som heter PHPTemplate. Denne er en del av Drupal-kjernen og ferdiginstallert sammen med Drupal. Det er også motoren som er vanligst å bruke. Men det er mulig å bytte ut denne med andre motorer slik som Smarty eller PHPTAL. En full oversikt over tilgjengelige utseendemal-motorer finner man på http://drupal.org/project/Theme+Engines. Forskjellen på de ulike motorene, og bruk av alternative motorer går lagt utover det som vil undervises i dette kurset.

3 Hvorfor utseendemaler?

I Drupal er all kildekode tilgjengelig, og man kan dermed kanskje spørre hvorfor vi i det hele tatt skal bry oss med å lage utseendemaler. Kanskje man til og med faller for fristelsen å ikke gjøre det. Kildekoden er jo tilgjengelig, og det er jo langt enklere å bare “hacke” seg til endringene man måtte ha behov for. Ikke gjør det.

Kildekoden i Drupal-kjernen skal man ikke ha behov for å røre, og det av gode grunner. Drupal er helt bevisst lagd slik at man aldri skal ha behov for å endre kjernefunksjonaliteten når man lager nettsteder. Det gis stadig ut nye utgivelser av Drupal som blant annet reparerer kritiske feil i koden. Man skal derfor alltid sørge for at Drupal-installasjonen man bruker er oppdatert. Om man har “hacket” ting i kjernen, vil endringene man har gjort forsvinner hver eneste gang man oppdaterer, og dermed blir oppdatering en enorm jobb.

Ved å endre kjernen lager man i utgangspunktet en egen proprietær variant av Drupal som ikke lenger er kompatibel. Om man skulle oppdage noe feil i kjernen, rapporter det som en feil, fiks det gjerne og last opp en fiks som alle kan nyte godt av, men ikke lag din egen proprietære Drupal-variant. Da garanterer du at nettstedet ditt havarerer og havner i bakevja.

4 Hvordan Drupal genererer utseende

Alt innhold behandles i Drupal av moduler. Hvilke moduler varierer avhengig av innholdet. En node vil behandles av Node-modulen, en administrasjonsside vil behandles av System-modulen, mens annet innhold vil f. eks. behandles av Views-modulen som vi tok for oss på forrige forelesning. Felles for alle slike moduler er at de alle som en, etter å ha generert innhold, kaller på spesialfunksjonen theme(), som da vil ta seg av formatering av innhold. Figuren under illustrerer dette nærmere.

PIC

Som man ser av figuren tar utseendemal-motoren (theme engine) seg av plassering av elementer, formatering av elementer og lignende, mens selve CSS-en tar seg av utseende. Det er naturligvis mulig å gjøre dette på andre måter. Man kan f. eks. i stor grad benytte CSS for å bestemme plassering av elementer.

5 Vi slakter en utseendemal

Vi skal i dette dokumentet gjøre enkle endringer på en eksisterende utseendemal. Disse enkle endringene skal gjøre dere i stand til å forstå hvordan utseendemaler fungerer, og hvordan dere selv kan gjøre langt mer avanserte og komplekse endringer. En av oppgavene i dette kurset går ut på nettopp å lage deres egen utseendemal basert på en et eksisterende skjelett-mal.

Til deres eget prosjekt vil jeg anbefale at dere bruker Zen-utseendemalen

Dette dokumenet bør sees på som en lett introduksjon til utseendemaler i Drupal. Vi skummer bare toppen av det som er mulig. Emnet er såpass vidt og omfattende at det ber blitt skrevet hele bøker om det. Jeg anbefaler at dere bruker den anbefalte Drupal-pensum-boken som støttelitteratur.

I dette dokumentet skal vi gjøre noen enkle endringer på standardtemaet Garland. Det vil naturligvis være en dum ide å gjøre endringer i selve Garland temaet. For det første vil vi da ikke lenger ha tilgang til standard Garland, og for det andre vil vi miste endringene våre hver gang vi oppdaterer Drupal, siden Garland er en del av kjernen til Drupal.

Kopier mappen themes/garland som ligger under Drupal-mappen til sites/all/themes. Omdøp den deretter til mygarland og beveg deg til slutt inn i den nye mygarland-mappen: cp -r themes/garland sites/all/themes; mv sites/all/themes/garland sites/all/themes/mygarland; cd sites/all/themes/mygarland

Vi tar nå en titt på filene i mappen:

PIC

Legg merke til undermappen som heter minelli. Det har seg slik at Minelli-utseendemalen er en underutsendemal av Garland. Vi kommer ikke til å gå innom underutsendemaler i dette kurset, og siden vi skal bygge vår egen Garland-utseendemal kan vi trygt slette minelli-undermappen i vår nye mappe: rm -r minelli.

Legg merke til .css-filene og .tpl.php-filene som ligger i rot-mappa. Vi kommer tilbake til disse snart.

Legg også merke til screenshot.png-filen. Dette er filen som vil gi en liten forhåndsvisning av utseendemalen vår i listen over utseendemaler tilgjengelig på nettstedet. Ved å legge en .png-fil på 150x90 pixler i rot-mappen til en utseendemal og gi den navnet screenshot.png, vil Drupal automagisk forstå at dette er en forhåndsvisning av utseendemalen vår og vise den i listen over utseendemaler.

6 .info-filen

“Hovedfilen” til en utseendemal er en fil som heter <navnpåutseendemal>.info. I litteraturen omtales denne filen vanligvis som “.info-filen”. Denne filen har to hovedfunksjoner. Selve filen gjør at Drupal-kjernen oppfatter mappen den ligger i som en utseendemal-mappe, og innholdet av filen gir en beskrivelse av selve utseendemalen. Hva man beskriver i denne filen kommer vi tilbake til straks. Først må dere gi filen et nytt navn: mv garland.info mygarland.info.

Du skal nå åpne filen i din favoritteditor (jeg antar at det naturligvis er Emacs):

$Id: garland.info,v 1.5 2007/07/01 23:27:32 goba Exp $ 
name = Garland 
description = Tableless, recolorable, multicolumn, fluid width theme (default). 
version = VERSION 
core = 6.x 
engine = phptemplate 
stylesheets[all][] = style.css 
stylesheets[print][] = print.css 
 
; Information added by drupal.org packaging script on 20091216 
version = ”6.15” 
project = ”drupal” 
datestamp = ”1260996916”

Den første linjen er en “magisk” linje som brukes av versjons-kontrollsystemet til Drupal. Denne linjen er ikke påkrevd, med mindre man ønsker å laste opp utseendemalen man lager på drupal.org for å dele den med andre. Man kan fjerne den helt, men vi fjerner bare den Garland-spesifikke informasjonen nå. Rediger linjen slik at den ser ut som eksempelet nedenfor.

Vider endrer vi name til myGarland, skriver en beskrivelse av utseendemalen vår (description) og gir utseendemalen et versjonsnummer. Legg merke til at versjonsnummeret nå er VERSJON. Dette er en spesiell kode som gjør at Drupal henter versjonsnummeret fra pakkesystemet. Som nevnt skal vi ikke bruke pakkesystemet, så vi endrer denne til et tall, f. eks. 1.0

De siste 4 linjene er lagt til av versjons-kontrollsystemet til Drupal. Vi kan derfor trygt fjerne dem. Filen din burde nå se slik ut:

$Id $ 
name = myGarland 
description = Egen utseendemal basert paa Garland 
version = 1.0 
core = 6.x 
engine = phptemplate 
stylesheets[all][] = style.css 
stylesheets[print][] = print.css

Om du nå navigerer til oversikten over utseendemaler på nettstedet ditt (Administrer…Oppbygging…Utseendemaler), vil du oppdaget at det har dukket opp en ny utseendemal i listen over utseendemaler. Sørg for at denne er aktivert og satt som standard. Innen du gjør dette, sørg for at å sette administrator-utseendemalen til en annen utseendemal enn stadard slik vi viste på andre forelesning.

PIC

Vi tar nå en kjapp oppsummering av de opsjonene i .info-filen vi bruker som ikke er nevnt enda:

7 CSS-filer

stylesheet-opsjonene i .info-filen brukes for å angi hvilke .css-filer utseendemalen vår skal bruke. Som dere ser bruker Garland to css-filer. Den ene, style.css brukes på alle sider, mens print.css brukes til utskrift av sider til printer. Om vi f. eks. skulle ønske å legge til en ny .css-fil som het tull.css ville css-delen av .info-filen vår se slik ut ut:

stylesheets[all][] = style.css 
stylesheets[all][] = tull.css 
stylesheets[print][] = print.css

Vi skal ikke gjøre dette nå, da vi i denne tutorialen ganske enkelt skal endre eksisterende .css-filer. Merk også at stien til .css-filene er relativ til utseendemal-mappen vår. Om vi ønsket å samle .css-filene våre i en undermappe som het css kunne vi fint gjort dette, og endret .css-opsjonene til:

stylesheets[all][] = css/style.css 
stylesheets[print][] = css/print.css

Om man ikke inkluderer noen stylesheet-opsjoner i .info filen vil Drupal automatisk anta at det finnes en fil som heter style.css i utseendemal-mappa du har lagd, og bruke denne. Om den ikke finnes, vil Drupal bruke sin egen standard style.css-fil. Ved å gi “hoved-css-filen” vår navnet style.css sier vi til Drupal at den bare skal bruke denne og ikke inkludere noe innhold fra sin egen style.css. Dersom vi i stedet gir den et annet navn (vi kan velge hva som helst), vil Drupal bruke sin egen style.css og supplere den med innholdet av vår egen .css-fil.

Videre har ofte moduler egne .css-filer de benytter seg av. Man ønsker naturligvis ikke å endre disse da slike endringer vil skje på tvers av alle utseendemaler og dessuten forsvinne når man oppdaterer modulen. Derimot kan man enkelt overstyre disse i utseendemalen man lager, ved å inkludere .css-filer med samme navn.

Eksempel: System-modulen bruker en .css-fil som heter system-menus.css. Denne ligger under modules/system. Dere skal nå endre system-menyen slik at den får en tynn ramme rundt seg. Det første dere må gjøre er å kopiere filen modules/system/system-menus.css (relativ til drupal-installsjonen deres) til utseendemal-mappa vi har lagd som heter mygarland. Åpne filen i din favoritteditor (har du virkelig ikke konvertert til Emacs enda?). Og let deg frem til denne teksten:

ul.menu { 
  liststyle: none; 
  border: none; 
  textalign:left; /* LTR *
}

og rediger den slik:

ul.menu { 
  liststyle: none; 
  border: 1px solid black; 
  textalign:left; /* LTR *
}
[dangerous l bend]

Det vi nå har gjort er å endre en .css-fil. Vi kommer i utgangspunktet ikke til å gjennomgå CSS i dette kurset, da vi antar at det er kjent for de fleste. Om det er noen som måtte ønske en kort introduksjon til CSS, send meg en epost og vi kan ta det på en av de frie gruppetimene. Ellers vil jeg påpeke at CSS i utgangspunktet er rimelig enkelt, og det finnes en rekke gode introduksjoner til CSS på nett.

Det siste vi må gjøre er å inkludere .css-filen i utseendemalen vår. Legg til en ny linje i .info-filen slik at den ser ut som nedenfor:

$Id $ 
name = myGarland 
description = Egen utseendemal basert paa Garland 
version = 1.0 
core = 6.x 
engine = phptemplate 
stylesheets[all][] = style.css 
stylesheets[all][] = systemmenus.css 
stylesheets[print][] = print.css

Hver gang man har gjort en slik endring, må man tømme nettstedets mellomlager før den vil vises på nettstedet (Administrer…Innstillinger…Ytelse…Tøm mellomlagrede data). I tillegg må man vanligvis tømme “utseendemal-mellomlager. Dette gjøres ved å de-aktivere, og så re-aktivere utseendemalen man jobber på. Høres tungvindt ut, ikke sant? Vell. Heldigvis har vi installert devel-modulen. Naviger til Adminstrer…Innstillinger…Devel settings og hak av for valget Rebuild the theme registry on every page load, så skjer dette automatisk for oss. Bare husk å slå av dette valget straks man er ferdig med å utvikle utseendemalen.

Nettstedet ditt burde nå se omtrent slik ut:

PIC

Spørsmålet nå er hvordan man kan vite hvilken .css-fil man skal endre for å endre ulike elementer? Tommelfingerregelen er at “hoveddesignet” gjøres i “hoved-css-filen” til nettstedet, mens design av elementer generert av moduler (også kjerne-moduler) gjøres i .css-filer i modulen (som da må kopieres inn og inkluderes i utseendemalen vår slik som beskrevet over). Dette høres kanskje vanskelig ut, og mer som ren gjetting?

Heldigvis har vi installert en modul som heter Drupal for firebug samt Firebug-plugin til Firefox. (Dette ble presentert i forrige forelesning). Ved å velge Tools…Firebug…Inspect elements i Firefox (eller trykke hurtigtasten Ctrl+Shift+c), kan man holde musen over et hvilket som helst element på Drupal-nettstedet vårt og få opp en beskrivelse av alle CSS-innstillingene som dette elementet benytter seg av, og hvilke filer disse ligger i.

PIC

Før du går videre bør du nå leke deg litt med å endre .css-filer. Forsøk både å gjøre endringer i den eksisterende style.css filen i utseendemalmappa du har lagd deg og å finne .css-filer i moduler og overstyre dem ved å kopiere dem før endringer gjøres. Om du trenger tips til oppgaver kan du forsøke følgende: Endre skriftfargen på alle lenker på nettstedet ditt slik at de blir røde, samt endre “stjernene” som vises i mobiltelefoninnholdstypen vi lagde i CCK-forelesningen slik at de får en svart ramme rundt seg.

8 Mer om .info-filen - javascript

Enkelte utseendemaler (også Drupal-kjernen) tar i bruk javascript-filer. Man kan, på samme måte som med .css-filer lage egne javascript-filer og/eller overstyre eksisterende javascript-filer når man lager utseendemal. Jeg kommer ikke til å gå gjennom hvordan dette gjøres i dette kurset, da jeg antar de fleste, om ikke alle grupper ikke kommer til å ha behov for å gjøre dette på nettsidene sine. Jeg nevner bare derfor at opsjonen man benytter seg av i .info-filen tilsvarer opsjonen man benytter seg av for .css:

scripts[] = tullejavascript.js

9 Templates

Du har sikkert allerede oppdaget at det finnes “template”-filer i utseendemalmappa vi har kopiert. Templates er spesielle filer som beskriver plassering av innhold, og som slutter på filendelsen .tpl.php.

Som vi har sett bruker man .css-filer for å bestemme utseende til elementene på nettstedet vårt. Templates brukes for å bestemme plasseringen av de samme elementene. Alt innholdet på nettstedet vårt plasseres ved hjelp av Template-filer, og alt innholdet kjøres gjennom ulike Templates. Alt fra Noder, blokker og kommentarer til selve siden som vises. Template-filer navngis ut fra hvilke elementer de kontrollerer, slik som node.tpl.php som naturligvis kontrollerer noder. Drupal har et avansert template-hierarki man kan bruke for å bestemme når de ulike Template-filene skal brukes og ikke. Et raskt eksempel er at mens node.tpl.php vil påvirke alle noder, vil node-story.tpl.php bare påvirke noder som har innhold av type story.

PIC

[dangerous l bend]

Vi kommer ikke til å gjennomgå template-hierarkiet noe videre her. Dere får selv i oppgave å utforske dette hierarkiet. På denne siden vil dere finne en god oversikt over Templates som er tilgjengelig i Drupals kjerne, samt en oversikt over det nevnte hierarkiet.

Vi har nå pratet om hva en Template gjør, men ikke om hvordan den fungerer. En Template består for det meste av (X)HTML-kode samt noe PHP-kode. (X)HTML-koden er koden som plasserer innholdet på nettstedet, mens PHP-koden er den som genererer selve innholdet, eller elementene om man vil. Dette illustreres med et (helt banalt) eksempel:

<html> 
<head> 
<title><?php print $head_title; ?></title> 
</head 
<body><?php print $content;?></body> 
</html>

Dette er et eksempel på en veldig simpel page.tpl.php som er Template-en som genererer innholdet for en hel side på nettstedet vårt. Jeg går ut fra at alle ser hva som er HTML-kode i eksemplet, og også at alle legger merke til begge PHP-snuttene som altså gjør følgene:

Vi skal nå utføre et praktisk eksempel som illustrerer hvordan man jobber når man skal redigere Templates. Vi har bestemt oss for å endre nodevisningene våre slik at datoen og navn på forfatter vises helt på toppen over tittelen på noden: Gå til en side på nettstedet som viser en node. Hak av Themer info boksen, og klikk på elementet du ønsker å endre (i dette tilfelle navn og forfatter). I sprettoppvinduet kan vi nå se hvilken Template det er som håndterer dette elementet, altså hvilken Template vi må endre. I dette tilfelle node.tpl.php.

PIC

Ved å klikke på navnet på Template-en får vi om mer informasjon vi trenger. Vi får opp informasjon om hvor Template-filen ligger, samt informasjon om andre mulige Template-filer i hierarkiet som kunne blitt brukt. I dette tilfelle får vi beskjed om at vi også kunne brukt Template-navnet story-node.tpl.php. Fra før av vet vi at dette betyr at vi kan, ved å velge story-node.tpl.php, la endringene bare gjelde for noder av type story. Om vi ønsket å gjøre dette, og vi ikke allerede hadde en story-node.tpl.php-fil fra før av, ville prosedyren være å kopiere vår eksisterende node.tpl.php til story-node.tpl.php.

Vi ser av stien til node.tpl.php som vi får oppgitt at den allerede ligger i utseendemalen vår. Om den ikke gjorde det, så måtte vi huske å kopiere filen til utseendemalmappa vår før vi endret den.

PIC

Du skal nå åpne node.tpl.php:

<?php 
// $Id: node.tpl.php,v 1.5 2007/10/11 09:51:29 goba Exp $ 
?> 
<div id=''node<?php print $node>nid; ?>” class=”node<?php if ($sticky) { print ' sticky'} ?><?php if (!$status) { print ' nodeunpublished'} ?>> 
 
<?php print $picture ?> 
 
<?php if ($page == 0): ?> 
  <h2><a href=”<?php print $node_url ?>” title=”<?php print $title ?>><?php print $title ?></a></h2> 
<?php endif; ?> 
 
  <?php if ($submitted): ?> 
    <span class=”submitted”><?php print $submitted; ?></span> 
  <?php endif; ?> 
 
  <div class=''content clearblock''> 
    <?php print $content ?> 
  </div> 
 
  <div class=”clearblock”> 
    <div class=”meta”> 
    <?php if ($taxonomy): ?> 
      <div class=''terms''><?php print $terms ?></div> 
    <?php endif;?> 
    </div> 
 
    <?php if ($links): ?> 
      <div class=”links”><?php print $links; ?></div> 
    <?php endif; ?> 
  </div> 
 
</div>

Vi sa at vi skulle flytte datoen og forfatter-informasjonen opp over tittelen på noden. De fleste variabelnavnene som er brukt i Drupal er ganske selvforklarende. Jeg kan avsløre at vi skal flytte HTML-en rundt $submitted opp over HTML-en til $title. Template-en vår blir da seende slik ut:

<?php 
// $Id: node.tpl.php,v 1.5 2007/10/11 09:51:29 goba Exp $ 
?> 
<div id=”node<?php print $node>nid; ?>” class=”node<?php if ($sticky) { print ' sticky'} ?><?php if (!$status) { print ' nodeunpublished'} ?>> 
 
<?php print $picture ?> 
 
<?php if ($submitted): ?> 
  <span class=''submitted''><?php print $submitted; ?></span> 
<?php endif; ?> 
 
<?php if ($page == 0): ?> 
  <h2><a href=”<?php print $node_url ?>” title=”<?php print $title ?>><?php print $title ?></a></h2> 
<?php endif; ?> 
 
  <div class=”content clearblock”> 
    <?php print $content ?> 
  </div> 
 
  <div class=”clearblock”> 
    <div class=”meta”> 
    <?php if ($taxonomy): ?> 
      <div class=”terms”><?php print $terms ?></div> 
    <?php endif;?> 
    </div> 
 
    <?php if ($links): ?> 
      <div class=”links”><?php print $links; ?></div> 
    <?php endif; ?> 
  </div> 
 
</div>

Lagre node.tpl.php-filen vi har gjort endringer på, og ta nå en titt på nettstedet vårt. Det burde nå se omtrent slik ut:

PIC

Om endringen ikke er synlig, tøm nettstedets mellomlager, og forsøk igjen.

Før du går videre, bør du leke litt med og utforske Templates. Sørg for å både endre Templates som finnes i utseendemalmappa vår, og Templates du selv må kopiere slik at de overstyres. Trenger du tips til oppgaver kan du forsøke å flytte “mission statement” fra toppen av siden og ned på bunnen av siden, samt endre CCK-felt slik at merkelappen (label) vises til høyre for feltet, i stedet for til venstre.

10 Regioner

Om du allerede har tatt en titt på de ulike utseendemalene som er tilgjengelig for Drupal har du kanskje oppdaget at hvor man får lov å plassere blokker på nettsiden avhenger av hvilken utseendemal man benytter seg av. Når man tenker seg om er jo dette rimelig, da hvor man har mulighet for å plassere innhold vil variere fra nettsted til nettsted avhengig av designet. Men hvordan får man dette til?

Svaret er todelt. Man må endre på to ulike filer, nemlig .info-filen tilhørende utseendemalen, samt page.tpl.php. La oss først ta en titt på .info-filen:

Stedene man får lov å plassere blokker kalles i Drupal for regioner. Som standard har man 5 regioner som vil brukes, dersom utvikler av utseendemalen ikke ønsker å overstyre dette. Dersom dere aktiverer utseendemalen vi jobber på (evt. Garland utseendemalen) og navigerer dere til Administrer…Oppbygging…Blokker vil dere se disse standardregionene:

Man kan legge til nye regioner i .info-filen. Vær dog klar over at disse fem standardregionene bare brukes dersom man ikke har definert noen regioner i det hele tatt. Om man ønsker å legge til en ny region samtidig som man beholder eksisterende standardregioner er man nødt for å også legge til standardregionene. Vi skal legge til en region som heter irriterende og som legger seg øverst oppe på siden nedenfor toppteksten. Vi må da legge til standardregionene samt en ekstra region i .info-fila vår:

regions[header] = Header 
regions[footer] = Footer 
regions[left] = Left sidebar 
regions[right] = Right sidebar 
regions[content] = Content 
regions[irriterende] = Irriter bruker

Formatet for hver region er regions[<maskinlesbartnavn>] = <Menneskelesbart Navn>.

Før vår nye region fungerer må vi i tillegg fortelle Drupal hvor vi ønsker at innholdet i regionen skal plasseres rent fysisk på siden. Dette gjøres i page.tpl.php-filen. Vi sa at vi skulle plassere regionen mellom header-regionen og menyen. Let gjennom filen til du finner header div-taggen samt primary-links. Og lim inn koden nedenfor. Jeg har tatt med en linje over, og en linje under selve koden dere skal lime inn, slik at det skal være lettere å finne fram:

1</div> 
2 
3<?php if ($irriterende):?> 
4  <div id=”irriterende”> 
5    <?php print $irriterende;?> 
6  </div> 
7<?php endif; ?> 
8 
9<?php if (isset($primary_links)) : ?>

Jeg tar en gjennomgang linje for linje, og forklarer hva koden gjør:

  1. Eksisterende kode
  2. ...
  3. Dersom irriterende-regionen har innhold (altså at vi har puttet noe i den)
  4. XHTML-kode som lager en DIV
  5. Print innholdet av irriterende-regionen
  6. XHTML-kode for å avslutte DIV-en
  7. Slutt på dersom
  8. ...
  9. Eksisterende kode
[dangerous l bend]

Husk at dette bare er et eksempel, og at man gjerne vil inkludere css-tagger slik at man kan bestemme utseende i .css-filene

Tøm nettstedets mellomlager og naviger til Administrer…Oppbygging…Blokker og du vil se at vi nå har fått en “Irriter bruker”-region:

PIC

Dra og slipp en blokk (f. eks. “Laget av Drupal”) inn i den nye regionen du har lagd, og trykk på Lagre blokker-knappen. Naviger deg til forsiden, og du vil nå se at Drupal-logoen har havnet i den nye regionen vår øverst på siden:

PIC

11 Mer om .info-filen - andre muligheter

Det finnes en del saker man kan spesifisere i .info-filen som vi ikke har gått gjennom her. Vi kommer ikke til å gå nærmere inn på dem her, og anbefaler at dere kikker innom denne siden for å få en oversikt. Særlig bør dere legge merke til Features som brukes for å fortelle Drupal hva slags Features (f. eks. logo, sidenavn, søkeboks, mv) som er tilgjengelig i utseendemalen man har lagd.

Jeg skal også nevne at det er mulig å spesifisere egne interne variabler i .info-filen om man skulle ha behov. Et godt eksempel på hvordan dette kan brukes finnes i Zen-utseendemalen.

12 templates.php

Vi har nå sett på hvordan man kan endre utseende på elementer (ved hjelp av css) og hvordan man kan endre hvor på siden ulike elementer skal plasseres. Det gjenstår fortsatt en ting man må kunne når man skal lage utseendemaler: Muligheten for å endre selve innholdet før det presenteres. Det er her utseendemal-mulighetene i Drupal virkelig begynner å bli kraftige.

[dangerous l bend]

Vær klar over at for å få noen nytte ut av denne delen av tutorialen må man ha kjennskap til PHP. Det har lite for seg å lese videre om man aldri har brukt, eller har veldig lite kjennskap til PHP. Det er fullt mulig å gjennomføre kurset uten å ta i bruk templates.php, selv om man kanskje ikke vil se seg like fornøyd med sluttresultatet.

Når vi skal gjøre slike endringer trenger vi bare forholde oss til en eneste fil: template.php, altså en ren PHP-fil. Før vi tar en titt på denne trengs en liten forklaring: Som vi har vært inne på i en tidligere forelesing kontrolleres Drupal i stor grad ved hjelp av Hooks. (Hooks er alfa og omega når man skal utvikle egne moduler - noe vi dessverre ikke får tid å gjennomgå i dette kurset.) De fleste av dere vil allerede være kjent med hooks, men da gjerne under navnet Callback functions. Enkelt forklart er hooks metoder/funksjoner Drupal eksekverer når noe “skal gjøres”. Finurlig navngivningspolitikk sørger for at utvikler vet hvilket navn man skal gi til en hook for en bestemt funksjon, og Drupal vil automatisk lette etter hooks ut fra deres navn, og bruke dem dersom de finnes.

I tillegg til hooks, legger Drupal alt innhold i variabler med “kjente navn”, og man kan dermed gå inn å endre på innholdet, dersom man har kjennskap til variabelnavnet. Vi skal ta en titt på å overstyre både variabler og Hooks snart. Men først må dere vite hvordan Drupal bestemmer hvilken hook den skal bruke. Drupal ser etter hooks etter første ord i metodenavnet i stigende rekkefølge. La oss si at vi har en hook som heter tull. Drupal vil da først lete etter en metode som heter <utseendemalnavn>_tull(), hvor <utseendemalnavn> er det navnet på utseendemalen vår (med andre ord det som står før punktum i .info-filnavnet vårt). Om metoden ikke finnes vil Drupal se etter metoden <utseendemal-motor>_tull(), hvor <utseendemal-motor> er navnet på utseendemal-motoren i bruk (dere kan fint ignorere dette siden vi ikke har gjennomgått utseendemal-motorer i dette kurset). Om ingen av disse metodene finnes vil den bruke theme_tull(), som er Drupals egen interne metode (ergo en metode vi aldri skal røre, eller opprette).

Før eksemplene vil jeg også nevne at det er fullt mulig å opprette egne variable, i tillegg til Drupal-variablene som allerede har innhold, og bruke disse i utseendemalen man lager, men dette er et avansert emne, vi ikke kommer til å gjennomgå her.

12.1 Overstyre variabler

Drupal har spesielle hooks som blir utført etter at innholdet er generert, men før innholdet blir kjørt gjennom Templates-systemet. Det er disse vi bruker for å endre på innholdet i variabler. Hook-en som utføres etter at innholdet til en node heter preprocess_node. (Hook-ene for andre innholdstyper får dere i oppgave å finne selv.)

Vi skal nå gjennomføre et praktisk eksempel, som forhåpentligvis gjør dette litt mer forståelig. Vi skal gjøre noe, som svært mange Drupal-administratorer ønsker å gjøre, og som det stadig spørres om i ulike fora på nett. Vi skal endre datoen og brukernavnet som vises under hver node på nettstedet (med andre ord elementet vi flyttet forrige kapittel). “tir, 03/09/2010 - 18:02 — Brendan Johan Lee” skal bli “Skrevet 3. mars 2010”

Vi går nå tilbake til node.tpl.php-filen vi tidligere endret, for å finne ut hvilken variabel det er som faktisk inneholder dette elementet. Om man ikke vet hvilken Template som skriver ut elementet, benytter man metoden beskrevet i forrige kapittel for å finne Template-filen.

<span class=”submitted”><?php print $submitted; ?></span>

Vi ser altså at variabelen vi er på jakt etter heter $submitted

Nå er det på tide å åpne template.php. Dere vil oppdage at det er “masse” innhold der allerede. Ikke bry dere om dette enda, dere vil forstå mer av innholdet etterhvert som dere får mer trening. Alt innholdet er knyttet til utseendemal-motoren, og om du husker tilbake et par avsnitt, så vil vi ved å knytte våre hooks til utseendemal overstyre disse. (Om du ikke forstod noe som helst av dette - ikke fortvil. Bare bla forbi alt innholdet i filen).

Lim inn følgende innhold nederst i filen:

1function mygarland_preprocess_node(&$vars) { 
2   $vars['submitted'] = t('Skrevet ') . 
3    format_date($vars['node']>created, 'custom'' j. F, Y'); 
4}

Vi tar det linje for linje:

  1. Overstyr preprocess_node hook-en
  2. Sett variabelen til “Skrevet ” konkatinert med
  3. Formater nodens opprettelsesdato 1

Tøm nettstedets mellomlager, og naviger deg til nettstedets forside. Den vil nå se omtrent slik ut:

PIC

[dangerous l bend]

Du la kanskje merke til at vi brukte en merkelig metode t() på linje 2. Årsaken er at Drupal kan operere på mange ulike språk. Derfor skal all tekst som legges inn i moduler eller utseendemaler legges inn ved hjelp av t()-metoden som sørger for at teksten blir tilgjengelig for oversettelse, og at riktig språk brukes dersom teksten er oversatt. Drupal-standarden sier at man alltid skal bruke engelsk tekst i t()-metoden, og heller lage en oversettelsesfil dersom man lager nettstedet i et annet språk. Årsaken til dette er for å sørge for at mest mulig av Drupal blir oversatt. De fleste Drupal-oversettere kan engelsk, samt et annet språk. Om man laster opp noe til Drupal på norsk, vil det neppe noensinne bli oversatt. Siden vi ikke kommer til å gå nærmere inn på hvordan man lager oversettelsesfiler i dette kurset, kommer vi ikke til å kreve dette av dere. Men for de som kommer til å bruke Drupal også etter kurset, er dette en veldig bra vane å legge seg til med en gang.

12.2 Overstyre hooks

Det siste vi skal se på er hvordan man overstyrer selve hooks-ene. Noen ganger ønsker vi å endre informasjon man ikke kan, eller som det er svært tungvindt å endre etter at den har blitt plassert i en variabel. For å gjøre dette må man overstyre selve hook-en som generer informasjon, i motsetning til å bare endre variabelen slik vi gjorde over.

For å illustrere bedre hvorfor dette noen ganger må gjøres, og hvordan det gjøres skal vi ta et eksempel. Det vi skal gjøre er å endre skilletegnet mellom Brødsmulene. I Garland brukes skilletegnet >. Vi ønsker å bytte dette ut med ::.

Det første vi må gjøre er å finne ut hvilken hook som genererer brødsmulene. Gå inn på nettstedet ditt, og aktiver Themer info, og klikk deretter på brødsmulene. Man vil da finne navnet på hook-en som har generert brødsmulene, som vi ser er theme_breadcrumb():

PIC

Man ser også hvilke navn man kan bruke for å overstyre denne hook-en, og i hvilken rekkefølge overstyringen gjøres:

PIC

For å finne og kopiere selve hook-metoden, er det vanligvis nok å klikke på metodenavnet (i hvertfall når det er tale om hooks som er en del av Drupal-kjernen). Da videresendes man til Drupals API-dokumentasjon for selve hook-en, hvor man vanligvis får oppgitt hele metoden, slik at man kopiere den. Dersom dette ikke er tilfelle (forsøk for eksempel å finne hook-en som genererer stjernene i Mobiltelefontypen vi lagde i CCK-forelesningen) må man selv finne metoden i Drupals filer.

Hvordan finner man da hooks som ikke er beskrevet i API-dokumentasjonen? Kjerne-hooks ligger i .inc-filer i Drupals includes-mappe, mens hooks tilhørende moduler ligger i en av filene tilhørende modulen. Å lete seg fram til funksjonen er både tidkrevende og frustrerende. Derfor kan vi ta i bruk *nix-verktøy for å hjelpe oss.

Om vi f. eks. ønsker å finne hook-en som heter theme_fivestar_static kjører vi følgende kommando i rot-mappa til Drupal:

find . exec grep 'theme_fivestar_static' {} ;

som gir oss følgende informasjon:

./sites/all/modules/fivestar/fivestar.module:1395:function theme_fivestar_static($rating, $stars = 5, $tag = 'vote'{ 
./sites/all/modules/fivestar/fivestar.module:1462:function theme_fivestar_static_element($value, $title = NULL, $description = NULL) {

Altså ligger hook-en i filen sites/all/modules/fivestar/fivestar.module på linje nr 1395.

Men tilbake til eksempelet. Det du nå skal gjøre er å kopiere metoden vi fant i API-dokumentasjonen:

function phptemplate_breadcrumb($breadcrumb) { 
  if (!empty($breadcrumb)) { 
    return '<div class=”breadcrumb”>'. implode(' > '$breadcrumb) .'</div>'
  } 
}

inn nederst i template.php og gi den et nytt navn, i tråd med navngivningskonvensjonen vi tittet på, samt bytte ut >-tegnet med ::

function mygarland_breadcrumb($breadcrumb) { 
  if (!empty($breadcrumb)) { 
    return '<div class=”breadcrumb”>'. implode(' :: '$breadcrumb) .'</div>'
  } 
}

Naviger deg til en del av nettstedet ditt hvor brødsmulene vises, og siden burde nå se omtrent slik ut:

PIC

12.3 Øvelse gjør mester

Med mindre du allerede hadde kjennskap til utseendemaler i Drupal innen du leste dette dokumentet, er du nå høyst sannsynlig forvirret. Fortvil ikke, det er forventet. Sœrlig dette med overstyring av hooks og variabler er kompliserte greier, og det er ikke noe man lærer seg ved å lese et par avsnitt i en tutorial. Gå tilbake, og les gjennom de siste to kapitlene grundig, og forsøk å forstå hva som skjer. Deretter bør du sette deg ned og begynne å utforske mulighetene. Prøv å bruk disse metodene for å lage kule design-features til nettstedet ditt. Lek og lær.

Det er bare fantasien som begrenser hva man kan få til med disse metodene, men man behersker dem ikke i løpet av en halvtime. Øvelse gjør mester.

13 Til inspirasjon

Her kommer et forslag til de som enda ikke har fått nok (og de som kanskje ønsker å gjøre re-maken deres såpass bra at den kanskje tas i bruk senere). På denne siden finnes det en samling av det som kalles snippets. Snippets er små kodesnutter som kan brukes i utseendemaler, moduler, visninger, blokker, mm for å utvide funksjonaliteten til Drupal. Dette er altså en samling av kodesnutter som Drupal-administratorer har lagd for sine nettsider, og mener er såpass nyttige at de ønsker å dele dem med verden. Her finner man alt fra en kodesnutt for å vise brukerne av nettstedet som har høyest aktivitet til en kodesnutt som lar en ha ikoner i menyene.

Her er det altså mye inspirasjon å hente, og man kan spare mye tid og arbeid ved å se om det allerede finnes en snippet som gjør det man ønsker. Bare vær klar over at snippets er brukerbidrag og på ingen som helst måte kvalitetskontrollert, så ikke bruk dem helt ukritisk.