Spring naar hoofdtekst

Liturgische lezingen in PHP

Geplaatst op door ,
Laatste aanpassing op .

Inleiding

Dit is deel 2 van een tweedelig artikel over een online feestdagkalender met archief van bijbehorende bijbellezingen. Lees ook het eerste deel.

Liturgisch jaar

De katholieke kerk maakt gebruik van een driejarige cyclus van lezingen. Hierin wordt elke drie jaar dezelfde lezing voor een zelfde zondag gelezen. Men spreekt van het Liturgisch jaar A, B of C. Om te weten welke lezing voor een bepaalde dag geldt, moet eerst worden bepaald in welk Liturgisch jaar de datum valt.

De functie _getLiturgicYear() verwacht als argument een DateTime-object; een datum waarvoor wordt bepaald in welk liturgisch jaar hij ligt. Op basis van de datum van Kerstmis (25-12) in dat jaar, wordt met _getFirstAdvent() de datum van de 1e Advent bepaald. Daarna wordt het jaartal eerst door 100, dan door 3 gedeeld. De rest van deze berekeningen bepaalt in relatie tot de 1e Advent in welk jaar de datum valt.

<?php
class LiturgischJaar
{
    const JAAR_A = 'A';
    const JAAR_B = 'B';
    const JAAR_C = 'C';
}

private static function _getFirstAdvent(\DateTime $christmas)
{
    $dayChristmas = (int)$christmas->format('w');
    if ($dayChristmas == 0) {
        $dayChristmas = 28; 
    } else {
        $dayChristmas = 21 + $dayChristmas; 
    }
    $diAdvent1 = new \DateInterval('P'.$dayChristmas.'D');
    return self::wrap($christmas)->sub($diAdvent1);
}

private static function _getLiturgicYear(\DateTime $dt)
{
    $christmas = new \DateTime($dt->format('Y').'-12-25');
    $firstAdvent = self::_getFirstAdvent($christmas);

    $year = (int)$dt->format('Y');
    $year = ($year % 100);
    $x = ($year % 3);

    switch($x){
    case 0: 
        return ($dt >= $firstAdvent) ? self::JAAR_C : self::JAAR_B;
    case 1: 
        return ($dt >= $firstAdvent) ? self::JAAR_A : self::JAAR_C;
    case 2: 
        return ($dt >= $firstAdvent) ? self::JAAR_B : self::JAAR_A;
    }
}

Bron

In het verleden bood de Katholieke Bijbelstichting een online archief aan met liturgische lezingen van alle zon- en feestdagen. Er was echter geen hapklare manier om de bezoekers van 'mijn' site van Parochiecluster U.o.W. hier naar door te verwijzen. Dus heb ik het archief geautomatiseerd toegankelijk gemaakt. Onderstaande code leest en verwerkt de (gecachte) originele XML-bestanden uit die tijd.

Code

De code werkt in grote lijnen als volgt:

  • Als eerste wordt bepaald in welk liturgisch jaar de datum valt, en welke (feest-) dag het is.
  • Bestaat er al een XML-bestand van deze specifieke datum? Dan is dat onze oplossing.
  • Is de ddatum geen bekende feestdag (DAG_ONBEKEND)? Dan hoeven we ook niet te zoeken in de cache-bestanden.
  • Is de datum 24 of 25 december? Kies dan voor de vaststaande XML-bestanden van het hoogfeest van Kerstmis.
  • Verzamel alle cachebestanden en bepaal voor elk het liturgisch jaar en de feestdag. Komen beide overeen met de gezochte datum? Dan is dat onze oplossing.
<?php
$l = new LiturgischJaar($date);
$d = (int)$date->format('d');
$m = (int)$date->format('m');

$xmlfile = sprintf('cache/bijbelnet_%1$s.xml', $date->format('Y-m-d'));
if (file_exists($xmlfile)) {
    $this->sourceURL = $xmlfile;
    return;
}

if ($this->dag == LiturgischJaar::DAG_ONBEKEND) {
    $this->sourceURL = null;
    return;
}

