From c7764957c49edc798f1fc6debf2376f177a417bc Mon Sep 17 00:00:00 2001 From: Repellent Date: Sun, 1 Sep 2019 23:18:32 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D0=BF=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=BB=D1=8F=20AVE.CMS=20v3.25=20=D0=B8=20?= =?UTF-8?q?=D0=B2=D1=8B=D1=88=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +- contactsnew/class.contactsnew.php | 1618 ---------------- contactsnew/demo/demo_ajax_jqval.php | 313 ---- contactsnew/demo/demo_jqval.php | 303 --- contactsnew/js/jquery.form.min.js | 23 - contactsnew/js/jquery.validate.min.js | 4 - contactsnew/lang/bg.txt | 187 -- contactsnew/lang/en.txt | 187 -- contactsnew/lang/index.php | 8 - contactsnew/lang/ua.txt | 187 -- contactsnew/module.php | 166 -- contactsnew/sql.php | 133 -- contactsnew/templates/index.php | 8 - forms/class/forms.php | 1653 +++++++++++++++++ {contactsnew/demo => forms}/demo.php | 32 +- {contactsnew => forms}/images/ref.png | Bin forms/index.php | 8 + forms/info.php | 19 + {contactsnew/demo => forms/lang}/index.php | 0 {contactsnew => forms}/lang/ru.txt | 33 +- forms/module.php | 158 ++ forms/sql.php | 81 + {contactsnew => forms}/templates/dialog.tpl | 14 +- .../templates/form_edit.tpl | 53 +- .../templates/form_fields.tpl | 11 +- {contactsnew => forms}/templates/forms.tpl | 19 +- {contactsnew => forms}/templates/history.tpl | 14 +- {contactsnew => forms/templates}/index.php | 0 28 files changed, 2004 insertions(+), 3242 deletions(-) delete mode 100755 contactsnew/class.contactsnew.php delete mode 100644 contactsnew/demo/demo_ajax_jqval.php delete mode 100644 contactsnew/demo/demo_jqval.php delete mode 100644 contactsnew/js/jquery.form.min.js delete mode 100644 contactsnew/js/jquery.validate.min.js delete mode 100644 contactsnew/lang/bg.txt delete mode 100644 contactsnew/lang/en.txt delete mode 100644 contactsnew/lang/index.php delete mode 100644 contactsnew/lang/ua.txt delete mode 100644 contactsnew/module.php delete mode 100644 contactsnew/sql.php delete mode 100644 contactsnew/templates/index.php create mode 100644 forms/class/forms.php rename {contactsnew/demo => forms}/demo.php (91%) rename {contactsnew => forms}/images/ref.png (100%) create mode 100644 forms/index.php create mode 100644 forms/info.php rename {contactsnew/demo => forms/lang}/index.php (100%) rename {contactsnew => forms}/lang/ru.txt (86%) create mode 100644 forms/module.php create mode 100644 forms/sql.php rename {contactsnew => forms}/templates/dialog.tpl (91%) rename {contactsnew => forms}/templates/form_edit.tpl (94%) rename {contactsnew => forms}/templates/form_fields.tpl (96%) rename {contactsnew => forms}/templates/forms.tpl (67%) mode change 100755 => 100644 rename {contactsnew => forms}/templates/history.tpl (82%) rename {contactsnew => forms/templates}/index.php (100%) diff --git a/README.md b/README.md index d2fdf1a..46c150e 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,21 @@ -## contactsnew +## forms -# Модуль Контакты New v1.2.6 +# Модуль Формы v1.26.0 -![Module Contacts new](https://gitget.ru/img/module_con_new.png "Module Contacts new") +![Module Forms](https://gitget.ru/img/module_con_new.png "Module Forms") -### адаптирован для AVE.CMS v3.2.х +### адаптирован для AVE.CMS v3.26 ## Модуль предназначен для создания веб-форм (например, обратной связи или простейшего оформления заказа), которые могут состоять из любого набора полей. -## Для вывода в публичной части сайта используйте тег [mod_contactsnew:XXX], где XXX - это id или алиас формы. +## Для вывода в публичной части сайта используйте тег [mod_forms:XXX], где XXX - это id или алиас формы. -## Перед копированием модуля в папку modules, удалите файл README.md, копируйте только корневую папку contactsnew со всем ее содержимым внутри! +## Перед копированием модуля в папку modules, удалите файл README.md, копируйте только корневую папку forms со всем ее содержимым внутри! ## Changelog: +01.09.2019 - Версия v1.26.0 - Модуль переименован в модуль Формы. Адаптация для версии ave-cms версии 3.25 и выше, удалено лишнее. + 10.04.2019 - Версия 1.2.6 - изменена структура расположения демо-файлов, добавлен пример создания демо-формы с jQuery Validation Plugin и reCAPTCHA v3, API ключи для reCAPTCHA v3 необходимо установить непосредственно в AVE.cms (версия 3.23 начиная с обновления в репозитории от 24.03.2019) в разделе Системные настройки->Дополнительные настройки. В шаблоне демо-формы в js скрипте параметр data.score < 0.5 - означает минимальную оценку для успешной верификации reCAPTCHA. diff --git a/contactsnew/class.contactsnew.php b/contactsnew/class.contactsnew.php deleted file mode 100755 index 427faba..0000000 --- a/contactsnew/class.contactsnew.php +++ /dev/null @@ -1,1618 +0,0 @@ - array( - 'new' => true, - 'title' => 'email', - 'type' => 'input', - 'main' => 1, - 'setting' => 'FILTER_VALIDATE_EMAIL', - 'required' => 1 - ), - 'subject' => array( - 'new' => true, - 'title' => 'subject', - 'type' => 'input', - 'main' => 1 - ), - 'receivers' => array( - 'new' => true, - 'title' => 'receivers', - 'type' => 'select', - 'main' => 1, - 'setting' => array() - ), - 'copy' => array( - 'new' => true, - 'title' => 'copy', - 'type' => 'checkbox', - 'main' => 1 - ), - 'captcha' => array( - 'new' => true, - 'title' => 'captcha', - 'type' => 'input', - 'main' => 1, - 'required' => 1 - ) - ); - // переменная для хранения формы - public $form = array(); - -/** - * Внутренние методы класса - */ - - /** - * Конструктор - */ - function __construct () - { - $this->fields_main = array_keys($this->fields_main_data); - $this->fields_main_in_string = "'" . implode("','",$this->fields_main) . "'"; - } - - - /** - * Возвращаем JSON - */ - function _json($data, $exit = false) - { - header("Content-Type: application/json;charset=utf-8"); - - $json = json_encode($data); - - if ($json === false) - { - $json = json_encode(array("jsonError", json_last_error_msg())); - - if ($json === false) - { - $json = '{"jsonError": "unknown"}'; - } - - http_response_code(500); - } - - echo $json; - - if ($exit) - exit; - } - - - /** - * Метод забирает форму из бд по алиасу/id - */ - function _form ($alias_id, $_fields = true) - { - global $AVE_DB, $AVE_Template; - - // иначе забираем из бд форму - $form = array(); - - // основные параметры - $form = $AVE_DB->Query(" - SELECT * FROM " . PREFIX . "_module_contactsnew_forms - WHERE - " . (is_numeric($alias_id) ? 'id' : 'alias') . " = '" . $alias_id . "' - ")->FetchAssocArray(); - - // если форма не обнаружена, выходим - if (empty($form)) - return array(); - - $form['alias_id'] = $alias_id; - - // получатели - $form['mail_set'] = unserialize($form['mail_set']); - - if ($_fields === true) - { - // поля - $sql = $AVE_DB->Query(" - SELECT * FROM " . PREFIX . "_module_contactsnew_fields - WHERE form_id = '" . $form['id'] . "' - ORDER BY id ASC - "); - - $form['fields'] = array(); - - while ($field = $sql->FetchAssocArray()) - { - // раскрываем массив настроек для селектов - if (in_array($field['type'],array('select','multiselect','doc','multidoc'))) - { - // @fix для v1.0 beta <= 2: поддержка одной рубрики, не массива - if (in_array($field['type'],array('doc','multidoc')) && !empty($field['setting']) && is_numeric($field['setting'])) - $field['setting'] = array(0 => $field['setting']); - else - $field['setting'] = unserialize($field['setting']) !== false ? unserialize($field['setting']) : array(); - } - // если тип поля поменялся, ставим пустую строку - elseif (unserialize($field['setting']) !== false) $field['setting'] = ''; - - // раскрываем массив опций по умолчанию для мультиселекта - if ($field['type'] == 'multiselect') - { - $field['defaultval'] = unserialize($field['defaultval']) !== false ? unserialize($field['defaultval']) : array(); - } - // если тип поля поменялся, ставим пустую строку - elseif (unserialize($field['defaultval']) !== false) $field['defaultval'] = ''; - - // главные поля - if (in_array($field['title'],$this->fields_main) && $field['main']) - { - $form['fields_main'][$field['title']] = $field['id']; - $field['title_lang'] = $AVE_Template->get_config_vars('mfld_' . $field['title']); - } - - $form['fields'][$field['id']] = $field; - } - } - - // убираем слеши - $form = $this->_stripslashes($form); - - // сохраняем форму в переменную класса - $this->form = $form; - - return $form; - } - - /** - * Метод убирает слэши во всей переменной - */ - function _stripslashes($var) - { - if (! is_array($var)) - return stripslashes($var); - else - return array_map(array($this, '_stripslashes'), $var); - } - - /** - * Метод тримует всю переменную - */ - function _trim($var) - { - if (! is_array($var)) - return trim($var); - else - return array_map(array($this, '_trim'), $var); - } - - /** - * Метод чистит переменную от пустых значений и массивов - */ - function _cleanvar($var) - { - if (! is_array($var)) - return trim($var) > '' - ? trim($var) - : null; - - $narr = array(); - - while(list($key, $val) = each($var)) - { - if (is_array($val)) - { - $val = _cleanvar($val); - - if (count($val) > 0) - $narr[$key] = $val; - } - else - { - if (trim($val) > '') - $narr[$key] = $val; - } - } - - unset ($var); - - return $narr; - } - - /** - * Валидация Email-а - */ - function _email_validate ($email = '') - { - return (filter_var($email, FILTER_VALIDATE_EMAIL) === false ? false : true); - } - - /** - * Проверка алиаса тега на валидность и уникальность - */ - function _alias_validate ($alias = '', $fid = 0) - { - global $AVE_DB; - - // соответствие требованиям - if ( - empty ($alias) || - preg_match('/^[A-Za-z0-9-_]{1,20}$/i', $alias) !== 1 || - is_numeric($alias) - ) return 'syn'; - - // уникальность - return !(bool)$AVE_DB->Query(" - SELECT 1 FROM " . PREFIX . "_module_contactsnew_forms - WHERE - alias = '" . $alias . "' AND - id != '" . $fid . "' - ")->GetCell(); - } - - - /** - * Получение списка рубрик - */ - function _rubrics () - { - global $AVE_DB; - - $rubs = array(); - - $sql = $AVE_DB->Query(" - SELECT Id, rubric_title FROM " . PREFIX . "_rubrics - "); - - while ($rub = $sql->FetchAssocArray()) - $rubs[$rub['Id']] = $rub['rubric_title']; - - return $rubs; - } - - - /** - * Получение списка документов - */ - function _docs ($rubs_id = array()) - { - global $AVE_DB; - - if (empty($rubs_id)) - return array(); - - // @fix для v1.0 beta <= 2: поддержка одной рубрики, не массива - if (! is_array($rubs_id)) - $rubs_id = array(0 => $rubs_id); - - $docs = array(); - - $sql = $AVE_DB->Query(" - SELECT Id, document_title FROM " . PREFIX . "_documents - WHERE rubric_id IN (" . implode(',',$rubs_id) . ") - "); - - while ($doc = $sql->FetchAssocArray()) - $docs[$doc['Id']] = $doc['document_title']; - - return $docs; - } - - - /** - * Парсинг главных тегов - */ - function _parse_tags ($str) - { - global $AVE_Core, $AVE_DB; - - if (empty($_SESSION['user_login'])) - $_SESSION['user_login'] = (UGROUP != 2) - ? $AVE_DB->Query("SELECT user_name FROM " . PREFIX . "_users WHERE Id = '" . UID . "'")->GetCell() - : ''; - - $str = preg_replace_callback('/\[tag:(css|js):([^ :\/]+):?(\S+)*\]/', array($AVE_Core, '_parse_combine'), $str); - - $str = parse_hide($str); - - return str_replace(array( - '[tag:docid]', - '[tag:formtitle]', - // @fix для v1.0 beta <= 2: поддержка тега formaction - '[tag:formaction]', - '[tag:document]', - '[tag:formalias]', - '[tag:path]', - '[tag:mediapath]', - '[tag:captcha]', - '[tag:uname]', - '[tag:ufname]', - '[tag:ulname]', - '[tag:ulogin]', - '[tag:uemail]', - '[tag:sitename]', - '[tag:sitehost]', - ),array( - $AVE_Core->curentdoc->Id, - $this->form['title'], - $_SERVER['REQUEST_URI'], - $_SERVER['REQUEST_URI'], - $this->form['alias'] ? $this->form['alias'] : $this->form['id'], - ABS_PATH, - ABS_PATH . 'templates/' . THEME_FOLDER . '/', - 'inc/captcha.php', - $_SESSION['user_name'], - get_user_rec_by_id(UID)->firstname, - get_user_rec_by_id(UID)->lastname, - $_SESSION['user_login'], - $_SESSION['user_email'], - htmlspecialchars(get_settings('site_name'), ENT_QUOTES), - $_SERVER['HTTP_HOST'], - ), $str); - } - - /** - * Внутренний PHP-парсер - */ - function _eval2var($code) - { - global $AVE_DB, $AVE_Core, $AVE_Template; - - ob_start(); - - eval($code); - - return ob_get_clean(); - } - - /** - * Приведение тегов главных полей к стандартной форме - */ - function _parse_tag_fld_main ($tpl='', $save_is=false) - { - foreach ($this->fields_main as $field_title) - { - $count = 0; - - $tpl = str_replace(array( - '[tag:fld:' . $field_title . ']', - '[tag:if_fld:' . $field_title, - '[tag:elseif_fld:' . $field_title, - ), array( - '[tag:fld:' . $this->form['fields_main'][$field_title] . ']', - '[tag:if_fld:' . $this->form['fields_main'][$field_title], - '[tag:elseif_fld:' . $this->form['fields_main'][$field_title], - ),$tpl,$count); - - if ($save_is) - $this->form['is_' . $field_title] = $count > 0 ? true : false; - } - - return $tpl; - } - - /** - * Замена тега условия - */ - function _parse_tag_if (&$tpl,$tag='',$open = true) - { - if ($open) - $tpl = str_replace(array('[tag:' . $tag . ']','[/tag:' . $tag . ']'),'',$tpl); - else - $tpl = preg_replace('/\[tag:' . $tag . '](.*?)\[\/tag:' . $tag . ']/si','',$tpl); - } - - /** - * Замена тега названия поля - */ - function _parse_tag_title ($matches) - { - $field_id = $matches[1]; - - return !$this->form['fields'][$field_id]['main'] - ? $this->form['fields'][$field_id]['title'] - : $this->form['fields'][$field_id]['title_lang']; - } - - /** - * Замена тега поля на значение $_POST - */ - function _parse_tag_fld_post ($matches) - { - return $_POST['form-' . $this->form['alias_id']][$matches[1]]; - } - - /** - * Замена тега поля при выводе формы - */ - function _parse_tag_fld_form ($matches) - { - $field_id = (int)$matches[1]; - - // забираем массив поля - $field = $this->form['fields'][$field_id]; - - // если поля нет, возвращаем тег обратно - if (empty($field)) - return $matches[0]; - - // если поле выключено, возвращаем пустую строку - if (empty($field['active'])) - return ''; - - $alias_id = $this->form['alias_id']; - - $fld_val = $this->form['is_submited'] - ? $this->_stripslashes($_POST['form-' . $alias_id][$field_id]) - : (in_array($field['type'],array('input','textarea')) - ? $this->_eval2var('?>' . $field['defaultval'] . 'form['fields'][$field_id]['is_used'] = true; - - $input = ''; - $return = ''; - - switch ($field['type']) - { - case 'input': - $input = ''; - break; - - case 'textarea': - $input = ''; - break; - - case 'select': - $input = ''; - break; - - case 'multiselect': - $input = ''; - break; - - case 'checkbox': - $input = ' - - '; - break; - - case 'file': - $input = ''; - break; - - case 'doc': - $input = ''; - break; - - case 'multidoc': - $input = ''; - break; - } - - // вставляем поле в шаблон поля - $return = trim($field['tpl']) > '' - ? str_replace('[tag:fld]',$input,$field['tpl']) - : $input; - - // парсим теги названия и id - $return = str_replace(array( - '[tag:id]', - '[tag:title]', - ), array( - $field['id'], - '[tag:title:' . $field_id . ']', - ), $return); - - // если попытка отправить форму, обрабатываем валидацию и пустоту - if ($this->form['is_submited']) - { - // валидация (только для капчи, input, textarea и file) - if ( - ($field['title'] == 'captcha' && $field['main'] && $this->form['is_captcha'] === true) || - (in_array($field['type'],array('input','textarea','file')) && !empty($field['setting'])) - ) - { - $valid = false; - // если капча - if ($field['title'] == 'captcha') $valid = (empty($_SESSION['captcha_keystring']) || empty($fld_val) || $_SESSION['captcha_keystring'] != $fld_val) ? false : true; - // если файл - elseif ($field['type'] == 'file') $valid = ($_FILES['form-' . $alias_id]['size'][$field_id] / 1024 / 1024) <= $field['setting']; - // если передали регулярку - elseif ($field['setting']{0} == '/') $valid = preg_match($field['setting'],$fld_val) === 1 ? true : false; - // если константу - elseif (defined($field['setting'])) $valid = filter_var($fld_val,constant($field['setting'])) !== false ? true : false; - // иначе, ничего не делаем - else return 'Неверные параметры валидации!'; - // парсим теги валидности - $this->_parse_tag_if($return,'if_valid',$valid); - $this->_parse_tag_if($return,'if_invalid',!$valid); - // записываем результаты - $this->form['ajax']['fields'][$field_id]['validate'] = true; - $this->form['ajax']['fields'][$field_id]['pattern'] = $field['setting']; - $this->form['ajax']['fields'][$field_id]['is_valid'] = $valid; - if (!$valid) - { - $this->form['is_valid'] = false; - $this->form['ajax']['form']['is_valid'] = false; - } - } - else - { - $this->form['ajax']['fields'][$field_id]['validate'] = false; - $this->form['ajax']['fields'][$field_id]['is_valid'] = null; - } - - // пустота (для любых обязательных полей) - if (! empty($field['required']) && $field['required']) - { - if ($field['type'] == 'file') - $empty = ( - empty($_FILES['form-' . $alias_id]['tmp_name'][$field_id]) || - !empty($_FILES['form-' . $alias_id]['error'][$field_id]) - ); - else - { - $clean_fld_val = $this->_cleanvar($fld_val); - $empty = empty($clean_fld_val); - } - // парсим теги - $this->_parse_tag_if($return,'if_empty',$empty); - $this->_parse_tag_if($return,'if_notempty',!$empty); - // записываем результаты - $this->form['ajax']['fields'][$field_id]['required'] = true; - $this->form['ajax']['fields'][$field_id]['is_empty'] = $empty; - if ($empty) - { - $this->form['is_valid'] = false; - $this->form['ajax']['form']['is_valid'] = false; - } - } - else - { - $this->form['ajax']['fields'][$field_id]['required'] = false; - $this->form['ajax']['fields'][$field_id]['is_empty'] = null; - } - } - // удаляем оставшиеся теги - $this->_parse_tag_if($return,'if_valid',false); - $this->_parse_tag_if($return,'if_invalid',false); - $this->_parse_tag_if($return,'if_empty',false); - $this->_parse_tag_if($return,'if_notempty',false); - - return $return; - } - - /** - * Замена тега поля в шаблоне письма - */ - function _parse_tag_fld_mail ($matches) - { - global $AVE_DB, $AVE_Template; - - $field_id = (int)$matches[1]; - // забираем массив поля - $field = $this->form['fields'][$field_id]; - // если поля нет, возвращаем тег обратно - if (empty($field)) return $matches[0]; - // если поля не было в шаблоне формы, убираем тег - if ($field['is_used'] !== true || empty($field['active'])) return ''; - // иначе, продолжаем - $alias_id = $this->form['alias_id']; - $val = $_POST['form-' . $alias_id][$field_id]; - $newval = ''; - $tag_mail_empty = ($this->form['mail_set']['format'] === 'text' ? '<' : '<') . $AVE_Template->get_config_vars('tag_mail_empty') . ($this->form['mail_set']['format'] === 'text' ? '>' : '>'); - - // делаем поправки для типов - switch ($field['type']) - { - case 'select': - $newval = $field['setting'][$val]; - if ($field['title'] == 'receivers') $newval = $newval['name']; - break; - - case 'multiselect': - foreach ($val as $val1) $newval .= $field['setting'][$val1] . ','; - $newval = rtrim($newval,','); - break; - - case 'checkbox': - $newval = ($val ? $AVE_Template->get_config_vars('yes') : $AVE_Template->get_config_vars('no')); - break; - - case 'doc': - if (!empty($val)) $newval = $AVE_DB->Query("SELECT document_title FROM " . PREFIX . "_documents WHERE Id='" . $val . "'")->GetCell(); - break; - - case 'multidoc': - if (!empty($val)) - { - $sql = $AVE_DB->Query("SELECT document_title FROM " . PREFIX . "_documents WHERE Id IN (" . implode(',',$val) . ")"); - while ($titl = $sql->GetCell()) $titls[] = $titl; - $newval = implode(', ',$titls); - } - break; - - case 'file': - $newval = implode(', ',$_FILES['form-' . $alias_id]['name']); - break; - - default: - $newval = $val; - } - return (empty($newval) ? $tag_mail_empty : $newval); - } - -/** - * Внешние методы класса - */ - - /** - * Вывод списка форм - */ - function forms_list () - { - global $AVE_DB, $AVE_Template; - $assign = array(); - - $limit = 20; - $start = get_current_page() * $limit - $limit; - $sql = $AVE_DB->Query(" - SELECT SQL_CALC_FOUND_ROWS - f.*, - SUM(IF(h.status='new',1,0)) AS history_new, - SUM(IF(h.status='viewed',1,0)) AS history_viewed, - SUM(IF(h.status='replied',1,0)) AS history_replied - FROM " . PREFIX . "_module_contactsnew_forms AS f - LEFT OUTER JOIN " . PREFIX . "_module_contactsnew_history AS h ON f.id = h.form_id - GROUP BY f.id - ORDER BY f.id ASC - LIMIT " . $start . "," . $limit . " - "); - $num = (int)$AVE_DB->Query("SELECT FOUND_ROWS()")->GetCell(); - $pages = @ceil($num / $limit); - if ($num > $limit) - { - $page_nav = '{t}'; - $page_nav = get_pagination($pages, 'page', $page_nav); - $AVE_Template->assign('page_nav', $page_nav); - } - - while ($row = $sql->FetchAssocArray()) - { - $assign['forms'][] = $row; - } - - $AVE_Template->assign($assign); - $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'forms.tpl')); - } - - /** - * Создание/редактирование формы - */ - function form_edit () - { - global $AVE_DB, $AVE_Template; - $form = array(); - $assign = array(); - $fid = $assign['fid'] = !empty($_REQUEST['fid']) ? (int)$_REQUEST['fid'] : 0; - - if ($fid) - { - $form = $this->_form($fid); - - // для правильного вывода селектов - if (empty($form['mail_set']['receivers'])) $form['mail_set']['receivers'] = array(0 => array()); - foreach ($form['fields'] as &$field) - { - if (($field['type'] == 'select' || $field['type'] == 'multiselect') && empty($field['setting'])) - { - $field['setting'] = array(0 => ''); - $field['setting_empty'] = true; - } - } - } - - // алерт при открытии правки - if (!empty($_SESSION['module_contactsnew_admin'][$fid]['edit_alert'])) - { - $assign['alert']['text'] = $AVE_Template->get_config_vars($_SESSION['module_contactsnew_admin'][$fid]['edit_alert']['text']); - $assign['alert']['theme'] = $_SESSION['module_contactsnew_admin'][$fid]['edit_alert']['theme']; - unset($_SESSION['module_contactsnew_admin'][$fid]['edit_alert']); - } - $assign['form'] = $form; - $assign['form_fields_tpl'] = $this->tpl_dir . 'form_fields.tpl'; - $assign['rubrics'] = $this->_rubrics(); - - // назначаем массив CodeMirror - $assign['codemirror'] = array( - 'rubheader' => 200, - 'from_name' => 60, - 'from_email' => 60, - 'subject_tpl' => 60, - 'form_tpl' => 460, - 'mail_tpl' => 460, - 'finish_tpl' => 320, - 'code_onsubmit' => 200, - 'code_onvalidate' => 200, - 'code_onsend' => 200 - ); - - $AVE_Template->assign($assign); - $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'form_edit.tpl')); - } - - /** - * Получение полей через аякс - */ - function form_fields_fetch () - { - global $AVE_DB, $AVE_Template; - $fid = $assign['fid'] = !empty($_REQUEST['fid']) ? (int)$_REQUEST['fid'] : 0; - if (!$fid) return; - $form = $this->_form($fid); - // для правильного вывода селектов - if (empty($form['mail_set']['receivers'])) $form['mail_set']['receivers'] = array(0 => array()); - foreach ($form['fields'] as &$field) - { - if (($field['type'] == 'select' || $field['type'] == 'multiselect') && empty($field['setting'])) - { - $field['setting'] = array(0 => ''); - $field['setting_empty'] = true; - } - } - $AVE_Template->assign('fields',$form['fields']); - $AVE_Template->assign('rubrics',$this->_rubrics()); - $AVE_Template->assign('field_tpl_open',$_REQUEST['field_tpl_open']); - - return $AVE_Template->fetch($this->tpl_dir . 'form_fields.tpl'); - } - - /** - * Сохранение формы - */ - function form_save ($fid) - { - global $AVE_DB; - - // проверяем Email-ы получателей - $receivers = array(); - foreach ($_REQUEST['mail_set']['receivers'] as $receiver) - { - if ($this->_email_validate($receiver['email'])) $receivers[] = $receiver; - } - $_REQUEST['mail_set']['receivers'] = $receivers; - // параметры отправителя - if (!trim($_REQUEST['mail_set']['from_email']) > '') $_REQUEST['mail_set']['from_email'] = get_settings('mail_from'); - if (!trim($_REQUEST['mail_set']['from_name']) > '') $_REQUEST['mail_set']['from_name'] = get_settings('mail_from_name'); - - if ($fid) - { - $AVE_DB->Query(" - UPDATE " . PREFIX . "_module_contactsnew_forms - SET - title = '" . addslashes($_REQUEST['title']) . "', - protection = '" . (int)$_REQUEST['protection'] . "', - " . (($_REQUEST['alias'] === '' || $this->_alias_validate($_REQUEST['alias'],$fid) === true) ? " alias = '" . $_REQUEST['alias'] . "'," : '') . " - mail_set = '" . addslashes(serialize($_REQUEST['mail_set'])) . "', - rubheader = '" . addslashes($_REQUEST['rubheader']) . "', - form_tpl = '" . addslashes($_REQUEST['form_tpl']) . "', - mail_tpl = '" . addslashes($_REQUEST['mail_tpl']) . "', - finish_tpl = '" . addslashes($_REQUEST['finish_tpl']) . "', - code_onsubmit = '" . addslashes($_REQUEST['code_onsubmit']) . "', - code_onvalidate = '" . addslashes($_REQUEST['code_onvalidate']) . "', - code_onsend = '" . addslashes($_REQUEST['code_onsend']) . "' - WHERE - id = '" . $fid . "' - "); - } - else - { - $mail_set = array( - 'from_name' => get_settings('mail_from_name'), - 'from_email' => get_settings('mail_from'), - 'receivers' => array(0 => array( - 'name' => get_settings('mail_from_name'), - 'email' => get_settings('mail_from') - ), - ), - 'subject_tpl' => '[tag:formtitle]', - 'format' => 'text' - ); - $AVE_DB->Query(" - INSERT INTO " . PREFIX . "_module_contactsnew_forms - SET - title = '" . addslashes($_REQUEST['title']) . "', - " . (($this->_alias_validate($_REQUEST['alias'],$fid) === true || $_REQUEST['alias'] === '') ? " alias = '" . $_REQUEST['alias'] . "'," : '') . " - mail_set = '" . addslashes(serialize($mail_set)) . "' - "); - $fid = (int)$AVE_DB->InsertId(); - $_REQUEST['fields'] = $this->fields_main_data; - // прописываем алерт об успешном создании - if ($fid > 0) $_SESSION['module_contactsnew_admin'][$fid]['edit_alert'] = array('text' => 'created', 'theme' => 'accept'); - - // если устанавливаем пример - if (!empty($_REQUEST['demo'])) - { - $demo = array(); - // если выбрана демоформа jQuery Validation Plugin и reCAPTCHA v3 - if ($_REQUEST['demo'] == 'jqval_cap') { - include(BASE_DIR . '/modules/contactsnew/demo/demo_jqval.php'); - } elseif ($_REQUEST['demo'] == 'ajax_jqval_cap') { - include(BASE_DIR . '/modules/contactsnew/demo/demo_ajax_jqval.php'); - } else { - include(BASE_DIR . '/modules/contactsnew/demo/demo.php'); - } - $_REQUEST = array_merge($_REQUEST,$demo); - // обновляем форму с данными примера - $this->form_save($fid); - // подставляем в шаблон новые id полей - $demo['form_tpl'] = preg_replace_callback('/\[tag:fld:(\d+)]/', create_function('$matches','return "[tag:fld:" . $_REQUEST["demo_change"][(int)$matches[1]] . "]";'),$demo['form_tpl']); - // если выбрана демоформа jQuery Validation Plugin и reCAPTCHA v3 - if ($_REQUEST['demo'] == 'jqval_cap') { - // подставляем в шаблон новые значения атрибутов name - $demo['form_tpl'] = preg_replace_callback('/form-jqval_cap\[(\d+)]/', create_function('$matches','return "form-jqval_cap[" . $_REQUEST["demo_change"][(int)$matches[1]] . "]";'),$demo['form_tpl']); - } - if ($_REQUEST['demo'] == 'ajax_jqval_cap') { - // подставляем в шаблон новые значения атрибутов name - $demo['form_tpl'] = preg_replace_callback('/form-ajax_jqval_cap\[(\d+)]/', create_function('$matches','return "form-ajax_jqval_cap[" . $_REQUEST["demo_change"][(int)$matches[1]] . "]";'),$demo['form_tpl']); - } - $AVE_DB->Query(" - UPDATE " . PREFIX . "_module_contactsnew_forms - SET - form_tpl = '" . addslashes($demo['form_tpl']) . "' - WHERE id = '" . $fid . "' - "); - return $fid; - } - } - - // сохраняем поля - foreach ($_REQUEST['fields'] as $field_id => $field) - { - if (!trim($field['title'])) continue; - if (is_array($field['setting'])) - { - $settings = array(); - foreach ($field['setting'] as $setting) - { - // если получатели - if ($field['title'] == 'receivers' && is_array($setting) && trim($setting['name']) > '' && trim($setting['email']) > '' && $this->_email_validate($setting['email'])) - $settings[] = $setting; - // другое - elseif (!is_array($setting) && trim($setting) > '') - $settings[] = $setting; - } - $field['setting'] = serialize($settings); - } - elseif ($field['type'] == 'file') $field['setting'] = (int)$field['setting']; - - if (is_array($field['defaultval'])) $field['defaultval'] = serialize($field['defaultval']); - - $sql = " - title = '" . addslashes($field['title']) . "', - active = '" . (int)$field['active'] . "', - type = '" . $field['type'] . "', - setting = '" . addslashes($field['setting']) . "', - required = '" . (int)$field['required'] . "', - defaultval = '" . addslashes($field['defaultval']) . "', - attributes = '" . addslashes(trim($field['attributes'])) . "', - tpl = '" . addslashes($field['tpl']) . "' - "; - if ($field['new']) - { - $AVE_DB->Query(" - INSERT INTO " . PREFIX . "_module_contactsnew_fields - SET - form_id = '" . (int)$fid . "', - main = '" . (int)$field['main'] . "', - " . $sql . " - "); - if ($_REQUEST['demo']) $_REQUEST['demo_change'][$field_id] = (int)$AVE_DB->InsertId(); - } - else - { - $AVE_DB->Query(" - UPDATE " . PREFIX . "_module_contactsnew_fields - SET - " . $sql . " - WHERE - id = '" . (int)$field_id . "' AND - form_id = '" . $fid . "' - "); - } - } - foreach ($_REQUEST['field_del'] as $field_id => $delete) - { - if (empty($delete)) continue; - $AVE_DB->Query(" - DELETE FROM " . PREFIX . "_module_contactsnew_fields - WHERE - id = '" . (int)$field_id . "' AND - main != '1' - "); - } - - return $fid; - } - - /** - * Удаление формы - */ - function form_del ($fid) - { - global $AVE_DB; - - $AVE_DB->Query(" - DELETE FROM " . PREFIX . "_module_contactsnew_forms - WHERE id = '" . $fid . "' - "); - $AVE_DB->Query(" - DELETE FROM " . PREFIX . "_module_contactsnew_fields - WHERE form_id = '" . $fid . "' - "); - } - - /** - * Сохранение формы - */ - function form_copy ($fid) - { - global $AVE_DB; - - // форма - $form = $AVE_DB->Query(" - SELECT * FROM " . PREFIX . "_module_contactsnew_forms - WHERE id = '" . $fid . "' - ")->FetchAssocArray(); - if (empty($form)) return; - $query = "INSERT INTO " . PREFIX . "_module_contactsnew_forms SET "; - foreach ($form as $key => $val) - { - if ($key == 'id' || $key == 'alias') continue; - $query .= $key . " = '" . addslashes($val) . "', "; - } - $query = rtrim($query,', '); - $AVE_DB->Query($query); - $fid_new = (int)$AVE_DB->InsertId(); - - // поля - $sql = $AVE_DB->Query(" - SELECT * FROM " . PREFIX . "_module_contactsnew_fields - WHERE form_id = '" . $fid . "' - "); - while ($row = $sql->FetchAssocArray()) - { - if (empty($row['id'])) continue; - $query = "INSERT INTO " . PREFIX . "_module_contactsnew_fields SET "; - foreach ($row as $key => $val) - { - if ($key == 'id') continue; - elseif ($key == 'form_id') $val = $fid_new; - $query .= $key . " = '" . addslashes($val) . "', "; - } - $query = rtrim($query,', '); - $AVE_DB->Query($query); - } - - return $fid_new; - } - - - /** - * Вывод формы - */ - function form_display ($alias_id) - { - global $AVE_Template; - - $form = $this->_form($alias_id); - - if (empty($form)) - return "[mod_contactsnew:$alias_id] - " . $AVE_Template->get_config_vars('form_notfound'); - - // по дефолту форма валидна, но не отправлена - потом перезаписываем, если что - $this->form['is_valid'] = true; - $this->form['ajax']['form']['is_valid'] = true; - $this->form['ajax']['form']['is_sent'] = false; - $this->form['ajax']['form']['finish_tpl'] = null; - - // rubheader - $GLOBALS['user_header']['module_contactsnew_' . $alias_id] = $this->_parse_tags($this->form['rubheader']); - - // вывод финишной страницы, если включена проверка от повторной отправки - if (! empty($_GET['mcnfinish']) && $form['protection']) - { - if ($_SESSION['mcnfinish'][$form['id'] . $_GET['mcnfinish']] === true) - { - unset($_SESSION['mcnfinish'][$form['id'] . $_GET['mcnfinish']]); - - // формируем финишную страницу - $tpl = $this->_parse_tags($form['finish_tpl']); - $tpl = $this->_eval2var('?>' . $tpl . 'form['is_submited'] = false; - - if (! empty($_POST['form-' . $alias_id])) - { - $this->form['is_submited'] = true; - // выполняем код после отправки формы - eval('?>' . $this->form['code_onsubmit'] . 'form['form_tpl']; - // меняем теги основных полей на стандартные - $tpl = $this->_parse_tag_fld_main($tpl,true); - // парсим теги полей и названий - $tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_form'), $tpl); - $tpl = preg_replace_callback('/\[tag:title:([A-Za-z0-9-_]+)]/', array($this,'_parse_tag_title'),$tpl); - - // выполняем код после валидации - eval('?>' . $this->form['code_onvalidate'] . 'form['is_submited'] === true && $this->form['is_valid'] === true) - return $this->form_submit($alias_id); - // иначе - заканчиваем вывод - else - { - // парсим основные теги - $tpl = $this->_parse_tags($tpl); - // теги общей валидности - if ($this->form['is_submited']) - { - $this->_parse_tag_if($tpl,'if_form_valid',$this->form['is_valid']); - $this->_parse_tag_if($tpl,'if_form_invalid',!$this->form['is_valid']); - } - else - { - $this->_parse_tag_if($tpl,'if_form_valid',false); - $this->_parse_tag_if($tpl,'if_form_invalid',false); - } - // заменяем теги условий - $tpl = preg_replace('/\[tag:(if|elseif)_fld:(\d*)(.*?)]/si','',$tpl); - $tpl = str_replace(array('[tag:else_fld]','[/tag:if_fld]'),array('',''),$tpl); - // выполняем код - return $this->_eval2var('?>' . $tpl . 'form; - - $fields = $form['fields']; - - $fid = $form['id']; - - // формируем список получателей - $recs = array(); - - // пользователь (отправка копии) - if ( - ($form['is_copy'] === true && $_POST['form-' . $alias_id][$form['fields_main']['copy']] == 1) || - $fields[$form['fields_main']['copy']]['defaultval'] == 1 - ) - { - $email = ''; - - if ($form['is_email'] === true) - $email = $_POST['form-' . $alias_id][$form['fields_main']['email']]; - - if (empty($email)) - $email = $_SESSION['user_email']; - - if (! empty($email)) - { - $recs[] = array( - 'email' => $email, - 'name' => $_SESSION['user_name'], - 'agent' => 'user', - ); - } - - $history['email'] = $email; - } - else // если чекбоксы - отправить копию неактивные - { - $email = ''; - - if ($form['is_email'] === true) - $email = $_POST['form-' . $alias_id][$form['fields_main']['email']]; - - if (empty($email)) - $email = $_SESSION['user_email']; - - $history['email'] = $email; - } - - // главные получатели - $recs = array_merge($recs, $form['mail_set']['receivers']); - - // выбранные в форме получатели - if ($this->form['is_receivers'] === true) - { - $recs_field_id = $form['fields_main']['receivers']; - $recs[] = $fields[$recs_field_id]['setting'][$_POST['form-' . $alias_id][$recs_field_id]]; - } - - // если ни один получатель не назначен, отправляем админскому - if (empty($recs)) $recs[] = array( - 'name' => get_settings('mail_from_name'), - 'email' => get_settings('mail_from') - ); - - // перезаписываем список уникальных получателей в переменную письма - $this->form['receivers'] = array(); - - foreach ($recs as $rec) - { - if (!isset($this->form['receivers'][$rec['email']]) && trim($rec['email']) > '') - $this->form['receivers'][trim($rec['email'])] = $rec; - } - - $recs = $this->form['receivers']; - $recs[] = array('agent' => 'history'); - - // обрабатываем тему по умолчанию - if (!$form['fields'][$form['fields_main']['subject']]['active'] || !$form['fields'][$form['fields_main']['subject']]['is_used']) - { - $_POST['form-' . $alias_id][$form['fields_main']['subject']] = $form['fields'][$form['fields_main']['subject']]['defaultval']; - } - - // обрабатываем шаблон письма - $tpl = $form['mail_tpl']; - - // меняем теги основных полей на стандартные - $tpl = $this->_parse_tag_fld_main($tpl); - - // парсим [tag:easymail] - if (strpos($tpl,'[tag:easymail]') !== false) - { - $easy = ''; - - foreach ($fields as $field_id => $field) - { - if ($field['is_used'] !== true || $field['title'] == 'captcha' || empty($field['active'])) - continue; - - $easy .= "[tag:title:$field_id]" . ": [tag:fld:$field_id];" . ($form['mail_set']['format'] === 'text' ? "\r\n" : '
'); - } - - // убираем последний перевод строки - $easy = ($form['mail_set']['format'] === 'text') ? rtrim($easy) : substr($easy,0,-4); - $tpl = str_replace('[tag:easymail]',$easy,$tpl); - } - - // парсим теги полей и названий - $tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_mail'),$tpl); - $tpl = preg_replace_callback('/\[tag:title:([A-Za-z0-9-_]+)]/', array($this,'_parse_tag_title'),$tpl); - - // парсим основные теги - $tpl = $this->_parse_tags($tpl); - - // заменяем теги условий - $tpl = preg_replace('/\[tag:(if|elseif)_fld:(\d*)(.*?)]/si','',$tpl); - $tpl = str_replace(array('[tag:else_fld]','[/tag:if_fld]'),array('',''),$tpl); - - // файлы-вложения - $attach = array(); - - if (! empty($_FILES['form-' . $alias_id]['tmp_name'])) - { - foreach ($_FILES['form-' . $alias_id]['name'] as $field_id => $fname) - { - $ext = (end(explode('.', $fname))); - - if ( - !empty($_FILES['form-' . $alias_id]['tmp_name'][$field_id]) && - !empty($form['fields'][$field_id]) && - empty($_FILES['form-' . $alias_id]['error'][$field_id]) && - !in_array($ext,array('php', 'phtml', 'php3', 'php4', 'php5', 'js', 'pl')) - ) - { - $fname = BASE_DIR . '/' . ATTACH_DIR . '/' . str_replace(' ', '_', mb_strtolower(trim($fname))); - - if (file_exists($fname)) - $fname = rtrim($fname,'.' . $ext) . '_' . mt_rand(0,10000) . '.' . $ext; - - @move_uploaded_file($_FILES['form-' . $alias_id]['tmp_name'][$field_id], $fname); - - $attach[] = $fname; - } - } - } - - // Имя отправителя - $from_name_tpl = $form['mail_set']['from_name']; - $from_name_tpl = $this->_parse_tags($from_name_tpl); - $from_name_tpl = $this->_parse_tag_fld_main($from_name_tpl); - $from_name_tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_post'),$from_name_tpl); - - // Email отправителя - $from_email_tpl = $form['mail_set']['from_email']; - $from_email_tpl = $this->_parse_tags($from_email_tpl); - $from_email_tpl = $this->_parse_tag_fld_main($from_email_tpl); - $from_email_tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_post'),$from_email_tpl); - - // Тема - $subject_tpl = $form['mail_set']['subject_tpl']; - $subject_tpl = $this->_parse_tags($subject_tpl); - $subject_tpl = $this->_parse_tag_fld_main($subject_tpl); - $subject_tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_post'),$subject_tpl); - - // отправляем письма - foreach ($recs as $rec) - { - $mail = $tpl; - - $from_name = $from_name_tpl; - - $from_email = $from_email_tpl; - - $subject = $subject_tpl; - - $if_user_open = ($rec['agent'] === 'user'); - $if_admin_open = !$if_user_open; - - $this->_parse_tag_if($mail,'if_user',$if_user_open); - $this->_parse_tag_if($mail,'if_admin',$if_admin_open); - $this->_parse_tag_if($subject,'if_user',$if_user_open); - $this->_parse_tag_if($subject,'if_admin',$if_admin_open); - - // @fix для v1.0 beta <= 2: поддержка тега if_notuser - $this->_parse_tag_if($mail,'if_notuser',$if_admin_open); - $this->_parse_tag_if($subject,'if_notuser',$if_admin_open); - - $mail = trim($this->_eval2var('?>' . $mail . '_eval2var('?>' . $subject . 'Query(" - INSERT INTO " . PREFIX . "_module_contactsnew_history - SET - form_id = '" . $fid . "', - email = '" . $history['email'] . "', - subject = '" . addslashes($subject) . "', - date = '" . time() . "', - dialog = '" . addslashes(serialize($history['dialog'])) . "', - postdata = '" . addslashes(serialize($_POST)) . "' - "); - - unset($history); - } - // иначе, отправляем письмо - else - { - $this->_parse_tag_if($from_name,'if_user',$if_user_open); - $this->_parse_tag_if($from_name,'if_admin',$if_admin_open); - $this->_parse_tag_if($from_email,'if_user',$if_user_open); - $this->_parse_tag_if($from_email,'if_admin',$if_admin_open); - - $from_name = $this->_eval2var('?>' . $from_name . '_eval2var('?>' . $from_email . '' . $this->form['code_onsend'] . '_parse_tags($form['finish_tpl']); - $tpl = $this->_eval2var('?>' . $tpl . 'form['ajax']['form']['is_sent'] = true; - $this->form['ajax']['form']['finish_tpl'] = $tpl; - - return $tpl; - } - } - - /** - * Вывод истории - */ - function history_list ($fid) - { - global $AVE_DB, $AVE_Template; - $assign = array(); - $assign['fid'] = $fid; - $assign['form'] = $this->_form($fid,false); - - $limit = 50; - $start = get_current_page() * $limit - $limit; - $sql = $AVE_DB->Query(" - SELECT SQL_CALC_FOUND_ROWS * - FROM " . PREFIX . "_module_contactsnew_history - WHERE form_id = '" . $fid . "' - ORDER BY date DESC - LIMIT " . $start . "," . $limit . " - "); - $num = (int)$AVE_DB->Query("SELECT FOUND_ROWS()")->GetCell(); - $pages = @ceil($num / $limit); - if ($num > $limit) - { - $page_nav = '{t}'; - $page_nav = get_pagination($pages, 'page', $page_nav); - $AVE_Template->assign('page_nav', $page_nav); - } - - while ($row = $sql->FetchAssocArray()) - { - unset($row['dialog']); - $assign['dialogs'][] = $row; - } - - $assign = $this->_stripslashes($assign); - $AVE_Template->assign($assign); - $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'history.tpl')); - } - - /** - * Удаление выбранного e-mail - */ - function email_del ($hid) - { - global $AVE_DB, $AVE_Template; - - $AVE_DB->Query(" - DELETE FROM " . PREFIX . "_module_contactsnew_history - WHERE id = '" . $hid . "' - "); - } - - /** - * Сохранение статуса диалога - */ - function dialog_status ($hid) - { - global $AVE_DB; - - if ($_REQUEST['status'] !== 'new') - { - $AVE_DB->Query(" - UPDATE " . PREFIX . "_module_contactsnew_history - SET - status = '" . $_REQUEST['status'] . "' - WHERE id = '" . $hid . "' - "); - } - - if (empty($_REQUEST['ajax'])) - { - header('Location: index.php?do=modules&action=modedit&mod=contactsnew&moduleaction=history_list&fid=' . $_REQUEST['fid'] . '&cp=' . SESSION); - exit; - } - } - - /** - * Вывод диалога - */ - function history_dialog ($hid) - { - global $AVE_DB, $AVE_Template; - $assign = array(); - - $assign['hid'] = $hid; - $history = $AVE_DB->Query(" - SELECT * - FROM " . PREFIX . "_module_contactsnew_history - WHERE id = '" . $hid . "' - ")->FetchAssocArray(); - $history['dialog'] = unserialize($history['dialog']); - $history = $this->_stripslashes($history); - $assign['fid'] = $history['form_id']; - $assign['form'] = $this->_form($history['form_id'],false); - - // меняем статус на прочитанное - if ($history['status'] === 'new') - { - $AVE_DB->Query(" - UPDATE " . PREFIX . "_module_contactsnew_history - SET - status = 'viewed' - WHERE id = '" . $hid . "' - "); - } - - // обращение - $request_author = $AVE_DB->Query(" - SELECT Id AS user_id, user_name, firstname, lastname - FROM " . PREFIX . "_users - WHERE email = '" . $history['email'] . "' - ")->FetchAssocArray(); - if (!empty($request_author)) $history['dialog']['request'] = array_merge($history['dialog']['request'], $request_author); - - // ответы - foreach ($history['dialog']['response'] as &$response) - { - $response_author = $AVE_DB->Query(" - SELECT user_name, firstname, lastname - FROM " . PREFIX . "_users - WHERE Id = '" . $response['user_id'] . "' - ")->FetchAssocArray(); - if (!empty($response_author)) $response = array_merge($response, $response_author); - } - - // форма ответа - if (empty($history['dialog']['response_draft'])) - { - $history['dialog']['response_draft'] = array( - 'from_email' => get_settings('mail_from'), - 'from_name' => get_settings('mail_from_name'), - 'body' => "\r\n\r\n\r\n--\r\n" . get_settings('mail_signature'), - ); - } - - // алерт при открытии - if (!empty($_SESSION['module_contactsnew_admin'][$fid]['dialog_alert'])) - { - $assign['alert']['text'] = $AVE_Template->get_config_vars($_SESSION['module_contactsnew_admin'][$fid]['dialog_alert']['text']); - $assign['alert']['theme'] = $_SESSION['module_contactsnew_admin'][$fid]['dialog_alert']['theme']; - unset($_SESSION['module_contactsnew_admin'][$fid]['dialog_alert']); - } - - $AVE_Template->assign($assign); - $AVE_Template->assign($history); - $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'dialog.tpl')); - } - - /** - * Сохранение и отправка ответа - */ - function history_dialog_submit ($hid) - { - global $AVE_DB; - - $history = $AVE_DB->Query(" - SELECT * - FROM " . PREFIX . "_module_contactsnew_history - WHERE id = '" . $hid . "' - ")->FetchAssocArray(); - $history['dialog'] = unserialize($history['dialog']); - - if ($_REQUEST['send']) - { - $response = $_POST; - $response['user_id'] = UID; - $response['date'] = time(); - $history['dialog']['response'][] = $response; - $history['status'] = 'replied'; - unset($history['dialog']['response_draft']); - send_mail( - $history['email'], - $_POST['body'], - $_POST['subject'], - $_POST['from_email'], - $_POST['from_name'], - $_POST['format'], - array(), - false,false - ); - } - else - { - $history['dialog']['response_draft'] = $_POST; - } - - $AVE_DB->Query(" - UPDATE " . PREFIX . "_module_contactsnew_history - SET - dialog = '" . addslashes(serialize($history['dialog'])) . "', - status = '" . $history['status'] . "' - WHERE id = '" . $hid . "' - "); - - if ($_REQUEST['send']) - { - // прописываем алерт об успешной отправке письма - $_SESSION['module_contactsnew_admin'][$fid]['dialog_alert'] = array('text' => 'respose_sent', 'theme' => 'accept'); - - header('Location: index.php?do=modules&action=modedit&mod=contactsnew&moduleaction=history_dialog&hid=' . $hid . '&cp=' . SESSION); - exit; - } - } -} -?> diff --git a/contactsnew/demo/demo_ajax_jqval.php b/contactsnew/demo/demo_ajax_jqval.php deleted file mode 100644 index b59f3db..0000000 --- a/contactsnew/demo/demo_ajax_jqval.php +++ /dev/null @@ -1,313 +0,0 @@ - -'
-
-
-

