Completed
Push — master ( 326616...009a61 )
by Tom
02:33
created

Template::printDocument()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 5
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php
2
/* @description     Transformation Style Sheets - Revolutionising PHP templating    *
3
 * @author          Tom Butler [email protected]                                             *
4
 * @copyright       2015 Tom Butler <[email protected]> | https://r.je/                      *
5
 * @license         http://www.opensource.org/licenses/bsd-license.php  BSD License *
6
 * @version         1.0                                                             */
7
namespace Transphporm;
8
/** Loads an XML string into a DomDocument and allows searching for specific elements using xpath based hooks */
9
class Template {
10
	private $hooks = [];
11
	private $document;
12
	private $xpath;
13
	private $prefix = '';
14
15
	/** Takes an XML string and loads it into a DomDocument object */
16
	public function __construct($doc) {
17
		$this->document = new \DomDocument;
18
		
19
		$this->loadDocument($doc);
20
21
		$this->xpath = new \DomXPath($this->document);
22
		$this->xpath->registerNamespace('php', 'http://php.net/xpath');
23
		$this->xpath->registerPhpFunctions();
24
25
		if ($this->document->documentElement->namespaceURI !== null) {
26
			$this->xpath->registerNamespace('nsprefix', $this->document->documentElement->namespaceURI);
27
			$this->prefix = 'nsprefix:';
28
		}
29
	}
30
31
	/** Loads a HTML or XML document */ 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
32
	private function loadDocument($doc) {
33
		libxml_use_internal_errors(true);
34
		if ($this->document->loadXml($doc) === false) {
35
			$htmlDoc = new \DomDocument;
36
			$htmlDoc->loadHtml($doc);
37
			
38
			if (strpos($doc, '<!') === 0) $doc = $htmlDoc;
0 ignored issues
show
Unused Code introduced by
$doc is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
39
			else {
40
				$templateNode = $htmlDoc->getElementsByTagName('template')[0];
41
				$this->document->appendChild($this->document->importNode($templateNode, true));
42
			}
43
		}
44
		libxml_clear_errors();
45
	}
46
47
	/** Returns the document's XML prefix */
48
	public function getPrefix() {
49
		return $this->prefix;
50
	}
51
	
52
	/** Assigns a $hook which will be run on any element that matches the given $xpath query */
53
	public function addHook($xpath, $hook) {
54
		$this->hooks[] = [$xpath, $hook];
55
	}
56
57
	/** Loops through all assigned hooks, runs the Xpath query and calls the hook */
58
	private function processHooks() {
59
		foreach ($this->hooks as list($query, $hook)) {
60
			foreach ($this->xpath->query($query) as $element) $hook->run($element);
61
		}
62
		$this->hooks = [];
63
	}
64
65
	/** Prints out the current DomDocument as HTML */
66
	private function printDocument(\DomDocument $doc) {
67
		$output = '';
68
		foreach ($doc->documentElement->childNodes as $node) $output .= $doc->saveXML($node, LIBXML_NOEMPTYTAG);
69
		return $output;
70
	}
71
72
	/** Outputs the template's header/body. Returns an array containing both parts */
73
	public function output($document = false) {
74
		//Process all hooks
75
		 $this->processHooks();
76
77
		//Generate the document by taking only the childnodes of the template, ignoring the <template> and </template> tags
78
		//TODO: Is there a faster way of doing this without string manipulation on the output or this loop through childnodes?
79
		 //Either return a whole DomDocument or return the output HTML
80
		if ($document) return $this->document;
81
82
83
		$output = ($this->document->doctype) ? $this->document->saveXml($this->document->doctype) . "\n" : '';
84
85
		if ($this->document->documentElement->tagName !== 'template') $output .= $this->document->saveXml($this->document->documentElement, LIBXML_NOEMPTYTAG);
86
		else $output = $this->printDocument($this->document);
87
88
		//repair empty tags. Browsers break on <script /> and <div /> so can't avoid LIBXML_NOEMPTYTAG but they also break on <base></base> so repair them
89
		$output = str_replace(['></img>', '></br>', '></meta>', '></base>', '></link>', '></hr>', '></input>'], ' />', $output);
90
		return trim($output);
91
	}
92
}
93