Programming Support

Vorbemerkung:

  • alle Beispiele ohne Garantie auf Fehlerfreiheit.
  • wer die API und das concrete5 Framework kennt und Erfahrung in der PHP Programmierung besitzt kann jetzt zur concrete5 API Docu wechseln.
    Hier sollen nur kleine Hilfestellungen gegeben werde, für WebDesigner, die keine Programmierer sind, aber schon mal PHP Code in den Seitentypen modifiziert haben.

Video Einbettung mit dem Block-Element Video

Im Standard Reportoire von concrete5 gibt es das Blockelement Video. Damit ist es möglich lokal abgelegte Videos anzuzeigen. Dank HTML5 sollte dies ohne Probleme möglich sein, weil dazu ein eigenes "TAG" geschaffen wurde, das "video" Tag. Näheres dazu findet man unter: w3schools

Am besten ist es - um Browserkompatibilität sicherzustellen - das Video in den 3 Formaten vorzuhalten:

  • MP4
  • WebM
  • ogg

Im Netz gibt es dazu eine fülle von Konvertern, beispielsweise folgende Website:
Videokonverter

Das Video Block Element besitzt für alle 3 Formate die entsprechenden Zuweisungsmöglichkeiten, wenn sich die 3 Formate in der Datei-Ablage befinden.

Will man das Video dann beispielsweise im Seiten-Header großformatig automatisiert ohne dem Starter-Control mit Ton abspielen, dann stellt man fest, dass es nicht auf allen Browsern funktioniert, beispielsweise nicht mit dem FireFox unter Windows. Meine Recherche ergab, dass "autoplay" nur mit "muted" (ojhne Ton) funktioniert. Und ohne das Start-Control lässt sich dann das Video nicht starten.

Mit folgendem WorkAround lässt sich das Video zumindest starten, wenn die Kobination "autoplay" ohne "muted" und ohne anfängliches Control gewünscht ist. Dazu kopieren sie eine view.js Datei in das Video Block-Element mit folgendem Inhalt:

window.addEventListener('load', async () => {

let video = document.querySelector('video[autoplay]');

try {

if(video.muted) {

video.muted = false;

}

await video.play();

} catch (err) {

video.controls = true;

}

});

Damit das DOM Element gefunden werden kann, muss natürlich das Attribut "autoplay" gesetzt sein, am besten man modifiziert dazu auch gleich die view.php Datei des video Blockelementes. Und wenn man die view.php schon anpasst, dann kann man auch gleich eine ID vergeben und das DOM Element mit

video = document.getElementById("idwert")

abfragen.

Anpassung von autonav für ein Seitenleiste Menü

Hier wird kurz die Lösung für folgende Anforderung erläutert:

Es soll ein linker Untermenü-Block erstellt werden, der ab einer bestimmten Seite die weitergehende Navigation anzeigen soll. Prinzipiell kann dazu natürlich auch die page_list verwendet werden, jedoch nicht wenn weitere Ebenen notwendig sind und die Eigenschaften des autonav Blockelementes benötigt werden.

Problem: ist das Flag $ignore_exclude_nav gesetzt, um zu verhindern, dass ein DropDown im MainMenü erscheint, dann erscheint es natürlich auch nicht im linken Seitenmenü. Was tun?

Lösung:

1) unter autonav/templates eine neue Datei anlegen (z.B. Kopieren der view.php im concrete Ordner von autonav) und anpassen d.h. kapseln mit eigenen CSS Klassen.

2) jetzt einfach den Aufruf

$navItems = $controller->getNavItems(true);

wie oben mit dem Parameter "true" versehen, bedeutet, das Flag $ignore_exclude_nav wird dadurch ignoriert und es werden alle Untermenüs aufgelistet.


Leere Blöcke NICHT im Frontend Anzeigen

Hier eine Funktion, die prüft, ob ein Block leer ist:

public static function isEmptyArea($blockName)
{
        $ret = true;
        $pageObject = Page::getCurrentPage();
        $pageBlocks = $pageObject->getBlocks($blockName);
        $hasStuff = false;
        foreach ($pageBlocks as $pb) {
            if ($pb->btHandle != NULL) {$hasStuff = true;}
            break;
            }
        if ($hasStuff || $pageObject->isEditMode())
            $ret = false;
        return $ret;
}

Aufruf im Seitentemplate:

if ( !isEmptyArea('XXX') ) {
           $a = new Area('XXX');
           $a->display($c);
}

Eine Datei im Theme Bereich einbinden

Manchmal möchte man eine Datei, welche sich im "theme" Pfad befindet in einen XML Knoten einbinden, hier beispielsweise eine favicon.ico

