Phtml.js
{
"type": "file",
"namespace": {
"type": "namespace",
"name": "Taeluf",
"declaration": "namespace Taeluf;",
"class": [
{
"type": "class",
"docblock": {
"type": "docblock",
"description": "Makes DUMDocument... less terrible, but still not truly good"
},
"namespace": "Taeluf",
"fqn": "Taeluf\\Phtml",
"name": "Phtml",
"extends": "\\DOMDocument",
"declaration": "class Phtml extends \\DOMDocument",
"properties": [
{
"type": "property",
"modifiers": [
"protected",
"string"
],
"docblock": {
"type": "docblock",
"description": "The source HTML + PHP code\n",
"attribute": [
{
"type": "attribute",
"name": "var",
"description": "string"
}
]
},
"name": "src",
"declaration": "protected string $src;"
},
{
"type": "property",
"modifiers": [
"protected",
"string"
],
"docblock": {
"type": "docblock",
"description": "The source code with all the PHP replaced by placeholders"
},
"name": "cleanSrc",
"declaration": "protected string $cleanSrc;"
},
{
"type": "property",
"modifiers": [
"protected",
"array"
],
"docblock": {
"type": "docblock",
"description": "[ 'phpplaceholder' => $phpCode, 'placeholder2' => $morePHP ]"
},
"name": "php",
"declaration": "protected array $php;"
},
{
"type": "property",
"modifiers": [
"protected"
],
"docblock": {
"type": "docblock",
"description": "A random string used when adding php code to a node's tag declaration. This string is later removed during output()"
},
"name": "phpAttrValue",
"declaration": "protected $phpAttrValue;"
}
],
"comments": [
"\/**",
"* True if the source html had a '<html>' tag",
"* Except we're not implementing that???",
"* @var bool",
"*\/",
"protected bool $isHTMLDoc = false;"
],
"methods": [
{
"type": "method",
"args": [
{
"type": "arg",
"name": "html",
"declaration": "$html"
}
],
"docblock": {
"type": "docblock",
"description": "Create a DOMDocument, passing your HTML + PHP to __construct. \n\n",
"attribute": [
{
"type": "attribute",
"name": "param",
"description": "mixed $html a block of HTML + PHP code. It does not have to have PHP. PHP will be handled gracefully."
},
{
"type": "attribute",
"name": "return",
"description": "void"
}
]
},
"modifiers": [
"public"
],
"name": "__construct",
"body": "parent::__construct();\n$this->srcHTML = $html;\n$parser = new PHTML\\PHPParser($html);\n$enc = $parser->pieces();\n$this->php = $enc->php;\n$this->cleanSrc = $enc->html;\n$this->cleanSrc = $this->cleanHTML($this->cleanSrc);\n$hideXmlErrors=true;\nlibxml_use_internal_errors($hideXmlErrors);\n$this->registerNodeClass('DOMElement', '\\\\Taeluf\\\\PHTML\\\\Node');\n$this->registerNodeClass('DOMText', '\\\\Taeluf\\\\PHTML\\\\TextNode');\n\/\/ $this->registerNodeClass('DOMText', 'RBText');\n$html = '<root>'.$this->cleanSrc.'<\/root>';\n$this->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);\n$this->formatOutput = true;\nlibxml_use_internal_errors(false);",
"declaration": "public function __construct($html)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"arg_types": [
"string"
],
"name": "string",
"declaration": "string $string"
}
],
"modifiers": [
"public"
],
"name": "placeholder",
"return_types": [
"string"
],
"body": "$placeholder = PHTML\\PHPParser::getRandomAlpha();\n$placeholder = 'php'.$placeholder.'php';\n$this->php[$placeholder] = $string;\nreturn $placeholder;",
"declaration": "public function placeholder(string $string): string"
},
{
"type": "method",
"args": [
{
"type": "arg",
"arg_types": [
"string"
],
"name": "placeholder",
"declaration": "string $placeholder"
}
],
"docblock": {
"type": "docblock",
"description": "Get the code that's represented by the placeholder",
"attribute": [
{
"type": "attribute",
"name": "return",
"description": "the stored code or null"
}
]
},
"modifiers": [
"public"
],
"name": "codeFromPlaceholder",
"return_types": [
"string"
],
"body": "$code = $this->php[trim($placeholder)] ?? null;\nreturn $code;",
"declaration": "public function codeFromPlaceholder(string $placeholder): string"
},
{
"type": "method",
"args": [
{
"type": "arg",
"arg_types": [
"string"
],
"name": "enclosedPHP",
"declaration": "string $enclosedPHP"
}
],
"docblock": {
"type": "docblock",
"description": "Get a placeholder for the given block of code\nIntention is to parse a single '<?php \/\/piece of php code ?>' and not '<?php \/\/stuff ?><?php \/\/more stuff?>'\nWhen used as intended, will return a single 'word' that is the placeholder for the given code\n",
"attribute": [
{
"type": "attribute",
"name": "param",
"description": "mixed $enclosedPHP an HTML + PHP string"
},
{
"type": "attribute",
"name": "return",
"description": "string the parsed block of content where PHP code blocks are replaced by placeholders."
}
]
},
"modifiers": [
"public"
],
"name": "phpPlaceholder",
"return_types": [
"string"
],
"body": "$parser = new PHTML\\PHPParser($enclosedPHP);\n$enc = $parser->pieces();\n\/\/ This block doesn't work because it's over-eager. A workaround to just add code, regardless of open\/close tags, would be good.\n\/\/ if (count($enc->php)==0){\n \/\/ $code = \\PHTML\\PHPParser::getRandomAlpha();\n \/\/ $enc->php = [\"php${code}php\"=>$enclosedPhp];\n \/\/ $enc->html = $code;\n\/\/ }\n$this->php = array_merge($this->php,$enc->php);\nreturn $enc->html;",
"declaration": "public function phpPlaceholder(string $enclosedPHP): string"
},
{
"type": "method",
"args": [
{
"type": "arg",
"arg_types": [
"string"
],
"name": "codeWithPlaceholders",
"declaration": "string $codeWithPlaceholders"
}
],
"docblock": {
"type": "docblock",
"description": "Decode the given code by replacing PHP placeholders with the PHP code itself\n",
"attribute": [
{
"type": "attribute",
"name": "param",
"description": "mixed $str"
},
{
"type": "attribute",
"name": "return",
"description": "void"
}
]
},
"modifiers": [
"public"
],
"name": "fillWithPHP",
"return_types": [
"string"
],
"body": "$decoded = str_replace(array_keys($this->php),$this->php,$codeWithPlaceholders);\nreturn $decoded;",
"declaration": "public function fillWithPHP(string $codeWithPlaceholders): string"
},
{
"type": "method",
"args": [],
"docblock": {
"type": "docblock",
"description": "See output()\n",
"attribute": [
{
"type": "attribute",
"name": "return",
"description": "string"
}
]
},
"modifiers": [
"public"
],
"name": "__toString",
"body": "return $this->output();",
"declaration": "public function __toString()"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "withPHP",
"value": "true",
"declaration": "$withPHP=true"
}
],
"docblock": {
"type": "docblock",
"description": "Return the decoded document as as tring. All PHP will be back in its place\n",
"attribute": [
{
"type": "attribute",
"name": "param",
"description": "mixed $withPHP passing FALSE means placeholders will still be present & PHP code will not be"
},
{
"type": "attribute",
"name": "return",
"description": "string the final document with PHP where it belongs"
}
]
},
"modifiers": [
"public"
],
"name": "output",
"body": "\/\/ echo \"\\n\".'-start output call-'.\"\\n\";\n$list = $this->childNodes[0]->childNodes;\n$hiddenTagsNodes = $this->xpath('\/\/*[@hideOwnTag]');\nforeach ($hiddenTagsNodes as $htn){\n if ($htn->hideOwnTag==false||$htn->hideOwnTag=='false'){\n unset($htn->hideOwnTag);\n continue;\n }\n $parent = $htn->parentNode;\n $childNodeList = $htn->children;\n foreach ($childNodeList as $child){\n $htn->removeChild($child);\n $parent->insertBefore($child, $htn);\n }\n $parent->removeChild($htn);\n}\n$html = '';\nforeach ($list as $item){\n $html .= $this->saveHTML($item);\n}\n\/** Run the php-code-replacer as long as there is a placeholder (while preventing infinite looping) *\/\n$html = $this->fill_php($html, $withPHP);\n$html = $this->restoreHtml($html);\nreturn $html;",
"declaration": "public function output($withPHP=true)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "html",
"declaration": "$html"
},
{
"type": "arg",
"name": "withPHP",
"value": "true",
"declaration": "$withPHP=true"
}
],
"modifiers": [
"public"
],
"name": "fill_php",
"body": "$maxIters = 25;\n$iters = 0;\nwhile ($iters++<$maxIters&&preg_match('\/php([a-zA-Z]{26})php\/', $html, $match)){\n foreach ($this->php as $id=>$code){\n if ($withPHP)$html = str_replace($id,$code,$html);\n else $html = str_replace($id,'',$html);\n }\n}\nif (($phpAttrVal=$this->phpAttrValue)!=null){\n $html = str_replace(\"=\\\"$phpAttrVal\\\"\", '', $html);\n}\nreturn $html;",
"declaration": "public function fill_php($html, $withPHP=true)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "xpath",
"declaration": "$xpath"
},
{
"type": "arg",
"name": "refNode",
"value": "null",
"declaration": "$refNode=null"
}
],
"docblock": {
"type": "docblock",
"description": "get the results of an xpath query\n",
"attribute": [
{
"type": "attribute",
"name": "param",
"description": "mixed $xpath the xpath query, such as: \/\/tagname[@attributename=\"value\"]\n If you use a refnode, prepend '.' at the beginning of your xpath query string"
},
{
"type": "attribute",
"name": "param",
"description": "mixed $refNode a parent-node to search under"
},
{
"type": "attribute",
"name": "return",
"description": "array the resulting DomNodeList is converted to an array & returned"
}
]
},
"modifiers": [
"public"
],
"name": "xpath",
"body": "$xp = new \\DOMXpath($this);\nif ($refNode==null)$list = $xp->query($xpath);\nelse $list = $xp->query($xpath,$refNode);\n$arr = [];\nforeach ($list as $item){\n $arr[] = $item;\n}\nreturn $arr;",
"declaration": "public function xpath($xpath,$refNode=null)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "node",
"declaration": "$node"
},
{
"type": "arg",
"name": "phpCode",
"declaration": "$phpCode"
}
],
"docblock": {
"type": "docblock",
"description": "Set an attribute that will place PHP code inside the tag declartion of a node. \nBasically: `<node phpCodePlaceholder>`, which pHtml will later convert to `<node <?='some_stuff'?>>`. \nThis avoids problems caused by attributes requiring a `=\"\"`, which `DOMDocument` automatically places.\n",
"attribute": [
{
"type": "attribute",
"name": "param",
"description": "$phpCode A block of php code with opening & closing tags like <?='some stuff'?>"
},
{
"type": "attribute",
"name": "return",
"description": "\\Taeluf\\PHTML\\ValuelessAttribute"
}
]
},
"modifiers": [
"public"
],
"name": "addPhpToTag",
"body": "$this->phpAttrValue = $this->phpAttrValue ?? PHTML\\PHPParser::getRandomAlpha();\n$placeholder = $this->phpPlaceholder($phpCode);\n$node->setAttribute($placeholder, $this->phpAttrValue);\nreturn $placeholder;",
"declaration": "public function addPhpToTag($node, $phpCode)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"arg_types": [
"\\DOMNode"
],
"name": "node",
"declaration": "\\DOMNode $node"
},
{
"type": "arg",
"name": "phpCode",
"declaration": "$phpCode"
}
],
"modifiers": [
"public"
],
"name": "insertCodeBefore",
"body": "\/\/ $placeholder = $this->phpPlaceholder($phpCode);\n$placeholder = $this->placeholder($phpCode);\n$text = new \\DOMText($placeholder);\nreturn $node->parentNode->insertBefore($text, $node);",
"declaration": "public function insertCodeBefore(\\DOMNode $node, $phpCode)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"arg_types": [
"\\DOMNode"
],
"name": "node",
"declaration": "\\DOMNode $node"
},
{
"type": "arg",
"name": "phpCode",
"declaration": "$phpCode"
}
],
"modifiers": [
"public"
],
"name": "insertCodeAfter",
"body": "$placeholder = $this->placeholder($phpCode);\n$text = new \\DOMText($placeholder);\nif ($node->nextSibling!==null)return $node->parentNode->insertBefore($text,$node->nextSibling);\nreturn $node->parentNode->insertBefore($text);",
"declaration": "public function insertCodeAfter(\\DOMNode $node, $phpCode)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "html",
"declaration": "$html"
}
],
"modifiers": [
"public"
],
"name": "cleanHTML",
"body": "\/\/ fix doctype\n$html = preg_replace('\/\\<\\!DOCTYPE(.*)\\>\/i', '<tlfphtml-doctype$1><\/tlfphtml-doctype>',$html);\n\/\/ fix <html> tag\n$html = preg_replace('\/<html([ >])\/','<tlfphtml-html$1',$html);\n$html = str_ireplace('<\/html>', '<\/tlfphtml-html>', $html);\n\/\/ fix <head> tag\n$html = preg_replace('\/<head([ >])\/', '<tlfphtml-head$1',$html);\n$html = str_ireplace('<\/head>', '<\/tlfphtml-head>',$html);\nreturn $html;",
"declaration": "public function cleanHTML($html)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "html",
"declaration": "$html"
}
],
"modifiers": [
"public"
],
"name": "restoreHtml",
"body": "$html = preg_replace('\/\\<tlfphtml\\-doctype(.*)\\>\\<\\\/tlfphtml\\-doctype\\>\/i', '<!DOCTYPE$1>',$html);\n\/\/ fix <html> tag\n$html = str_ireplace('<tlfphtml-html','<html',$html);\n$html = str_ireplace('<\/tlfphtml-html>', '<\/html>', $html);\n\/\/ fix <head> tag\n$html = str_ireplace('<tlfphtml-head', '<head', $html);\n$html = str_ireplace('<\/tlfphtml-head>', '<\/head>', $html);\nreturn $html;",
"declaration": "public function restoreHtml($html)"
},
{
"type": "method",
"args": [
{
"type": "arg",
"name": "param",
"declaration": "$param"
}
],
"modifiers": [
"public"
],
"name": "__get",
"body": "if ($param == 'form'){\n return $this->xpath('\/\/form')[0] ?? null;\n}",
"declaration": "public function __get($param)"
}
]
}
]
}
}