Артур Шевченко

Артур Шевченко

С нами с 24 мая 2019; Место в рейтинге пользователей: #7
Отправить деньги
Артур Шевченко
09 марта 2022, 23:44
0
В общем, по п.2 переписал, только логику немного изменил. Поскольку я научил класса, который на сервере, генерировать уникальный селектор, класс в JS теперь всегда работает с одной конкретной формой, поэтому я в конструкторе сделал так
this.form = document.querySelector(selector);

        if (!this.form) {
            console.error('Form not found. Check the correctness of the selector.');
            return false;
        }
Если нет формы, то нет смысла и дальше что-то делать. Тут вылез ещё один интересный момент, уже в сниппите. Там есть вот такой кусок кода
// Add selector to tag form
if (preg_match('#<form.*?class=(?:"|\')(.*?)(?:"|\')#i', $content, $matches)) {
    $classes = explode(' ', $matches[1]);
    if (!in_array($formSelector, $classes)) {
        $classes[] = $formSelector;
        $classes = preg_replace(
            '#class=(?:"|\')' . $matches[1] . '(?:"|\')#i',
            'class="' . implode(' ', $classes) . '"',
            $matches[0]
        );
        $content = str_ireplace($matches[0], $classes, $content);
    }
} else {
    $content = str_ireplace('<form', '<form class="' . $formSelector . '"', $content);
}
По-моему, он устарел, проще прямо в чанк передавать весь конфиг и устанавливать селектор так {$formSelector} или так [[+formSelector]]. Хотя с другой стороны, ну есть и есть, да?

И ещё в оригинальном сниппите сделано вот так
<?php
/** @var array $scriptProperties */
/** @var AjaxForm $AjaxForm */
if (!$modx->loadClass('ajaxform', MODX_CORE_PATH . 'components/ajaxform/model/ajaxform/', false, true)) {
    return false;
}
$AjaxForm = new AjaxForm($modx, $scriptProperties);

$snippet = $modx->getOption('snippet', $scriptProperties, 'FormIt', true);
$tpl = $modx->getOption('form', $scriptProperties, 'tpl.AjaxForm.example', true);
$formSelector = $modx->getOption('formSelector', $scriptProperties, 'ajax_form', true);
$objectName = $modx->getOption('objectName', $scriptProperties, 'AjaxForm', true);
Мне кажется это нелогично, ведь создавая экземпляр класса, мы мерджим дефолтный конфиг и $scriptProperties, т.е. на мой взгляд, в getOption нужно писать так
$snippet = $modx->getOption('snippet', $config, 'FormIt', true);
$tpl = $modx->getOption('form', $config, 'tpl.AjaxForm.example', true);
$formSelector = $modx->getOption('formSelector', $config, 'ajax_form', true);
$objectName = $modx->getOption('objectName', $config, 'AjaxForm', true);
Или я чего-то не понимаю?
Артур Шевченко
09 марта 2022, 15:32
0
Без разницы где велась разработка. Нужно проверять пути и права на файлы и папки.
Артур Шевченко
09 марта 2022, 14:39
0
В путях. Правда непонятно как получилось запороть пути к конкретному компоненту. При переносе случайно ядро не перемещали на уровень выше? Ещё можно права на папки проверить.
Артур Шевченко
09 марта 2022, 13:15
0
Пара советов, если позволишь:
Не просто позволю, а ещё и благодарен буду)))

и далее в коде методов ты не будешь париться и обращаться к конфигу так:
Ну вообще запись станет длиннее this.config.someprop против this.someprop, но я доверюсь твоему опыту.

Обычно принято в мире js передавать селектор первым аргументом, а вторым конфиг плагина
Тут отдельная проблема. В конструктор надо передавать уникальный селектор, потому что в противном случае если на странице больше 1 вызова AjaxForm обработчики навешиваются столько раз сколько вызывается сниппет, а это плохо по понятным причинам. И передавать селектор в каждом вызове мне кажется неудобным. Я думаю надо установить селектор по умолчанию и дополнять его меткой времени и тоже самое делать с переданным селектором, чтобы на 100% исключить вероятность дублирования или есть варианты решения получше?

