aliases[$alias] = $original; } /** * Defines a new tag. * * @param string $tagName The tag name. * @param string $src The tag source. * @return void No value is returned. * @throws \InvalidArgumentException */ public function addTag(string $tagName, string $src) { if (preg_match('/^[a-z\-]+$/', $tagName) !== 1) { throw new \InvalidArgumentException('The tag name provided is not valid! It may contain letters (a-z) and dashes (-).'); } $this->tags[strtolower(trim($tagName))] = $src; } /** * Converts components code (if any) into HTML code. * * @param string|\IvoPetkov\HTMLServerComponent $content The content to be processed. * @param array $options Compiler options. * @return string The result HTML code. */ public function process($content, array $options = []) { $tagNames = array_keys($this->tags); $tagNames[] = 'component'; if (is_string($content)) { $found = false; foreach ($tagNames as $tagName) { if (strpos($content, '<' . $tagName) !== false) { $found = true; break; } } if (!$found) { return $content; } } elseif (!($content instanceof HTMLServerComponent)) { throw new \InvalidArgumentException(''); } $getComponentFileContent = static function ($file, $component, $variables) { if (is_file($file)) { $__componentFile = $file; unset($file); if (!empty($variables)) { extract($variables, EXTR_SKIP); } unset($variables); ob_start(); include $__componentFile; $content = ob_get_clean(); return $content; } else { throw new \Exception('Component file cannot be found (' . $file . ')'); } }; $getComponentResultHTML = function ($component) use (&$getComponentFileContent, $options) { $srcAttributeValue = $component->getAttribute('src'); if ($srcAttributeValue === null) { if (isset($this->tags[$component->tagName])) { $srcAttributeValue = $this->tags[$component->tagName]; } else { throw new \Exception('Component tag name is not defined at ' . (string) $component . '!'); } } if ($srcAttributeValue !== null) { // todo check alias of alias $sourceParts = explode(':', isset($this->aliases[$srcAttributeValue]) ? $this->aliases[$srcAttributeValue] : $srcAttributeValue, 2); if (isset($sourceParts[0], $sourceParts[1])) { $scheme = $sourceParts[0]; if ($scheme === 'data') { if (substr($sourceParts[1], 0, 7) === 'base64,') { return base64_decode(substr($sourceParts[1], 7)); //$this->process(, isset($componentOptions) ? $componentOptions : $options); } throw new \Exception('Components data URI scheme only supports base64 (data:base64,ABCD...)!'); } elseif ($scheme === 'file') { return $getComponentFileContent(urldecode($sourceParts[1]), $component, isset($options['variables']) && is_array($options['variables']) ? $options['variables'] : []); //$this->process(isset($componentOptions) ? $componentOptions : $options); } throw new \Exception('Components URI scheme not valid! It must be \'file:\', \'data:\' or an alias.'); } throw new \Exception('Components URI scheme or alias not found at ' . (string) $component . '!'); } throw new \Exception('Component src attribute is missing at ' . (string) $component . '!'); }; $disableLevelProcessing = false; $domDocument = new HTML5DOMDocument(); if ($content instanceof HTMLServerComponent) { $domDocument->loadHTML($getComponentResultHTML($content), HTML5DOMDocument::ALLOW_DUPLICATE_IDS); if (isset($options['recursive']) && $options['recursive'] === false) { $disableLevelProcessing = true; } } else { $domDocument->loadHTML($content, HTML5DOMDocument::ALLOW_DUPLICATE_IDS); } if (!$disableLevelProcessing) { $tagsQuerySelector = implode(',', $tagNames); for ($level = 0; $level < 1000; $level++) { $componentElements = $domDocument->querySelectorAll($tagsQuerySelector); if ($componentElements->length === 0) { break; } $insertHTMLSources = []; $list = []; // Save the elements into an array because removeChild() messes up the NodeList foreach ($componentElements as $index => $componentElement) { $parentNode = $componentElement->parentNode; $list[$index] = [$componentElement, $parentNode, []]; // The last one will contain the parents tag names while ($parentNode !== null && isset($parentNode->tagName)) { $tagName = $parentNode->tagName; $list[$index][2][] = $tagName; if ($tagName === 'head' || $tagName === 'body') { break; } $parentNode = $parentNode->parentNode; } } foreach ($list as $index => $componentData) { if (!empty(array_intersect($componentData[2], $tagNames))) { continue; } $componentElement = $componentData[0]; $component = $this->makeComponent($componentElement->getAttributes(), $componentElement->innerHTML, $componentElement->tagName); $componentResultHTML = $getComponentResultHTML($component); if (array_search('body', $componentData[2]) !== false) { $insertTargetName = 'html-server-components-compiler-insert-target-' . $index; $componentData[1]->insertBefore($domDocument->createInsertTarget($insertTargetName), $componentElement); $componentData[1]->removeChild($componentElement); // must be before insertHTML because a duplicate elements IDs can occur. $insertHTMLSources[] = ['source' => $componentResultHTML, 'target' => $insertTargetName]; } else { $componentData[1]->removeChild($componentElement); $insertHTMLSources[] = ['source' => $componentResultHTML]; } } $domDocument->insertHTMLMulti($insertHTMLSources); if (isset($options['recursive']) && $options['recursive'] === false) { break; } } } $domDocument->modify(HTML5DOMDocument::FIX_MULTIPLE_TITLES | HTML5DOMDocument::FIX_DUPLICATE_METATAGS | HTML5DOMDocument::FIX_MULTIPLE_HEADS | HTML5DOMDocument::FIX_MULTIPLE_BODIES | HTML5DOMDocument::OPTIMIZE_HEAD | HTML5DOMDocument::FIX_DUPLICATE_STYLES); return $domDocument->saveHTML(); } /** * Constructs a component object. * * @param array $attributes The attributes of the component object. * @param string $innerHTML The innerHTML of the component object. * @param string $tagName The tag name of the component object. * @return \IvoPetkov\HTMLServerComponent A component object. */ public function makeComponent(array $attributes = [], string $innerHTML = '', string $tagName = 'component') { if (self::$newComponentCache === null) { self::$newComponentCache = new HTMLServerComponent(); } $component = clone (self::$newComponentCache); $component->setAttributes($attributes); $component->innerHTML = $innerHTML; $component->tagName = $tagName; return $component; } } __halt_compiler();----SIGNATURE:----Dv42dlDe01j6wpNGmHK5hSzpZO/1qM0ukaCgp1fpsExAEyP+FeYtjUvRowubA7ryRgNups6pa1xJhmSAMn9tVo/QcwnIqo7JAlUUS5BClmIMufB70BmLahzc+MM0dpwQSq09WsWaUgDPSqThkvB2nkEREULTSkxg38kvbLzOOQls09vE6osXcHtAQ2cppD/BORk9fUuvEAXAPDfjd/y/v6zgaErzEs/M6HHcLQWtOSILThIt7/ojtmXw4GidvDphrr51/L7z+pS11vQmKr+/Fjol/qwWgCN8VjZio3dT2V/VDxoYZspP3hD2gveuXkiDiVbics8WbLLgJ7ArwzBDlP9J00fh1T3fUlrq9kVsfc5TBFB3OHlLTg7b+xWabHJYK1WStGfTMoOJdgXRVowyTDBUDtGYywcQjNW4spBmsoZBsr/m32Fx8sONCmg3lS5IQ43/j0fhG8LKdkP8b8wQT4+0Y8jJeTvXJyhxa1Ka10VsDEBp8z09RFgfl43055VO+ZcbVpL8RljFT8mk4CL/XEkNazSM8CIjLKSc+Elai1PiH4nTd/kipdwnABP48kLssCg0bnwWKFbjaDROjSoMTpiNb9KqSMm4oRrsgD+1iuxtzvBFVJpit2TYgmyLw24DPJav6VfeJ5RClKu/MyjI/kf5owEkZ38VAFDhYPW1Msk=----ATTACHMENT:----NTMyMjcyOTI1MDAxMTMxOSAyMjc3NDczOTAyMzg4Mjc4IDc2ODU5MzM0MDQxNTUwNDc=