php-gdlabel/src/Loader/XmlLoader.php

98 lines
2.6 KiB
PHP

<?php
namespace NoccyLabs\GdLabel\Loader;
use NoccyLabs\CssLike\Stylesheet;
use NoccyLabs\GdLabel\Label;
use SimpleXMLElement;
use NoccyLabs\GdLabel\Element;
class XmlLoader
{
public function loadFile($filename)
{
$xml = simplexml_load_file($filename);
$label = new Label();
$styles = new Stylesheet();
foreach ($xml->style as $style) {
if (($src = (string)@$style['src'])) {
$ss = file_get_contents($src);
} else {
$ss = (string)$style;
}
$ssb = new Stylesheet();
$ssb->parseString($ss);
$styles->appendStylesheet($ssb);
}
$rules = $styles->select("label");
foreach ($rules as $prop=>$value) {
$label->setProp($prop, $value);
}
$this->parseAttributes($xml, $label, $styles);
foreach ($xml->children() as $child) {
if ($child->getName() == "style") {
continue;
}
$this->parseElement($child, $label, $styles);
}
return $label;
}
private function parseElement(SimpleXmlElement $xml, Element $elem, Stylesheet $style)
{
$name = $xml->getName();
$fqcn = "NoccyLabs\\GdLabel\\Elements\\".ucwords($name)."Element";
if (!class_exists($fqcn)) {
throw new \RuntimeException("Invalid element {$name} (expected {$fqcn})");
}
$obj = new $fqcn();
$rules = $style->select($name);
foreach ($rules as $prop=>$value) {
$elem->setProp($prop, $value);
}
$this->parseAttributes($xml, $obj, $style);
foreach ($xml->children() as $child) {
$this->parseElement($child, $obj, $style);
}
$elem->addChild($obj);
}
private function parseAttributes(SimpleXmlElement $xml, Element $elem, Stylesheet $style)
{
$props = [];
foreach ($xml->attributes() as $attr) {
$name = $this->camelToDash($attr->getName());
$value = (string)$attr;
$props[$name] = $value;
}
if (array_key_exists("class", $props)) {
$classes = explode(" ",trim($props['class']));
foreach ($classes as $class) {
$rule = $style->select(".".$class);
$props = array_merge($rule, $props);
}
}
foreach ($props as $prop=>$value) {
$elem->setProp($prop, $value);
}
}
private function camelToDash($name)
{
return strtolower(preg_replace("/([A-Z]{1})/", "-\$1", $name));
}
}