if ($m == 12 && $d == 24) {
    $this->sourceURL = 'cache/bijbelnet_0000-12-24.xml';
    return;
}

if ($m == 12 && $d == 25) {
    $this->sourceURL = 'cache/bijbelnet_0000-12-25.xml';
    return;
}

$cachefiles = array();
if ($dir = opendir('cache')) {
    while (false !== ($f = readdir($dir))) {
        if (!is_dir($f)
            && preg_match(
                '/^bijbelnet_[12][0-9]{3}(?:-[0-9]{2}){2}.xml$/i',
                $f
            ) > 0
        ) {
            $cachefiles[] = $f; 
        }
    }
    closedir($dir);
    asort($cachefiles); 
}

foreach ($cachefiles as $cf) {
    $matches = array();
    preg_match(
        '/^bijbelnet_([12][0-9]{3}(?:-[0-9]{2}){2}).xml$/i',
        $cf,
        $matches
    );
    $dt = new \DateTime($matches[1]);
    $lj = new LiturgischJaar($dt);

    if ($lj->jaarABC == $this->jaarABC && $lj->welkeDag == $this->dag) {
        $this->sourceURL = 'cache/'.$cf;
        return;
    }
}

Caching

Hoewel ik het nooit objectief heb gemeten, was ik er van overtuigd dat het telkens weer opnieuw analyseren van alle cachebestanden enorm veel tijd zou kosten. Daarom bedacht ik een caching-oplossing waarbij ik in één geautomatiseerde ronde voor alle cachebestanden het liturgisch jaar en de feestdag bepaalde, en dat resultaat als herbruikbaar bestand bewaarde.

<?php
private static $_datematchesfile = 'cache/datematches.cache';
private $_datematches = array();

public function __construct(\DateTime $date)
{
    // Bestaat het cache-bestand? Lees het dan in.
    if (file_exists(self::$_datematchesfile)) {
        $this->_datematches = unserialize(
            base64_decode(file_get_contents(self::$_datematchesfile))
        );
    } else {
        // Zo niet, maak het dan aan.
        $this->_writeCache();
    }

    // Komt de gezochte datum al voor in het cache-geheugen?
    if (array_key_exists($date->format('Y-m-d'), $this->_datematches)) {
        $this->sourceURL
            = 'cache/bijbelnet_'.
            $this->_datematches[$date->format('Y-m-d')].
            '.xml';
        return;
    }

    // ...

    if ($lj->jaarABC == $this->jaarABC && $lj->welkeDag == $this->dag)
    {
        // Voeg, tijdens het doorlopen van alle XML-bestanden, alle
        // bepaalde feestdagen toe aan het cache-geheugen.
        $this->_datematches[$date->format('Y-m-d')] = $matches[1]; 
        $this->_writeCache();

        $this->sourceURL = 'cache/'.$cf;
        return;
    }
}
private function _writeCache()
{
    file_put_contents(
        self::$_datematchesfile,
        base64_encode(serialize($this->_datematches))
    );
}

Conclusie

Met de code uit deze tweedelige artikelreeks heeft de parochiesite een bijna eeuwigdurende kalender voor de zondagse bijbellezingen. Het was voor mij een uitdagend project waarin ik, samen met pastoor Ed Smeets, de al dan niet geschreven regels van het kerkelijk en liturgisch jaar in code heb gegoten.

Toen we er twee weken geleden achter kwamen, dat één bepaalde feestdag ontbrak, moest ik op zoek naar hoe het ook weer allemaal werkte. Dan loont het om een of twee artikeltjes te schrijven. Al is het maar als eigen documentatie voor later!

N.B. Als er behoefte is aan een beschrijving van het low-level dirty-work met de genoemde XML-bestanden, kan ik daar een nieuw artikel aan wijden. Laat het me weten, bijvoorbeeld via Contact!

Inhoudsopgave

Klik op één van de onderstaande categorieën om de lijst met artikelen te filteren.