Read HTML Metadata to Describe a Template

For an application I had to write a selector for a bunch of *.html files in a folder.

That's fairly easy by doing:


foreach (glob("*.html") as $filename) {
    $files[] = '<option>'.basename($filename).'</option>';
}

echo sprintf('<select>%s</select>', implode('',$files));

and get a list of template filenames, that you can stuff in a <select>.

But with that, you have to use descriptive filenames and it's a bit of a bare-bone experience.

Why not add some meta information about the template file into the template file itself and use that for a richer presentation with some javascript dropdown like Select2?

For that we add some good old <meta> tags into the html>head and parse them with the get_meta_tags().

The template file look like this:


<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="utf-8">

    <meta name="template:author" content="TEST, test@gmail.com">
    <meta name="template:name" content="Two Columns Layout">
    <meta name="template:description" content="This is a Two Column Layout">
    <meta name="template:icon" content="template-2col.svg">
    <meta name="template:color" content="orange">

    <title>{{ @page.title }} - {{ @page.subtitles }}</title>
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">
    <link rel="stylesheet" type="text/css" href="/assets/css/print.css">
    <style type="text/css">
        body {
            font-family: Roboto, sans-serif;
        }
    
</style>
</head>
<body class="A4">
</body>
</html>

It includes a template author, the filename for an icon, stored somewhere on thee server and a title/description to show in the dropdown. All this information is used in the javascript dropdown/combobox.

Next you read all the HTML files in a directory and get_meta_tags while looping through them.


foreach (glob("/path/*.html") as $filename) {
    $meta[basename($filename)] = get_meta_tags($filename);
}

print_r($meta);

$meta now contains something like this:



(
    [alternative_template.html] => Array
    (
        [template:author] => TEST, test@gmail.com
        [template:name] => 2 Spalten Testlayout
        [template:description] => Zweispaltiges Template über die gesamte Breite
        [template:icon] => template-2col.svg
        [template:color] => orange
    )

    [print-wide.html] => Array
    (
        [template:author] => TEST, test@gmail.com
        [template:name] => 1 Spalte
        [template:description] => Einspaltiges Template über die gesamte Breite
        [template:icon] => template-1col.svg
        [template:color] => #379a9a
    )

    [print.html] => Array
    (
        [template:author] => TEST, test@gmail.com
        [template:name] => 2 Spalten
        [template:description] => Zweispaltiges Template über die gesamte Breite
        [template:icon] => template-2col.svg
        [template:color] => #000
    )

)

that lets you use the name of the template and an icon for the advanced combo box, select, dropdown... you name it, of your choice.

That's it!

There might be a case where you have to read the meta tags not from a HTML file, but from a <html> string.

Here it's best to parse the HTML with DOMDocument and access the <meta> tags with a xpath query.

See the following example.



$html = '
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="utf-8">

    <meta name="template:author" content="TEST, test@gmail.com">
    <meta name="template:name" content="Two Columns Layout">
    <meta name="template:description" content="This is a Two Column Layout">
    <meta name="template:icon" content="template-2col.svg">
    <meta name="template:color" content="orange">

    <title>{{ @page.title }} - {{ @page.subtitles }}</title>
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">
    <link rel="stylesheet" type="text/css" href="/assets/css/print.css">
    <style type="text/css">
        body {
            font-family: Roboto, sans-serif;
        }
    </style>
</head>
<body class="A4">
</body>
</html>
'
;

function get_meta_tags_from_string($html) {
    $doc = new DOMDocument();
    libxml_use_internal_errors(true);
    $doc->loadHTML($html);
    libxml_clear_errors();

    $xpath = new DOMXPath($doc);
    $nodes = $xpath->query('//head/meta[@name]');
    $meta = [];

    foreach($nodes as $node) {
        $meta[$node->getAttribute('name')] = $node->getAttribute('content');
    }

    return $meta;
}

$meta = get_meta_tags_from_string($html);