Funktion dafür: $view->getThemePath()
favicon Einbettung:
<link rel="shortcut icon" type="image/x-icon" href="<?php $view->getThemePath(); ?>/favicon.ico">


Aktuelle Sprache abrufen

Manchmal muss man in einem Block einen sprachabhängigen Text ändern, sofern dieser nicht im Backend editierbar ist, beispielsweise, weil man mit dem Block Designer ein eigenes Modul erstellt hat. Hier der Code dazu:

Localization::activeLanguage();

Liefert die Sprachkennung als String zurück: 'de', 'en', ...

concrete5 - tar Datei entpacken

Oft kann man auf einen Kundenzugang nur mittels FTP zugreifen. Das Projekt wurde aber auf einen Entwicklungs-Server soweit vorbereitet und soll jetzt auf den Kunden-Server installiert werden. concrete5 enthällt sehr viele Einzeldateien, das "hochschieben" mittels FTP ist dann ein Gedulds-Spiel. Besser ist es, alle Dateien unter DocRoot mittels dem tar Kommando zu einer einzigen komprimierten Archiv Datei (docroot-dateien.tgz) zusammenzufassen und diese auf den Server mittels FTP zu übertragen.Dort kann sie mit folgendem kleinen PHP Script dann in sekundenschnelle entpackt werden:

<?php
if (system("tar -zxvf docroot-dateien.tgz") ) 
      echo '
<b>file uncompressed successfully!</b>';
else 
      echo '
<b>tar Befehl steht auf dem Server nicht zur Verfügung</b>';
?>

Wie frage ich ein Page-Attribut in der PHP Seitenvorlage ab?

Man hat sich im Backend ein neues Attribut angelegt und möchte dieses dann in einer Seitenvorlage abfragen. Die generelle Member-Funktion der Klasse Page nennt sich getAttribute().

Ist das Attribut ein "einfaches Objekt", wie z.B. ein Text, dann liefert die Funktion direkt den Text-String. Ich möchte es hier an einem komplexeren Objekt, dem Auswahl - Objekt verdeutlichen, es ist nur "Einfachselektion" eingestellt.

/* Zeiger der aktuellen Page holen */
$pageObject = Page::getCurrentPage();

/* Attribut ist ein Auswahlobjekt, mit mehreren Farbschemas für eine Seite. Das Farbschema definiert en CSS Klasse, die dann über abgeleiete CSS Klassen Farben für Rahmen, Überschriften, ... vorgeben */

$colorSchema = $pageObject->getAttribute('color_schema');
$pageCSSName = 'page-color-default';  // Voreinstellung
if ( $colorSchema && isset($colorSchema) ) {
    /* current() liefert das eingestellte Item */
    $colorOptions = $colorSchema->current();
    if ( $colorOptions && isset($colorOptions)) {
        $pageColor = $colorOptions->getSelectAttributeOptionDisplayValue('text');
        $pageCSSName = 'page-color-' . $pageColor;
        }
    }

/* Die CSS Klasse $pageCSSName kann jetzt irgendwo mit eingebaut werden: */
<div class="<?php echo $pageCSSName;?>">...</div

Attribut-Memberfunktion current() geht nicht mehr mit Version 8.x. Deshalb dann immer die unten beschriebene Funktion verwenden, auch wenn nur ein Eintra existiert.

Falls das Attribut vom Typ "Auswahl" Mehrfachselektion zulässt, können die Attribut-Werte wie folgt ausgelesen werden; mehr dazu in der API Beschreibung:

<code><span id="6" class="l"><span class="php-keyword1">class</span> OptionList</span></code>


$colorOptions = $colorSchema->getOptions;
foreach ($colorOptions as $cOption) {
    $pageColor = $cOption->getSelectAttributeOptionDisplayValue('text');
} 


Seitenattribut vom Typ Bild

Manchmal möchte man einer Seite ein Bild zuweisen, das dann als Vorschau oder als Hintergrundbild eingebaut werden kann.

Hier der Code dazu:

<?php // $c ist eine globale Variable, die mit der aktuellen Seite vorbelegt ist, ansonsten $c = Page::getCurrentPage();
$thumbnail = $c->getAttribute('thumbnail');
if (is_object($thumbnail)) {
    $img = Core::make('html/image', array($thumbnail));
    $tag = $img->getTag();
    $tag->addClass('img-responsive');
    print $tag;
}
?>

Bei ältere PageList Versionen ist die aktuelle Selektion nicht markiert.

Am besten man legt für die PageList ein neues Template an und kopiert die view.php dorthin. Hier die Modifikation, damit die aktuelle Seite in der Aufzählung markiert wird.

