static function updateAssetsUrls($content, $ajaxMode) { $serverUrl = \BearCMS\Internal\Options::$serverUrl; if ($ajaxMode) { $hasChange = false; $contentData = json_decode($content, true); if (isset($contentData['jsFiles'])) { $newJsFiles = []; foreach ($contentData['jsFiles'] as $src) { if (isset($src[0]) && strpos($src, $serverUrl) === 0) { $hasChange = true; $scriptBundle[] = $src; } else { $newJsFiles[] = $src; } } if (!empty($scriptBundle)) { $newJsFiles[] = self::getAssetsUrl(array_unique($scriptBundle)); } $contentData['jsFiles'] = $newJsFiles; } if ($hasChange) { return json_encode($contentData); } } else { $hasChange = false; $dom = new \IvoPetkov\HTML5DOMDocument(); $dom->loadHTML($content); $scripts = $dom->querySelectorAll('script'); $scriptBundle = []; $scriptsToRemove = []; foreach ($scripts as $script) { $src = (string) $script->getAttribute('src'); if (isset($src[0]) && strpos($src, $serverUrl) === 0) { $hasChange = true; if ($script->getAttribute('async') === 'async') { $scriptsToRemove[] = $script; $scriptBundle[] = $src; } else { $script->setAttribute('src', self::getAssetsUrl([$src])); } } } foreach ($scriptsToRemove as $script) { $script->parentNode->removeChild($script); } if (!empty($scriptBundle)) { $script = $dom->createElement('script'); $script->setAttribute('async', 'async'); $script->setAttribute('src', self::getAssetsUrl(array_unique($scriptBundle))); $dom->querySelector('body')->appendChild($script); } if ($hasChange) { return $dom->saveHTML(); } } return $content; }
/** * Sets the value for the property specified * * @param string $name * @param string $value * @throws \InvalidArgumentException * @throws \Exception */ public function __set($name, $value) { if (!is_string($value)) { throw new \InvalidArgumentException('The value argument must be of type string'); } if ($name === 'innerHTML') { while ($this->hasChildNodes()) { $this->removeChild($this->firstChild); } $tmpDoc = new \IvoPetkov\HTML5DOMDocument(); $tmpDoc->loadHTML('<body>' . $value . '</body>'); foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) { $node = $this->ownerDocument->importNode($node, true); $this->appendChild($node); } return; } elseif ($name === 'outerHTML') { $tmpDoc = new \IvoPetkov\HTML5DOMDocument(); $tmpDoc->loadHTML('<body>' . $value . '</body>'); foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) { $node = $this->ownerDocument->importNode($node, true); $this->parentNode->insertBefore($node, $this); } $this->parentNode->removeChild($this); return; } throw new \Exception('Undefined property: HTML5DOMElement::$' . $name); }
$attributes = ''; $attributes .= ' type="' . $menuType . '"'; if (strlen($component->class) > 0) { $attributes .= ' class="' . htmlentities($component->class) . '"'; } $attributes .= ' moreItemHtml="' . htmlentities('<li class="bearcms-navigation-element-item bearcms-navigation-element-item-more"><a></a><ul class="bearcms-navigation-element-item-children"></ul></li>') . '"'; $dataResponsiveAttributes = $component->getAttribute('data-responsive-attributes'); if (strlen($dataResponsiveAttributes) > 0) { $attributes .= ' data-responsive-attributes="' . htmlentities(str_replace('=>menuType=', '=>type=', $dataResponsiveAttributes)) . '"'; } if ($pages !== null && $showHomeButton) { $pages->unshift(new \BearCMS\DataObject(['id' => '_home', 'path' => '/', 'name' => $homeButtomText, 'parentID' => '', 'status' => 'published'])); } $itemsHtml = (string) $component->innerHTML; if (isset($itemsHtml[0])) { $domDocument = new IvoPetkov\HTML5DOMDocument(); $domDocument->loadHTML($itemsHtml); $ulElements = $domDocument->querySelectorAll('ul'); foreach ($ulElements as $index => $ulElement) { $ulElement->setAttribute('class', trim($ulElement->getAttribute('class') . ' ' . ($index === 0 ? 'bearcms-navigation-element' : 'bearcms-navigation-element-item-children'))); } $liElements = $domDocument->querySelectorAll('li'); foreach ($liElements as $index => $liElement) { $liClasssName = 'bearcms-navigation-element-item'; if ($liElement->firstChild) { $liPath = str_replace($app->request->base, '', $liElement->firstChild->getAttribute('href')); if ($liPath === $selectedPath) { $liClasssName .= ' bearcms-navigation-element-item-selected'; } elseif ($liPath !== '/' && strpos($selectedPath, $liPath) === 0) { $liClasssName .= ' bearcms-navigation-element-item-in-path'; }
static function getRawDataFromComponent($component) { $type = self::$elementTypes[$component->src]; $data = []; $copyString = function ($name) use($component, &$data) { $data[$name] = (string) $component->{$name}; }; $copyBoolean = function ($name) use($component, &$data) { $data[$name] = $component->{$name} === 'true' ? true : false; }; $copyInt = function ($name) use($component, &$data) { $data[$name] = (int) $component->{$name}; }; if ($type === 'heading') { $copyString('text'); $copyString('size'); } elseif ($type === 'text') { $copyString('text'); } elseif ($type === 'link') { $copyString('url'); $copyString('text'); $copyString('title'); } elseif ($type === 'video') { $copyString('url'); $copyString('filename'); } elseif ($type === 'image') { $copyString('filename'); $copyString('title'); $copyString('onClick'); $copyString('url'); } elseif ($type === 'imageGallery') { $copyString('type'); $copyString('columnsCount'); if (is_numeric($data['columnsCount'])) { $data['columnsCount'] = (int) $data['columnsCount']; } $copyString('imageSize'); $copyString('imageAspectRatio'); $data['files'] = []; if (strlen($component->innerHTML) > 0) { $domDocument = new \IvoPetkov\HTML5DOMDocument(); $domDocument->loadHTML($component->innerHTML); $files = $domDocument->querySelectorAll('file'); foreach ($files as $file) { $filename = $file->getAttribute('filename'); $data['files'][] = ['filename' => $filename]; } } } elseif ($type === 'navigation') { $copyString('type'); $copyString('pageID'); } elseif ($type === 'html') { $copyString('code'); } elseif ($type === 'blogPosts') { $copyString('type'); $copyBoolean('showDate'); $copyInt('limit'); } return ['id' => $component->id, 'type' => $type, 'data' => $data]; }
/** * Converts components code (if any) into HTML code * * @param string|\IvoPetkov\HTMLServerComponent $content The content to be processed * @param array $options Compiler options * @throws \InvalidArgumentException * @return string The result HTML code */ public function process($content, $options = []) { if (!is_string($content) && !$content instanceof \IvoPetkov\HTMLServerComponent) { throw new \InvalidArgumentException(''); } if (!is_array($options)) { throw new \InvalidArgumentException(''); } if (is_string($content) && strpos($content, '<component') === false) { return $content; } if (isset($options['_internal_process_components']) && $options['_internal_process_components'] === false) { return $content; } $getComponentFileContent = 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) { if (isset($component->attributes['src'])) { // todo check alias of alias $srcAttributeValue = $component->attributes['src']; if (isset($this->aliases[$srcAttributeValue])) { $sourceParts = explode(':', $this->aliases[$srcAttributeValue], 2); } else { $sourceParts = explode(':', $srcAttributeValue, 2); } if (sizeof($sourceParts) === 2) { $scheme = $sourceParts[0]; if (isset($options['recursive']) && $options['recursive'] === false) { $componentOptions = array_merge($options, ['_internal_process_components' => false]); } if ($scheme === 'data') { if (substr($sourceParts[1], 0, 7) === 'base64,') { return $this->process(base64_decode(substr($sourceParts[1], 7)), isset($componentOptions) ? $componentOptions : $options); } throw new \Exception('Components data URI scheme only supports base64 (data:base64,ABCD...)!'); } elseif ($scheme === 'file') { return $this->process($getComponentFileContent(urldecode($sourceParts[1]), $component, isset($options['variables']) && is_array($options['variables']) ? $options['variables'] : []), 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 . '!'); }; $domDocument = new \IvoPetkov\HTML5DOMDocument(); if ($content instanceof \IvoPetkov\HTMLServerComponent) { $domDocument->loadHTML($getComponentResultHTML($content)); } else { $domDocument->loadHTML($content); $componentElements = $domDocument->getElementsByTagName('component'); $componentElementsCount = $componentElements->length; if ($componentElementsCount > 0) { for ($i = 0; $i < $componentElementsCount; $i++) { $componentElement = $componentElements->item(0); $component = $this->constructComponent($componentElement->getAttributes(), $componentElement->innerHTML); $componentResultHTML = $getComponentResultHTML($component); $isInBodyTag = false; $parentNode = $componentElement->parentNode; while ($parentNode !== null && isset($parentNode->tagName)) { if ($parentNode->tagName === 'body') { $isInBodyTag = true; break; } $parentNode = $parentNode->parentNode; } if ($isInBodyTag) { $insertTargetName = 'html-server-components-compiler-target-' . uniqid(); $componentElement->parentNode->insertBefore($domDocument->createInsertTarget($insertTargetName), $componentElement); $domDocument->insertHTML($componentResultHTML, $insertTargetName); } else { $domDocument->insertHTML($componentResultHTML); } $componentElement->parentNode->removeChild($componentElement); } } } return $domDocument->saveHTML(); }
} $lazyLoadImages = false; if ($component->lazyLoadImages === 'true') { $lazyLoadImages = true; } $galleryID = 'imggallery' . uniqid(); $containerAttributes = ''; if ($onClick === 'fullscreen') { $hasLightbox = true; $jsData = ['galleryID' => $galleryID, 'lightboxData' => ['images' => []], 'images' => []]; $index = 0; foreach ($files as $file) { $filename = $file->getAttribute('filename'); $imageContainerID = $galleryID . 'img' . $index; $html = $app->components->process('<div id="' . $imageContainerID . '"><component style="background-color:#000;" src="lazy-image" filename="' . $filename . '"/></div>'); $imageDomDocument = new IvoPetkov\HTML5DOMDocument(); $imageDomDocument->loadHTML($html); $imageHTMLBody = $imageDomDocument->querySelector('body'); $imageHTML = $imageHTMLBody->innerHTML; $imageHTMLBody->parentNode->removeChild($imageHTMLBody); $jsData['lightboxData']['images'][] = ['html' => $imageHTML, 'onBeforeShow' => 'window.' . $galleryID . 'ig.onBeforeShow(' . $index . ');', 'onShow' => 'window.' . $galleryID . 'ig.onShow(' . $index . ');']; list($imageWidth, $imageHeight) = $app->images->getSize($filename); $jsData['images'][] = [$imageWidth, $imageHeight, $imageDomDocument->saveHTML()]; $index++; } } $getColumnsStyle = function ($columnsCount, $attributeSelector = '') use($galleryID, $spacing) { $result = '#' . $galleryID . $attributeSelector . '>div{vertical-align:top;display:inline-block;width:calc((100% - ' . $spacing . '*' . ($columnsCount - 1) . ')/' . $columnsCount . ');margin-right:' . $spacing . ';margin-top:' . $spacing . ';}'; $result .= '#' . $galleryID . $attributeSelector . '>div:nth-child(' . $columnsCount . 'n){margin-right:0;}'; for ($i = 1; $i <= $columnsCount; $i++) { $result .= '#' . $galleryID . $attributeSelector . '>div:nth-child(' . $i . '){margin-top:0;}';
<?php /* * Bear CMS addon for Bear Framework * https://bearcms.com/ * Copyright (c) 2016 Amplilabs Ltd. * Free to use under the MIT license. */ use BearFramework\App; $app = App::get(); $domDocument = new IvoPetkov\HTML5DOMDocument(); $domDocument->loadHTML($component->innerHTML); $files = $domDocument->querySelectorAll('file'); $spacing = $component->spacing; $content = '<div class="bearcms-image-gallery-element" style="font-size:0;">'; $attributes = ''; if (strlen($component->type) > 0) { $attributes .= ' type="' . $component->type . '"'; } if (strlen($component->columnsCount) > 0) { $attributes .= ' columnsCount="' . $component->columnsCount . '"'; } if (strlen($component->imageSize) > 0) { $attributes .= ' imageSize="' . $component->imageSize . '"'; } if (strlen($component->imageAspectRatio) > 0) { $attributes .= ' imageAspectRatio="' . $component->imageAspectRatio . '"'; } if (strlen($component->imageLoadingBackground) > 0) { $attributes .= ' imageLoadingBackground="' . $component->imageLoadingBackground . '"'; }
$temp = (string) $component->type; if ($temp !== '') { if (array_search($temp, ['horizontal-down', 'vertical-left', 'vertical-right', 'list-vertical', 'list-horizontal']) !== false) { $type = $temp; } } $moreItemHtml = '<li><a>...</a><ul></ul></li>'; $temp = (string) $component->moreItemHtml; if ($temp !== '') { $moreItemHtml = $temp; } $innerHTML = trim($component->innerHTML); if (!isset($innerHTML[0])) { $innerHTML = '<ul></ul>'; } $domDocument = new IvoPetkov\HTML5DOMDocument(); $domDocument->loadHTML($innerHTML); $rootElement = $domDocument->querySelector('ul'); if ($rootElement === null) { return; } $elementID = 'nvgmn' . md5(uniqid()); $rootElement->setAttribute('id', $elementID); if ($type === 'horizontal-down' || $type === 'vertical-left' || $type === 'vertical-right') { $rootElement->setAttribute('data-nm-type', $type); $rootElement->setAttribute('data-nm-more', $moreItemHtml); } $dataResponsiveAttributes = $component->getAttribute('data-responsive-attributes'); if (strlen($dataResponsiveAttributes) > 0) { $rootElement->setAttribute('data-responsive-attributes', str_replace('=>type=', '=>data-nm-type=', $dataResponsiveAttributes)); }
static function replaceContent($data, $response) { $app = App::$instance; $body = $response['body']; $content = $app->components->process($data['content']); $domDocument = new \IvoPetkov\HTML5DOMDocument(); $domDocument->loadHTML($content); $bodyElement = $domDocument->querySelector('body'); $content = $bodyElement->innerHTML; $bodyElement->parentNode->removeChild($bodyElement); $allButBody = $domDocument->saveHTML(); $startPosition = strpos($body, '{bearcms-replace-content-' . $data['id'] . '-'); if ($startPosition === false) { return; } $endPosition = strpos($body, '}', $startPosition); $modificationsString = substr($body, $startPosition + 58, $endPosition - $startPosition - 58); $parts = explode('\'', $modificationsString); $singleQuoteSlashesCount = strlen($parts[0]); $doubleQuoteSlashesCount = strlen($parts[1]) - 1; for ($i = 0; $i < $doubleQuoteSlashesCount; $i += 2) { $content = substr(json_encode($content), 1, -1); } for ($i = 0; $i < $singleQuoteSlashesCount; $i += 2) { $content = addslashes($content); } $body = str_replace(substr($body, $startPosition, $endPosition - $startPosition + 1), $content, $body); //todo optimize $response1 = ['js' => 'html5DOMDocument.insert(' . json_encode($allButBody, true) . ');']; $response2 = json_decode($body, true); $response['body'] = json_encode(Server::mergeAjaxResponses($response1, $response2)); }