Артем

Артем

Был в сети 23 марта 2022, 14:24
Заказы не принимаю
Василий Наумкин
Василий Наумкин
Другой вариант, который уже больше подходит для концепции REST — отсылаем все запросы как и договаривались на адрес по маске /api/**/*
MODX предсказуемо выдаст событие onPageNotFound — ну а дальше как завещал @Василий Наумкин выстраиваем плагин маршрутизации — и делаем что захотим.
Это если решать все вопросы одним MODX. Да и тогда лучше использовать OnHandleRequest.

А так, лично я давно всё отправляю через Nginx:
location ~ ^/api/ {
    rewrite ^/api/(.*)$ /api.php?q=$1;
}
И там уже любые маршруты с контроллерами.
Василий Наумкин
Василий Наумкин
У меня все письма перед отправкой проходят через pelago/emogrifier — так что на расхождений в отображении почти нет.

Грузим свой почтовый класс раньше всех:
$modx->getService('mail', 'extraMail', 'path/to/class');

А в классе extraMail добавляем свою обработку:
<?php
if (!class_exists('modPHPMailer')) {
    /** @noinspection PhpIncludeInspection */
    require MODX_CORE_PATH . 'model/modx/mail/modphpmailer.class.php';
}

class extraMail extends modPHPMailer
{
    /** @var PHPMailer $mailer */
    public $mailer;
    
    /**
     * @param string $key
     * @param mixed $value
     */
    public function set($key, $value)
    {
        if ($key == modMail::MAIL_BODY) {
            $emogrifier = new \Pelago\Emogrifier($value);
            $value = $emogrifier->emogrify();
            $this->set(modMail::MAIL_BODY_TEXT, $this->mailer->html2text(nl2br($value)));
        }
        parent::set($key, $value);
    }
Василий Наумкин
Василий Наумкин
500 000 страниц сайта — это нормально. А вот 500 000 ресурсов — совершенно нет, MODX к такому не готов.

Разница в том, что ресурсы нужны для разделов сайта, служебных страниц и всего такого. Если же сайт продаёт полмиллиона товаров или содержит объявления — нужно это выносить в отдельные таблицы, с нужными колонками и индексами.

Например,
вот я делал vrmedia.tv. Ресурсов в дереве там меньше 50, а фоторепортажей и картинок многие тысячи. Всё летает, лайкается, добавляется в избранное — и хранится в отдельных таблицах.

В таком направлении и нужно двигаться, используя MODX как удобную обёртку для своих данных.
Константин Ильин
Константин Ильин
Чтож, уже ноябрь, но лучше поздно чем никогда)

Спасибо Сергей Шлокову, он на пальцах мне обьяснил что так как я хотел сделать выше — нельзя.
Последовательность такая:
1. Нажимается кнопка.
2. В функции кнопки вызывается ajax запрос к процессору который выдает поля.
3. Только когда ajax выполнился вызывается окно. В вызов окна сразу подсовываются готовые поля, сформированные из ответа ajax.

Код функции процессора — process ()
public function process()
    {
        /*некий код*/
	$fields = '';
        // Существует какая то некая таблица в которой 1 строка это поле
        $table = $this->modx->getTableName('FieldsItems');
        $query = $this->modx->query("SELECT * FROM ".$table." WHERE active = 1");
	
        if (!is_object($query)) {
           
           return $this->failure($this->modx->lexicon('fl_data_err_get_field'));

        }else{

           $arr = $query->fetchAll(PDO::FETCH_ASSOC);

           foreach ($arr as $value) {

               $fields[] = array(
                    'xtype' => 'textarea',
                    'fieldLabel' => $value['name'],
                    'name' => "fl-".$value['code'],
                    'id' => 'ext-gen-fl-'.$value['code'],
                    'anchor' => "99%",
                    'allowBlank' => "false",
                    'value' => $fieldsValues[$value['code']] 
                );
           }

        }
        return $this->success('',$fields); // Возвращаем массив полей
    }

