Александр Мельник

Александр Мельник

С нами с 02 сентября 2016; Место в рейтинге пользователей: #64
Александр Мельник
20 июня 2022, 12:24
0
я имел ввиду, что использование collections или же «настройки форм» позволяет назначать создаваемым ресурсам корректные шаблоны. Тоесть если создает менеджер ресурс. Кликнула правой кнопкой мыши по Услуги и выбирает — создать ресурс, то при создании ему автоматически будет добавлен шаблон — Услуга. А мой плагин уже ориентируется на этот шаблон и понимает из какого вспомогательного ресурса (те что на скрине внутри 48) ему нужно забрать содержимое blocklist и скопировать его в создаваемый ресурс.
Александр Мельник
20 июня 2022, 07:37
0
У меня работает следующим образом.
Смотрим скриншот.

Есть тв поле blocklist которое содержит в себе перечень всех возможных на сайте блоков. Под блоком я понимаю — название, указание на чанк в котором вьюшка и прочая инфа.
В ресурсе «Настройки (2)» перед началом работы с сайтом я заполняю это поле, причем заполняю максимально, тоесть все все блоки которые есть на данный момент.
Чтобы менеджеру было проще, а система в целом была гибче, есть еще группа ресурсов, на скрине это ресурсы в родителе «Настройка шаблонов (48)». Эти ресурсы уже отвечают за какой-то определенный тип страниц. Здесь я тоже перед началом работы создаю все все блоки, НО ненужные деактивирую, сортирую блоки, так чтобы они соответствовали макету этой страницы. Ну к примеру если это услуга, то я деактивирую все, кроме блоков
— хлебные крошки
— h1
— баннер
— текстовое поле
— форма заказа
— ссылка назад
Что происходит далее. Я через инструмент «Настройка форм» и через компонент «Collections» стараюсь максимально автоматизировать правильное применение шаблонов, когда менеджер создает новый ресурс.
И вот уже при создании нового ресурса срабатывает плагин, который просто наполняет этот новый ресурс блоками (заполняет тв поле blocklist). Если плагин видит, что создается ресурс с шаблоном 8 (к примеру это услуги) то он скопирует этот список с ресурса 56, где уже настроены блоки для услуг. Если не можем понять, какую именно страницу создает менеджер, то будет скопирован список блоков со страницы «Настройки», тоесть полный список и менеджер сам потом деактивирвует ненужное, расставит блоки в нужной очередности.
В итоге получается, что менеджер может:
— быстро создать страницу с уже заранее продуманными блоками под нее
— после создания изменить страницу как угодно, ведь скопировались абсолютно все блоки, просто они деактивированы. Ничто не мешает конкретно эту страницы «услуги» сделать совершенно другой и активировать на ней блок «слайдер» и блок «дополнительная форма обратной связи».
— изменить в какой-то момент настройки (перечень активных блоков) для тех же услуг (если смотреть на скрин то изменить блоки в ресурсе 53) и все создаваемые после этого страницы тоже изменятся.
Сам плагин очень примитивен.
<?php
switch ($modx->event->name) { 
    case 'OnDocFormSave':
        $template = $resource->get('template');
        switch ($template) {
            case '3': // продукция
                $example = 49;
                break;
            case '8': // услуги
                $example = 53;
                break;
            case '7': //новость
                $example = 56;
                break;
                      
            case '9': // типовые решения
                $example = 55;
                break;
                
            case '4': // инфо страница
                $example = 57;
                break;
                 
            case '19': // акции
                $example = 62;
                break;
            case '21': // реализованные проекты
                $example = 54;
                break;
            default:
            $example = 2;
                break;
        }

        if ( $resource->get('id')!=2 and $mode == 'new') {
           
            $where = array(
                'contentid' => $example
              , 'tmplvarid' => 3
            );
        $tv = $modx->getObject('modTemplateVarResource', $where);
        $value=  $tv->get('value');
           
            $resource->setTVValue('blockList', $value);
        }
        
    break;
}
Александр Мельник
18 июня 2022, 19:22
+1
спасибо, что находите время и силы на улучшения. Это круто и заслуживает уважения.
Александр Мельник
17 июня 2022, 08:05
+2
Я опять немного пофилософствую. Мне кажется, что у компонентов, которые представлены на modx.pro есть одна практически общая проблема. И проблема эта звучит так — по описанию компонента практически невозможно догадаться для чего он и какую задачу можно с его помощью решить.