<?php
$c = Page::getCurrentPage();
$curpgID = $c->getCollectionID();

    
foreach ($pages as $page):
    // ....
    $beSelected = false;
    if ($page->getCollectionID() == $curpgID) { $beSelected = true;}
?>

<div class="ccm-block-page-list-title">
     <a href="<?php echo $url ?>" target="<?php echo $target ?>" <?php if ($beSelected) echo 'class="selected"';?>><?php echo $title ?></a>
</div>
...

 <?php endforeach; ?>

Über die CSS Klasse selected kann dann der Eintrag farblich markiert werden.

 .ccm-block-page-list-page-entry {
        a.selected {
            color: red!important;
        }

}

HTML Text-Block im Composer bearbeiten

Manchmal wünscht man sich, alle Informationen einer speziellen Seite (beispielsweise eine Beschreiung einer Veranstaltung oder eines Events) komplett im Composer zu bearbeiten: Datum, Beschreibung, Ort, Verantwortlicher usw. Diese Datenfelder kann man als Attribute einer Seite definieren und im Composer einblenden. Zusätzlich möchte man jedoch auch noch einen speziellen Block mit aufnehmen, zuum Beispiel einen (HTML-) Text Bock, ohne nachträglich die neu erstellte Seite extra noch mal in den Edit Modus zu schalten. Der Block soll bereits im Composer bereits editiert werden können - so wie alle anderen Seitenattribute auch.

Dazu fügt man dem Seitentyp den gewünschten Block (z.B. Inhalt) hinzu:
(Seitentyp -> Formular bearbeiten)





Diesen Block muss mann dann nur noch im Bearbeitungsmodus der Seitenvorgabe einfügen:
(Seitentyp -> Ausgabe -> Standards bearbeiten)


Das entsprechende Blockelement findet man ganz Unten Rechts im Auswahlmenü:


Jetzt kann dieses Blockelement im Composer bearbeitet werden. Es erscheint dort, wo es im "Seitenstandard" eingefügt wurde.

Link als Attribut im Composer anlegen und auf der Seite abfragen

Genau so wie man oft ein Thumbnail Bild als Seiten-Attribut verwendet und auf der Seite dann einbettet kann es vorkommen, dass man ein Link Attribut für einen Seitentyp definiert hat, das man dann in der Seiten PHP Datei ansprechen möchte. Hier der Code dafür (Link Attribut mit ID 'event_flyer'):

$flyer =  $c->getAttribute('event_flyer');
$flyerEmbeddcode = '';
if ( is_object($flyer)) {
    $fileurl = $flyer->getDownloadURL();
    $flyerEmbeddcode = '<p><b>Flyer:</b> ' . '<a class="" href="' . $fileurl . '" target="_blank">Download</a></p>';
}
....
if ( $flyerEmbeddcode != '') echo $flyerEmbeddcode;
                  

Textumbruch beispielsweise beim Title in der page_list steuern

Responsive Design hat schon manchmal seine Tücken. Auf dem einen Gerät schaut alles gut aus, auf dem anderen wird der Titel mehr als ungünstig umgebrochen. Ich hatte beispielsweise eine Pagelist als Subnavigation verwendet für Maschinentypen, genauer gesagt Pressen. Diese haben Kennzahlen, die dem max. Druckbereich vorgeben. Beispiel:

C-Gestell-Pressen EXP 100 kN - 1.600 kN

In der Sub-Navigation sah es dann so aus:

C-Gestell-Pressen EXP 100 kN - 1.600
kN

Mehr als unschön. Was tun? Es gibt zwar Möglichkeiten innerhalb von CSS Wörter brutal oder gar nicht unzubrechen, man kann auch das Umbrechen von WhiteSpaces im Satz verhindern, man kann abschneiden - alles keine sinnvollen Lösungen.

Bei der Analyse des Titeltextes sieht man, dass "eine Zahl gefolgt von der Benennung (kN)" möglichst nicht auseinandergerissen werden sollte. Die Kennzahlen endeten alle zudem auf "00". das machte die Sache dann noch einfacher, aber mit dem Einsatz von regexp können auch kompliziertere Such- und Ersetz Routinen in PHP programmiert werden. Hier der Code, den ich in die page_list view.php einbaute, um den Titel schöner anzeigen zu können:

 <strong></strong>$title = str_replace ( '00 kN', '<span style="white-space:nowrap" rel="white-space:nowrap" rel="white-space:nowrap" rel="white-space:nowrap" rel="white-space:nowrap" rel="white-space:nowrap" rel="white-space:nowrap" rel="white-space:nowrap">00 kN</span>', $title);

white-space: nowrap verhindert, dass der Text zwischen der Zahl und der Benennung umgebrochen wird.