Демо интеграции в Модуль Контакты New v1.2.5

jQuery Validation Plugin   и   reCAPTCHA v3

-
-
- Если форма не работает, или не работает валидация (отправляется пустая форма без проверки и т.п.) убедитесь, что библиотека jQuery (jquery.min.js - по умолчанию подключается модулем) подключена на странице только один раз! и расположена в секции <head> , а также подключен скрипт jquery.form.min.js (по умолчанию подключается модулем в разделе Скрипты и стили, необходимые для оформления и функционирования формы) - -
-
-
-
-

[tag:formtitle]

-
-
-
-[tag:fld:email] -[tag:fld:subject] -[tag:fld:6] -[tag:fld:7] -[tag:fld:8] -[tag:fld:9] -
-
- -
-
-
-
-
-
- -' -); - -$demo = array( - 'alias' => 'ajax_jqval_cap', - 'title' => 'Демо форма с Ajax, jQuery Validation Plugin и reCAPTCHA v3', - 'mail_set' => array( - 'from_name' => '', - 'from_email' => '', - 'subject_tpl' => '[tag:fld:subject]', - 'receivers' => array( - array( - 'email' => '', - 'name' => '' - ) - ), - 'format' => 'text', - ), - 'rubheader' => ' - - - -', - 'form_tpl' => $form_tpl[$_REQUEST['demo']], - 'mail_tpl' => '[tag:easymail]', - 'finish_tpl' => '
- Форма успешно отправлена! Обновить страницу -
-', - 'code_onsubmit' => '', - 'code_onvalidate' => '', - 'code_onsend' => '', - 'fields' => array( - 1 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'email', - 'active' => 1, - 'type' => 'input', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 2 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'subject', - 'active' => 1, - 'type' => 'input', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 3 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'receivers', - 'active' => 0, - 'type' => 'select', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => 0, - 'attributes' => '', - 'tpl' => '' - ), - 4 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'copy', - 'active' => 0, - 'type' => 'checkbox', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => 1, - 'attributes' => '', - 'tpl' => '' - ), - 5 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'captcha', - 'active' => 0, - 'type' => 'input', - 'main' => 1, - 'setting' => '', - 'required' => 1, - 'defaultval' => '', - 'attributes' => '', - 'tpl' => '' - ), - 6 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Никнейм', - 'active' => 1, - 'type' => 'input', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 7 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Текст сообщения', - 'active' => 1, - 'type' => 'textarea', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 8 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Работа чекбокса', - 'active' => 1, - 'type' => 'checkbox', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" value="agree"', - 'tpl' => '
-
-
- -
-
-
' - ), - 9 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Оценка отправителя формы сервисом reCAPTCHA', - 'active' => 1, - 'type' => 'input', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="hidden_fld_[tag:formalias]" type="hidden"', - 'tpl' => '[tag:fld]' - ) - - - ) -); \ No newline at end of file diff --git a/contactsnew/demo/demo_jqval.php b/contactsnew/demo/demo_jqval.php deleted file mode 100644 index 9fd4312..0000000 --- a/contactsnew/demo/demo_jqval.php +++ /dev/null @@ -1,303 +0,0 @@ - -'
-
-
-

