getEncoding(); $html = '' . PHP_EOL; return $html; } /** * @param array|\Traversable $list * @param callable $renderFn * @param array $options * * @return string */ public static function renderIteratorFn($list, $renderFn = null, array $options = []) { if (empty($list)) { return ''; } $options = array_merge([ 'listTag' => 'ul', 'itemTag' => 'li', 'listAttribs' => [], 'itemAttribs' => [], ], $options); $html = '<' . $options['listTag'] . self::renderAttribs($options['listAttribs']) . '>'; foreach ($list as $key => $value) { $html .= '<' . $options['itemTag'] . self::renderAttribs($options['itemAttribs']) . '>' . ($renderFn ? $renderFn($value, $key) : $value) . '' . PHP_EOL; } $html .= '' . PHP_EOL; return $html; } public static function renderLink($url, $text = null, array $attribs = []) { if (empty($text)) { $text = $url; } $attribs['href'] = $url; return self::renderContainer('a', $text, $attribs); } public static function renderAttribs(array $attribs) { $xhtml = ''; $enc = Qs_View::getInstance()->getEncoding(); foreach ((array) $attribs as $key => $val) { $key = htmlspecialchars($key, ENT_COMPAT, $enc); if (empty($val)) { $xhtml .= ' ' . $key; continue; } if (is_array($val)) { if (array_key_exists('callback', $val) && is_callable($val['callback']) ) { $val = call_user_func($val['callback']); } else { $val = implode(' ', $val); } } $val = htmlspecialchars($val, ENT_COMPAT, $enc); $xhtml .= " $key=\"$val\""; } return $xhtml; } /** * @param $tags * * @param $content * @param array $attribs * @return string */ public static function renderContainer($tags, $content, array $attribs = []) { if (is_string($tags)) { $tags = [['tag' => $tags]]; } if (is_array($tags)) { $tags = array_map(function ($value) { if (is_array($value)) { return $value; } return ['tag' => $value]; }, $tags); } $tags = array_reverse($tags); $firstKey = key($tags); if ($attribs && !array_key_exists('attribs', $tags[$firstKey])) { $tags[$firstKey]['attribs'] = $attribs; } $xhtml = $content; reset($tags); foreach ($tags as $tag) { $xhtml = '<' . $tag['tag'] . self::renderAttribs(Qs_Array::get($tag, 'attribs', [])) . '>' . $xhtml . '' . PHP_EOL; } return $xhtml; } public static function renderTag($tag, array $attribs = []) { return '<' . $tag . self::renderAttribs($attribs) . '/>' . PHP_EOL; } public static function renderStylesheetLink($href, $media = 'all') { $type = 'text/css'; $rel = 'stylesheet'; return self::renderTag('link', compact('href', 'media', 'type', 'rel')); } public static function toggleClass($class, $name, $display) { if ($display) { return self::addClass($class, $name); } return self::removeClass($class, $name); } public static function removeClass($class, $name) { $parts = explode(' ', $class); $parts = array_filter($parts, 'trim'); return implode(' ', Qs_Array::excludeValue($parts, $name)); } public static function addClass($class, $name) { $parts = explode(' ', $class); $parts = array_filter($parts, 'trim'); if (!in_array($name, $parts)) { $parts[] = $name; } return implode(' ', $parts); } public static function template($html, array $placeholders) { $html = Qs_String::fill($html, $placeholders); if (false === strpos($html, 'data-st-if')) { return $html; } $dom = new DOMDocument(); if (false === $dom->loadHTML($html)) { return $html; } $xpath = new DomXpath($dom); $list = $xpath->query('//*[@data-st-if]'); /** @var \DOMElement $node */ foreach ($list as $node) { $value = $node->attributes->getNamedItem('data-st-if')->value; $node->removeAttribute('data-st-if'); $node->removeAttribute('data-st-comment'); if ($value) { $value = htmlspecialchars_decode($value); $revert = false; if ('!' === $value[0]) { $revert = true; $value = substr($value, 1); } if ($revert !== empty($placeholders[$value])) { $node->parentNode->removeChild($node); } } } // remove automatically added tags: "doctype", "html", "body" $html = preg_replace('~<(?:!DOCTYPE|/?(?:html|body))[^>]*>\s*~i', '', $dom->saveHTML()); return $html; } }