Scripts
dom bouwen
Met deze DOM-bouwer kan je programmatisch eenvoudig een HTML5 structuur bouwen. Het werkt zonder DOMDocument of andere XML-extentie en is daardoor portable. Het geeft geen onnodige spaties die tot CSS-problemen kunnen leiden en correcte escaping is eenvoudig. Voor unicode escaping wordt gebruik gemaakt van de grapheme_X() functies van de Intl-extentie, maar die zijn eenvoudig aan te passen naar mbstring of wat anders. Voorbeeldgebruik:
dom.php
<?php
declare (strict_types=1);
/**
* Basisklasse helpt objecten identificeren en voorkomt tikfouten
*/
abstract class basis
{
/** Trigger foutmelding */
protected function fout($k)
{
trigger_error('Eigenschap "' . $k . '" van object "'
. get_class($this) . '" bestaat niet of is niet publiek.');
}
/** Voorkomt magic getter */
function __get(string $k)
{
$this->fout($k);
}
/** Voorkomt magic setter */
function __set(string $k, $v)
{
$this->fout($k);
}
}
/**
* Supersimpele DOM-bouwer die openstaandetags sluit
* Niet nodig: DOMDocument, html_X-functies en output buffer
*/
class dom extends basis
{
/** @var string $buffer uitvoerbuffer */
protected $buffer;
/** @var array $tags stapel voor open tags */
protected $tags;
/** Constructor */
function __construct(string $doctype)
{
$this->buffer = $doctype;
$this->tags = [];
}
/** of een tag andere tags kan bevatten */
protected function is_gesloten(string $naam) : bool
{
return in_array($naam, ["area", "base", "br", "col", "command", "embed",
"hr", "img", "input", "keygen", "link", "meta", "param", "source",
"track", "wbr"]);
}
/** voeg het begin van een tag toe aan de uitvoerbuffer */
protected function schrijf_tag_start(string $naam)
{
$this->buffer .= "<" . $naam;
}
/** voeg het einde van een tag toe aan de uitvoerbuffer */
protected function schrijf_tag_sluit_direct()
{
$this->buffer .= ">"; // voor pure XML werd "/>" gebruikt
}
/** voeg attributen toe aan de uitvoerbuffer */
protected function schrijf_tag_attributen(array $attr)
{
foreach ($attr as $index => $waarde) {
$this->buffer .= " " . $index . "=\"" . $this->escape($waarde) . "\"";
}
}
/** voeg het einde van een tag toe aan de uitvoerbuffer en laat open */
protected function schrijf_tag_open()
{
$this->buffer .= ">";
}
/** voeg een tag met tekst toe aan de uitvoerbuffer */
protected function schrijf_tag_tekst(string $naam, string $tekst)
{
if ($naam != "script" && $naam != "style" ) {
$this->buffer .= $this->escape($tekst);
} else {
$this->buffer .= $tekst;
}
}
/** sluit een openstaande tag af in de uitvoerbuffer */
protected function schrijf_tag_sluit(string $naam)
{
$this->buffer .= "</" . $naam . ">";
}
/** escape html entiteiten (unicode veilig) */
function escape(string $tekst) : string
{
$esc = "";
$lengte = grapheme_strlen($tekst);
for ($offset = 0; $offset < $lengte; $offset++) {
$c = grapheme_substr($tekst, $offset, 1);
switch ($c) {
case "&": $esc .= "&"; break;
case "\"": $esc .= """; break;
case "'": $esc .= "'"; break;
case "<": $esc .= "<"; break;
case ">": $esc .= ">"; break;
default: $esc .= $c;
}
}
return $esc;
}
/** escape javascript literal */
function js_escape_literal($tekst) : string
{
return str_replace("'", "\'", str_replace("\\", "\\\\", $tekst));
}
/** voeg tag toe aan uitvoerbuffer */
function tag(string $naam) : Self
{
$this->schrijf_tag_start($naam);
if ($this->is_gesloten($naam)) {
$this->schrijf_tag_sluit_direct();
} else {
$this->schrijf_tag_open();
$this->schrijf_tag_sluit($naam);
}
return $this;
}
/** voeg een tag met tekst toe aan de uitvoerbuffer */
function tag_tekst(string $naam, string $tekst) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_open();
$this->schrijf_tag_tekst($naam, $tekst);
$this->schrijf_tag_sluit($naam);
return $this;
}
/** voeg een tag met attributen toe aan de uitvoerbuffer */
function tag_attr(string $naam, array $attr) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_attributen($attr);
if ($this->is_gesloten($naam)) {
$this->schrijf_tag_sluit_direct();
} else {
$this->schrijf_tag_open();
$this->schrijf_tag_sluit($naam);
}
return $this;
}
/** voeg een tag met attributen en tekst toe aan de uitvoerbuffer */
function tag_attr_tekst(string $naam, array $attr, string $tekst) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_attributen($attr);
$this->schrijf_tag_open();
$this->schrijf_tag_tekst($naam, $tekst);
$this->schrijf_tag_sluit($naam);
return $this;
}
/** voeg een tag toe aan de uitvoerbuffer en laat deze open */
function tag_in(string $naam) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_open();
array_push($this->tags, $naam);
return $this;
}
/** voeg een tag met tekst toe aan de uitvoerbuffer en laat deze open */
function tag_tekst_in(string $naam, string $tekst) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_open();
$this->schrijf_tag_tekst($naam, $tekst);
array_push($this->tags, $naam);
return $this;
}
/** voeg een tag met attributen toe aan de uitvoerbuffer en laat deze open */
function tag_attr_in(string $naam, array $attr) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_attributen($attr);
$this->schrijf_tag_open();
array_push($this->tags, $naam);
return $this;
}
/** voeg een tag met attributen en tekst toe aan de uitvoerbuffer en laat deze
* open */
function tag_attr_tekst_in(string $naam, array $attr, string $tekst) : Self
{
$this->schrijf_tag_start($naam);
$this->schrijf_tag_attributen($attr);
$this->schrijf_tag_open();
$this->schrijf_tag_tekst($naam, $tekst);
array_push($this->tags, $naam);
return $this;
}
/** voeg tekst toe aan de uitvoerbuffer */
function tekst(string $tekst) : Self
{
$this->buffer .= $this->escape($tekst);
return $this;
}
/** voeg een XML-fragment toe aan de uitvoerbuffer */
function fragment(string $xml) : Self
{
$this->buffer .= $xml;
return $this;
}
/** sluit de meest recent openstaande tag in de uitvoerbuffer (FIFO) */
function uit() : Self
{
if (count($this->tags) == 0) {
trigger_error("DEBUG: geen openstaande tags", E_USER_WARNING);
return $this;
}
$naam = array_pop($this->tags);
$this->schrijf_tag_sluit($naam);
return $this;
}
/** sluit alle openstaande stags en print de uitvoerbuffer */
function teken() : String
{
while (count($this->tags) > 0) {
$this->buffer .= "</" . array_pop($this->tags) . ">";
}
header('Content-Type: text/html; charset=utf-8');
print $this->buffer;
}
}
Reacties
0