Демо интеграции в Модуль Контакты New v1.2.5

jQuery Validation Plugin   и   reCAPTCHA v3

-
-
- Если не работает валидация (отправляется пустая форма без проверки и т.п.) убедитесь, что библиотека jQuery (jquery.min.js - по умолчанию подключается модулем) подключена на странице только один раз! и расположена в секции <head> - -
-
-
-
-

[tag:formtitle]

-
-
-
-[tag:fld:email] -[tag:fld:subject] -[tag:fld:6] -[tag:fld:7] -[tag:fld:8] -[tag:fld:9] -
-
- -
-
-
-
-
-
- -' -); - -$demo = array( - 'alias' => 'jqval_cap', - 'title' => 'Демо форма с jQuery Validation Plugin и reCAPTCHA v3', - 'mail_set' => array( - 'from_name' => '', - 'from_email' => '', - 'subject_tpl' => '[tag:fld:subject]', - 'receivers' => array( - array( - 'email' => '', - 'name' => '' - ) - ), - 'format' => 'text', - ), - 'rubheader' => ' - - -', - 'form_tpl' => $form_tpl[$_REQUEST['demo']], - 'mail_tpl' => '[tag:easymail]', - 'finish_tpl' => '
- Форма успешно отправлена! Обновить страницу -
-', - 'code_onsubmit' => '', - 'code_onvalidate' => '', - 'code_onsend' => '', - 'fields' => array( - 1 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'email', - 'active' => 1, - 'type' => 'input', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 2 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'subject', - 'active' => 1, - 'type' => 'input', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 3 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'receivers', - 'active' => 0, - 'type' => 'select', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => 0, - 'attributes' => '', - 'tpl' => '' - ), - 4 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'copy', - 'active' => 0, - 'type' => 'checkbox', - 'main' => 1, - 'setting' => '', - 'required' => 0, - 'defaultval' => 1, - 'attributes' => '', - 'tpl' => '' - ), - 5 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'captcha', - 'active' => 0, - 'type' => 'input', - 'main' => 1, - 'setting' => '', - 'required' => 1, - 'defaultval' => '', - 'attributes' => '', - 'tpl' => '' - ), - 6 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Никнейм', - 'active' => 1, - 'type' => 'input', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 7 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Текст сообщения', - 'active' => 1, - 'type' => 'textarea', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" class="form-control" placeholder="[tag:title]"', - 'tpl' => '
- -
-[tag:fld] -
-
' - ), - 8 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Работа чекбокса', - 'active' => 1, - 'type' => 'checkbox', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="fld[[tag:id]]" value="agree"', - 'tpl' => '
-
-
- -
-
-
' - ), - 9 => array( - 'new' => true, - 'form_id' => $fid, - 'title' => 'Оценка отправителя формы сервисом reCAPTCHA', - 'active' => 1, - 'type' => 'input', - 'main' => 0, - 'setting' => '', - 'required' => 0, - 'defaultval' => '', - 'attributes' => 'id="hidden_fld_[tag:formalias]" type="hidden"', - 'tpl' => '[tag:fld]' - ) - - - ) -); \ No newline at end of file diff --git a/contactsnew/js/jquery.form.min.js b/contactsnew/js/jquery.form.min.js deleted file mode 100644 index 9a447f7..0000000 --- a/contactsnew/js/jquery.form.min.js +++ /dev/null @@ -1,23 +0,0 @@ -/*! - * jQuery Form Plugin - * version: 4.2.2 - * Requires jQuery v1.7.2 or later - * Project repository: https://github.com/jquery-form/form - - * Copyright 2017 Kevin Morris - * Copyright 2006 M. Alsup - - * Dual licensed under the LGPL-2.1+ or MIT licenses - * https://github.com/jquery-form/form#license - - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ -!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,r){return void 0===r&&(r="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(r),r}:e(jQuery)}(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(t.target).closest("form").ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=r.form;if(i.clk=r,"image"===r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n=/\r?\n/g,i={};i.fileapi=void 0!==e('').get(0).files,i.formdata=void 0!==window.FormData;var o=!!e.fn.prop;e.fn.attr2=function(){if(!o)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t,r,n,s){function u(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;a',k).val(f.extraData[c].value).appendTo(w)[0]):u.push(e('',k).val(f.extraData[c]).appendTo(w)[0]));f.iframeTarget||h.appendTo(D),v.attachEvent?v.attachEvent("onload",s):v.addEventListener("load",s,!1),setTimeout(t,15);try{w.submit()}catch(e){document.createElement("form").submit.apply(w)}}finally{w.setAttribute("action",i),w.setAttribute("enctype",o),r?w.setAttribute("target",r):p.removeAttr("target"),e(u).remove()}}function s(t){if(!x.aborted&&!X){if((O=n(v))||(a("cannot access response document"),t=L),t===A&&x)return x.abort("timeout"),void S.reject(x,"timeout");if(t===L&&x)return x.abort("server abort"),void S.reject(x,"error","server abort");if(O&&O.location.href!==f.iframeSrc||T){v.detachEvent?v.detachEvent("onload",s):v.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"===f.dataType||O.XMLDocument||e.isXMLDoc(O);if(a("isXml="+o),!o&&window.opera&&(null===O.body||!O.body.innerHTML)&&--C)return a("requeing onLoad callback, DOM not available"),void setTimeout(s,250);var u=O.body?O.body:O.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=O.XMLDocument?O.XMLDocument:O,o&&(f.dataType="xml"),x.getResponseHeader=function(e){return{"content-type":f.dataType}[e.toLowerCase()]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var c=(f.dataType||"").toLowerCase(),l=/(json|script|text)/.test(c);if(l||f.textarea){var p=O.getElementsByTagName("textarea")[0];if(p)x.responseText=p.value,x.status=Number(p.getAttribute("status"))||x.status,x.statusText=p.getAttribute("statusText")||x.statusText;else if(l){var m=O.getElementsByTagName("pre")[0],g=O.getElementsByTagName("body")[0];m?x.responseText=m.textContent?m.textContent:m.innerText:g&&(x.responseText=g.textContent?g.textContent:g.innerText)}}else"xml"===c&&!x.responseXML&&x.responseText&&(x.responseXML=q(x.responseText));try{M=N(x,c,f)}catch(e){i="parsererror",x.error=r=e||i}}catch(e){a("error caught: ",e),i="error",x.error=r=e||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&x.status<300||304===x.status?"success":"error"),"success"===i?(f.success&&f.success.call(f.context,M,"success",x),S.resolve(x.responseText,"success",x),d&&e.event.trigger("ajaxSuccess",[x,f])):i&&(void 0===r&&(r=x.statusText),f.error&&f.error.call(f.context,x,i,r),S.reject(x,"error",r),d&&e.event.trigger("ajaxError",[x,f,r])),d&&e.event.trigger("ajaxComplete",[x,f]),d&&!--e.active&&e.event.trigger("ajaxStop"),f.complete&&f.complete.call(f.context,x,i),X=!0,f.timeout&&clearTimeout(j),setTimeout(function(){f.iframeTarget?h.attr("src",f.iframeSrc):h.remove(),x.responseXML=null},100)}}}var u,c,f,d,m,h,v,x,y,b,T,j,w=p[0],S=e.Deferred();if(S.abort=function(e){x.abort(e)},r)for(c=0;c',k)).css({position:"absolute",top:"-1000px",left:"-1000px"}),v=h[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{v.contentWindow.document.execCommand&&v.contentWindow.document.execCommand("Stop")}catch(e){}h.attr("src",f.iframeSrc),x.error=r,f.error&&f.error.call(f.context,x,r,t),d&&e.event.trigger("ajaxError",[x,f,r]),f.complete&&f.complete.call(f.context,x,r)}},(d=f.global)&&0==e.active++&&e.event.trigger("ajaxStart"),d&&e.event.trigger("ajaxSend",[x,f]),f.beforeSend&&!1===f.beforeSend.call(f.context,x,f))return f.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;(y=w.clk)&&(b=y.name)&&!y.disabled&&(f.extraData=f.extraData||{},f.extraData[b]=y.value,"image"===y.type&&(f.extraData[b+".x"]=w.clk_x,f.extraData[b+".y"]=w.clk_y));var A=1,L=2,F=e("meta[name=csrf-token]").attr("content"),E=e("meta[name=csrf-param]").attr("content");E&&F&&(f.extraData=f.extraData||{},f.extraData[E]=F),f.forceSync?i():setTimeout(i,10);var M,O,X,C=50,q=e.parseXML||function(e,t){return window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!==t.documentElement.nodeName?t:null},_=e.parseJSON||function(e){return window.eval("("+e+")")},N=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i=("xml"===r||!r)&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&(("json"===r||!r)&&n.indexOf("json")>=0?o=_(o):("script"===r||!r)&&n.indexOf("javascript")>=0&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var l,f,d,p=this;"function"==typeof t?t={success:t}:"string"==typeof t||!1===t&&arguments.length>0?(t={url:t,data:r,dataType:n},"function"==typeof s&&(t.success=s)):void 0===t&&(t={}),l=t.method||t.type||this.attr2("method"),(d=(d="string"==typeof(f=t.url||this.attr2("action"))?e.trim(f):"")||window.location.href||"")&&(d=(d.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:d,success:e.ajaxSettings.success,type:l||e.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&!1===t.beforeSerialize(this,t))return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var h=t.traditional;void 0===h&&(h=e.ajaxSettings.traditional);var v,g=[],x=this.formToArray(t.semantic,g,t.filtering);if(t.data){var y=e.isFunction(t.data)?t.data(x):t.data;t.extraData=y,v=e.param(y,h)}if(t.beforeSubmit&&!1===t.beforeSubmit(x,this,t))return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[x,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var b=e.param(x,h);v&&(b=b?b+"&"+v:v),"GET"===t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+b,t.data=null):t.data=b;var T=[];if(t.resetForm&&T.push(function(){p.resetForm()}),t.clearForm&&T.push(function(){p.clearForm(t.includeHidden)}),!t.dataType&&t.target){var j=t.success||function(){};T.push(function(r,a,n){var i=arguments,o=t.replaceTarget?"replaceWith":"html";e(t.target)[o](r).each(function(){j.apply(this,i)})})}else t.success&&(e.isArray(t.success)?e.merge(T,t.success):T.push(t.success));if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=T.length;i0,D="multipart/form-data",A=p.attr("enctype")===D||p.attr("encoding")===D,L=i.fileapi&&i.formdata;a("fileAPI :"+L);var F,E=(k||A)&&!L;!1!==t.iframe&&(t.iframe||E)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){F=c(x)}):F=c(x):F=(k||A)&&L?function(r){for(var a=new FormData,n=0;n0)&&(n={url:n,data:i,dataType:o},"function"==typeof s&&(n.success=s)),n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var u={s:this.selector,c:this.context};return!e.isReady&&u.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(u.s,u.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().on("submit.form-plugin",n,t).on("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.off("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r,a){var n=[];if(0===this.length)return n;var o,s=this[0],u=this.attr("id"),c=t||void 0===s.elements?s.getElementsByTagName("*"):s.elements;if(c&&(c=e.makeArray(c)),u&&(t||/(Edge|Trident)\//.test(navigator.userAgent))&&(o=e(':input[form="'+u+'"]').get()).length&&(c=(c||[]).concat(o)),!c||!c.length)return n;e.isFunction(a)&&(c=e.map(c,a));var l,f,d,p,m,h,v;for(l=0,h=c.length;l").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!(c.settings.submitHandler&&!c.settings.debug)||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0],k="undefined"!=typeof this.attr("contenteditable")&&"false"!==this.attr("contenteditable");if(null!=j&&(!j.form&&k&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr.pseudos||a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");if(!this.form&&c&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name")),d===this.form){var e=a.data(this.form,"validator"),f="on"+b.type.replace(/^validate/,""),g=e.settings;g[f]&&!a(this).is(g.ignore)&&g[f].call(e,this,b)}}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.currentForm,e=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){e[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name"),e="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),e&&(this.form=a(this).closest("form")[0],this.name=d),this.form===b.currentForm&&(!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0))})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type,g="undefined"!=typeof e.attr("contenteditable")&&"false"!==e.attr("contenteditable");return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=g?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);"function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f&&(j=f.call(b,j),delete g.normalizer);for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+""),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur").find(".validate-lessThan-blur").off(".validate-lessThan").removeClass("validate-lessThan-blur").find(".validate-lessThanEqual-blur").off(".validate-lessThanEqual").removeClass("validate-lessThanEqual-blur").find(".validate-greaterThanEqual-blur").off(".validate-greaterThanEqual").removeClass("validate-greaterThanEqual-blur").find(".validate-greaterThan-blur").off(".validate-greaterThan").removeClass("validate-greaterThan-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),""===d&&(d=!0),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:void 0!==b&&null!==b&&b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(){var a=!1;return function(b,c){return a||(a=!0,this.settings.debug&&window.console&&console.warn("The `date` method is deprecated and will be removed in version '2.0.0'.\nPlease don't use it, since it relies on the Date constructor, which\nbehaves very differently across browsers and locales. Use `dateISO`\ninstead or one of the locale specific methods in `localizations/`\nand `additional-methods.js`.")),this.optional(c)||!/Invalid|NaN/.test(new Date(b).toString())}}(),dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a}); \ No newline at end of file diff --git a/contactsnew/lang/bg.txt b/contactsnew/lang/bg.txt deleted file mode 100644 index ed45f7a..0000000 --- a/contactsnew/lang/bg.txt +++ /dev/null @@ -1,187 +0,0 @@ -contacts = "Контакти New" -mod_info = "В дадения раздел са всички контактни форми в системата. тук Вие може да добавите нова контактна форма. както и да редактирате вече съществуващи." -forms = "Списък форми" -form = "Форма" -noforms = "В модула няма добавени форми" -form_new = "Добавяне на форма" -form_deleting = "Сигурни ли сте, че желаете да изтриете формата?" - -form_creating = "Добавяне на нова форма" -form_notfound = "тази форма не е намерена" -form_editing = "Редактиране на форма" -main_sets = "Основни параметри" -title = "Наименование" -alias = "Алиас" -protection = "Защита от повторно изпращане" -protect_i = "Препоръчително за форми без Ajax.<br/><br/>Ако защитата е включена, на финалната страница (след успешното изпращане на формата) при обновяванто на страницата потребителя няма да види съобщението "Подтвърдете повторното изпращане на данните...". Вместо това ще се зареди наново празна форма." -demo = "Създаване на примерна форма" -demo_noajax = "без Ajax" -demo_ajax = "Ajax, сървъра връща кода на формата" -demo_ajax_o = "Ajax, сървъра връща резултатът от валидацията" -alias_i = "Опционално. Алиасът на формата позволява да се използва леко запомнящ се таг [mod_contact:alias] вместо [mod_contact:id]. Алиасът не трябва да бъде число, може да съдържа само цифри, латински букви, долна черта и дължина не повече от 20 символа и да е уникално в пределите на модула" -alias_accept = "Този алиас може да се използва" -alias_er_syn = "Грешен алиас!
Алиасът не може да бъде число, може да съдържа само цифри, латински букви, долна черта и дължина не повече от 20 символа" -alias_er_exists = "Грешен алиас!
Този алиас вече е зададен на друга контактна форма" -recs = "Получатели" -name = "Име" -fields_sets = "Настройки на полетата" -active_i = "Активиране на поле (ако чекбокса е празен, тагът в шаблона ще бъде заменен с празен ред)" -type = "Тип" -doc = "Документ" -multidoc = "Документ (multi)" -other_input = "Друг input" -other_input_i = "Атрибут type" -pattern_i = "Шаблон за preg_match
Пример: /^[A-Za-z0-9]+$/ie

Или филтър за filter_var
Пример: FILTER_VALIDATE_EMAIL" -pattern = "Валидация" -defaultval = "По подразбиране" -sets = "Параметри" -attributes = "Атрибути на тега поле" -field_add = "Добави поле" -form_tpl = "Шаблон на формата" -mail_tpl = "Шаблон на писмо" -finish_tpl = "Шаблон на страница след изпращане на формата" -conditions = "Условия" -rubheader = "Скриптове и стилове, необходими за оформяне и функциониране на формата" -rubheader_info = "Избягвайте дублиране на скриптовете в модула и шаблона" -tag = "Таг" -field_creating = "Добавяне на поле..." -field_new_error = "Моля, въведете наименование на полето!" -type_i = "За input в атрибутите може да се укаже свой type (по подразбиране се поставя text)" -fld_tpl_toggle = "Покажи/скрий шаблона за извеждане на полето" -field_tpl = "Шаблон на полето" -fld_del = "Сигурни ли сте, че желаете да изтриете това поле?" -fld_deleting = "Изтриване на поле..." -required = "Задължително поле" -setting_empty = "Първо настройте опциите за избор (вляво)" -yes = "да" -no = "не" -fld_i = "Полето работи само ако тагът в поставен в шаблон и вляво е маркирано полето активация" -copy_fld_i = "Отправка копии будет выполнена, даже если в значении по умолчанию стоит галка, а тег в шаблон не вставлен / поле не активировано" -select_req_i = "Селект будет считаться не заполненным, если выбран первый вариант" -file_size = "Макс. размер, мб" -file_size2 = "Ограничение на размера на файла, мб" - -create = "Добави" -edit = "Редактиране" -copy = "Копиране" -delete = "Изтриване" -actions = "Действия" -saved = "Съхранено" -notsaved = "Възникна грешка по време на съхранението" -created = "Формата е успешно записана" -copied = "Формата е успешно копирана и записана
Моля, редактирайте наименованието и алиаса" -deleting = "Изтриване..." -add_refresh = "Добави и обнови" -save = "Запиши" -return_to_forms = "Върни се към списъка с контактни форми" -refresh = "Обнови" -mail_set = "Настройки на писмата" -format = "Формат" -text = "Текст" -from_email = "Имейл на изпращача" -from_name = "Име на изпращача" -recs_main = "Главни получатели" -recs_main_i = "Тези адресати ще получават писмото задължително" -subject_tpl = "Шаблон на темата" - -email_accept = "Правилен имейл" -email_error = "Грешен синтаксис на имейл!" - -tag_fld = "Таг за поле, полето се поставя с използване на своя шаблон" -tag_fld_mail = "Значение на полето, въведено от потребителя" -tag_fld_tpl = "Таг за поле, полето се поставя с атрибутите си" -tag_attr = "Вмъкни основни атрибити" -tag_id = "Id на полето" -tag_title = "Таг за наименование на поле" -tag_valid = "Извеждано съдържание, ако полето съответства на зададения шаблон" -tag_invalid = "Извеждано съдържание, ако полето не съответства на зададения шаблон" -tag_nempty = "Извеждано съдържание, ако полето е маркирано като задължително и потребителя е въвел данни" -tag_empty = "Извеждано съдържание, ако полето е маркирано като задължително и потребителя не е въвел данни" -tag_path = "Път към корена на инсталацията" -tag_media = "Път към папката с шаблона

Пример: [tag:mediapath]images/logo.gif" -tag_css = "Свива няколко css-файла в един. Връща път.
FFF - имена на файлове, разделени с запетая
P - път към папката с файлове, назадължителен. По подразбиране - [tag:mediapath]css/

Пример: href="[tag:css:reset.css,style.css]"" -tag_js = "Свива няколко js-файла в един. Връща път.
FFF - имена на файлове, разделени с запетая
P - път към папката с файлове, назадължителен. По подразбиране - [tag:mediapath]js/

Пример: href="[tag:js:common.js,main.js]"" -tag_formtitle = "Наименование на формата" -tag_formalias = "Алиас на формата (или id, ако не е въведен алиас)" -tag_url = "URL на текущата страница" -tag_docid = "ID на текущия документ" -tag_hide = "Таг, позволяващ скрит контент за определени групи потребители

Х - номер на групата
TEXT - текст, ако достъпа е забранен

Пример: [tag:hide:2:Тази форма не е за вас!][/tag:hide]" -tag_uemail = "Имейл на потребителя (въз основата на данните от профила, а не на формата!)" -tag_uname = "Име и Фамилия на потребителя (въз основа на данните от профила)" -tag_ufname = "Име на потребителя (въз основа на данните от профила)" -tag_ulname = "Фамилия на потребителя (въз основа на данните от профила)" -tag_ulogin = "Потребителско име (въз основа на данните от профила)" -tag_if_fld = "Условие за значението на полето. В тага, използвайте стандартните конструкции за сравнение на PHP/JS

Пример:
[tag:if_fld:15 == '1']
...
[tag:elseif_fld:15 > '2']
...
[tag:else_fld]
...
[/tag:if_fld]" -tag_f_valid = "Извеждано съдържание, ако всички полета са преминали валидацията" -tag_f_invalid = "Извеждано съдържание, ако поне едно поле не преминало валидацията" -tag_easymail = "Генерива списък на всички значения на полетата, участващи в шаблона на формата ( вместо ръчно да се описват всички тагове)" -tag_if_user = "Извежда съдържанието в писмото на потребителя, попълнил формата" -tag_if_admin = "Извежда съдържанието в писмото за получателя-админ ("главен получател" или получател от поле "избор на получателр")" -tag_fld_subject = "Значение на полето Тема" -tag_fld_email = "Значение на полето Имейл" -tag_sitename = "Наименование на сайта" -tag_sitehost = "Адрес на сайта" -info_php_tags = "Достъпни php и тагове" - -code = "Изпълним код" -code_info = "Данните на формата (валидация, шаблони, получатели и т.д.) се пазят е променливата на класа $this->form." -code_onsubmit = "Код, изпълняван след изпращането на формата (преди валидацията)" -code_onvalidate = "Код, изпълняван след валидацията на формата" -code_onsend = "Код, изпълняван след изпращането на писмата" - -mfld_email = "Имейл" -mfld_subject = "Тема" -mfld_receivers = "Избор на получатели" -mfld_captcha = "Капча" -mfld_copy = "Изпращане на копие" - -tag_mail_empty = "не е попълнено" - -history = "История" -date = "Дата" -author = "Автор" -status = "Статус" -stat_new = "Ново" -list_new = "Нови" -stat_viewed = "Видяно" -list_viewed = "Видени" -stat_replied = "Отговорено" -list_replied = "Отговорени" -request = "Обръщение" -response = "Отговор" -responses = "Отговори" -write_response = "Напиши отговор" -body = "Тяло на писмото" -save_draft = "Запази черновата" -send = "Изпрати отговор" -return_dialogs = "Върни се към списъка" -profile_look = "Премини към профила" -write_email = "Напиши писмо" -from = "от" -look = "Преглед" -set_replied = "Маркирай като отговорено" -marked_replied = "Маркирано като отговорено" -attach = "Прикачени" - -respose_sent = "Отговорът е успешно изпратен" - -cn_actions = "Действия" -cn_del_mail = "Сигурни ли сте, че желаете да изтриете този e-mail?" -cn_not_mail = "В тази форма няма писма ..." -cn_view = "Преглед на историята" -cn_status = "Статус на писмата" -cn_alias_not = " -- " -cn_count_messages = "писма: " -cn_copy_to_clipboard = "Копирай в буфера" -cn_return_list_form = "Връщане към списъка" -cn_mod_info = "Важно: модулът използва метода за изпращане на писма, установен в системните настройки " -cn_mod_info_a = "Настройки поща" -info_attr_name = "Значение атрибута name для этого поля:" -public_key_recaptcha_v3 = "Публичный ключ reCAPTCHA v3" -title_pub_key_recap = "Открытый ключ reCAPTCHA v3 указанный в системных настройках, используется на стороне клиента (например в js скриптах)" -found_key_recap_v3 = "В системных настройках обнаружены и будут использоваться модулем API ключи reCAPTCHA v3" -notfound_key_recap_v3_1 ="API ключи reCAPTCHA v3 не обнаружены." -notfound_key_recap_v3_2 =" Вы можете установить их в разделе " -notfound_key_recap_v3_3 ="Системные настройки" -demo_jqval_cap = "Без Ajax, с jQuery Validation Plugin и reCAPTCHA v3" -demo_ajax_jqval_cap = "Ajax, с jQuery Validation Plugin и reCAPTCHA v3" \ No newline at end of file diff --git a/contactsnew/lang/en.txt b/contactsnew/lang/en.txt deleted file mode 100644 index c803440..0000000 --- a/contactsnew/lang/en.txt +++ /dev/null @@ -1,187 +0,0 @@ -contacts = "Контакты New" -mod_info = "В данном разделе приведен список всех контактных форм. Вы можете, добавить новую форму или отредактировать существующую." -forms = "Список форм" -form = "Форма" -noforms = "В модуле пока нет ни одной контактной формы" -form_new = "Создать форму" -form_deleting = "Вы уверены, что хотите удалить форму?" - -form_creating = "Создание новой формы" -form_notfound = "указанная форма не найдена" -form_editing = "Редактирование формы" -main_sets = "Основные параметры" -title = "Название" -alias = "Алиас" -protection = "Защита от повторной отправки" -protect_i = "Рекомендуется включать для форм без Ajax.<br/><br/>Если защита включена, на финишной странице (после успешной отправки формы) при обновлении страницы пользователь не увидит сообщения "Подтвердите повторную отправку данных...". Вместо этого загрузится заново чистая форма." -demo = "Создать пример формы" -demo_noajax = "без Ajax" -demo_ajax = "Ajax, сервер возвращает код формы" -demo_ajax_o = "Ajax, сервер возвращает результат валидации" -alias_i = "Опционально. Алиас формы позволяет использовать легко запоминающийся тег [mod_contact:alias] вместо [mod_contact:id]. Алиас не должен являться числом, может содержать только цифры, латинские буквы, дефис, подчёркивание, иметь длину не более 20 символов и быть уникальным в пределах модуля" -alias_accept = "Этот алиас можно использовать" -alias_er_syn = "Неверный алиас!
Алиас не должен являться числом, может содержать только цифры, латинские буквы, дефис, подчёркивание и иметь длину не более 20 символов" -alias_er_exists = "Неверный алиас!
Данный алиас уже привязан к другой контактной форме" -recs = "Получатели" -name = "Имя" -fields_sets = "Настройки полей" -active_i = "Активировать поле (если чекбокс пустой, тег в шаблоне будет заменён на пустую строку)" -type = "Тип" -doc = "Документ" -multidoc = "Документ (multi)" -other_input = "Другой input" -other_input_i = "Аттрибут type" -pattern_i = "Шаблон для preg_match
Пример: /^[A-Za-z0-9]+$/ie

Либо фильтр для filter_var
Пример: FILTER_VALIDATE_EMAIL" -pattern = "Валидация" -defaultval = "По умолчанию" -sets = "Параметры" -attributes = "Аттрибуты тега поля" -field_add = "Добавить поле" -form_tpl = "Шаблон формы" -mail_tpl = "Шаблон письма" -finish_tpl = "Шаблон страницы после отправки формы" -conditions = "Условия" -rubheader = "Скрипты и стили, необходимые для оформления и функционирования формы" -rubheader_info = "Избегайте дублирования скриптов в модуле и шаблоне" -tag = "Тег" -field_creating = "Добавление поля..." -field_new_error = "Укажите название поля!" -type_i = "Для input в аттрибутах можно указать свой type (по умолчанию подставится text)" -fld_tpl_toggle = "Показать/свернуть шаблон вывода поля" -field_tpl = "Шаблон поля" -fld_del = "Вы уверены, что хотите удалить это поле?" -fld_deleting = "Удаление поля..." -required = "Обязательное поле" -setting_empty = "Сначала настройте опции для выбора (слева)" -yes = "да" -no = "нет" -fld_i = "Поле работает только если его тег вставлен в шаблон и слева стоит галочка активации" -copy_fld_i = "Отправка копии будет выполнена, даже если в значении по умолчанию стоит галка, а тег в шаблон не вставлен / поле не активировано" -select_req_i = "Селект будет считаться не заполненным, если выбран первый вариант" -file_size = "Макс. размер, мб" -file_size2 = "Ограничение размера файла, мб" - -create = "Создать" -edit = "Редактировать" -copy = "Копировать" -delete = "Удалить" -actions = "Действия" -saved = "Сохранено" -notsaved = "Во время сохранения произошла ошибка" -created = "Форма успешно создана" -copied = "Форма успешно скопирована и сохранена
Отредактируйте название и алиас" -deleting = "Удаление..." -add_refresh = "Добавить и обновить" -save = "Сохранить" -return_to_forms = "Вернуться к списку контактных форм" -refresh = "Обновить" -mail_set = "Настройки письма" -format = "Формат" -text = "Текст" -from_email = "Email отправителя" -from_name = "Имя отправителя" -recs_main = "Главные получатели" -recs_main_i = "Эти адресаты получат письмо в любом случае" -subject_tpl = "Шаблон темы" - -email_accept = "Правильный Email" -email_error = "Неверный синтаксис Email-а!" - -tag_fld = "Тег поля, поле подставляется с использованием своего шаблона" -tag_fld_mail = "Значение поля, введённое пользователем" -tag_fld_tpl = "Тег поля, поле подставляется с подстановкой аттрибутов" -tag_attr = "Вставить основные аттрибуты" -tag_id = "Id поля" -tag_title = "Тег названия поля" -tag_valid = "Выведет контент, если поле соответствует заданному шаблону" -tag_invalid = "Выведет контент, если поле не соответствует заданному шаблону" -tag_nempty = "Выведет контент, если поле помечено как обязательное и пользователь ввёл данные" -tag_empty = "Выведет контент, если поле помечено как обязательное и пользователь не ввёл данные" -tag_path = "Корневой путь установки" -tag_media = "Путь до папки с шаблоном

Пример: [tag:mediapath]images/logo.gif" -tag_css = "Сжимает несколько css-файлов в один. Возвращает путь.
FFF - имена файлов через запятую
P - путь к папке с файлами, не обязательно. По умолчанию - [tag:mediapath]css/

Пример: href="[tag:css:reset.css,style.css]"" -tag_js = "Сжимает несколько js-файлов в один. Возвращает путь.
FFF - имена файлов через запятую
P - путь к папке с файлами, не обязательно. По умолчанию - [tag:mediapath]js/

Пример: href="[tag:js:common.js,main.js]"" -tag_formtitle = "Название формы" -tag_formalias = "Алиас формы (или id, если алиас не назначен)" -tag_url = "URL текущей страницы" -tag_docid = "ID текущего документа" -tag_hide = "Тег, позволяющий скрыть контент для определенных групп пользователей

Х - номер группы
TEXT - текст, если доступ запрещён

Пример: [tag:hide:2:Эта форма не для вас!][/tag:hide]" -tag_uemail = "Email пользователя (на основе данных из профиля, а не формы!)" -tag_uname = "И. Фамилия пользователя (на основе данных из профиля)" -tag_ufname = "Имя пользователя (на основе данных из профиля)" -tag_ulname = "Фамилия пользователя (на основе данных из профиля)" -tag_ulogin = "Логин пользователя (на основе данных из профиля)" -tag_if_fld = "Условие на значение поля. В теге используйте стандартные конструкции сравнения PHP/JS

Пример:
[tag:if_fld:15 == '1']
...
[tag:elseif_fld:15 > '2']
...
[tag:else_fld]
...
[/tag:if_fld]" -tag_f_valid = "Выведет контент, если все поля формы прошли валидацию" -tag_f_invalid = "Выведет контент, если хотя бы одно поле формы не прошло валидацию" -tag_easymail = "Быстро генерирует список всех значений полей, участвующих в шаблоне формы (вместо того, чтобы прописывать все теги вручную)" -tag_if_user = "Выведет контент в письме пользователю, заполнившему форму" -tag_if_admin = "Выведет контент в письме получателям-админам ("главным получателям" или адресату из поля "получатель на выбор")" -tag_fld_subject = "Значение поля Тема" -tag_fld_email = "Значение поля Email" -tag_sitename = "Название сайта" -tag_sitehost = "Адрес сайта" -info_php_tags = "Доступен php и теги" - -code = "Исполняемый код" -code_info = "Данные формы (валидация, шаблоны, получатели и т.д.) хранятся в переменной класса $this->form." -code_onsubmit = "Код, исполняемый сразу после отправки формы (до валидации)" -code_onvalidate = "Код, исполняемый после валидации формы" -code_onsend = "Код, исполняемый после отправки писем" - -mfld_email = "Email" -mfld_subject = "Тема" -mfld_receivers = "Получатель на выбор" -mfld_captcha = "Капча" -mfld_copy = "Отправка копии" - -tag_mail_empty = "не заполнено" - -history = "История" -date = "Дата" -author = "Автор" -status = "Статус" -stat_new = "Новое" -list_new = "Новых" -stat_viewed = "Просмотрено" -list_viewed = "Просмотренных" -stat_replied = "Отвечено" -list_replied = "Отвеченных" -request = "Обращение" -response = "Ответ" -responses = "Ответы" -write_response = "Написать ответ" -body = "Тело письма" -save_draft = "Сохранить черновик" -send = "Отправить ответ" -return_dialogs = "Вернуться к списку обращений" -profile_look = "Перейти к профилю" -write_email = "Написать письмо" -from = "от" -look = "Посмотреть" -set_replied = "Пометить как отвеченное" -marked_replied = "Было отмечено как отвеченное" -attach = "Вложения" - -respose_sent = "Ответ успешно отправлен" - -cn_actions = "Действия" -cn_del_mail = "Вы уверены, что хотите удалить этот e-mail?" -cn_not_mail = "В этой форме нет писем..." -cn_view = "Просмотр истории" -cn_status = "Статус сообщений" -cn_alias_not = " -- " -cn_count_messages = "сообщений: " -cn_copy_to_clipboard = "Скопировать в буфер обмена" -cn_return_list_form = "Вернуться к списку форм" -cn_mod_info = "Важно: модуль использует метод отправки почты установленный в системных настройках, в разделе " -cn_mod_info_a = "Настройки почты." -info_attr_name = "Значение атрибута name для этого поля:" -public_key_recaptcha_v3 = "Публичный ключ reCAPTCHA v3" -title_pub_key_recap = "Открытый ключ reCAPTCHA v3 указанный в системных настройках, используется на стороне клиента (например в js скриптах)" -found_key_recap_v3 = "В системных настройках обнаружены и будут использоваться модулем API ключи reCAPTCHA v3" -notfound_key_recap_v3_1 ="API ключи reCAPTCHA v3 не обнаружены." -notfound_key_recap_v3_2 =" Вы можете установить их в разделе " -notfound_key_recap_v3_3 ="Системные настройки" -demo_jqval_cap = "Без Ajax, с jQuery Validation Plugin и reCAPTCHA v3" -demo_ajax_jqval_cap = "Ajax, с jQuery Validation Plugin и reCAPTCHA v3" \ No newline at end of file diff --git a/contactsnew/lang/index.php b/contactsnew/lang/index.php deleted file mode 100644 index 9c20174..0000000 --- a/contactsnew/lang/index.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/contactsnew/lang/ua.txt b/contactsnew/lang/ua.txt deleted file mode 100644 index c803440..0000000 --- a/contactsnew/lang/ua.txt +++ /dev/null @@ -1,187 +0,0 @@ -contacts = "Контакты New" -mod_info = "В данном разделе приведен список всех контактных форм. Вы можете, добавить новую форму или отредактировать существующую." -forms = "Список форм" -form = "Форма" -noforms = "В модуле пока нет ни одной контактной формы" -form_new = "Создать форму" -form_deleting = "Вы уверены, что хотите удалить форму?" - -form_creating = "Создание новой формы" -form_notfound = "указанная форма не найдена" -form_editing = "Редактирование формы" -main_sets = "Основные параметры" -title = "Название" -alias = "Алиас" -protection = "Защита от повторной отправки" -protect_i = "Рекомендуется включать для форм без Ajax.<br/><br/>Если защита включена, на финишной странице (после успешной отправки формы) при обновлении страницы пользователь не увидит сообщения "Подтвердите повторную отправку данных...". Вместо этого загрузится заново чистая форма." -demo = "Создать пример формы" -demo_noajax = "без Ajax" -demo_ajax = "Ajax, сервер возвращает код формы" -demo_ajax_o = "Ajax, сервер возвращает результат валидации" -alias_i = "Опционально. Алиас формы позволяет использовать легко запоминающийся тег [mod_contact:alias] вместо [mod_contact:id]. Алиас не должен являться числом, может содержать только цифры, латинские буквы, дефис, подчёркивание, иметь длину не более 20 символов и быть уникальным в пределах модуля" -alias_accept = "Этот алиас можно использовать" -alias_er_syn = "Неверный алиас!
Алиас не должен являться числом, может содержать только цифры, латинские буквы, дефис, подчёркивание и иметь длину не более 20 символов" -alias_er_exists = "Неверный алиас!
Данный алиас уже привязан к другой контактной форме" -recs = "Получатели" -name = "Имя" -fields_sets = "Настройки полей" -active_i = "Активировать поле (если чекбокс пустой, тег в шаблоне будет заменён на пустую строку)" -type = "Тип" -doc = "Документ" -multidoc = "Документ (multi)" -other_input = "Другой input" -other_input_i = "Аттрибут type" -pattern_i = "Шаблон для preg_match
Пример: /^[A-Za-z0-9]+$/ie

Либо фильтр для filter_var
Пример: FILTER_VALIDATE_EMAIL" -pattern = "Валидация" -defaultval = "По умолчанию" -sets = "Параметры" -attributes = "Аттрибуты тега поля" -field_add = "Добавить поле" -form_tpl = "Шаблон формы" -mail_tpl = "Шаблон письма" -finish_tpl = "Шаблон страницы после отправки формы" -conditions = "Условия" -rubheader = "Скрипты и стили, необходимые для оформления и функционирования формы" -rubheader_info = "Избегайте дублирования скриптов в модуле и шаблоне" -tag = "Тег" -field_creating = "Добавление поля..." -field_new_error = "Укажите название поля!" -type_i = "Для input в аттрибутах можно указать свой type (по умолчанию подставится text)" -fld_tpl_toggle = "Показать/свернуть шаблон вывода поля" -field_tpl = "Шаблон поля" -fld_del = "Вы уверены, что хотите удалить это поле?" -fld_deleting = "Удаление поля..." -required = "Обязательное поле" -setting_empty = "Сначала настройте опции для выбора (слева)" -yes = "да" -no = "нет" -fld_i = "Поле работает только если его тег вставлен в шаблон и слева стоит галочка активации" -copy_fld_i = "Отправка копии будет выполнена, даже если в значении по умолчанию стоит галка, а тег в шаблон не вставлен / поле не активировано" -select_req_i = "Селект будет считаться не заполненным, если выбран первый вариант" -file_size = "Макс. размер, мб" -file_size2 = "Ограничение размера файла, мб" - -create = "Создать" -edit = "Редактировать" -copy = "Копировать" -delete = "Удалить" -actions = "Действия" -saved = "Сохранено" -notsaved = "Во время сохранения произошла ошибка" -created = "Форма успешно создана" -copied = "Форма успешно скопирована и сохранена
Отредактируйте название и алиас" -deleting = "Удаление..." -add_refresh = "Добавить и обновить" -save = "Сохранить" -return_to_forms = "Вернуться к списку контактных форм" -refresh = "Обновить" -mail_set = "Настройки письма" -format = "Формат" -text = "Текст" -from_email = "Email отправителя" -from_name = "Имя отправителя" -recs_main = "Главные получатели" -recs_main_i = "Эти адресаты получат письмо в любом случае" -subject_tpl = "Шаблон темы" - -email_accept = "Правильный Email" -email_error = "Неверный синтаксис Email-а!" - -tag_fld = "Тег поля, поле подставляется с использованием своего шаблона" -tag_fld_mail = "Значение поля, введённое пользователем" -tag_fld_tpl = "Тег поля, поле подставляется с подстановкой аттрибутов" -tag_attr = "Вставить основные аттрибуты" -tag_id = "Id поля" -tag_title = "Тег названия поля" -tag_valid = "Выведет контент, если поле соответствует заданному шаблону" -tag_invalid = "Выведет контент, если поле не соответствует заданному шаблону" -tag_nempty = "Выведет контент, если поле помечено как обязательное и пользователь ввёл данные" -tag_empty = "Выведет контент, если поле помечено как обязательное и пользователь не ввёл данные" -tag_path = "Корневой путь установки" -tag_media = "Путь до папки с шаблоном

Пример: [tag:mediapath]images/logo.gif" -tag_css = "Сжимает несколько css-файлов в один. Возвращает путь.
FFF - имена файлов через запятую
P - путь к папке с файлами, не обязательно. По умолчанию - [tag:mediapath]css/

Пример: href="[tag:css:reset.css,style.css]"" -tag_js = "Сжимает несколько js-файлов в один. Возвращает путь.
FFF - имена файлов через запятую
P - путь к папке с файлами, не обязательно. По умолчанию - [tag:mediapath]js/

Пример: href="[tag:js:common.js,main.js]"" -tag_formtitle = "Название формы" -tag_formalias = "Алиас формы (или id, если алиас не назначен)" -tag_url = "URL текущей страницы" -tag_docid = "ID текущего документа" -tag_hide = "Тег, позволяющий скрыть контент для определенных групп пользователей

Х - номер группы
TEXT - текст, если доступ запрещён

Пример: [tag:hide:2:Эта форма не для вас!][/tag:hide]" -tag_uemail = "Email пользователя (на основе данных из профиля, а не формы!)" -tag_uname = "И. Фамилия пользователя (на основе данных из профиля)" -tag_ufname = "Имя пользователя (на основе данных из профиля)" -tag_ulname = "Фамилия пользователя (на основе данных из профиля)" -tag_ulogin = "Логин пользователя (на основе данных из профиля)" -tag_if_fld = "Условие на значение поля. В теге используйте стандартные конструкции сравнения PHP/JS

Пример:
[tag:if_fld:15 == '1']
...
[tag:elseif_fld:15 > '2']
...
[tag:else_fld]
...
[/tag:if_fld]" -tag_f_valid = "Выведет контент, если все поля формы прошли валидацию" -tag_f_invalid = "Выведет контент, если хотя бы одно поле формы не прошло валидацию" -tag_easymail = "Быстро генерирует список всех значений полей, участвующих в шаблоне формы (вместо того, чтобы прописывать все теги вручную)" -tag_if_user = "Выведет контент в письме пользователю, заполнившему форму" -tag_if_admin = "Выведет контент в письме получателям-админам ("главным получателям" или адресату из поля "получатель на выбор")" -tag_fld_subject = "Значение поля Тема" -tag_fld_email = "Значение поля Email" -tag_sitename = "Название сайта" -tag_sitehost = "Адрес сайта" -info_php_tags = "Доступен php и теги" - -code = "Исполняемый код" -code_info = "Данные формы (валидация, шаблоны, получатели и т.д.) хранятся в переменной класса $this->form." -code_onsubmit = "Код, исполняемый сразу после отправки формы (до валидации)" -code_onvalidate = "Код, исполняемый после валидации формы" -code_onsend = "Код, исполняемый после отправки писем" - -mfld_email = "Email" -mfld_subject = "Тема" -mfld_receivers = "Получатель на выбор" -mfld_captcha = "Капча" -mfld_copy = "Отправка копии" - -tag_mail_empty = "не заполнено" - -history = "История" -date = "Дата" -author = "Автор" -status = "Статус" -stat_new = "Новое" -list_new = "Новых" -stat_viewed = "Просмотрено" -list_viewed = "Просмотренных" -stat_replied = "Отвечено" -list_replied = "Отвеченных" -request = "Обращение" -response = "Ответ" -responses = "Ответы" -write_response = "Написать ответ" -body = "Тело письма" -save_draft = "Сохранить черновик" -send = "Отправить ответ" -return_dialogs = "Вернуться к списку обращений" -profile_look = "Перейти к профилю" -write_email = "Написать письмо" -from = "от" -look = "Посмотреть" -set_replied = "Пометить как отвеченное" -marked_replied = "Было отмечено как отвеченное" -attach = "Вложения" - -respose_sent = "Ответ успешно отправлен" - -cn_actions = "Действия" -cn_del_mail = "Вы уверены, что хотите удалить этот e-mail?" -cn_not_mail = "В этой форме нет писем..." -cn_view = "Просмотр истории" -cn_status = "Статус сообщений" -cn_alias_not = " -- " -cn_count_messages = "сообщений: " -cn_copy_to_clipboard = "Скопировать в буфер обмена" -cn_return_list_form = "Вернуться к списку форм" -cn_mod_info = "Важно: модуль использует метод отправки почты установленный в системных настройках, в разделе " -cn_mod_info_a = "Настройки почты." -info_attr_name = "Значение атрибута name для этого поля:" -public_key_recaptcha_v3 = "Публичный ключ reCAPTCHA v3" -title_pub_key_recap = "Открытый ключ reCAPTCHA v3 указанный в системных настройках, используется на стороне клиента (например в js скриптах)" -found_key_recap_v3 = "В системных настройках обнаружены и будут использоваться модулем API ключи reCAPTCHA v3" -notfound_key_recap_v3_1 ="API ключи reCAPTCHA v3 не обнаружены." -notfound_key_recap_v3_2 =" Вы можете установить их в разделе " -notfound_key_recap_v3_3 ="Системные настройки" -demo_jqval_cap = "Без Ajax, с jQuery Validation Plugin и reCAPTCHA v3" -demo_ajax_jqval_cap = "Ajax, с jQuery Validation Plugin и reCAPTCHA v3" \ No newline at end of file diff --git a/contactsnew/module.php b/contactsnew/module.php deleted file mode 100644 index 2c25049..0000000 --- a/contactsnew/module.php +++ /dev/null @@ -1,166 +0,0 @@ -[mod_contactsnew:XXX], где XXX - это id или алиас формы.'; - $modul['ModuleAutor'] = 'vudaltsov UPD Repellent'; - $modul['ModuleCopyright'] = '© 2007-2019 AVE.CMS Team'; - $modul['ModuleIsFunction'] = 1; - $modul['ModuleAdminEdit'] = 1; - $modul['ModuleFunction'] = 'mod_contactsnew'; - $modul['ModuleTag'] = '[mod_contactsnew:alias/id:email]'; - $modul['ModuleTagLink'] = null; - $modul['ModuleAveTag'] = '#\\\[mod_contactsnew:([A-Za-z0-9-_]{1,20})]#'; - $modul['ModulePHPTag'] = ""; -} - -/** - * Тег - */ -function mod_contactsnew($alias_id) -{ - global $AVE_Template; - - require_once(BASE_DIR . '/modules/contactsnew/class.contactsnew.php'); - - $contactsnew = new ContactsNew; - $contactsnew->tpl_dir = BASE_DIR . '/modules/contactsnew/templates/'; - - $lang_file = BASE_DIR . '/modules/contactsnew/lang/' . $_SESSION['user_language'] . '.txt'; - $AVE_Template->config_load($lang_file); - - echo $contactsnew->form_display($alias_id); -} - -/** - * AJAX-методы - */ -if (! defined('ACP') && isset($_REQUEST['module']) && $_REQUEST['module'] == 'contactsnew') -{ - global $AVE_Template; - - $alias_id = $_REQUEST['alias_id']; - - require_once(BASE_DIR . '/modules/contactsnew/class.contactsnew.php'); - - $contactsnew = new ContactsNew; - $contactsnew->tpl_dir = BASE_DIR . '/modules/contactsnew/templates/'; - - $lang_file = BASE_DIR . '/modules/contactsnew/lang/' . $_SESSION['user_language'] . '.txt'; - $AVE_Template->config_load($lang_file); - - switch($_REQUEST['action']) - { - case '': - case 'full': - exit ($contactsnew->form_display($alias_id)); - - case 'validate': - $contactsnew->form_display($alias_id); - $contactsnew->_json($contactsnew->form['ajax'], true); - } -} - -/** - * Админка - */ -if (defined('ACP') && isset($_REQUEST['mod']) && $_REQUEST['mod'] == 'contactsnew' && !empty($_REQUEST['moduleaction'])) -{ - $fid = !empty($_REQUEST['fid']) ? (int)$_REQUEST['fid'] : 0; - - require_once(BASE_DIR . '/modules/contactsnew/class.contactsnew.php'); - - $contactsnew = new ContactsNew; - $contactsnew->tpl_dir = BASE_DIR . '/modules/contactsnew/templates/'; - - $lang_file = BASE_DIR . '/modules/contactsnew/lang/' . $_SESSION['admin_language'] . '.txt'; - $AVE_Template->config_load($lang_file); - - // создаём переменные с версией движка - $ave14 = ((float)str_replace(',', '.', APP_VERSION) < 1.5); - $AVE_Template->assign('ave14', $ave14); - $AVE_Template->assign('ave15', !$ave14); - - switch($_REQUEST['moduleaction']) - { - case '1': - $contactsnew->forms_list(); - break; - - case 'form_edit': - $response = $contactsnew->form_edit($fid); - break; - - case 'form_save': - $response = $contactsnew->form_save($fid); - // если передан запрос на обновление полей, передаём tpl - if (isset($_REQUEST['fields_reload']) && $_REQUEST['fields_reload'] == 1) - { - exit ($contactsnew->form_fields_fetch()); - } - break; - - case 'form_del': - $contactsnew->form_del($fid); - header('Location: index.php?do=modules&action=modedit&mod=contactsnew&moduleaction=1&cp=' . SESSION); - exit; - - case 'form_copy': - $fid_new = $contactsnew->form_copy($fid); - $_SESSION['module_contactsnew_admin'][$fid_new]['edit_alert'] = array('text' => 'copied', 'theme' => 'accept'); - header('Location: index.php?do=modules&action=modedit&mod=contactsnew&moduleaction=form_edit&fid=' . $fid_new . '&cp=' . SESSION); - exit; - - case 'email_validate': - $response = (int)$contactsnew->_email_validate($_REQUEST['email']); - break; - - case 'alias_validate': - $response = $contactsnew->_alias_validate($_REQUEST['alias'],$fid); - $response = ($response === 'syn') ? 'syn' : (int)$response; - break; - - case 'history_list': - $contactsnew->history_list($fid); - break; - - case 'email_del': - $hid = !empty($_REQUEST['hid']) ? (int)$_REQUEST['hid'] : 0; - $contactsnew->email_del($hid); - $fid = !empty($_REQUEST['fid']) ? (int)$_REQUEST['fid'] : 0; - header('Location: index.php?do=modules&action=modedit&mod=contactsnew&moduleaction=history_list&fid=' . $fid . '&cp=' . SESSION); - exit; - - case 'history_dialog': - $hid = !empty($_REQUEST['hid']) ? (int)$_REQUEST['hid'] : 0; - $contactsnew->history_dialog($hid); - break; - - case 'history_dialog_submit': - $hid = !empty($_REQUEST['hid']) ? (int)$_REQUEST['hid'] : 0; - $contactsnew->history_dialog_submit($hid); - break; - - case 'dialog_status': - $hid = !empty($_REQUEST['hid']) ? (int)$_REQUEST['hid'] : 0; - $contactsnew->dialog_status($hid); - break; - } - if ($_REQUEST['ajax']) exit((string)$response); -} -?> \ No newline at end of file diff --git a/contactsnew/sql.php b/contactsnew/sql.php deleted file mode 100644 index fc90dfd..0000000 --- a/contactsnew/sql.php +++ /dev/null @@ -1,133 +0,0 @@ - \ No newline at end of file diff --git a/contactsnew/templates/index.php b/contactsnew/templates/index.php deleted file mode 100644 index 9c20174..0000000 --- a/contactsnew/templates/index.php +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/forms/class/forms.php b/forms/class/forms.php new file mode 100644 index 0000000..5cc0e5e --- /dev/null +++ b/forms/class/forms.php @@ -0,0 +1,1653 @@ + array( + 'new' => true, + 'title' => 'email', + 'type' => 'input', + 'main' => 1, + 'setting' => 'FILTER_VALIDATE_EMAIL', + 'required' => 1 + ), + 'subject' => array( + 'new' => true, + 'title' => 'subject', + 'type' => 'input', + 'main' => 1 + ), + 'receivers' => array( + 'new' => true, + 'title' => 'receivers', + 'type' => 'select', + 'main' => 1, + 'setting' => array() + ), + 'copy' => array( + 'new' => true, + 'title' => 'copy', + 'type' => 'checkbox', + 'main' => 1 + ), + 'captcha' => array( + 'new' => true, + 'title' => 'captcha', + 'type' => 'input', + 'main' => 1, + 'required' => 1 + ) + ); + // переменная для хранения формы + public $form = array(); + + /** + * Внутренние методы класса + */ + + /** + * Конструктор + */ + function __construct () + { + $this->fields_main = array_keys($this->fields_main_data); + $this->fields_main_in_string = "'" . implode("','",$this->fields_main) . "'"; + } + + + /** + * Возвращаем JSON + * + * @param $data + * @param bool $exit + */ + function _json($data, $exit = false) + { + header("Content-Type: application/json;charset=utf-8"); + + $json = json_encode($data); + + if ($json === false) + { + $json = json_encode(array("jsonError", json_last_error_msg())); + + if ($json === false) + { + $json = '{"jsonError": "unknown"}'; + } + + http_response_code(500); + } + + echo $json; + + if ($exit) + exit; + } + + + /** + * Метод забирает форму из бд по алиасу/id + * + * @param $alias_id + * @param bool $_fields + * + * @return array + */ + function _form ($alias_id, $_fields = true) + { + global $AVE_DB, $AVE_Template; + + // иначе забираем из бд форму + $form = array(); + + // основные параметры + $form = $AVE_DB->Query(" + SELECT * FROM " . PREFIX . "_module_forms_forms + WHERE + " . (is_numeric($alias_id) ? 'id' : 'alias') . " = '" . $alias_id . "' + ")->FetchAssocArray(); + + // если форма не обнаружена, выходим + if (empty($form)) + return array(); + + $form['alias_id'] = $alias_id; + + // получатели + $form['mail_set'] = unserialize($form['mail_set']); + + if ($_fields === true) + { + // поля + $sql = $AVE_DB->Query(" + SELECT * FROM " . PREFIX . "_module_forms_fields + WHERE form_id = '" . $form['id'] . "' + ORDER BY id ASC + "); + + $form['fields'] = array(); + + while ($field = $sql->FetchAssocArray()) + { + // раскрываем массив настроек для селектов + if (in_array($field['type'],array('select','multiselect','doc','multidoc'))) + { + // @fix для v1.0 beta <= 2: поддержка одной рубрики, не массива + if (in_array($field['type'],array('doc','multidoc')) && !empty($field['setting']) && is_numeric($field['setting'])) + $field['setting'] = array(0 => $field['setting']); + else + $field['setting'] = unserialize($field['setting']) !== false ? unserialize($field['setting']) : array(); + } + // если тип поля поменялся, ставим пустую строку + elseif (unserialize($field['setting']) !== false) $field['setting'] = ''; + + // раскрываем массив опций по умолчанию для мультиселекта + if ($field['type'] == 'multiselect') + { + $field['defaultval'] = unserialize($field['defaultval']) !== false ? unserialize($field['defaultval']) : array(); + } + // если тип поля поменялся, ставим пустую строку + elseif (unserialize($field['defaultval']) !== false) $field['defaultval'] = ''; + + // главные поля + if (in_array($field['title'],$this->fields_main) && $field['main']) + { + $form['fields_main'][$field['title']] = $field['id']; + $field['title_lang'] = $AVE_Template->get_config_vars('mfld_' . $field['title']); + } + + $form['fields'][$field['id']] = $field; + } + } + + // убираем слеши + $form = $this->_stripslashes($form); + + // сохраняем форму в переменную класса + $this->form = $form; + + return $form; + } + + + /** + * Метод убирает слэши во всей переменной + * + * @param $var + * + * @return array|string + */ + function _stripslashes($var) + { + if (! is_array($var)) + return stripslashes($var); + else + return array_map(array($this, '_stripslashes'), $var); + } + + + /** + * Метод тримует всю переменную + * + * @param $var + * + * @return array|string + */ + function _trim($var) + { + if (! is_array($var)) + return trim($var); + else + return array_map(array($this, '_trim'), $var); + } + + + /** + * Метод чистит переменную от пустых значений и массивов + * + * @param $var + * + * @return array|null|string + */ + function _cleanvar($var) + { + if (! is_array($var)) + return trim($var) > '' + ? trim($var) + : null; + + $narr = array(); + + while (list($key, $val) = each($var)) + { + if (is_array($val)) + { + $val = $this->_cleanvar($val); + + if (count($val) > 0) + $narr[$key] = $val; + } + else + { + if (trim($val) > '') + $narr[$key] = $val; + } + } + + unset ($var); + + return $narr; + } + + + /** + * Валидация Email-а + * + * @param string $email + * + * @return bool + */ + function _email_validate ($email = '') + { + return (filter_var($email, FILTER_VALIDATE_EMAIL) === false ? false : true); + } + + + /** + * Проверка алиаса тега на валидность и уникальность + * + * @param string $alias + * @param int $fid + * + * @return bool|string + */ + function _alias_validate ($alias = '', $fid = 0) + { + global $AVE_DB; + + // соответствие требованиям + if ( + empty ($alias) || + preg_match('/^[A-Za-z0-9-_]{1,20}$/i', $alias) !== 1 || + is_numeric($alias) + ) return 'syn'; + + // уникальность + return !(bool)$AVE_DB->Query(" + SELECT 1 FROM " . PREFIX . "_module_forms_forms + WHERE + alias = '" . $alias . "' AND + id != '" . $fid . "' + ")->GetCell(); + } + + + /** + * Получение списка рубрик + */ + function _rubrics () + { + global $AVE_DB; + + $rubs = array(); + + $sql = $AVE_DB->Query(" + SELECT Id, rubric_title FROM " . PREFIX . "_rubrics + "); + + while ($rub = $sql->FetchAssocArray()) + $rubs[$rub['Id']] = $rub['rubric_title']; + + return $rubs; + } + + + /** + * Получение списка документов + * + * @param array $rubs_id + * + * @return array + */ + function _docs ($rubs_id = array()) + { + global $AVE_DB; + + if (empty($rubs_id)) + return array(); + + // @fix для v1.0 beta <= 2: поддержка одной рубрики, не массива + if (! is_array($rubs_id)) + $rubs_id = array(0 => $rubs_id); + + $docs = array(); + + $sql = $AVE_DB->Query(" + SELECT Id, document_title FROM " . PREFIX . "_documents + WHERE rubric_id IN (" . implode(',',$rubs_id) . ") + "); + + while ($doc = $sql->FetchAssocArray()) + $docs[$doc['Id']] = $doc['document_title']; + + return $docs; + } + + + /** + * Парсинг главных тегов + */ + function _parse_tags ($str) + { + global $AVE_Core, $AVE_DB; + + if (empty($_SESSION['user_login'])) + $_SESSION['user_login'] = (UGROUP != 2) + ? $AVE_DB->Query("SELECT user_name FROM " . PREFIX . "_users WHERE Id = '" . UID . "'")->GetCell() + : ''; + + $str = preg_replace_callback('/\[tag:(css|js):([^ :\/]+):?(\S+)*\]/', array($AVE_Core, '_parse_combine'), $str); + + $str = parse_hide($str); + + return str_replace(array( + '[tag:docid]', + '[tag:formtitle]', + // @fix для v1.0 beta <= 2: поддержка тега formaction + '[tag:formaction]', + '[tag:document]', + '[tag:formalias]', + '[tag:path]', + '[tag:mediapath]', + '[tag:captcha]', + '[tag:uname]', + '[tag:ufname]', + '[tag:ulname]', + '[tag:ulogin]', + '[tag:uemail]', + '[tag:sitename]', + '[tag:sitehost]', + ),array( + $AVE_Core->curentdoc->Id, + $this->form['title'], + $_SERVER['REQUEST_URI'], + $_SERVER['REQUEST_URI'], + $this->form['alias'] ? $this->form['alias'] : $this->form['id'], + ABS_PATH, + ABS_PATH . 'templates/' . THEME_FOLDER . '/', + 'inc/captcha.php', + $_SESSION['user_name'], + get_user_rec_by_id(UID)->firstname, + get_user_rec_by_id(UID)->lastname, + $_SESSION['user_login'], + $_SESSION['user_email'], + htmlspecialchars(get_settings('site_name'), ENT_QUOTES), + $_SERVER['HTTP_HOST'], + ), $str); + } + + /** + * Внутренний PHP-парсер + */ + function _eval2var($code) + { + global $AVE_DB, $AVE_Core, $AVE_Template; + + ob_start(); + + eval($code); + + return ob_get_clean(); + } + + /** + * Приведение тегов главных полей к стандартной форме + */ + function _parse_tag_fld_main ($tpl='', $save_is=false) + { + foreach ($this->fields_main as $field_title) + { + $count = 0; + + $tpl = str_replace(array( + '[tag:fld:' . $field_title . ']', + '[tag:if_fld:' . $field_title, + '[tag:elseif_fld:' . $field_title, + ), array( + '[tag:fld:' . $this->form['fields_main'][$field_title] . ']', + '[tag:if_fld:' . $this->form['fields_main'][$field_title], + '[tag:elseif_fld:' . $this->form['fields_main'][$field_title], + ),$tpl,$count); + + if ($save_is) + $this->form['is_' . $field_title] = $count > 0 ? true : false; + } + + return $tpl; + } + + /** + * Замена тега условия + */ + function _parse_tag_if (&$tpl,$tag='',$open = true) + { + if ($open) + $tpl = str_replace(array('[tag:' . $tag . ']','[/tag:' . $tag . ']'),'',$tpl); + else + $tpl = preg_replace('/\[tag:' . $tag . '](.*?)\[\/tag:' . $tag . ']/si','',$tpl); + } + + /** + * Замена тега названия поля + */ + function _parse_tag_title ($matches) + { + $field_id = $matches[1]; + + return !$this->form['fields'][$field_id]['main'] + ? $this->form['fields'][$field_id]['title'] + : $this->form['fields'][$field_id]['title_lang']; + } + + /** + * Замена тега поля на значение $_POST + */ + function _parse_tag_fld_post ($matches) + { + return $_POST['form-' . $this->form['alias_id']][$matches[1]]; + } + + /** + * Замена тега поля при выводе формы + */ + function _parse_tag_fld_form ($matches) + { + $field_id = (int)$matches[1]; + + // забираем массив поля + $field = $this->form['fields'][$field_id]; + + // если поля нет, возвращаем тег обратно + if (empty($field)) + return $matches[0]; + + // если поле выключено, возвращаем пустую строку + if (empty($field['active'])) + return ''; + + $alias_id = $this->form['alias_id']; + + $fld_val = $this->form['is_submited'] + ? $this->_stripslashes($_POST['form-' . $alias_id][$field_id]) + : (in_array($field['type'],array('input','textarea')) + ? $this->_eval2var('?>' . $field['defaultval'] . 'form['fields'][$field_id]['is_used'] = true; + + $input = ''; + $return = ''; + + switch ($field['type']) + { + case 'input': + $input = ''; + break; + + case 'textarea': + $input = ''; + break; + + case 'select': + $input = ''; + break; + + case 'multiselect': + $input = ''; + break; + + case 'checkbox': + $input = ' + + '; + break; + + case 'file': + $input = ''; + break; + + case 'doc': + $input = ''; + break; + + case 'multidoc': + $input = ''; + break; + } + + // вставляем поле в шаблон поля + $return = trim($field['tpl']) > '' + ? str_replace('[tag:fld]',$input,$field['tpl']) + : $input; + + // парсим теги названия и id + $return = str_replace(array( + '[tag:id]', + '[tag:title]', + ), array( + $field['id'], + '[tag:title:' . $field_id . ']', + ), $return); + + // если попытка отправить форму, обрабатываем валидацию и пустоту + if ($this->form['is_submited']) + { + // валидация (только для капчи, input, textarea и file) + if ( + ($field['title'] == 'captcha' && $field['main'] && $this->form['is_captcha'] === true) || + (in_array($field['type'],array('input','textarea','file')) && !empty($field['setting'])) + ) + { + $valid = false; + // если капча + if ($field['title'] == 'captcha') $valid = (empty($_SESSION['captcha_keystring']) || empty($fld_val) || $_SESSION['captcha_keystring'] != $fld_val) ? false : true; + // если файл + elseif ($field['type'] == 'file') $valid = ($_FILES['form-' . $alias_id]['size'][$field_id] / 1024 / 1024) <= $field['setting']; + // если передали регулярку + elseif ($field['setting']{0} == '/') $valid = preg_match($field['setting'],$fld_val) === 1 ? true : false; + // если константу + elseif (defined($field['setting'])) $valid = filter_var($fld_val,constant($field['setting'])) !== false ? true : false; + // иначе, ничего не делаем + else return 'Неверные параметры валидации!'; + // парсим теги валидности + $this->_parse_tag_if($return,'if_valid',$valid); + $this->_parse_tag_if($return,'if_invalid',!$valid); + // записываем результаты + $this->form['ajax']['fields'][$field_id]['validate'] = true; + $this->form['ajax']['fields'][$field_id]['pattern'] = $field['setting']; + $this->form['ajax']['fields'][$field_id]['is_valid'] = $valid; + if (!$valid) + { + $this->form['is_valid'] = false; + $this->form['ajax']['form']['is_valid'] = false; + } + } + else + { + $this->form['ajax']['fields'][$field_id]['validate'] = false; + $this->form['ajax']['fields'][$field_id]['is_valid'] = null; + } + + // пустота (для любых обязательных полей) + if (! empty($field['required']) && $field['required']) + { + if ($field['type'] == 'file') + $empty = ( + empty($_FILES['form-' . $alias_id]['tmp_name'][$field_id]) || + !empty($_FILES['form-' . $alias_id]['error'][$field_id]) + ); + else + { + $clean_fld_val = $this->_cleanvar($fld_val); + $empty = empty($clean_fld_val); + } + // парсим теги + $this->_parse_tag_if($return,'if_empty',$empty); + $this->_parse_tag_if($return,'if_notempty',!$empty); + // записываем результаты + $this->form['ajax']['fields'][$field_id]['required'] = true; + $this->form['ajax']['fields'][$field_id]['is_empty'] = $empty; + if ($empty) + { + $this->form['is_valid'] = false; + $this->form['ajax']['form']['is_valid'] = false; + } + } + else + { + $this->form['ajax']['fields'][$field_id]['required'] = false; + $this->form['ajax']['fields'][$field_id]['is_empty'] = null; + } + } + // удаляем оставшиеся теги + $this->_parse_tag_if($return,'if_valid',false); + $this->_parse_tag_if($return,'if_invalid',false); + $this->_parse_tag_if($return,'if_empty',false); + $this->_parse_tag_if($return,'if_notempty',false); + + return $return; + } + + /** + * Замена тега поля в шаблоне письма + */ + function _parse_tag_fld_mail ($matches) + { + global $AVE_DB, $AVE_Template; + + $field_id = (int)$matches[1]; + // забираем массив поля + $field = $this->form['fields'][$field_id]; + // если поля нет, возвращаем тег обратно + if (empty($field)) return $matches[0]; + // если поля не было в шаблоне формы, убираем тег + if ($field['is_used'] !== true || empty($field['active'])) return ''; + // иначе, продолжаем + $alias_id = $this->form['alias_id']; + $val = $_POST['form-' . $alias_id][$field_id]; + $newval = ''; + $tag_mail_empty = ($this->form['mail_set']['format'] === 'text' ? '<' : '<') . $AVE_Template->get_config_vars('tag_mail_empty') . ($this->form['mail_set']['format'] === 'text' ? '>' : '>'); + + // делаем поправки для типов + switch ($field['type']) + { + case 'select': + $newval = $field['setting'][$val]; + if ($field['title'] == 'receivers') $newval = $newval['name']; + break; + + case 'multiselect': + foreach ($val as $val1) $newval .= $field['setting'][$val1] . ','; + $newval = rtrim($newval,','); + break; + + case 'checkbox': + $newval = ($val ? $AVE_Template->get_config_vars('yes') : $AVE_Template->get_config_vars('no')); + break; + + case 'doc': + if (!empty($val)) $newval = $AVE_DB->Query("SELECT document_title FROM " . PREFIX . "_documents WHERE Id='" . $val . "'")->GetCell(); + break; + + case 'multidoc': + if (!empty($val)) + { + $sql = $AVE_DB->Query("SELECT document_title FROM " . PREFIX . "_documents WHERE Id IN (" . implode(',',$val) . ")"); + while ($titl = $sql->GetCell()) $titls[] = $titl; + $newval = implode(', ',$titls); + } + break; + + case 'file': + $newval = implode(', ',$_FILES['form-' . $alias_id]['name']); + break; + + default: + $newval = $val; + } + return (empty($newval) ? $tag_mail_empty : $newval); + } + + /** + * Внешние методы класса + */ + + /** + * Вывод списка форм + */ + function forms_list () + { + global $AVE_DB, $AVE_Template; + $assign = array(); + + $limit = 20; + $start = get_current_page() * $limit - $limit; + $sql = $AVE_DB->Query(" + SELECT SQL_CALC_FOUND_ROWS + f.*, + SUM(IF(h.status='new',1,0)) AS history_new, + SUM(IF(h.status='viewed',1,0)) AS history_viewed, + SUM(IF(h.status='replied',1,0)) AS history_replied + FROM " . PREFIX . "_module_forms_forms AS f + LEFT OUTER JOIN " . PREFIX . "_module_forms_history AS h ON f.id = h.form_id + GROUP BY f.id + ORDER BY f.id ASC + LIMIT " . $start . "," . $limit . " + "); + $num = (int)$AVE_DB->Query("SELECT FOUND_ROWS()")->GetCell(); + $pages = @ceil($num / $limit); + if ($num > $limit) + { + $page_nav = '{t}'; + $page_nav = get_pagination($pages, 'page', $page_nav); + $AVE_Template->assign('page_nav', $page_nav); + } + + while ($row = $sql->FetchAssocArray()) + { + $assign['forms'][] = $row; + } + + $AVE_Template->assign($assign); + $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'forms.tpl')); + } + + /** + * Создание/редактирование формы + */ + function form_edit () + { + global $AVE_DB, $AVE_Template; + $form = array(); + $assign = array(); + $fid = $assign['fid'] = !empty($_REQUEST['fid']) ? (int)$_REQUEST['fid'] : 0; + + if ($fid) + { + $form = $this->_form($fid); + + // для правильного вывода селектов + if (empty($form['mail_set']['receivers'])) $form['mail_set']['receivers'] = array(0 => array()); + foreach ($form['fields'] as &$field) + { + if (($field['type'] == 'select' || $field['type'] == 'multiselect') && empty($field['setting'])) + { + $field['setting'] = array(0 => ''); + $field['setting_empty'] = true; + } + } + } + + // алерт при открытии правки + if (!empty($_SESSION['module_forms_admin'][$fid]['edit_alert'])) + { + $assign['alert']['text'] = $AVE_Template->get_config_vars($_SESSION['module_forms_admin'][$fid]['edit_alert']['text']); + $assign['alert']['theme'] = $_SESSION['module_forms_admin'][$fid]['edit_alert']['theme']; + unset($_SESSION['module_forms_admin'][$fid]['edit_alert']); + } + $assign['form'] = $form; + $assign['form_fields_tpl'] = $this->tpl_dir . 'form_fields.tpl'; + $assign['rubrics'] = $this->_rubrics(); + + // назначаем массив CodeMirror + $assign['codemirror'] = array( + 'rubheader' => 200, + 'from_name' => 60, + 'from_email' => 60, + 'subject_tpl' => 60, + 'form_tpl' => 460, + 'mail_tpl' => 460, + 'finish_tpl' => 320, + 'code_onsubmit' => 200, + 'code_onvalidate' => 200, + 'code_onsend' => 200, + 'code_beforesend' => 200 + ); + + $AVE_Template->assign($assign); + $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'form_edit.tpl')); + } + + /** + * Получение полей через аякс + */ + function form_fields_fetch () + { + global $AVE_DB, $AVE_Template; + $fid = $assign['fid'] = !empty($_REQUEST['fid']) ? (int)$_REQUEST['fid'] : 0; + if (!$fid) return; + $form = $this->_form($fid); + // для правильного вывода селектов + if (empty($form['mail_set']['receivers'])) $form['mail_set']['receivers'] = array(0 => array()); + foreach ($form['fields'] as &$field) + { + if (($field['type'] == 'select' || $field['type'] == 'multiselect') && empty($field['setting'])) + { + $field['setting'] = array(0 => ''); + $field['setting_empty'] = true; + } + } + $AVE_Template->assign('fields',$form['fields']); + $AVE_Template->assign('rubrics',$this->_rubrics()); + $AVE_Template->assign('field_tpl_open',$_REQUEST['field_tpl_open']); + + return $AVE_Template->fetch($this->tpl_dir . 'form_fields.tpl'); + } + + /** + * Сохранение формы + */ + function form_save ($fid) + { + global $AVE_DB; + + // проверяем Email-ы получателей + $receivers = array(); + foreach ($_REQUEST['mail_set']['receivers'] as $receiver) + { + if ($this->_email_validate($receiver['email'])) $receivers[] = $receiver; + } + $_REQUEST['mail_set']['receivers'] = $receivers; + // параметры отправителя + if (! trim($_REQUEST['mail_set']['from_email']) > '') $_REQUEST['mail_set']['from_email'] = get_settings('mail_from'); + if (! trim($_REQUEST['mail_set']['from_name']) > '') $_REQUEST['mail_set']['from_name'] = get_settings('mail_from_name'); + + if ($fid) + { + $AVE_DB->Query(" + UPDATE " . PREFIX . "_module_forms_forms + SET + title = '" . addslashes($_REQUEST['title']) . "', + protection = '" . (int)$_REQUEST['protection'] . "', + " . (($_REQUEST['alias'] === '' || $this->_alias_validate($_REQUEST['alias'],$fid) === true) ? " alias = '" . $_REQUEST['alias'] . "'," : '') . " + mail_set = '" . addslashes(serialize($_REQUEST['mail_set'])) . "', + rubheader = '" . addslashes($_REQUEST['rubheader']) . "', + form_tpl = '" . addslashes($_REQUEST['form_tpl']) . "', + mail_tpl = '" . addslashes($_REQUEST['mail_tpl']) . "', + finish_tpl = '" . addslashes($_REQUEST['finish_tpl']) . "', + code_onsubmit = '" . addslashes($_REQUEST['code_onsubmit']) . "', + code_onvalidate = '" . addslashes($_REQUEST['code_onvalidate']) . "', + code_onsend = '" . addslashes($_REQUEST['code_onsend']) . "', + code_beforesend = '" . addslashes($_REQUEST['code_beforesend']) . "' + WHERE + id = '" . $fid . "' + "); + } + else + { + $mail_set = array( + 'from_name' => get_settings('mail_from_name'), + 'from_email' => get_settings('mail_from'), + 'receivers' => array(0 => array( + 'name' => get_settings('mail_from_name'), + 'email' => get_settings('mail_from') + ), + ), + 'subject_tpl' => '[tag:formtitle]', + 'format' => 'text' + ); + $AVE_DB->Query(" + INSERT INTO " . PREFIX . "_module_forms_forms + SET + title = '" . addslashes($_REQUEST['title']) . "', + " . (($this->_alias_validate($_REQUEST['alias'],$fid) === true || $_REQUEST['alias'] === '') ? " alias = '" . $_REQUEST['alias'] . "'," : '') . " + mail_set = '" . addslashes(serialize($mail_set)) . "' + "); + $fid = (int)$AVE_DB->InsertId(); + $_REQUEST['fields'] = $this->fields_main_data; + // прописываем алерт об успешном создании + if ($fid > 0) $_SESSION['module_forms_admin'][$fid]['edit_alert'] = array('text' => 'created', 'theme' => 'accept'); + + // если устанавливаем пример + if (!empty($_REQUEST['demo'])) + { + $demo = array(); + include(BASE_DIR . '/modules/forms/demo.php'); + $_REQUEST = array_merge($_REQUEST,$demo); + // обновляем форму с данными примера + $this->form_save($fid); + // подставляем в шаблон новые id полей + $demo['form_tpl'] = preg_replace_callback('/\[tag:fld:(\d+)]/', create_function('$matches','return "[tag:fld:" . $_REQUEST["demo_change"][(int)$matches[1]] . "]";'),$demo['form_tpl']); + $AVE_DB->Query(" + UPDATE " . PREFIX . "_module_forms_forms + SET + form_tpl = '" . addslashes($demo['form_tpl']) . "' + WHERE id = '" . $fid . "' + "); + return $fid; + } + } + + // сохраняем поля + foreach ($_REQUEST['fields'] as $field_id => $field) + { + if (!trim($field['title'])) continue; + if (is_array($field['setting'])) + { + $settings = array(); + foreach ($field['setting'] as $setting) + { + // если получатели + if ($field['title'] == 'receivers' && is_array($setting) && trim($setting['name']) > '' && trim($setting['email']) > '' && $this->_email_validate($setting['email'])) + $settings[] = $setting; + // другое + elseif (!is_array($setting) && trim($setting) > '') + $settings[] = $setting; + } + $field['setting'] = serialize($settings); + } + elseif ($field['type'] == 'file') $field['setting'] = (int)$field['setting']; + + if (is_array($field['defaultval'])) $field['defaultval'] = serialize($field['defaultval']); + + $sql = " + title = '" . addslashes($field['title']) . "', + active = '" . (int)$field['active'] . "', + type = '" . $field['type'] . "', + setting = '" . addslashes($field['setting']) . "', + required = '" . (int)$field['required'] . "', + defaultval = '" . addslashes($field['defaultval']) . "', + attributes = '" . addslashes(trim($field['attributes'])) . "', + tpl = '" . addslashes($field['tpl']) . "' + "; + if ($field['new']) + { + $AVE_DB->Query(" + INSERT INTO " . PREFIX . "_module_forms_fields + SET + form_id = '" . (int)$fid . "', + main = '" . (int)$field['main'] . "', + " . $sql . " + "); + if ($_REQUEST['demo']) $_REQUEST['demo_change'][$field_id] = (int)$AVE_DB->InsertId(); + } + else + { + $AVE_DB->Query(" + UPDATE " . PREFIX . "_module_forms_fields + SET + " . $sql . " + WHERE + id = '" . (int)$field_id . "' AND + form_id = '" . $fid . "' + "); + } + } + foreach ($_REQUEST['field_del'] as $field_id => $delete) + { + if (empty($delete)) continue; + $AVE_DB->Query(" + DELETE FROM " . PREFIX . "_module_forms_fields + WHERE + id = '" . (int)$field_id . "' AND + main != '1' + "); + } + + return $fid; + } + + /** + * Удаление формы + */ + function form_del ($fid) + { + global $AVE_DB; + + $AVE_DB->Query(" + DELETE FROM " . PREFIX . "_module_forms_forms + WHERE id = '" . $fid . "' + "); + $AVE_DB->Query(" + DELETE FROM " . PREFIX . "_module_forms_fields + WHERE form_id = '" . $fid . "' + "); + } + + /** + * Сохранение формы + */ + function form_copy ($fid) + { + global $AVE_DB; + + // форма + $form = $AVE_DB->Query(" + SELECT * FROM " . PREFIX . "_module_forms_forms + WHERE id = '" . $fid . "' + ")->FetchAssocArray(); + if (empty($form)) return; + $query = "INSERT INTO " . PREFIX . "_module_forms_forms SET "; + foreach ($form as $key => $val) + { + if ($key == 'id' || $key == 'alias') continue; + $query .= $key . " = '" . addslashes($val) . "', "; + } + $query = rtrim($query,', '); + $AVE_DB->Query($query); + $fid_new = (int)$AVE_DB->InsertId(); + + // поля + $sql = $AVE_DB->Query(" + SELECT * FROM " . PREFIX . "_module_forms_fields + WHERE form_id = '" . $fid . "' + "); + while ($row = $sql->FetchAssocArray()) + { + if (empty($row['id'])) continue; + $query = "INSERT INTO " . PREFIX . "_module_forms_fields SET "; + foreach ($row as $key => $val) + { + if ($key == 'id') continue; + elseif ($key == 'form_id') $val = $fid_new; + $query .= $key . " = '" . addslashes($val) . "', "; + } + $query = rtrim($query,', '); + $AVE_DB->Query($query); + } + + return $fid_new; + } + + + /** + * Вывод формы + */ + function form_display ($alias_id) + { + global $AVE_Template; + + $form = $this->_form($alias_id); + + if (empty($form)) + return "[mod_forms:$alias_id] - " . $AVE_Template->get_config_vars('form_notfound'); + + // по дефолту форма валидна, но не отправлена - потом перезаписываем, если что + $this->form['is_valid'] = true; + $this->form['ajax']['form']['is_valid'] = true; + $this->form['ajax']['form']['is_sent'] = false; + $this->form['ajax']['form']['finish_tpl'] = null; + + // rubheader + $GLOBALS['user_header']['module_forms_' . $alias_id] = $this->_parse_tags($this->form['rubheader']); + + // вывод финишной страницы, если включена проверка от повторной отправки + if (! empty($_GET['mcnfinish']) && $form['protection']) + { + if ($_SESSION['mcnfinish'][$form['id'] . $_GET['mcnfinish']] === true) + { + unset($_SESSION['mcnfinish'][$form['id'] . $_GET['mcnfinish']]); + + // формируем финишную страницу + $tpl = $this->_parse_tags($form['finish_tpl']); + $tpl = $this->_eval2var('?>' . $tpl . 'form['is_submited'] = false; + + if (! empty($_POST['form-' . $alias_id])) + { + $this->form['is_submited'] = true; + // выполняем код после отправки формы + eval('?>' . $this->form['code_onsubmit'] . 'form['form_tpl']; + // меняем теги основных полей на стандартные + $tpl = $this->_parse_tag_fld_main($tpl,true); + // парсим теги полей и названий + $tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_form'), $tpl); + $tpl = preg_replace_callback('/\[tag:title:([A-Za-z0-9-_]+)]/', array($this,'_parse_tag_title'),$tpl); + + // выполняем код после валидации + eval('?>' . $this->form['code_onvalidate'] . 'form['is_submited'] === true && $this->form['is_valid'] === true) + return $this->form_submit($alias_id); + // иначе - заканчиваем вывод + else + { + // парсим основные теги + $tpl = $this->_parse_tags($tpl); + // теги общей валидности + if ($this->form['is_submited']) + { + $this->_parse_tag_if($tpl,'if_form_valid',$this->form['is_valid']); + $this->_parse_tag_if($tpl,'if_form_invalid',!$this->form['is_valid']); + } + else + { + $this->_parse_tag_if($tpl,'if_form_valid',false); + $this->_parse_tag_if($tpl,'if_form_invalid',false); + } + // заменяем теги условий + $tpl = preg_replace('/\[tag:(if|elseif)_fld:(\d*)(.*?)]/si','',$tpl); + $tpl = str_replace(array('[tag:else_fld]','[/tag:if_fld]'),array('',''),$tpl); + // выполняем код + return $this->_eval2var('?>' . $tpl . 'form; + + $fields = $form['fields']; + + $fid = $form['id']; + + // формируем список получателей + $recs = array(); + + // пользователь (отправка копии) + if ( + ($form['is_copy'] === true && $_POST['form-' . $alias_id][$form['fields_main']['copy']] == 1) || + $fields[$form['fields_main']['copy']]['defaultval'] == 1 + ) + { + $email = ''; + + if ($form['is_email'] === true) + $email = $_POST['form-' . $alias_id][$form['fields_main']['email']]; + + if (empty($email)) + $email = $_SESSION['user_email']; + + if (! empty($email)) + { + $recs[] = array( + 'email' => $email, + 'name' => $_SESSION['user_name'], + 'agent' => 'user', + ); + } + + $history['email'] = $email; + } + else // если чекбоксы - отправить копию неактивные + { + $email = ''; + + if ($form['is_email'] === true) + $email = $_POST['form-' . $alias_id][$form['fields_main']['email']]; + + if (empty($email)) + $email = $_SESSION['user_email']; + + $history['email'] = $email; + } + + // главные получатели + $recs = array_merge($recs, $form['mail_set']['receivers']); + + // выбранные в форме получатели + if ($this->form['is_receivers'] === true) + { + $recs_field_id = $form['fields_main']['receivers']; + $recs[] = $fields[$recs_field_id]['setting'][$_POST['form-' . $alias_id][$recs_field_id]]; + } + + // если ни один получатель не назначен, отправляем админскому + if (empty($recs)) $recs[] = array( + 'name' => get_settings('mail_from_name'), + 'email' => get_settings('mail_from') + ); + + // перезаписываем список уникальных получателей в переменную письма + $this->form['receivers'] = array(); + + foreach ($recs as $rec) + { + if (!isset($this->form['receivers'][$rec['email']]) && trim($rec['email']) > '') + $this->form['receivers'][trim($rec['email'])] = $rec; + } + + $recs = $this->form['receivers']; + $recs[] = array('agent' => 'history'); + + // обрабатываем тему по умолчанию + if (!$form['fields'][$form['fields_main']['subject']]['active'] || !$form['fields'][$form['fields_main']['subject']]['is_used']) + { + $_POST['form-' . $alias_id][$form['fields_main']['subject']] = $form['fields'][$form['fields_main']['subject']]['defaultval']; + } + + // обрабатываем шаблон письма + $tpl = $form['mail_tpl']; + + // меняем теги основных полей на стандартные + $tpl = $this->_parse_tag_fld_main($tpl); + + // парсим [tag:easymail] + if (strpos($tpl,'[tag:easymail]') !== false) + { + $easy = ''; + + foreach ($fields as $field_id => $field) + { + if ($field['is_used'] !== true || $field['title'] == 'captcha' || empty($field['active'])) + continue; + + $easy .= "[tag:title:$field_id]" . ": [tag:fld:$field_id];" . ($form['mail_set']['format'] === 'text' ? "\r\n" : '
'); + } + + // убираем последний перевод строки + $easy = ($form['mail_set']['format'] === 'text') ? rtrim($easy) : substr($easy,0,-4); + $tpl = str_replace('[tag:easymail]',$easy,$tpl); + } + + // парсим теги полей и названий + $tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_mail'),$tpl); + $tpl = preg_replace_callback('/\[tag:title:([A-Za-z0-9-_]+)]/', array($this,'_parse_tag_title'),$tpl); + + // парсим основные теги + $tpl = $this->_parse_tags($tpl); + + // заменяем теги условий + $tpl = preg_replace('/\[tag:(if|elseif)_fld:(\d*)(.*?)]/si','',$tpl); + $tpl = str_replace(array('[tag:else_fld]','[/tag:if_fld]'),array('',''),$tpl); + + // файлы-вложения + $attach = array(); + + if (! empty($_FILES['form-' . $alias_id]['tmp_name'])) + { + foreach ($_FILES['form-' . $alias_id]['name'] as $field_id => $fname) + { + $ext = (end(explode('.', $fname))); + + if ( + !empty($_FILES['form-' . $alias_id]['tmp_name'][$field_id]) && + !empty($form['fields'][$field_id]) && + empty($_FILES['form-' . $alias_id]['error'][$field_id]) && + !in_array($ext,array('php', 'phtml', 'php3', 'php4', 'php5', 'js', 'pl')) + ) + { + $fname = BASE_DIR . '/tmp/' . ATTACH_DIR . '/' . str_replace(' ', '_', mb_strtolower(trim($fname))); + + if (file_exists($fname)) + $fname = rtrim($fname,'.' . $ext) . '_' . mt_rand(0,10000) . '.' . $ext; + + @move_uploaded_file($_FILES['form-' . $alias_id]['tmp_name'][$field_id], $fname); + + $attach[] = $fname; + } + } + } + + // Имя отправителя + $from_name_tpl = $form['mail_set']['from_name']; + $from_name_tpl = $this->_parse_tags($from_name_tpl); + $from_name_tpl = $this->_parse_tag_fld_main($from_name_tpl); + $from_name_tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_post'),$from_name_tpl); + + // Email отправителя + $from_email_tpl = $form['mail_set']['from_email']; + $from_email_tpl = $this->_parse_tags($from_email_tpl); + $from_email_tpl = $this->_parse_tag_fld_main($from_email_tpl); + $from_email_tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_post'),$from_email_tpl); + + // Тема + $subject_tpl = $form['mail_set']['subject_tpl']; + $subject_tpl = $this->_parse_tags($subject_tpl); + $subject_tpl = $this->_parse_tag_fld_main($subject_tpl); + $subject_tpl = preg_replace_callback('/\[tag:fld:(\d+)]/', array($this,'_parse_tag_fld_post'),$subject_tpl); + + // выполняем код перед отправкой писем + eval(' ?>' . $this->form['code_beforesend'] . '_parse_tag_if($mail,'if_user',$if_user_open); + $this->_parse_tag_if($mail,'if_admin',$if_admin_open); + $this->_parse_tag_if($subject,'if_user',$if_user_open); + $this->_parse_tag_if($subject,'if_admin',$if_admin_open); + + // @fix для v1.0 beta <= 2: поддержка тега if_notuser + $this->_parse_tag_if($mail,'if_notuser',$if_admin_open); + $this->_parse_tag_if($subject,'if_notuser',$if_admin_open); + + $mail = trim($this->_eval2var(' ?>' . $mail . '_eval2var(' ?>' . $subject . 'Query(" + INSERT INTO " . PREFIX . "_module_forms_history + SET + form_id = '" . $fid . "', + email = '" . $history['email'] . "', + subject = '" . addslashes($subject) . "', + date = '" . time() . "', + dialog = '" . addslashes(serialize($history['dialog'])) . "', + postdata = '" . addslashes(serialize($_POST)) . "' + "); + + unset($history); + } + // иначе, отправляем письмо + else + { + $this->_parse_tag_if($from_name,'if_user',$if_user_open); + $this->_parse_tag_if($from_name,'if_admin',$if_admin_open); + $this->_parse_tag_if($from_email,'if_user',$if_user_open); + $this->_parse_tag_if($from_email,'if_admin',$if_admin_open); + + $from_name = $this->_eval2var('?>' . $from_name . '_eval2var('?>' . $from_email . '' . $this->form['code_onsend'] . '_parse_tags($form['finish_tpl']); + $tpl = $this->_eval2var(' ?>' . $tpl . 'form['ajax']['form']['is_sent'] = true; + $this->form['ajax']['form']['finish_tpl'] = $tpl; + + return $tpl; + } + } + + + /** + * Вывод истории + */ + function history_list ($fid) + { + global $AVE_DB, $AVE_Template; + $assign = array(); + $assign['fid'] = $fid; + $assign['form'] = $this->_form($fid,false); + + $limit = 50; + $start = get_current_page() * $limit - $limit; + $sql = $AVE_DB->Query(" + SELECT SQL_CALC_FOUND_ROWS * + FROM " . PREFIX . "_module_forms_history + WHERE form_id = '" . $fid . "' + ORDER BY date DESC + LIMIT " . $start . "," . $limit . " + "); + + $num = (int)$AVE_DB->Query("SELECT FOUND_ROWS()")->GetCell(); + $pages = @ceil($num / $limit); + + if ($num > $limit) + { + $page_nav = '{t}'; + $page_nav = get_pagination($pages, 'page', $page_nav); + $AVE_Template->assign('page_nav', $page_nav); + } + + while ($row = $sql->FetchAssocArray()) + { + unset($row['dialog']); + $assign['dialogs'][] = $row; + } + + $assign = $this->_stripslashes($assign); + $AVE_Template->assign($assign); + $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'history.tpl')); + } + + /** + * Удаление выбранного e-mail + */ + function email_del ($hid) + { + global $AVE_DB, $AVE_Template; + + $AVE_DB->Query(" + DELETE FROM " . PREFIX . "_module_forms_history + WHERE id = '" . $hid . "' + "); + } + + /** + * Сохранение статуса диалога + */ + function dialog_status ($hid) + { + global $AVE_DB; + + if ($_REQUEST['status'] !== 'new') + { + $AVE_DB->Query(" + UPDATE " . PREFIX . "_module_forms_history + SET + status = '" . $_REQUEST['status'] . "' + WHERE id = '" . $hid . "' + "); + } + + if (empty($_REQUEST['ajax'])) + { + header('Location: index.php?do=modules&action=modedit&mod=forms&moduleaction=history_list&fid=' . $_REQUEST['fid'] . '&cp=' . SESSION); + exit; + } + } + + /** + * Вывод диалога + */ + function history_dialog ($hid) + { + global $AVE_DB, $AVE_Template; + $assign = array(); + + $assign['hid'] = $hid; + $history = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_forms_history + WHERE id = '" . $hid . "' + ")->FetchAssocArray(); + + $history['dialog'] = unserialize($history['dialog']); + $history = $this->_stripslashes($history); + $assign['fid'] = $history['form_id']; + $assign['form'] = $this->_form($history['form_id'],false); + + // меняем статус на прочитанное + if ($history['status'] === 'new') + { + $AVE_DB->Query(" + UPDATE " . PREFIX . "_module_forms_history + SET + status = 'viewed' + WHERE id = '" . $hid . "' + "); + } + + // обращение + $request_author = $AVE_DB->Query(" + SELECT Id AS user_id, user_name, firstname, lastname + FROM " . PREFIX . "_users + WHERE email = '" . $history['email'] . "' + ")->FetchAssocArray(); + + if (!empty($request_author)) + $history['dialog']['request'] = array_merge($history['dialog']['request'], $request_author); + + // ответы + foreach ($history['dialog']['response'] as &$response) + { + $response_author = $AVE_DB->Query(" + SELECT user_name, firstname, lastname + FROM " . PREFIX . "_users + WHERE Id = '" . $response['user_id'] . "' + ")->FetchAssocArray(); + + if (!empty($response_author)) + $response = array_merge($response, $response_author); + } + + // форма ответа + if (empty($history['dialog']['response_draft'])) + { + $history['dialog']['response_draft'] = array( + 'from_email' => get_settings('mail_from'), + 'from_name' => get_settings('mail_from_name'), + 'body' => "\r\n\r\n\r\n--\r\n" . get_settings('mail_signature'), + ); + } + + // алерт при открытии $fid -> $hid + if (!empty($_SESSION['module_forms_admin'][$hid]['dialog_alert'])) + { + $assign['alert']['text'] = $AVE_Template->get_config_vars($_SESSION['module_forms_admin'][$hid]['dialog_alert']['text']); + $assign['alert']['theme'] = $_SESSION['module_forms_admin'][$hid]['dialog_alert']['theme']; + unset($_SESSION['module_forms_admin'][$hid]['dialog_alert']); + } + + $AVE_Template->assign($assign); + $AVE_Template->assign($history); + $AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'dialog.tpl')); + } + + /** + * Сохранение и отправка ответа + */ + function history_dialog_submit ($hid) + { + global $AVE_DB; + + $history = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_forms_history + WHERE id = '" . $hid . "' + ")->FetchAssocArray(); + $history['dialog'] = unserialize($history['dialog']); + + if ($_REQUEST['send']) + { + $response = $_POST; + $response['user_id'] = UID; + $response['date'] = time(); + $history['dialog']['response'][] = $response; + $history['status'] = 'replied'; + unset($history['dialog']['response_draft']); + send_mail( + $history['email'], + $_POST['body'], + $_POST['subject'], + $_POST['from_email'], + $_POST['from_name'], + $_POST['format'], + array(), + false,false + ); + } + else + { + $history['dialog']['response_draft'] = $_POST; + } + + $AVE_DB->Query(" + UPDATE " . PREFIX . "_module_forms_history + SET + dialog = '" . addslashes(serialize($history['dialog'])) . "', + status = '" . $history['status'] . "' + WHERE id = '" . $hid . "' + "); + + if ($_REQUEST['send']) + { + // прописываем алерт об успешной отправке письма $fid -> $hid + $_SESSION['module_forms_admin'][$hid]['dialog_alert'] = array('text' => 'respose_sent', 'theme' => 'accept'); + + header('Location: index.php?do=modules&action=modedit&mod=forms&moduleaction=history_dialog&hid=' . $hid . '&cp=' . SESSION); + exit; + } + } + } +?> \ No newline at end of file diff --git a/contactsnew/demo/demo.php b/forms/demo.php similarity index 91% rename from contactsnew/demo/demo.php rename to forms/demo.php index 06a9105..0b9d875 100644 --- a/contactsnew/demo/demo.php +++ b/forms/demo.php @@ -42,8 +42,7 @@ $form_tpl = array( [/tag:hide]', 'ajax' => '[tag:hide:2:У вас нет прав для заполнения данной формы!] -
-
+
Если форма не работает, убедитесь, что скрипт jquery.form.min.js подключен к странице @@ -72,20 +71,22 @@ $form_tpl = array(
-
[/tag:hide]', 'ajax_o' => '[tag:hide:2:У вас нет прав для заполнения данной формы!] @@ -135,11 +135,11 @@ $form_tpl = array( - - \ No newline at end of file + \ No newline at end of file diff --git a/contactsnew/templates/forms.tpl b/forms/templates/forms.tpl old mode 100755 new mode 100644 similarity index 67% rename from contactsnew/templates/forms.tpl rename to forms/templates/forms.tpl index d1697fd..df5df4c --- a/contactsnew/templates/forms.tpl +++ b/forms/templates/forms.tpl @@ -13,7 +13,6 @@
  • {#mod_info#}
  • {#cn_mod_info#}{#cn_mod_info_a#}
  • -
  • {if $smarty.const.GOOGLE_PUBLIC_RECAPTCHA3_KEY && $smarty.const.GOOGLE_PRIVATE_RECAPTCHA3_KEY}{#found_key_recap_v3#}{else}{#notfound_key_recap_v3_1#}{#notfound_key_recap_v3_2#}{#notfound_key_recap_v3_3#}{/if}
@@ -22,7 +21,7 @@ @@ -31,7 +30,7 @@
{#forms#}
@@ -61,28 +60,28 @@ - + - + {foreachelse} diff --git a/contactsnew/templates/history.tpl b/forms/templates/history.tpl similarity index 82% rename from contactsnew/templates/history.tpl rename to forms/templates/history.tpl index 2b190d4..83d2c35 100644 --- a/contactsnew/templates/history.tpl +++ b/forms/templates/history.tpl @@ -24,9 +24,9 @@ $smarty['stat_viewed'] = '{#stat_viewed#}'; @@ -35,7 +35,7 @@ $smarty['stat_viewed'] = '{#stat_viewed#}';
{$form.id} - {$form.title|stripslashes|escape} + {$form.title|stripslashes|escape} {if $form.history_new > 0}{#list_new#}: {$form.history_new}{else}{#list_new#}: {$form.history_new}{/if}{if $form.history_new > 0}{#list_new#}: {$form.history_new}{else}{#list_new#}: {$form.history_new}{/if} {#list_viewed#}: {$form.history_viewed} {#list_replied#}: {$form.history_replied}{#cn_view#}{#cn_view#}
- +
- + - + - +
@@ -62,7 +62,7 @@ $smarty['stat_viewed'] = '{#stat_viewed#}'; {$dialog.date|date_format:$TIME_FORMAT|pretty_date} {foreachelse} @@ -109,7 +109,7 @@ function status_change (sel) { var td = sel.parents('td'); var hid = sel.attr('data-hid'); $.ajax({ - url: 'index.php?do=modules&action=modedit&mod=contactsnew&moduleaction=dialog_status', + url: 'index.php?do=modules&action=modedit&mod=forms&moduleaction=dialog_status', type: 'POST', data: { hid: hid, diff --git a/contactsnew/index.php b/forms/templates/index.php similarity index 100% rename from contactsnew/index.php rename to forms/templates/index.php
- {$dialog.subject|stripslashes|escape} + {$dialog.subject|stripslashes|escape} {$dialog.email} @@ -78,7 +78,7 @@ $smarty['stat_viewed'] = '{#stat_viewed#}'; {/if} - +