Артур

Артур

С нами с 24 мая 2019; Место в рейтинге пользователей: #35

Проверка доступности стороннего сайта для запроса по api

Сниппет называется isSiteAvailible, написал его не я, автора не помню, но говорят штука полезная, чтобы твой сайт работал, даже если чужой, куда ты шлешь запросы, лежит.
<?php
if(!$url){return false;}
// Проверка правильности URL
if(!filter_var($url, FILTER_VALIDATE_URL)){
    return false;
}

// Инициализация cURL
$curlInit = curl_init($url);

// Установка параметров запроса
curl_setopt($curlInit,CURLOPT_CONNECTTIMEOUT,1);
curl_setopt($curlInit,CURLOPT_HEADER,true);
curl_setopt($curlInit,CURLOPT_NOBODY,true);
curl_setopt($curlInit,CURLOPT_RETURNTRANSFER,true);

// Получение ответа
$response = curl_exec($curlInit);

// закрываем CURL
curl_close($curlInit);

return $response ? true : false;
Вопрос в том нужно ли это делать и если да, но насколько верен предложенный способ?
Артур
09 апреля 2021, 23:31
modx.pro
184
-2

[СДЕЛАЙ САМ] DaData. Определение города по ip

Сниппет называется detectRegion. Для работы необходимо зарегистрироваться на сайте DaData и создать системную настройку для ключа api с названием dadata_api_key
<?php
$url = 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/iplocate/address';
$siteIsAvaliable = $modx->runSnippet('isSiteAvailible', array('url' => $url));
if($siteIsAvaliable){
    $token = $modx->getOption('dadata_api_key');
    $ip = $_SERVER['REMOTE_ADDR'];
    $headers = array(
    	'Accept: application/json',
    	'Authorization: Token ' . $token
    );
    $ch = curl_init($url.'?ip='.$ip);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HEADER, false);
    $result = json_decode(curl_exec($ch),1);
    curl_close($ch);
    $region = $result['location']['data']['city'];
    return  $region;
}else{
    $modx->log(1, 'detectRegion: Не возможно определить регион. Сервис DaData недоступен');
    return false;
}
P.S. isSiteAvailible
Артур
09 апреля 2021, 23:28
modx.pro
1
132
+3

[СДЕЛАЙ САМ] Контексты для регионов в интернет-магазине.

Задача: сделать максимально простое добавление новых контекстов на сайт для создания региональных копий с собственными ресурсами, robots.txt и sitemap.xml, уникальными для каждого региона ресурсами и ценами на некоторые товарные позиции.

Проблемы:
1. Вывод галереи изображений товаров
2. Добавление дополнительных категорий к товарам в новом контексте.
3. Связывание товаров.

Решение:
1. Настраиваем редирект со всех поддоменов на основной домен (как это сделать уточняйте у хостера или в Google);
2. Подключаем плагин для переключения контекстов:
<?php
// Работаем только на фронтенде
if ($modx->event->name != 'OnHandleRequest' || $modx->context->key == 'mgr') {return;}

// Определяем запрашиваемый хост
$host = $_SERVER['HTTP_HOST'];
$ctx = $modx->getObject('modContextSetting', array('key' => 'http_host', 'value' => $host)); 

if($ctx->get('context_key') != 'web'){
    $modx->switchContext($ctx->get('context_key'));
}

Логика такая: определяем по url какой контекст запросили, если это не основной контекст (web), то переключаем контекст на запрошенный, в противном случае смотрим есть ли в $_COOKIE город, если нет, то устанавливаем $_COOKIE['curCity'], проверяем есть ли в списке контекстов запрошенный, если есть, то переключаем, если нет остаемся на основном контексте. На фронте этим управляет вот такой код
let btns = document.querySelectorAll('.jsChooseBtn'), // это кнопки подтверждения ДА и НЕТ
        tooltip = document.querySelector('.jsCityTooltip'); // это само окно с вопросом "ЭТО ВАШ ГОРОД"
    for(let i = 0; i < btns.length; i++){
        btns[i].addEventListener('click', function(e){
            tooltip.classList.add('d-none');
            if(e.target.classList.contains('jsCityConfirm')){ // если нажали да
               document.cookie = 'curCity='+ e.target.dataset.city + '; path=/;domain=ecodecking.ru'; 
            }
        });
    }
    if(document.cookie.indexOf('curCity') != -1){ // проверяем есть ли город в куках
        tooltip.classList.add('d-none'); 
    }