Я прекрасно понимаю почему это происходит. Когда разработчик сделал что то новое и готов им поделиться, он «живет это разработкой», он работал над ней несколько дней (недель, месяцев) и ему кажется, что в ней и так все понятно. Вот ему же все понятно и логично, значит и другим будет понятно тоже. Но это не так.

Программист по сути тот же писатель, результатом нашей работы тоже является текст. И грамотность, продуманность, иерархичность должны присутствовать не только в коде, но и в наших мыслях, в наших текстах.

Может я один такой глупый, но прочитав 5 раз описание customExtra я так и не понял что он делает. И может это именно то, что я бы хотел, но из-за сжатых, странных формулировок в описании я пройду мимо и не куплю, просто потому что не пойму зачем этот компонент.

modstore.pro/packages/utilities/customextra
Под самым название компонента видим — Дополнительная табличка в админке MODX. Уже честно говоря сбивает с толку, потому что не понятное слово «табличка» еще и в уменьшительно ласкательном варианте. Это про таблицы в базе данных? Это про таблицы генерируемые extjs? Что за «табличка..»
Ниже по тексту читаем
Компонент позволяет гибко кастомизировать табличку и формы создания / редактирования объектов из админки.
Снова ступор. Ведь выше написано, что это для создания дополнительных (тоесть новых ) табличек, а это предложение говорит «кастомизировать» (то есть изменить существующую.)
И ниже идут скриншоты, простите но очень невнятные, на которых предлагается создать какой- то предмет. Что за предмет, не известно.

В итоге, дочитав описание до конца, я все еще остаюсь в состоянии полного непонимания, что же конкретно делает и какие задачи этот компонент решает.

А насколько было бы интуитивно понятнее, если бы автор пусть и в текстовом виде, привел пример какой то решаемой задачи.

По крайней мере для моего мозга справедливо все то, что я описал) Возможно другие люди прекрасно понимают такие вот краткие и сумбурные описания.
Александр Мельник
15 июня 2022, 07:11
+2
Можно я поразмышляю вслух? Это не вопрос к автору поста и речь не о конкретно minishop, а просто так — подискутировать с утра.
Что заставляет нас устанавливать обновления?
Мифическая вера в то, что каждая свежая версия программного обеспечения «лучше» предыдущей?
Но так ли это на самом деле? Справедливо ли это для любого программного обеспечения? Как оценить плюсы и минусы обновления? Что правильнее?
1) каждый раз все обновлять и тем самым сильно увеличивать риск возникновения сбоев в своем продукте (ведь по сути если наш код зависит от чьих-то сторонних компонентов, то мы обязаны просто «верить», что разработчик выпуская новую версию исправил в ней больше багов чем добавил).
2) Или же единожды собрав стабильную систему (пусть и из сторонних компонентов) и тестами и временем убедившись, что именно эти версии компонентов хорошо работают в связке друг с другом, оставить систему в таком стабильном состоянии и ничего не обновлять? Ведь «лучшее это враг хорошего», как говорит народная мудрость и попытке улучшить то что и так работает хорошо, скорее всего приведет к тому, что все станет работать плохо.

