Node.js

{
    "type": "file",
    "namespace": {
        "type": "namespace",
        "name": "Taeluf\\PHTML",
        "declaration": "namespace Taeluf\\PHTML;",
        "class": [
            {
                "type": "class",
                "docblock": {
                    "type": "docblock",
                    "description": "less sucky HTML DOM Element\n\nThis class extends PHP's DOMElement to make it suck less\n\nThe original version of this file was a pre-made script by the author below.\nThe only meaningful pieces of code I kept are the two `if 'innerHTML'` blocks of code.\nNo license information was available in the copied code and I don't remember what it said on the author's website.\n\nThe original package had the following notes from the author:\n\n- Authored by: Keyvan Minoukadeh - http:\/\/www.keyvan.net - keyvan@keyvan.net\n  - See: http:\/\/fivefilters.org (the project this was written for)"
                },
                "namespace": "Taeluf\\PHTML",
                "fqn": "Taeluf\\PHTML\\Node",
                "name": "Node",
                "extends": "\\DOMElement",
                "declaration": "class Node extends \\DOMElement",
                "comments": [
                    "public $hideOwnTag = false;",
                    "protected $children = [];",
                    ""
                ],
                "methods": [
                    {
                        "type": "method",
                        "args": [],
                        "modifiers": [
                            "public"
                        ],
                        "name": "__construct",
                        "body": "parent::__construct();\n\/\/ $children = [];\n      \/\/ foreach ($this->childNodes as $childNode){\n          \/\/ $children[] = $childNode;\n      \/\/ }\n      \/\/ $this->children = $children;",
                        "declaration": "public function __construct()"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "arg_types": [
                                    "string"
                                ],
                                "name": "tagName",
                                "declaration": "string $tagName"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "is this node the given tag"
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "is",
                        "return_types": [
                            "bool"
                        ],
                        "body": "if (strtolower($this->tagName)==strtolower($tagName))return true;\nreturn false;",
                        "declaration": "public function is(string $tagName): bool"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "arg_types": [
                                    "string"
                                ],
                                "name": "attribute",
                                "declaration": "string $attribute"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "",
                            "attribute": [
                                {
                                    "type": "attribute",
                                    "name": "alias",
                                    "description": "for DOMDocument::hasAttribute();"
                                }
                            ]
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "has",
                        "return_types": [
                            "bool"
                        ],
                        "body": "return $this->hasAttribute($attribute);",
                        "declaration": "public function has(string $attribute): bool"
                    },
                    {
                        "type": "method",
                        "args": [],
                        "docblock": {
                            "type": "docblock",
                            "description": "get an array of DOMAttrs on this node"
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "attributes",
                        "body": "$attrs = $this->attributes;\n$list = [];\nforeach ($attrs as $attr){\n\t$list[] = $attr;\n}\nreturn $list;",
                        "declaration": "public function attributes()"
                    },
                    {
                        "type": "method",
                        "args": [],
                        "docblock": {
                            "type": "docblock",
                            "description": "return an array of attributes ['attributeName'=>'value', ...];"
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "attributesAsArray",
                        "body": "$list = [];\nforeach ($this->attributes as $attr){\n    $list[$attr->name] = $attr->value;\n}\nreturn $list;",
                        "declaration": "public function attributesAsArray()"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "name",
                                "declaration": "$name"
                            },
                            {
                                "type": "arg",
                                "name": "value",
                                "declaration": "$value"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "Used for setting innerHTML like it's done in JavaScript:\n@code\n$div->innerHTML = '<h2>Chapter 2<\/h2><p>The story begins...<\/p>';\n@endcode"
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "__set",
                        "body": "if (strtolower($name) == 'innerhtml') {\n\t\/\/ first, empty the element\n\tfor ($x=$this->childNodes->length-1; $x>=0; $x--) {\n\t\t$this->removeChild($this->childNodes->item($x));\n\t}\n\t\/\/ $value holds our new inner HTML\n\tif ($value != '') {\n\t\t$f = $this->ownerDocument->createDocumentFragment();\n\t\t\/\/ appendXML() expects well-formed markup (XHTML)\n\t\t$result = @$f->appendXML($value); \/\/ @ to suppress PHP warnings\n\t\tif ($result) {\n\t\t\tif ($f->hasChildNodes()) $this->appendChild($f);\n\t\t} else {\n\t\t\t\/\/ $value is probably ill-formed\n\t\t\t$f = new DOMDocument();\n\t\t\t$value = mb_convert_encoding($value, 'HTML-ENTITIES', 'UTF-8');\n\t\t\t\/\/ Using <htmlfragment> will generate a warning, but so will bad HTML\n\t\t\t\/\/ (and by this point, bad HTML is what we've got).\n\t\t\t\/\/ We use it (and suppress the warning) because an HTML fragment will\n\t\t\t\/\/ be wrapped around <html><body> tags which we don't really want to keep.\n\t\t\t\/\/ Note: despite the warning, if loadHTML succeeds it will return true.\n\t\t\t$result = @$f->loadHTML('<htmlfragment>'.$value.'<\/htmlfragment>');\n\t\t\tif ($result) {\n\t\t\t\t$import = $f->getElementsByTagName('htmlfragment')->item(0);\n\t\t\t\tforeach ($import->childNodes as $child) {\n\t\t\t\t\t$importedNode = $this->ownerDocument->importNode($child, true);\n\t\t\t\t\t$this->appendChild($importedNode);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t\/\/ oh well, we tried, we really did. :(\n\t\t\t\t\/\/ this element is now empty\n\t\t\t}\n\t\t}\n\t}\n} else {\n\t$this->setAttribute($name,$value);\n\treturn;\n\t$trace = debug_backtrace();\n\ttrigger_error('Undefined property via __set(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);\n}",
                        "declaration": "public function __set($name, $value)"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "name",
                                "declaration": "$name"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "if the node has the named attribute, it will be removed. Otherwise, nothing happens"
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "__unset",
                        "body": "if ($this->hasAttribute($name))$this->removeAttribute($name);",
                        "declaration": "public function __unset($name)"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "name",
                                "declaration": "$name"
                            }
                        ],
                        "modifiers": [
                            "public"
                        ],
                        "name": "__isset",
                        "body": "return $this->hasAttribute($name);",
                        "declaration": "public function __isset($name)"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "name",
                                "declaration": "$name"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "Used for getting innerHTML like it's done in JavaScript:\n@code\n$string = $div->innerHTML;\n@endcode"
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "__get",
                        "body": "      if (method_exists($this, $getter = 'get'.strtoupper($name))){\n          return $this->$getter();\n      } else if ($name=='doc'){\n          return $this->ownerDocument;\n      } else if (strtolower($name) == 'innerhtml') {\n              $inner = '';\n              foreach ($this->childNodes as $child) {\n                  $inner .= $this->ownerDocument->saveXML($child);\n              }\n              return $inner;\n          } else if ($name=='form'&&strtolower($this->tagName)=='input'){\n          $parent = $this->parentNode ?? null;\n          while ($parent!=null&&strtolower($parent->tagName)!='form')$parent = $parent->parentNode ?? null;\n          return $parent;\n      } else if ($name=='inputs' && strtolower($this->tagName)=='form'){\n          $inputList = $this->doc->xpath('\/\/input', $this);\n          \/\/ var_dump($inputList);\n          \/\/ exit;\n          return $inputList;\n      } else if ($name=='children'){\n          $children = [];\n          for ($i=0;$i<$this->childNodes->count();$i++){\n              $children[] = $this->childNodes->item($i);\n          }\n          return $children;\n      }\n      else if ($this->hasAttribute($name)){\n          return $this->getAttribute($name);\n      } else {\n          return null;\n      }\n\/\/ $trace = debug_backtrace();\n\/\/ trigger_error('Undefined property via __get(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);\n\/\/ return null;",
                        "declaration": "public function __get($name)"
                    },
                    {
                        "type": "method",
                        "args": [],
                        "modifiers": [
                            "public"
                        ],
                        "name": "__toString",
                        "body": "return $this->ownerDocument->saveHTML($this);\n\/\/ return '['.$this->tagName.']';",
                        "declaration": "public function __toString()"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "xpath",
                                "declaration": "$xpath"
                            }
                        ],
                        "modifiers": [
                            "public"
                        ],
                        "name": "xpath",
                        "body": "return $this->doc->xpath($xpath, $this);",
                        "declaration": "public function xpath($xpath)"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "inputName",
                                "declaration": "$inputName"
                            },
                            {
                                "type": "arg",
                                "name": "value",
                                "declaration": "$value"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "Adds a hidden input to a form node\nIf a hidden input already exists with that name, do nothing\nIf a hidden input does not exist with that name, create and append it\n",
                            "attribute": [
                                {
                                    "type": "attribute",
                                    "name": "param",
                                    "description": "mixed $key"
                                },
                                {
                                    "type": "attribute",
                                    "name": "param",
                                    "description": "mixed $value"
                                },
                                {
                                    "type": "attribute",
                                    "name": "throws",
                                    "description": "\\BadMethodCallException if this method is called on a non-form node"
                                },
                                {
                                    "type": "attribute",
                                    "name": "return",
                                    "description": "void"
                                }
                            ]
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "addHiddenInput",
                        "body": "if (strtolower($this->tagName)!='form')throw new \\BadMethodCallException(\"addHiddenInput can only be called on a Form node\");\n      $xPath = new \\DOMXpath($this->ownerDocument);\n      $inputs = $xPath->query('\/\/input[@name=\"'.$inputName.'\"][@type=\"hidden\"]');\n      if (count($inputs)>0)return;\n$input = $this->ownerDocument->createElement('input');\n$input->setAttribute('name',$inputName);\n$input->setAttribute('value',$value);\n$input->setAttribute('type','hidden');\n$this->appendChild($input);",
                        "declaration": "public function addHiddenInput($inputName, $value)"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "attributeName",
                                "declaration": "$attributeName"
                            }
                        ],
                        "docblock": {
                            "type": "docblock",
                            "description": "Find out if this node has a true value for the given attribute name.\nLiterally just returns $this->hasAttribute($attributeName)\n\nI wanted to implement an attribute=\"false\" option... but that goes against the standards of HTML5, so that idea is on hold.\n\nSee https:\/\/stackoverflow.com\/questions\/4139786\/what-does-it-mean-in-html-5-when-an-attribute-is-a-boolean-attribute \n",
                            "attribute": [
                                {
                                    "type": "attribute",
                                    "name": "param",
                                    "description": "mixed $attributeName The name of the attribute we're checking for."
                                },
                                {
                                    "type": "attribute",
                                    "name": "return",
                                    "description": "bool"
                                }
                            ]
                        },
                        "modifiers": [
                            "public"
                        ],
                        "name": "boolAttribute",
                        "body": "return $this->hasAttribute($attributeName);",
                        "declaration": "public function boolAttribute($attributeName)"
                    },
                    {
                        "type": "method",
                        "args": [],
                        "modifiers": [
                            "public"
                        ],
                        "name": "getInnerText",
                        "body": "return $this->textContent;",
                        "declaration": "public function getInnerText()"
                    },
                    {
                        "type": "method",
                        "args": [
                            {
                                "type": "arg",
                                "name": "method",
                                "declaration": "$method"
                            },
                            {
                                "type": "arg",
                                "name": "args",
                                "declaration": "$args"
                            }
                        ],
                        "modifiers": [
                            "public"
                        ],
                        "name": "__call",
                        "body": "if (substr($method,0,2)=='is'){\n    $prop = lcfirst(substr($method,2));\n    if ($this->has($prop)&&$this->$prop != 'false')return true;\n    return false;\n}\nthrow new \\BadMethodCallException(\"Method '$method' does not exist on \".get_class($this));",
                        "declaration": "public function __call($method, $args)"
                    }
                ]
            }
        ]
    }
}