2.1 если кому интересно город я определяю через сайт DaData.Код сниппета detectRegion тут.
<?php
$url = 'https://suggestions.dadata.ru/suggestions/api/4_1/rs/iplocate/address';
$siteIsAvaliable = $modx->runSnippet('isSiteAvailible', array('url' => $url));
if($siteIsAvaliable){
    $token = $modx->getOption('dadata_api_key');
    $ip = $_SERVER['REMOTE_ADDR'];
    $headers = array(
    	'Accept: application/json',
    	'Authorization: Token ' . $token
    );
    $ch = curl_init($url.'?ip='.$ip);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HEADER, false);
    $result = json_decode(curl_exec($ch),1);
    curl_close($ch);
    $region = $result['location']['data']['city'];
    return  $region;
}else{
    $modx->log(1, 'detectRegion: Не возможно определить регион. Сервис DaData недоступен');
    return false;
}

3. Подключаем плагин для создания настроек контекста, при копировании или создании нового.
Артур
07 апреля 2021, 19:51
modx.pro
2
185
+3

[СДЕЛАЙ САМ] mFilter2 фильтрация по диапазону дат.

Приветствую, к сожалению не нашёл приемлемого для себя решения данной задачи поэтому «написал» своё, в кавычках потому что немного подправил. На мой взгляд очевидно, что дата это число, а в mFilter2 есть фильтрация по диапазону чисел, значит нужно превратить дату в число. Чтобы при обновлении компонента ничего не сломалось, создадим свой класс фильтрации customfilter.class.php в папке core/components/msearch2/custom/filters/, потом прописываем в системную настройку mse2_filters_handler_class = CustomFiltersHandler
Артур
29 марта 2021, 00:14
modx.pro
7
280
+8

mspReceiptAccount как добавить свой шаблон и автоматически отправить письмо при смене статуса

Тут написано, что это за зверь.

Я напишу как создать свой шаблон.

Может показаться, что для этого достаточно зайти в меню компонента и создать там новый элемент. Однако уже там видно что требуется указать класс-обработчик, поскольку под мои задачи подходил стандартный я его просто скопировал и положил рядом со стандартными в папку core/components/mspreceiptaccount/model/payments/. И казалось бы все, но нет.

Если посмотреть в логи, там будет написано что не найден какой-то класс и будет написано его название. Так сходу непонятно что это за класс и где он должен быть, но я разгадал эту загадку))). Копируем название класса, которое есть в логах и создаем вот такой файл
core/components/mspreceiptaccount/custom/item/receiptaccountact.class.php
, я туда скопировал код из соседнего класса
core/components/mspreceiptaccount/custom/item/receiptaccountsh.class.php
.

Всё, теперь можно создавать свой шаблон, например для акта выполненных работ.
Артур
03 марта 2021, 16:36
modx.pro
2
247
+3

[УПУЩЕННОЕ] Настраиваем расчёт скидки в minishop2 версии 2.7.0 и выше

Приветствую, как-то так случилось, что я упустил вот этот релиз, и тут понадобилось мне сделать возможность устанавливать скидку на каждый товар, начал я писать плагин и увидел в объекте корзине два ранее не встречавшихся ключа discount_price и discount_cost, связался с @Иван Бочкарев, он меня и просветил, что расчёт скидки уже внедрён, надо только указать старую цену и всё посчитается. Это круто, но зачастую удобнее указать скидку в % от цены или просто числом, поэтому я написал небольшой плагин, который при сохранении товара рассчитывает новую цену, а старую записывает в поле old_price, если же скидка равна 0 или не указана и поле old_price заполнено, то его содержимое переносится в price, а old_price обнуляем. Уверен, что многие сами могут такой плагин написать, но кому-то возможно захочется сэкономить 5 минут, код под катом.
Артур
05 февраля 2021, 23:51
modx.pro
3
372
+3

Уведомления в реальном времени

Приветствую, появилась мысль разобраться в websocket и с чем их едят, а главное как готовить))) Начал гуглить и наткнулся на статью про некий фреймворк Workerman, в статье говорилось, что с его помощью можно легко развернуть сервер для websocket на modx, и, таким образом, получить независимые уведомления в реальном времени. Минус в том, что подробных инструкций как это сделать конкретно для этого фреймворка я не нашёл. Собственно решил написать сюда, кто что знает по теме уведомлений, поделитесь информацией, пожалуйста. Объясните почему до сих пор никто не написал компонент для этого, точнее компоненты есть, но они используют сторонние сервисы типа comet-серверов и т.д. Мне непонятно почему данный функционал нельзя реализовать независимо на своём сайте? Это очень сложно? Это никому не нужно? Это будет слишком сильно нагружать сервер? В общем расскажите кто что может.
Спасибо.
Артур
02 февраля 2021, 09:01
modx.pro
113
+1