3. У тебя на 20-ой строке есть странность if (this.beforeSubmit(e.target)) { и судя по коду твой метод beforeSubmit всегда возвращает true, тогда я понятия не имею зачем тут проверка.
Это у меня он возвращает true, а если кто-то захочет свою логику, например не отправлять пока не прочитают политику работы с персональными данными?

Ну и можно по стандартам пройтись :|
Я самоучка, это не оправдание, но что значит пройтись по стандартам не понимаю.

И есть ещё один момент — уведомления
if (AjaxForm.Message != 'undefined') {
    AjaxForm.Message.close();
}
Это я оставил для обратной совместимости, но это объект, мне кажется правильнее было бы сделать показ сообщения методом или методами класса, но как туда впихнуть код выше? Тут предлагали сделать как @Николай Савин в minishop2, но у него это тоже объект. Может уведомления сделать отдельным классом? Добавить из коробки уведомления не требующие jQuery, только вот надо же ещё дать возможность подключать произвольные уведомления, но как это лучше сделать?
Артур Шевченко
08 марта 2022, 23:02
+3
Вот мой код к которому обращается cron
<?php
$snippet = $argv[1] ?: $_GET['snippet'];
$allowSnippets = array('modstoreParser', 'updatePrice', 'bussinessCenterParser'); // массив разрешённых сниппетов, нужно потому что скрипт доступен с фронта и принимает get-параметры.
if(in_array($snippet, $allowSnippets)){
    require_once 'document/root/path/public_html/config.core.php'; // заменить на свой путь до корня сайта
    require_once MODX_CORE_PATH.'model/modx/modx.class.php';
    $modx = new modX();
    $modx->initialize('web');
    $modx->getService('error','error.modError', '', '');
    echo $modx->runSnippet($snippet);
}
Как создавать задачи для cron можно загуглить поискать в Яндексе.
А как должен выглядеть сниппет, я могу только предполагать. Учитывая, что есть «текстовые цены», наверное нужно будет использовать регулярные выражения. Если в самом простом варианте, без регулярок и модификаций, только основная цена товара, то примерно так
<?php
$coefficient = $modx->getOption('coefficient'); // получаем системную настройку, которую предварительно создали
if($coefficient){
    $products = $modx->getIterator('msProductData'); // получаем все товары  
    foreach($products as $product){
        $oldPrice =  $product->get('price');
        $product->set('price', $price*$coefficient);
        $product->save();
    }
}
Артур Шевченко
08 марта 2022, 21:29
+1
Самый простой способ, наверно, где-то в админке сделать коэффициент и чтобы все существующие цены на него умножались.
Да. И добавь к этому задание в планировщике и сниппет который будет цены менять.
Артур Шевченко
08 марта 2022, 13:01
0
Тогда как альтернативу могу предложить написать плагин на это событие и в нём обрабатывать тэги.
Артур Шевченко
08 марта 2022, 12:13
0
Я в написании правил для.htaccess не очень силён, но чтобы получить url вида vyvod-tegov/?tag=$1 редирект писать необязательно, можно сразу написать
<a href="[[~145]]?tag=[[+alias]]">[[+tag]]</a>
Артур Шевченко
07 марта 2022, 20:43
0
Вынес в отдельный метод. Ошибку самого запроса выносить не стал, потому как пользователь всё равно повлиять не её исправление не может.
Артур Шевченко
07 марта 2022, 16:37
0
Я не знаю, но я точно знаю, что завести компонент с Fetch у меня не получилось, а разбираться в причинах не охота.
Артур Шевченко
07 марта 2022, 16:07
0
1. Логику из конструктора хорошо бы вынести в отдельный метод.
Переписал конструктор.
Артур Шевченко
07 марта 2022, 16:04
0
3. Я бы заменил XHR на fetch.
Может быть когда-нибудь потом)))
Артур Шевченко
07 марта 2022, 15:35
0
2. Старайся использовать const вместо let
А это зачем?
Артур Шевченко
07 марта 2022, 15:31
0
4. А разве не должно быть метода error для работы с ошибками?
Может быть и должен быть, но в оригинальном скрипте не было, вроде бы. Расскажи подробнее, что должен делать метод, я постараюсь его написать.
Артур Шевченко
07 марта 2022, 15:00
+1
Наконец-то дошли руки. Переписал. Если будет минутка — посмотри в репозитории код.
Артур Шевченко
05 марта 2022, 22:22
0
Очень легко: нужно под каждую комбинацию опций создать отдельное правило SEO. Под две опции, нужно 3 правила
1. {$option1}
2. {$option2}
3. {$option1}/{$option2}
Для трех опций нужно 7 правил
1. {$option1}
2. {$option2}
3. {$option3}
4. {$option1}/{$option2}
5. {$option1}/{$option2}/{$option3}
6. {$option1}/{$option3}
7. {$option2}/{$option3}
И так далее
Артур Шевченко
05 марта 2022, 09:48
+1
Непосредственно html-тэги нельзя отправить, но можно сделать так
<htm>
    <body>
        <form>
            <p>Some text</p>
            <input type="hidden" name="service">
        </form>  
        <script>
            let  form = document.querySelector('form');
            form.addEventListener('submit', function(e){
            e.preventDefault();
            let par = document.querySelector('p'),
                input = document.querySelector('input[name="service"]');
            input.value = par.innerText;
            });
        </script>
    </body>
</html>
Артур Шевченко
04 марта 2022, 14:11
+1
Можно под каждую таблицу создать отдельное ТВ или по три ТВ, но по-моему лучше обойтись одним MIGX.
Артур Шевченко
04 марта 2022, 14:10
0
ну так-то да, но есть один нюанс, если заказчик, а так бывает, захочет добавить ещё раздел на первом уровне или переименовать существующий, статически выведенное меню нужно будет менять вручную, поэтому я бы так не делал, просто из-за лени)))
Артур Шевченко
04 марта 2022, 14:07
0
А я не говорил про id страницы, у каждого пункта меню, т.к. это ресурс, есть id и при выводе меню вы проверяете равен ли id текущего пункта например 2, где 2 это id ресурса Товары, если равен, то вызываете pdoResources/pdoMenu/