А теперь просто о моем личном опыте, хотя это совершенно не показатель что такой подход правильный.
Начну с операционной системы. Я на всех своих устройствах пользуюсь линуксом на базе debian. Это и сервера и мои копмьютеры. Эти дистрибутивы разрабатываются очень крутой компанией canonical, новые версии выходят каждые 6 месяцев. И даже при условии, что разработкой занимаются профи, есди скачать релиз в день его выхода — он будет полон глюков. У людей 6 месяцев на доработку и тесты, люди профи и все равно в релизе много багов. Только через пару месяцев его уже можно скачать и кайфовать.
Если говорить про modx. Из многих десятков сайтов, которые у нас есть, 80 процентов работает на modx 2.65 и прекрасно выполняет свои функции. Да, разрабатывая новый сайт, я беру самые последние версии компонентов. Но сделав один раз продукт, который показывает свою стабильность и полностью устраивает и меня и заказчика — я не вижу смысла что то в нем менять. Каждый раз, когда я пытаюсь что то обновить, возникают те или иные проблемы. И хорошо если этот баг сразу виден, например сайт полностью упал, но куда страшнее баги, которые не столь очевидны и вылазят спустя месяц после обновления. Да, я даже соглашусь, что такие баги при обновлении скорее всего говорят о моем невысоком уровне знаний (хотя исходники компонентов я никогда не правлю), но факт остается фактом, чем меньше я обновляю — тем стабильнее наши проекты. Такой вот парадокс.
Александр Мельник
12 июня 2022, 16:32
0
просите Дмитрий, но я уже даже не помню, чем закончилась эта задача. Три долгих года прошло.
Александр Мельник
09 июня 2022, 08:41
0
ваши страницы станут открываться в разы или десятки раз медленнее. Особенно если это какая то категория товаров и отображается 60 товаров и нужно в реальном времени «наложить» 60 водяных знаков. Обновили страницу — и все по новой, снова накладываем 60 водяных знаков.
Александр Мельник
31 мая 2022, 22:13
+1
Задача заключается в том, чтобы сделать так, чтобы при клике на корзинку в мобильной версии, выезжало это боковое меню сразу с развернутыми, добавленными товарами, а не пустым. Это ж не логично.
но зачем вы тогда используете подгрузку содержимого корзины по клику?
Я вижу несколько вариантов решения.
1) на странице не должно быть отдельно блоков для мобильного и отдельно для десктопа. [[HeaderDesktop]], [[HeaderMobile]] это плохая практика. Внешний вид должен адаптироваться под разные устройства за счет каскадных стилей и медиа запросов, а не за счет скрытия блоков для десктопа и отображения блоков для мобильных. В таком случае и корзина у вас всегда будет существовать на странице, потому что шапка остается всегда одной и той же.
2) Я вижу что у вас используется скорее всего какой то готовый шаблон интернет магазина, взятый с бескрайних просторов интернета, а значит переверстывать никто не будет. Тогда действительно придется иметь два разных чанка для шапки, в каждом полноценно вызывать [[!msMiniCart?&tpl=`miniCart`]], а не подгружать по клику, НО решать какой из чанков показать вам нужно еще на уровне обработки запроса на сервере. Помоему для modx даже была какой-то сниппет типа MobileDetect или как то так, который позволяет определить с какого устройства пришел запрос.
Александр Мельник
29 мая 2022, 07:38
+1
Юрий, вы всегда можете посмотреть, что содержит в себе та или иная переменная в феном, распечатав ее при помощи модификатора print {$delivery|print}
Наверняка там содержится и поле id и вы можете сделать как написал выше Артур.
Синтаксис шаблонизатора феном можно посмотреть тут github.com/fenom-template/fenom/tree/master/docs/ru
Александр Мельник
29 мая 2022, 07:26
0
Вы хотите чтобы ваш сниппет оперировал информацией, которую получает с формы.
Формы могут отправлять данные используя два метода http запросов — POST и GET
Следовательно вам нужно разместить на одной странице и форму и ваш сниппет.
Далее псевдо код, который не рассматривает вопросы безопасности.
<form method=post action=this page>
<input name=id>
<button>
</form>

[[snippet]]
if $_POST[id] {
sql = SELECT * FROM table WHERE id=$_POST[id]
get data by sql;
}
Александр Мельник
28 мая 2022, 15:13
0
Вам нужно просто поручить это сделать тому человеку, который разбирается.
Потому что даже подсказывать вам опасно, вы ведь сделаете по примеру и не подумаете о безопасности, о том, что давать возможность пользователю напрямую передавать данные из формы в sql запрос это очень опасно.
Александр Мельник
28 мая 2022, 10:43
0
по нескольким урлам надо открывать один и от же ресурс?
я лично уже запутался, о чем спрашивал автор статьи и на что мы ищем ответ.
Автор говорит
Ситуация — часть товаров выводятся в разных категориях.
насколько я понимаю, речь идет о том, что один товар minishop создан в одной категории, а в другие расставлен при помощи галочек. Но в таком случае, урл товара всегда одинаков ведь, разве нет? Не важно откуда мы на него перейдем, из основной категории или из виртуальной, урд товара будет один и тот же.
Александр Мельник
20 мая 2022, 10:56
0
Я хочу создать простой отчет с фильтром в менеджере
Что это значит? Вы хотите внутри человека менеджера запихнуть фильтр и бумажный отчет? Это жестоко.
Но если без иронии, то тоже не понятно. Что в вашем понимании «отчет». Отчет чего или кого. Причем тут фильтр?