[СДЕЛАЙ САМ] Мультилендинг с помощью MIGX

Для начала постараюсь описать результат того, что получится в итоге. Это будет некий примитивный конструктор страниц, т.е. дизайн должен быть сделан так, чтобы можно было без ущерба для внешнего вида менять местами блоки. Сами блоки или секции имеют постоянную структуру, что позволит сделать их контент редактируемым.
Дальше будет много букав, я предупредил.
Итак, поехали!
Артур
28 января 2021, 18:18
modx.pro
4
616
+9

[РЕШЕНО] Вопрос для академиков

Сразу оговорюсь, никакого сарказма, на мой взгляд задача действительно должна быть известна тем кто получил академическое образование по специальности программирование. Собственно задача.
Дан массив
[246 => 1, 267 =>2, 296 => 3, 308 => 4, 309 => 5]
Его ключи это id ресурсов, а значения отвечают за их сортировку, пусть будет menuidex. Нужно, чтобы при изменении значения например с ключом 308 с 4 на 2 получился массив
[246 => 1, 267 => 3, 296 => 4, 308 => 2, 309 => 5].
Я написал такое рашение
<?php
switch ($modx->event->name) {
    case 'OnDocFormSave':
        $resource->set('publishedon', time());
        $resource->save();
        if($resource->get('class_key') == 'Ticket'){
            $curPosition = $resource->getTVValue('position');
            $positions = [];
            if($resource->get('parent') == 73){
                $resources = $modx->getIterator('modResource', array('class_key' => 'Ticket', 'id:!=' => $id, 'parent' => 73));
            }
            else{
                $resources = $modx->getIterator('modResource', array('class_key' => 'Ticket', 'id:!=' => $id, 'parent:!=' => 73));
            }
            foreach($resources as $res){
                $pos = $res->getTVValue('position');
                if($pos){
                    $positions[$res->get('id')] = $pos;
                }
            }
            
            if(in_array($curPosition,$positions)){
                asort($positions);
                foreach($positions as $id => $pos){
                    if($pos >= $curPosition){
                        $modx->log(1, print_r($curPosition,1));
                        $modx->log(1, print_r($pos,1));
                        $res = $modx->getObject('modResource', $id);
                        $res->setTVValue('position', $pos + 1);
                        $res->save();
                        $curPosition = $pos + 1;
                    }
                }
            }
            //$modx->log(1, print_r($positions,1));
        }
    break;
}
Но кажется мне, что в нём что-то не так, но вот что именно не могу понять.
Артур
28 января 2021, 09:42
modx.pro
183
+1

[РЕШЕНО] Не могу получить ресурс

Всем привет, есть вот такой код
<?php
$result = $modx->runSnippet('FormIt', $scriptProperties);
foreach($modx->placeholders as $key => $ph){
    if(strpos($key, $scriptProperties[placeholderPrefix].'error.') === 0){
        $placeholders[$key] = $ph;
    } 
}

if (!count($placeholders)) {
    $loginResponse = $modx->runProcessor('/security/login', $_POST);
    if(!$loginResponse->response['success']){
        $placeholders['auth.error.msg'] = '<span class="error">'.$loginResponse->response['message'].'</span>';
        return  $AjaxForm->error($loginResponse->response['message'], array('error' => $loginResponse->response['message']));
    }else{
        $resource = $modx->getObject('modResource', $scriptProperties['loginResourceId']);
        $context = $resource->get('context_key');
        return $AjaxForm->success('Вы успешно авторизованы', array(
                'url' => $modx->makeUrl($scriptProperties['loginResourceId'], $context, '', 'full' )
            ));
    }
    
}else{
    return  $AjaxForm->error('В форме содержатся ошибки', array('error' => $placeholders));
}

//$modx->log(1, print_r($loginResponse->response,1));
Его написал я. на одном сайте он работает отлично, на другом, куда я его просто скопировал он не работает. В частности не срабатывает
$resource = $modx->getObject('modResource', $scriptProperties['loginResourceId']);
При этом $scriptProperties['loginResourceId'], если выводить в лог содержит 18 и это id ресурса который существует. Если этот код скопировать в Console и поменять $scriptProperties['loginResourceId'] на 18 проблем нет.
У кого есть идеи что не так?
Артур
26 января 2021, 00:04
modx.pro
147
0