<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* MaxSite CMS
* (c) https://max-3000.com/
*
*/
// формируем скрытый input для формы с текущей сессией
function mso_form_session($name_form = 'flogin_session_id')
{
return '<input type="hidden" value="' . getinfo('session_id') . '" name="' . $name_form . '">';
}
// вывод логин-формы
// в login_form_auth_title для разделителей используется код [end] - нужен для того, чтобы перечислять через запятую
function mso_login_form($conf = [], $redirect = '', $echo = true)
{
if ($redirect == '') $redirect = urlencode(mso_current_url());
// готовим переменные для файла шаблонизатора loginform-common-tmpl.php
$login = $conf['login'] ?? '';
$password = $conf['password'] ?? '';
$submit = $conf['submit'] ?? '';
$submit_value = $conf['submit_value'] ?? tf('Войти');
$submit_end = $conf['submit_end'] ?? '';
$form_end = $conf['form_end'] ?? '';
$login_add = $conf['login_add'] ?? '';
$password_add = $conf['password_add'] ?? '';
$tmpl_file = $conf['tmpl_file'] ?? 'type/loginform/units/loginform-common-tmpl.php';
$action = getinfo('site_url') . 'login';
$session_id = getinfo('session_id');
$login_form_auth_title = $conf['login_form_auth_title'] ?? tf('Вход через:') . ' ';
$hook_login_form_auth = mso_hook_present('login_form_auth') ? '<span class="login-form-auth-title">' . $login_form_auth_title . '</span>' . mso_hook('login_form_auth') : '';
if ($hook_login_form_auth) {
$hook_login_form_auth = trim(str_replace('[end]', ' ', $hook_login_form_auth));
$hook_login_form_auth = '<div class="login-form-auth">' . str_replace(' ', ', ', $hook_login_form_auth) . '</div>';
}
if ($echo) {
eval(mso_tmpl_ts($tmpl_file));
} else {
ob_start();
eval(mso_tmpl_ts($tmpl_file));
$out = ob_get_contents();
ob_end_clean();
return $out;
}
}
// формируем li-элементы для меню
// элементы представляют собой текст, где каждая строчка один пункт
// каждый пункт делается так: http://ссылка | название | подсказка | class | class_для_span | атрибуты ссылки
// на выходе так:
// <li class="selected"><a href="url"><span>ссылка</span></a></li>
// если первый символ [ то это открывает группу ul
// если ] то закрывает - позволяет создавать многоуровневые меню
// если адрес равен # то ссылка не формируется, только текст <li class=""><span>ссылка</span></li>
// если пункт меню равен --- то формируется разделитель li.divider Имеет смысл только в подпунктах
function mso_menu_build($menu = '', $select_css = 'selected', $add_link_admin = false)
{
// добавить ссылку на admin
if ($add_link_admin and is_login()) $menu .= NR . 'admin|Admin';
$menu = str_replace("\r", "", $menu); // если это windows
$menu = str_replace("_NR_", "\n", $menu);
$menu = str_replace(" ~ ", "\n", $menu);
$menu = str_replace("\n\n\n", "\n", $menu);
$menu = str_replace("\n\n", "\n", $menu);
// в массив
$menu = explode("\n", trim($menu));
// обработаем меню на предмет пустых строк, корректности и подсчитаем кол-во элементов
$count_menu = 0;
foreach ($menu as $elem) {
if (strlen(trim($elem)) > 1) $count_menu++;
}
// определим текущий url
$current_url = mso_current_url(true);
// $current_url = getinfo('site_protocol') . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$out = '';
$i = 1; // номер пункта
$n = 0; // номер итерации цикла
$group_in = false;
$group_in_first = false;
$group_num = 0; // номер группы
$group_work = false; // открытая группа?
$selected_present = false; // есть ли выделеный пункт?
$group_elem = 0; // элемент в группе
foreach ($menu as $elem) {
// разобъем строчку по адрес | название
$elem = explode('|', trim($elem));
// должно быть два элемента
if (count($elem) > 1) {
$url = trim($elem[0]); // адрес
$name = trim($elem[1]); // название
if (isset($elem[2]))
$title = ' title="' . htmlspecialchars(trim($elem[2])) . '"';
else
$title = '';
// если адрес = ## то не выводим ссылку
$a_link = ($url != '##');
// нет в адресе http:// - значит это текущий сайт
// если начинается с # или ? — ничего не делаем
if (
($url != '#')
and strpos($url, '#') !== 0
and strpos($url, '?') !== 0
and strpos($url, 'http://') === false
and strpos($url, 'https://') === false
) {
if ($url == '/')
$url = getinfo('siteurl'); // это главная
else
$url = getinfo('siteurl') . $url;
}
// если текущий адрес совпал, значит мы на этой странице
if ($url == $current_url) {
$class = ' ' . $select_css;
$selected_present = true;
} else {
$class = '';
}
// возможно указан css-класс
if (isset($elem[3])) $class .= ' ' . trim($elem[3]);
// возможно указан class_для_span
if (isset($elem[4]))
$class_span = ' class="' . trim($elem[4]) . '"';
else
$class_span = '';
// возможно указан атрибут_для_ссылки
$link_attr = (isset($elem[5])) ? ' ' . trim($elem[5]) : '';
// для первого элемента добавляем класс first
if ($i == 1) $class .= ' first';
if ($group_in_first) {
$class .= ' group-first';
$group_in_first = false;
}
// для последнего элемента добавляем класс last
if ($i == $count_menu) $class .= ' last';
if ($class == ' ') $class = '';
if ($group_in) {
// открываем группу
$group_num++;
$class .= ' group-num-' . $group_num;
if ($a_link) {
$out .= '<li class="group' . $class . '"><a href="' . $url . '"' . $title . $link_attr . '><span' . $class_span . '>' . $name . '</span></a><ul>';
} else {
$out .= '<li class="group' . $class . '"><span' . $class_span . '>' . $name . '</span><ul>';
}
$group_in = false;
$group_in_first = true;
} else {
if ($group_elem > 0 and array_key_exists($i, $menu) and isset($menu[$n + 1]) and trim($menu[$n + 1]) == ']') $class .= ' group-last';
if ($a_link) {
$out .= '<li class="' . trim($class) . '"><a href="' . $url . '"' . $title . $link_attr . '><span' . $class_span . '>' . $name . '</span></a></li>';
} else {
$out .= '<li class="' . trim($class) . '"><span' . $class_span . '>' . $name . '</span></li>';
}
}
if ($url == $current_url and $group_work) {
// выделяем родителя группы, если в ней выделенный подпункт
$out = str_replace('group-num-' . $group_num, 'group-num-' . $group_num . ' group-selected', $out);
$selected_present = true;
}
$i++;
$group_elem++;
} else {
// если это [, то это начало группы ul
// если ] то /ul
if ($elem[0] == '[') {
$group_in = true;
$group_work = true;
$group_elem = 0;
}
if ($elem[0] == ']') {
$group_elem = 0;
$group_in = false;
$group_work = false;
$out .= '</ul></li>';
}
if ($elem[0] == '---') {
// разделитель
$out .= '<li class="divider"><span></span></li>';
}
}
$n++;
}
$out = str_replace('<li class="">', '<li>', $out);
// если ничего не выделено, то для первой группы прописываем класс group-default
if (!$selected_present)
$out = str_replace('group-num-1', 'group-num-1 group-default', $out);
//pr($out, 1);
return $out;
}
// функция построения из массивов списка UL
// вход - массив из с [childs]=>array(...)
function mso_create_list($a = [], $options = [], $child = false)
{
static $level = 0;
if (!$a) return '';
if (!isset($options['class_ul'])) $options['class_ul'] = ''; // класс UL
if (!isset($options['class_ul_style'])) $options['class_ul_style'] = ''; // свой стиль для UL
if (!isset($options['class_child'])) $options['class_child'] = 'child'; // класс для ребенка
if (!isset($options['class_child_style'])) $options['class_child_style'] = ''; // свой стиль для ребенка
if (!isset($options['class_current'])) $options['class_current'] = 'current-page'; // класс li текущей страницы
if (!isset($options['class_current_style'])) $options['class_current_style'] = ''; // стиль li текущей страницы
if (!isset($options['class_li'])) $options['class_li'] = ''; // класс LI
if (!isset($options['class_li_style'])) $options['class_li_style'] = ''; // стиль LI
if (!isset($options['format'])) $options['format'] = '[LINK][TITLE][/LINK]'; // формат ссылки
if (!isset($options['format_current'])) $options['format_current'] = '<span>[TITLE]</span>'; // формат для текущей
if (!isset($options['title'])) $options['title'] = 'page_title'; // имя ключа для титула
if (!isset($options['link'])) $options['link'] = 'page_slug'; // имя ключа для слага
if (!isset($options['descr'])) $options['descr'] = 'category_desc'; // имя ключа для описания
if (!isset($options['id'])) $options['id'] = 'page_id'; // имя ключа для id
if (!isset($options['slug'])) $options['slug'] = 'page_slug'; // имя ключа для slug
if (!isset($options['menu_order'])) $options['menu_order'] = 'page_menu_order'; // имя ключа для menu_order
if (!isset($options['id_parent'])) $options['id_parent'] = 'page_id_parent'; // имя ключа для id_parent
if (!isset($options['count'])) $options['count'] = 'count'; // имя ключа для количества элементов
if (!isset($options['prefix'])) $options['prefix'] = 'page/'; // префикс для ссылки
if (!isset($options['current_id'])) $options['current_id'] = true; // текущая страница отмечается по page_id - иначе по текущему url
if (!isset($options['childs'])) $options['childs'] = 'childs'; // поле для массива детей
// если true, то главная рабрика выводится без ссылки в <span>
if (!isset($options['group_header_no_link'])) $options['group_header_no_link'] = false;
// функция, которая сработает на [FUNCTION]
// эта функция получает в качестве параметра текущий массив $elem
if (!isset($options['function'])) $options['function'] = false;
// функция которая просто срабатывают в теле цикла —
// принимает текущий элемент, выходную строчку и опцию function1_data
if (!isset($options['function1'])) $options['function1'] = false;
if (!isset($options['function1_data'])) $options['function1_data'] = [];
if (!isset($options['nofollow']) or !$options['nofollow'])
$options['nofollow'] = ''; // можно указать rel="nofollow" для ссылок
else
$options['nofollow'] = ' rel="nofollow"';
$class_child = $class_child_style = $class_ul = $class_ul_style = '';
$class_current = $class_current_style = $class_li = $class_li_style = '';
// [LEVEL] - заменяется на level-текущий уровень вложенности
if ($options['class_child']) $class_child = ' class="' . $options['class_child'] . ' [LEVEL]"';
$class_child = str_replace('[LEVEL]', 'level' . $level, $class_child);
if ($options['class_child_style'])
$class_child_style = ' style="' . $options['class_child_style'] . '"';
if ($options['class_ul'])
$class_ul = ' class="' . $options['class_ul'] . '"';
if ($options['class_ul_style'])
$class_ul_style = ' style="' . $options['class_ul_style'] . '"';
if ($options['class_current'])
$class_current = ' class="' . $options['class_current'] . '"';
if ($options['class_current_style'])
$class_current_style = ' style="' . $options['class_current_style'] . '"';
if ($options['class_li'])
$class_li = ' class="' . $options['class_li'] . ' group"';
else
$class_li = ' class="group"';
if ($options['class_li_style']) $class_li_style = ' style="' . $options['class_li_style'] . '"';
if ($child)
$out = NR . ' <ul' . $class_child . $class_child_style . '>';
else
$out = NR . '<ul' . $class_ul . $class_ul_style . '>';
$current_url = getinfo('siteurl') . mso_current_url(); // текущий урл
// из текущего адресу нужно убрать пагинацию
$current_url = str_replace('/next/' . mso_current_paged(), '', $current_url);
foreach ($a as $elem) {
$title = $elem[$options['title']];
$elem_slug = mso_strip($elem[$options['link']]); // slug элемента
$url = getinfo('siteurl') . $options['prefix'] . $elem_slug;
// если это page, то нужно проверить вхождение этой записи в элемент рубрики
// если есть, то ставим css-класс curent-page-cat
$curent_page_cat_class = is_page_cat($elem_slug, false, false) ? ' class="curent-page-cat"' : '';
$link = '<a' . $options['nofollow'] . ' href="' . $url . '" title="' . htmlspecialchars($title) . '"' . $curent_page_cat_class . '>';
if (isset($elem[$options['descr']]))
$descr = $elem[$options['descr']];
else
$descr = '';
if (isset($elem[$options['count']]))
$count = $elem[$options['count']];
else
$count = '';
if (isset($elem[$options['id']]))
$id = $elem[$options['id']];
else
$id = '';
if (isset($elem[$options['slug']]))
$slug = $elem[$options['slug']];
else
$slug = '';
if (isset($elem[$options['menu_order']]))
$menu_order = $elem[$options['menu_order']];
else
$menu_order = '';
if (isset($elem[$options['id_parent']]))
$id_parent = $elem[$options['id_parent']];
else
$id_parent = '';
$cur = false;
if ($options['current_id']) // текущий определяем по id страницы
{
if (isset($elem['current'])) {
$e = $options['format_current'];
$cur = true;
} else {
$e = $options['format'];
}
} else // определяем по урлу
{
if ($url == $current_url) {
$e = $options['format_current'];
$cur = true;
} else {
$e = $options['format'];
}
}
$e = str_replace('[LINK]', $link, $e);
$e = str_replace('[/LINK]', '</a>', $e);
$e = str_replace('[TITLE]', $title, $e);
$e = str_replace('[TITLE_HTML]', htmlspecialchars($title), $e);
$e = str_replace('[DESCR]', $descr, $e);
$e = str_replace('[DESCR_HTML]', htmlspecialchars($descr), $e);
$e = str_replace('[ID]', $id, $e);
$e = str_replace('[SLUG]', $slug, $e);
$e = str_replace('[SLUG_HTML]', htmlspecialchars($slug), $e);
$e = str_replace('[MENU_ORDER]', $menu_order, $e);
$e = str_replace('[ID_PARENT]', $id_parent, $e);
$e = str_replace('[COUNT]', $count, $e);
$e = str_replace('[URL]', $url, $e);
if ($options['function'] and function_exists($options['function'])) {
$function = $options['function']($elem);
$e = str_replace('[FUNCTION]', $function, $e);
} else {
$e = str_replace('[FUNCTION]', '', $e);
}
if ($options['function1'] and function_exists($options['function1'])) {
$e = $options['function1']($e, $elem, $options['function1_data']);
}
if (isset($elem[$options['childs']])) {
if ($cur) {
$out .= NR . '<li' . $class_current . $class_current_style . '>' . $e;
} else {
if ($options['group_header_no_link'])
$out .= NR . '<li' . $class_li . $class_li_style . '><span class="group_header">' . $title . '</span>';
else
$out .= NR . '<li' . $class_li . $class_li_style . '>' . $e;
}
++$level;
$out .= mso_create_list($elem[$options['childs']], $options, true);
--$level;
$out .= NR . '</li>';
} else {
if ($child)
$out .= NR . ' ';
else
$out .= NR;
// если нет детей, то уберем класс group
$class_li_1 = str_replace('group', '', $class_li);
if ($cur)
$out .= '<li' . $class_current . $class_current_style . '>' . $e . '</li>';
else
$out .= '<li' . $class_li_1 . $class_li_style . '>' . $e . '</li>';
}
}
if ($child)
$out .= NR . ' </ul>' . NR;
else
$out .= NR . '</ul>' . NR;
$out = str_replace('<li class="">', '<li>', $out);
return $out;
}
// формирование rss в <link rel...>
// для страниц и рубрик добавляются свои RSS
function mso_rss()
{
global $MSO;
$out = '<link rel="alternate" type="application/rss+xml" title="'
. tf('Все новые записи') . '" href="'
. getinfo('rss_url') . '">' . NR;
$out .= '<link rel="alternate" type="application/rss+xml" title="'
. tf('Все новые комментарии') . '" href="'
. getinfo('rss_comments_url') . '">';
if (is_type('page') and mso_segment(2) and (isset($MSO->data['pages_is']) and $MSO->data['pages_is'])) {
$out .= NR . '<link rel="alternate" type="application/rss+xml" title="'
. tf('Комментарии этой записи') . '" href="'
. getinfo('site_url') . mso_segment(1) . '/' . mso_segment(2) . '/feed">';
} elseif (is_type('category') and mso_segment(2) and (isset($MSO->data['pages_is']) and $MSO->data['pages_is'])) {
$out .= NR . '<link rel="alternate" type="application/rss+xml" title="'
. tf('Записи этой рубрики') . '" href="'
. getinfo('site_url') . mso_segment(1) . '/' . mso_segment(2) . '/feed">';
}
return $out;
}
// функция формирует <link rel="$REL" $ADD>
// $rel - тип rel. Если он равен canonical, то формируется канонизация
// http://www.google.com/support/webmasters/bin/answer.py?answer=139066&hl=ru
// <link rel="canonical" href="http://www.example.com/page/about">
function mso_link_rel($rel = 'canonical', $add = '', $url_only = false)
{
if (!$rel) return; // пустой тип
if ($rel == 'canonical') {
// свой обработчик
// если хук вернул false или '', то обработка продолжается дальше
// иначе хук возвращает url и происходит его вывод
if (mso_hook_present('canonicalUrl')) {
$rh = mso_hook('canonicalUrl');
if ($rh) return '<link rel="canonical" href="' . $rh . '">';
}
if ($add) {
return '<link rel="canonical" ' . $add . '>';
} else {
// для разных типов данных формируем разный канонический адрес
// он напрямую зависит от типа
$url = '';
// если есть хук canonical, то выполняем его
// если хук вернул какое-то значение, то это $url
// если нет, то выполняем типовое определение канонического адреса
if (mso_hook_present('canonical')) $url = mso_hook('canonical');
if (!$url) {
if (
is_type('page')
or is_type('category')
or is_type('tag')
or is_type('author')
or is_type('users')
or (mso_segment(1) == 'sitemap')
or (mso_segment(1) == 'contact')
) {
if (mso_segment(2)) {
$url = getinfo('site_url') . mso_segment(1) . '/' . urlencode(mso_segment(2));
} else {
$url = getinfo('site_url') . mso_segment(1);
}
} elseif (is_type('home')) {
$url = getinfo('site_url');
}
}
// пагинация
if (($cur = mso_current_paged()) > 1) {
if (is_type('home')) {
$url .= 'home/next/' . $cur;
} else {
if ($url) $url .= '/next/' . $cur;
}
}
if ($url) {
if ($url_only)
return $url;
else
return '<link rel="canonical" href="' . $url . '">';
}
}
} else {
if ($add) return '<link rel="' . $rel . '" ' . $add . '>';
}
}
/**
* формирование TITLE, meta: description, keywords
* $info: только один из вариантов: title, description, keywords
* $args: входящий аргумент данных, например $pages (записи)
* $format: формат вывода. Замены для:
* %title%, %page_title%, %category_name%, %category_desc%, %users_nik%, || (разделитель)
* $sep: разделитель
* $only_meta == true — вывод только meta-данных
* $add_pag == true — добавка пагинации (из опции title_pagination)
*
*/
function mso_head_meta($info = 'title', $args = '', $format = '%page_title%', $sep = '', $only_meta = false, $add_pag = true)
{
global $MSO;
// выявляем ошибочный info
if ($info != 'title' and $info != 'description' and $info != 'keywords') return '';
if (mso_hook_present('head_meta')) {
// если есть хуки, то управление передаем им
return mso_hook('head_meta', array('info' => $info, 'args' => $args, 'format' => $format, 'sep' => $sep, 'only_meta' => $only_meta));
}
// добавка пагинации на основе опции title_pagination и только для TITLE
$pag = '';
if ($add_pag and $info == 'title' and ($cur = mso_current_paged()) > 1 and $onum = mso_get_option('title_pagination', 'general', t(' - страница [NUM]'))) {
$pag = htmlspecialchars(str_replace('[NUM]', $cur, $onum));
}
// измененный для вывода титле хранится в $MSO->title description или keywords
if (!$args) // нет аргумента - выводим что есть
{
if (!$MSO->$info)
$out = $MSO->$info = getinfo($info) . $pag;
else
$out = $MSO->$info;
} else // есть аргументы/записи
{
if (is_scalar($args)) {
$out = $args . $pag; // какая-то явная строка - отдаем её как есть
} else // входной массив - скорее всего это страница
{
// %page_title% %title% %category_name%
// || это разделитель, который = $sep
// pr($args);
$category_name = '';
$category_desc = '';
$page_title = '';
$users_nik = '';
$title = getinfo($info);
if (isset($args[0]['page_categories_detail'])) {
$slug = is_type('category') ? mso_segment(2) : '';
foreach ($args[0]['page_categories_detail'] as $id => $val) {
if ($slug == $val['category_slug']) {
$category_name = $val['category_name'];
$category_desc = $val['category_desc'];
break;
}
}
}
if (isset($args[0]['page_title'])) $page_title = $args[0]['page_title'];
if (isset($args[0]['users_nik'])) $users_nik = $args[0]['users_nik'];
// если есть мета, то берем её
if (isset($args[0]['page_meta'][$info][0]) and $args[0]['page_meta'][$info][0]) {
if ($only_meta)
$category_name = $category_desc = $title = $sep = '';
$page_title = $args[0]['page_meta'][$info][0];
if ($info != 'title') $title = $page_title;
} else {
// для страницы если не указаны свои keywords, попробуем указать из меток
if ($info == 'keywords' and is_type('page') and isset($args[0]['page_meta']['tags']) and $args[0]['page_meta']['tags']) {
$page_title = implode(', ', $args[0]['page_meta']['tags']); // разбиваем массив меток в строку
}
// для страниц, если не указан description вытягиваем его из самого текста
if ($info == 'description' and is_type('page') and $w = mso_get_option('description_of_page', 'general', 50)) {
// вообще нет поля
if (!isset($args[0]['page_meta']['description'][0])) $d = 333;
// поле есть, но оно пустое
if (isset($args[0]['page_meta']['description'][0]) and !$args[0]['page_meta']['description'][0]) $d = 333;
if ($d == 333) // если есть признак
{
$t = strip_tags($args[0]['page_content']);
$t = trim(str_replace("\r", "", $t));
$t = trim(str_replace("\n", ' ', $t));
$t = trim(str_replace("\t", ' ', $t));
$t = trim(str_replace(' ', ' ', $t));
$t = trim(str_replace(' ', ' ', $t));
$page_title = mso_str_word($t, $w);
}
}
}
$arr_key = ['%title%', '%page_title%', '%category_name%', '%category_desc%', '%users_nik%', '||'];
$arr_val = [htmlspecialchars($title), htmlspecialchars($page_title), htmlspecialchars($category_name), htmlspecialchars($category_desc), htmlspecialchars($users_nik), $sep];
$out = str_replace($arr_key, $arr_val, $format) . $pag;
}
}
// отдаем результат, сразу же указывая измененный $info в $MSO
$out = $MSO->$info = trim($out);
return $out;
}
// формирует <style> из указанного адреса
// игнорируются дубли подключений
function mso_load_style($url = '', $nodouble = true)
{
global $MSO;
if (!isset($MSO->data['_loaded_style'])) $MSO->data['_loaded_style'] = [];
if ($nodouble and in_array($url, $MSO->data['_loaded_style'])) return ''; // уже была загрузка
$MSO->data['_loaded_style'][] = $url; // добавляем в список загруженных
$MSO->data['_loaded_style'] = array_unique($MSO->data['_loaded_style']);
return '<link rel="stylesheet" href="' . $url . '">';
}
// формирует <script> из указанного адреса
// если скрипт был уже загружен, его подключение игнорируется
function mso_load_script($url = '', $nodouble = true, $attr = '')
{
global $MSO;
if (!isset($MSO->data['_loaded_script'])) $MSO->data['_loaded_script'] = [];
if ($nodouble and in_array($url, $MSO->data['_loaded_script'])) return ''; // уже была загрузка
$MSO->data['_loaded_script'][] = $url; // добавляем в список загруженных
$MSO->data['_loaded_script'] = array_unique($MSO->data['_loaded_script']);
$attr = ($attr) ? ' ' . $attr : '';
return '<script' . $attr . ' src="' . $url . '"></script>';
}
/**
* формирование <script> с внешним js-файлом или
* формирование <link rel="stylesheet> с внешним css-файлом
* имя файла указывается относительно каталога шаблона
* если файла нет, то ничего не происходит
* если $lazy == true, то подключение файла будет в конце BODY по хуку mso_hook('body_end')
* если $auto_dir = __DIR__ то путь будет определен относительно каталога исполняемого php-файла
* например: component/header/header.php:
* с $auto_dir
* mso_add_file('js/my.js', false, __DIR__); // component/header/js/my.js
*
* или нужно указывать путь к файлу:
* mso_add_file('component/header/js/my.js');
*
* $js_attr — атрибут для js-скрипта, например 'async'
*
*/
function mso_add_file($fn, $lazy = false, $auto_dir = false, $js_attr = '')
{
global $MSO;
if ($auto_dir) {
$fn = str_replace(str_replace('\\', '/', getinfo('template_dir')), '', str_replace('\\', '/', $auto_dir)) . '/' . $fn;
}
if (file_exists(getinfo('template_dir') . $fn)) {
$ext = strtolower(substr(strrchr($fn, '.'), 1)); // расширение файла
$out = '';
if ($ext == 'js')
$out = mso_load_script(getinfo('template_url') . $fn, true, $js_attr);
elseif ($ext == 'css')
$out = mso_load_style(getinfo('template_url') . $fn);
if (!$lazy) {
echo $out;
} elseif ($out) {
// вывод через хук body_end — mso_add_file_body_end()
if (!isset($MSO->data['add_file_to_body_end'])) $MSO->data['add_file_to_body_end'] = [];
$MSO->data['add_file_to_body_end'][] = $out;
}
}
}
/**
* Функция к хуку body_end по которой выводятся все подключенные файлы через mso_add_file(файл, true)
* Lazy-загрузка в конце BODY
*/
function mso_add_file_body_end($a)
{
global $MSO;
// jQuery имеет приоритет
$mode = mso_get_option('jquery_load', 'general', 'head');
if ($mode == 'body') {
if (mso_fe('assets/js/jquery.min.js'))
$fj = getinfo('template_url') . 'assets/js/jquery.min.js';
else
$fj = getinfo('common_url') . 'jquery/jquery.min.js';
echo '<script src="' . $fj . '"></script>';
}
if (!isset($MSO->data['add_file_to_body_end']) or !$MSO->data['add_file_to_body_end'])
return $a;
echo implode($MSO->data['add_file_to_body_end']);
return $a;
}
/**
* сжатие HTML
*
* @param $text входной текст
* @return string
*/
function mso_compress_text($text)
{
// защищенный текст
$text = preg_replace_callback('!(<pre.*?>)(.*?)(</pre>)!is', '_mso_protect_pre', $text);
$text = preg_replace_callback('!(<code.*?>)(.*?)(</code>)!is', '_mso_protect_pre', $text);
$text = preg_replace_callback('!(<script.*?>)(.*?)(</script>)!is', '_mso_protect_pre', $text); // _mso_protect_script
$text = preg_replace_callback('!(<style.*?>)(.*?)(</style>)!is', '_mso_protect_pre', $text);
$text = preg_replace_callback('!(<textarea.*?>)(.*?)(</textarea>)!is', '_mso_protect_pre', $text);
// сжатие
$text = str_replace("\r", "", $text);
$text = str_replace("\t", ' ', $text);
$text = str_replace("\n ", "\n", $text);
$text = str_replace("\n ", "\n", $text);
$text = str_replace("\n ", "\n", $text);
$text = str_replace("\n", '', $text);
$text = str_replace(' ', ' ', $text);
$text = str_replace(' ', ' ', $text);
// специфичные замены
$text = str_replace('<!---->', '', $text);
$text = str_replace('> <', '><', $text);
$text = str_replace('> <', '><', $text);
$text = str_replace('> <', '><', $text);
$text = preg_replace_callback('!\[html_base64\](.*?)\[\/html_base64\]!is', function ($m) {
return base64_decode($m[1]);
}, $text);
return $text;
}
/**
* заменяет в тексте все вхождения http:// и https:// на //
*
* @param $text текст
* @return string
*/
function mso_remove_protocol($text)
{
// защищенный текст
$text = preg_replace_callback('!(<pre.*?>)(.*?)(</pre>)!is', '_mso_protect_pre', $text);
$text = preg_replace_callback('!(<code.*?>)(.*?)(</code>)!is', '_mso_protect_pre', $text);
$text = preg_replace_callback('!(<script.*?>)(.*?)(</script>)!is', '_mso_protect_pre', $text); // _mso_protect_script
$text = preg_replace_callback('!(<style.*?>)(.*?)(</style>)!is', '_mso_protect_pre', $text);
$text = preg_replace_callback('!(<textarea.*?>)(.*?)(</textarea>)!is', '_mso_protect_pre', $text);
$text = str_replace('https://', '//', $text);
$text = str_replace('http://', '//', $text);
$text = preg_replace_callback('!\[html_base64\](.*?)\[\/html_base64\]!is', function ($m) {
return base64_decode($m[1]);
}, $text);
return $text;
}
/**
* pre, которое загоняется в [html_base64]
* callback
*
* @param $matches matches
* @return string
*/
function _mso_protect_pre($matches)
{
return '[html_base64]' . base64_encode($matches[1] . $matches[2] . $matches[3]) . '[/html_base64]';
/*
$text = str_replace('<p>', '', $text);
$text = str_replace('</p>', '', $text);
$text = str_replace('[', '[', $text);
$text = str_replace(']', ']', $text);
$text = str_replace("<br>", "\n", $text);
$text = str_replace("<br />", "<br>", $text);
$text = str_replace("<br/>", "<br>", $text);
$text = str_replace("<br>", "\n", $text);
$text = str_replace('<', '<', $text);
$text = str_replace('>', '>', $text);
$text = str_replace('<pre', '<pre', $text);
$text = str_replace('</pre', '</pre', $text);
$text = str_replace('pre>', 'pre>', $text);
$text = $matches[1] . "\n" . '[html_base64]' . base64_encode($text) . '[/html_base64]' . $matches[3];
*/
}
/**
* script и style, которые загоняются в [html_base64]
* callback
*
* @param $matches matches
* @return string
*/
# function _mso_protect_script($matches)
# {
# $text = trim($matches[2]);
# $text = $matches[1] . '[html_base64]' . base64_encode($text) . '[/html_base64]' . $matches[3];
#
# return $text;
# }
/**
* получает css из указанного файла
* в css-файле можно использовать php
* осуществляется сжатие css
* автозамена [TEMPLATE_URL] на url-шаблона
* функция возвращает только стили, без обрамляющего <style>
* Если <style> нужны, то $tag_style = true
* Если нужен сразу вывод в браузер, то $echo = true
*
* @param string $fn имя файла
* @param type $tag_style флаг для обрамления в STYLE
* @param type $echo флаг вывода результата по echo
* @return string
*/
function mso_out_css_file($fn, $tag_style = true, $echo = true)
{
$fn = getinfo('template_dir') . $fn;
$out = '';
if (file_exists($fn)) {
if ($r = @file_get_contents($fn)) $out .= $r . NR; // получаем содержимое
if ($out) {
ob_start();
eval('?>' . stripslashes($out) . '<?php ');
$out = ob_get_contents();
ob_end_clean();
$out = str_replace('[TEMPLATE_URL]', getinfo('template_url'), $out);
$out = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $out);
$out = str_replace(array('; ', ' {', ': ', ', '), array(';', '{', ':', ','), $out);
}
if ($tag_style) $out = '<style>' . $out . '</style>';
if ($echo) echo $out;
}
return $out;
}
/**
* Функция позволяет добавлять в секцию HEAD link rel="preload"
* Можно использовать совместно с mso_add_file() с опцией $lazy = true
*
* mso_add_preload('assets/js/tabs.js');
* mso_add_file('assets/js/tabs.js', true);
*
* @param $fn — имя файла относительно каталога шаблона
* @param $auto_dir — путь будет определен относительно каталога исполняемого php-файла см. mso_add_file()
*
* Файл может иметь расширение: js, css, woff, woff2, mp4
*
*/
function mso_add_preload($fn, $auto_dir = '')
{
global $MSO;
if ($auto_dir) {
$fn = str_replace(str_replace('\\', '/', getinfo('template_dir')), '', str_replace('\\', '/', $auto_dir)) . '/' . $fn;
}
if (file_exists(getinfo('template_dir') . $fn)) {
$ext = strtolower(substr(strrchr($fn, '.'), 1)); // расширение файла
$html = '';
if ($ext == 'js')
$html = '<link rel="preload" href="' . getinfo('template_url') . $fn . '" as="script">';
elseif ($ext == 'css')
$html = '<link rel="preload" href="' . getinfo('template_url') . $fn . '" as="style">';
elseif ($ext == 'woff2')
$html = '<link rel="preload" href="' . getinfo('template_url') . $fn . '" as="font" type="font/woff2" crossorigin="anonymous">';
elseif ($ext == 'woff')
$html = '<link rel="preload" href="' . getinfo('template_url') . $fn . '" as="font" type="font/woff" crossorigin="anonymous">';
elseif ($ext == 'mp4')
$html = '<link rel="preload" href="' . getinfo('template_url') . $fn . '" as="video" type="video/mp4">';
if ($html) mso_add_preload_html($html);
}
}
/**
* Функция к хуку head по которой выводятся preload
*/
function mso_add_preload_hook($a)
{
global $MSO;
if (!isset($MSO->data['preload_url']) or !$MSO->data['preload_url'])
return $a;
$MSO->data['preload_url'] = array_unique($MSO->data['preload_url']);
echo implode($MSO->data['preload_url']);
return $a;
}
/**
* Добавить любой html-код в конец BODY
* выводится как есть
*/
function mso_add_lazy($html)
{
global $MSO;
// вывод через хук body_end — mso_add_file_body_end()
if (!isset($MSO->data['add_file_to_body_end'])) $MSO->data['add_file_to_body_end'] = [];
$MSO->data['add_file_to_body_end'][] = $html;
}
/**
* Добавить любой html-код в секцию HEAD как preload
* выводится как есть
*/
function mso_add_preload_html($html)
{
global $MSO;
// вывод через хук head —см. mso_add_preload_hook()
if (!isset($MSO->data['preload_url'])) $MSO->data['preload_url'] = [];
$MSO->data['preload_url'][] = $html;
}
# end of file