Как это в EXT.JS. Тут два запроса ajax, первый получает поля, второй к процессору get который выдает данные об объекте.
MODx.Ajax.request({
            url: Fl.config.connectorUrl
            ,params: {
                action: "mgr/data/get_fields", // Тот самый процессор который выдает поля
                id_res: MODx.request.id,
            }
            ,listeners: {
                success: {fn: function(res) {
                    
                    var fieldsArr = res['object']; // Ответ от процессора с полями, он возвращает массив с данными полей
                    fieldsArr = fieldsArr || {}; 
                    MODx.Ajax.request({
                        url: this.config.url,
                        params: {
                            action: 'mgr/data/get',
                            id: MODx.request.id,
                        },
                        listeners: {
                            success: {
                                fn: function ( r ) { 
                                   
                                    var w = MODx.load({
                                        xtype: 'fl-data-window-update',
                                        id: Ext.id(),
                                        addFields: fieldsArr, // Здесь передаем поля в вызов окна
                                        record: r,
                                        listeners: {
                                            success: {
                                                fn: function () {
                                                    this.refresh();
                                                }, scope: this
                                            },
                                            hide: {
                                                fn: function () {
                                                    setTimeout(function(){w.destroy();},200);
                                                }, scope: this
                                            }
                                        }
                                    });
                                    w.reset();
                                    w.setValues(r.object);
                                    w.show(e.target);
                                }, scope: this
                            }
                        }
                    });
                }, scope: this}
            }
        });

В extende окна:
Ext.extend(Fl.window.UpdateItem, MODx.Window, {

    getFields: function (config) {
        return [{
            xtype: 'hidden',
            name: 'id',
            id: config.id + '-id',
            value: config.id
        },{
            xtype: 'xcheckbox',
            boxLabel: _('fl_lang_active'),
            name: 'active',
            id: config.id + '-active',
            checked: true,
        },
            config.addFields   // ВОТ ТУТ И ДОБАВЛЯЮТСЯ ПОЛЯ, т.е. тот массив полей который передали в ajax запросе
        ];
    },

    loadDropZones: function () {
    }

});
Ext.reg('fl-data-window-update', Fl.window.UpdateItem);
Как то так, наверняка посмотрев через год на этот код будет такая мысль:
«Под чем я был кода писал этот код»
Василий Наумкин
Василий Наумкин
Потому, что автор этих дополнений использует 2 разных события для одной цели, вместо того, чтобы использовать верное событие в обоих плагинах — msOnGetProductPrice.

Если что, у событий плагинов есть приоритет и одно событие можно использовать хоть в 100 плагинах, тогда изменение цены пройдёт по цепочке от низшего приоритета к высшему.
Василий Наумкин
Василий Наумкин
Ну тогда rewrite должен решить все твои проблемы.
location ~* ^/en/assets/images/ {
    rewrite	^/en/assets/images/(.*)    /assets/images/$1 permanent;
}

Кстати, можно сделать еще круче — без редиректа, а просто подставляя нужную директорию, вот так:
location ~* ^/en/assets/images/(.*) {
    alias /полный_путь_к_файлам_от_корня_сервера/assets/images/$1;
}
Василий Наумкин
Василий Наумкин
Лично я закрываю служебные директории через веб-сервер на случай обнаружения новой уязвимости в MODX.

Например, как это было, когда движок некорректно обрабатывал запросы в несуществующий контекст в коннекторах. Там еще одна PHP авторизация не помогла бы, так как хакер получал доступ к API через обычные GET запросы к определённому файлу.

Именно поэтому я закрываю для доступа снаружи и админку, и коннекторы, и ядро. Причём, не через потенциально уязвимый движок, а средствами гораздо менее потенциально уязвимого Nginx.
location ~* ^/(core|manager|connectors)/ {
    auth_basic "Restricted Access";
    auth_basic_user_file /home/site/.htpasswd;
    try_files               $uri $uri/ @rewrite;
    location ~ \.php$ {
            include         fastcgi_params;
            fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass    backend-site;
    }
}

А зачем нужна вот эта инструкция — большой вопрос.
Fi1osof
Fi1osof
Если ключ не хотите светить, то однозначно запрос надо слать с вашего сервера на донора. В MODX есть готовый CURL-клиент. Вот код для примера:
$client = $modx->getService('rest.modRestCurlClient');
$result = $client->request('https://ya.ru', '/', 'POST', $params = array('foo'  => 'foo'));
print $result;
Можете с этим кодом к консоли поиграться.