А ответ Артура следует понимать так — создать что либо в админ панели довольно сложно, вам нужно как минимум хорошо знать сам modx и фреймворк extjs который отвечает за отрисовку интерфейса. Поэтому гораздо проще создать в админке просто ресурс, но снять галочку — опубликован. Внутри этого ресурса, вставляйте какие угодно самописные (или нет) сниппеты, которые создадут нужную вам логику. Такую страницу можно открыть по урлу как любую другую, но изза того, что она неопубликована, видите ее только вы, предварительно авторизовавшись в админке.
Александр Мельник
17 мая 2022, 16:07
+1
мне кажется, раз вы предварительно уточняли у разработчика компонента seofilter и купили его — вам нужно ему и писать в техподдержку.
уверен, что тот код который у вас приведен выше, вам не пригодится больше для вывода товаров.
ну и в целом, фильтровать что то у вас будет или невозможно или очень сложно.
Ваши значения заполняются вручную, в одном поле храниться как величина (10) так и единица измерения (кг), менеджер может в одном месте написать 3.4, а в другом 3,4 и так далее.
Мой совет — переделайте сайт используя минишоп и избавьтесь от характеристик на migx/
Это будет быстрее и правильнее.
Александр Мельник
16 мая 2022, 08:50
0
время ответа сервера не идеально, но не критично.
Я использую такую блочную систему только если руководство требует ручного управления блоками на странице. Это нужно далеко не везде, чаще всего макеты страниц статичны.
Александр Мельник
15 мая 2022, 12:51
0
внутрь чанка пробрасывается информация о блоке. чтобы уже внутри чанка можно было разобраться, откуда грузить данные.
Александр Мельник
15 мая 2022, 12:49
0
<?php
$fqn = $modx->getOption('pdoFetch.class', null, 'pdotools.pdofetch', true);
$path = $modx->getOption('pdofetch_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;
}


$blockList = $modx->resource->getTVValue("blockList");
$blockList = json_decode($blockList ,true);

$html = "";
foreach ($blockList as $key => $block){
    if (empty($block['chunkName']) or $block['isActive'] != 'Да')
        continue;

    $chunk = '@FILE blocks/'.$block['chunkName'];

    $html .= $pdoFetch->getChunk($chunk, $block);
}

return $html;
примерно так.
Александр Мельник
15 мая 2022, 12:05
+2
Опишу вкратце, как организовывал подобный функционал я, может кому то будет интересно.
Кода не будет, будут только общие концепции.
1) Есть конфигурация migx которая содержит
— название блока. Это для того чтобы менеджеру было сразу понятно, о чем этот блок. Никакой другой цели не несет.
— скриншот. Хранит скриншот того, как этот блок выглядит на странице. Тоже чтобы менеджеру было удобно.
— заголовок блока. Это текст, который может быть в блоке а может и нет. Например на одной странице нам нужно вывести иконки и написать вверху над ними — наши преимущества. А где то нужно обойтись только иконками.
— чекбокс Активен блок или нет.
— название чанка, хранящего верстку блока.
— описание. Для удобства менеджера, если управление блоком не очевидно и требует каких то комментариев.
— откуда брать данные для блока. Выпадающий список с такими вариантами. — брать с текущей страницы — брать с общих настроек. Детальнее что это опишу ниже.
2) На основании этой конфигурации создаем ТВ поле блок. Привязываем к нужным нам шаблонам.
3) Для удобства менеджера облегчим ему жизнь. Создадим несколько служебных ресурсов. Назовем их
— общие настройки
— категория товара
-товар
— инфостраница
Называем примерно так, чтобы была визуальна видна связь с шаблонам. Зачем нужны эти ресурсы. Они будут являться образцами. К примеру мы идем в служебный ресурс Товар и создаем там блоки (имеются ввиду ТВ поля типа migx).
Настраиваем их, располагаем в нужном нам порядке, так как хотим чтобы выглядела страница товара.
4) При создании любого ресурса срабатывает наш плагин (важно. именно при создании нового а не при обновлении) который понимает какой именно ресурс хотят создать (анализируя шаблон или анализируя родителя, внутри которого его хотят создать). К примеру плагин понял что хотят создать товар. Он идет в служебный ресурс товар и копирует оттуда все блоки, которые заранее настроил менеджер. Если плагину не удалось точно понять, какой ресурс хотят создать, он скопирует блоки с служебного ресурса — общие настройки.
5) мы сохранили новый ресурс и он уже заполнен блоками в нужном нам порядке. Но если менеджер хочет что то изменить, он может редактировать блоки уже принадлежащие этому ресурсу. Сделать эту страницу чем то отличающуюся от стандартного шаблона.
6) как это все работает и почему блоки отображаются на странице. А шаблонах не содержится верстки, кроме основного скелета html. На странице вызывается самописный сниппет buildpage задача которого получить значение migx tv с блоками на этой странице, получить инфу активен ли блок (нужно ли его вообще отображать на странице) и если активен — вызвать нужный чанк (имя которого тоже лежит в блоке). Очередность блоков задается менеджером путем перетаскивания строк в админке.
7) последнее время чанки, которые формируют внешний вид блока начал делать по типу компонентов vue. Имеется ввиду лишь идея, в чанке прописан как блок со стилями, так и html так и javascript относящийся к блоку. Соответственно если блок не активен, то нет и лишних стилей и скриптов.
8) осталось рассказать только об одном — о данных. Сами блоки — это лишь внешний вид, им нужно откуда то брать данные, причем эти данные могут быть разными для блока, в зависимости от того на какой странице он вызван. Данные для блоков храню так же в migx tv полях. Возьму для примера тот же блок — наши преимущества (не знаю как у вас но наши сеошники аж трясутся над этим блоком и пихают его чуть ли не по 10 штук на страницу). Так вот. Создаю конфигурацию migx задача которой хранить изображения. Создаю ТВ поле — блок наши преимущества, которые построен на этой конфигурации. Это ТВ поле есть как у служебных ресурсов, так и у реальных ресурсов, создаваемых менеджером. Настройка в блоке, с именем «Откуда брать данные» как раз и отвечает за это. Менеджер может заполнить один раз данные для блока преимущества (загрузить иконки, возможно написать текст) в служебном ресурсе Общие настройки. Активируя блок «наши преимущества» на любой странице сайта менеджер просто выбирает — брать данные из общих настроек. Если нужно для этой страницы задать индивидуальные данные, то нужно всего лишь перезаполнить соответствующее ТВ поле уже этого ресурса и выставить у блока — «брать данные с этой страницы».
В общем то и все.
Александр Мельник
14 мая 2022, 08:49
0
а вот еще хотелось бы мне подискутировать на затронутую мной же тему jwt токенов.
Кто скажет, почему payload не шифруется а лишь кодируется? В чем сокральный смысл использовать base64, который очень просто раскодировать и узнать данные?
Как я понимаю жизненный цикл access токена:
— сервер авторизации и сервер, на котором мы хотим обратиться знают один и тот же ключ, при помощи которого создана сигнатура в токене.
— мы при каждом запросе мы передаем этот токен на сервер. Сервер (в каком то midleware ну или как там разработчик сделает) берет payload и кодирует тем же ключем. И сравнивает сигнатуру которую он получил с той, что пришла в токене.
— если сигнатуры совпали это говорит о том, что запрос пришел от того, кто обращался на наш сервис авторизации и смог получить токен.
— НО мы ничего еще не знаем о самом клиенте. Кто именно делает запрос. А если у нас есть деление на какие то роли и не каждый кто просто получил токен имеет пользоваться всем. Или же мы ведем логирование запросов и нам нужен хотя бы id пользователя. Тоесть как ни крути, там же на этапе аутентификации нужно раскодировать payload и получить исходные данные, чтобы получить например объект с перечислением ролей и определить, допустима ли тому, кто отправил запрос, операция удаления пользователей.
— тоесть сам факт проверки сигнатуры не дает еще полной картины, раскодировать payload прийдется каждый раз.
— и в такой схеме действительно возникает проблема. Если токен украли, то пока он «жив» вор может пользоваться им и нанести вред.

Теперь собственно моя идея.
— раз нам все равно на каждый запрос нужно раскодировать payload токена, то почему не включить в него информацию, которая позволит решить проблему с угоном токена. Что-то что будет служить дополнительной защитой.
— к примеру ip адрес того, кто обратился на сервер авторизации и получил токен. Добавим ip в payload и на этапе аутентификации на своем сервере, сравниваем, а тот ip что пришел в токене и реальный ip который мы получаем из самого запроса — совпадают ли?
— так же в случае если мы говорим про применение jwt не для общения с api, а для использования в браузере, в токен можно добавить user-agent, который даст информацию о том, с какой операционной системы и с какого браузера был получен токен. И есть еще масса уникальной информации, которую можно получить и использовать для идентификации того или иного устройства.
— что это нам дает. Решение классической проблемы — угнали токен и до конца его жизни могут пользоваться. Теперь даже в случае угона токена, он не будет принят на сервере, на который мы стучимся, потому что точно не пройдет проверку ip и скорее всего не пройдет проверку user-agent.
— нельзя конечно полностью утверждать, что это 100 процентная защита от угона токена, вернее от возможности его использование вором, но это уже сильно усложнит жизнь вору. Насколько я знаю, подделать ip с которого отправляешь свой запрос на какой то конкретный (а чтобы токен прошел валидацию нужен именно конкретный), не так уж и просто. Но предположим что супер хакеры умеют.
— и мы возвращаемся к моему вопросу — почему payload просто кодируют, а не шифруют? Тот кто украл токен имеет прямой доступ к информации, пусть даже и не знает ключа шифрования, при помощи которого была создана сигнатура. В моей схеме, вор получив токен сразу же использует его чтобы получить доступ к нашему сервису. Не выходит, банально потому что его ip не совпадает с тем с которого он совершает запрос.
— если payload только закодирован base64 вор получает с него данные и видит, что в данных содержится и ip. И начинает как то решать эту проблему и искать способ подделать свой ip на этот конкретный. Если время жизни токена невелико то и времени для поиска решения не много. Но ведь можно не дать ему и этого шанса. Не будем кодировать, будем шифровать payload. Мы уже используем один ключ, который создает сигнатуру. Можем использовать его или завести еще один. Чистые данные шифруем при помощи ключа. получаем payload. payload шифруем при помощи ключа — получаем сигнатуру. Складываем их вместе, получаем довольно безопасный токен.
— теперь даже если украсть токен, то «тупое» его использование ничего не даст и дело не во времени его жизни, а в несовпадении данных из токена с реальными данными запроса. И посмотреть что лежит в payload хакер тоже не может, данные не закодированы, а зашифрованы и не имея ключа их не расшифровать.

Такой подход, как мне кажется, даже позволит завести в свой системе авторизации пару приятных плюшек:
— автопродление токена. Поскольку у нас теперь токен содержит дополнительные уровни защиты, то в зависимости от уровня безопасности всего проекта, можно облегчить жизнь нашим пользователем. Если токен пришел на сервер и в нем все идеально, кроме времени жизни (он уже протух), можно не отправлять пользователя на повторную авторизацию руками, а самим сделать запрос на наш сервис авторизации, передать туда данные из payload и получить новый токен. Никто ведь из людей не любит очень часто вводить пароль. Но это для проектов, чей уровень безопасности не высок.
— можно вести статистику успешных и неуспешных использований токена и на основании ее изменять время жизни токена для конкретного пользователя. Если видим, что присылается токен с зашитым внутрь одним ip а запрос приходит с другого ip, то в следующий раз этому клиенты выдадим токен не на 30 минут, а на 5 минут.