MODX_API_MODE и процессоры

В рамках выполнения одной хитрой задачи, потребовалось написать скрипт, который будет запускаться по cron и что-то делать с MODX.

Проблемы, в общем то нет, вопрос изучен, но выплыл интересный глюк.
А именно: не работали процессоры для создания/обновления ресурсов.

То есть, процессор для логина — нормально, контекст mgr — нормально, а при попытке создать ресурс — просто пустая error.
Выложил вопрос на официальном форуме и никто мне не ответил. Пришлось разбираться самостоятельно, глубоко копая исходники.

И вот, что выяснилось: при запуске MODX из консоли, в режиме MODX_API_MODE, переменная $modx->error->message является массивом, тогда как должна быть строкой. Через это процессор при проверке ошибок, в ходе создания ресурсов, считает, что есть сообщение об ошибке — и выводит его мне. А я ничего не могу понять, ибо там пусто.

Таким образом, вот верный способ работы в MODX_API_MODE:
<?php
// Подключаем
define('MODX_API_MODE', true);
require dirname(dirname(__FILE__)).'/index.php';

// Включаем обработку ошибок
$modx->getService('error','error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_FATAL);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$modx->error->message = null; // Обнуляем переменную

// Логинимся в админку
$response = $modx->runProcessor('security/login', array('username' => 'admin', 'password' => '123456'));
if ($response->isError()) {
    $modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
    return;
}
$modx->initialize('mgr');

// Создаем ресурс
$response = $modx->runProcessor('resource/create', array(
    'pagetitle' => 'Имяресурса'
    ,'parent' => 1
    ,'content' => 'Текстресурса'
    ,'template' => 1
    ,'isfolder' => 1
    ,'published' => 1
));
if ($response->isError()) {
    $modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
    return;
}
else {
    print_r($response->response);
}
Вот теперь можно делать что хотите с MODX, из своих скриптов от лица авторизованного админа.
Василий Наумкин
08 сентября 2012, 04:23
modx.pro
26
10 817
0

Комментарии: 26

Иван Брежнев
08 сентября 2012, 12:24
0
Отличное решение, я давно пытался переделать ваш скрипт import_export.php на процессоры и столкнулся с той же проблемой, но не разобравшись бросил эту затею.
    kochurkov
    10 сентября 2012, 16:25
    0
    Нет слов, один сплошной восторг!
      Роман Харин
      12 сентября 2012, 13:34
      0
      Вот где «собака зарыта»!!!
        Антон ХайЭксель
        21 ноября 2012, 00:13
        0
        Вообщем снова я. помучался с процессорами. Добавление товаров в minishop получилось только под админом.
        как ни мучался с правами user — НОЛЬ.

        попробовал описанным методом, но тогда теряется авторизация пользователя…
        как сохранить её?
          Василий Наумкин
          21 ноября 2012, 04:47
          0
          Этот метод вообще придуман для запуска из консоли, по расписанию через cron.

          А чтобы юзер смог добавлять товары, ему надо назначить кучу прав, типа «edit_document»,«publish_document» и т.д.
          Я так даже не заморачивался ни разу.
            Антон ХайЭксель
            21 ноября 2012, 08:27
            0
            Пробовал давать user права вплоть до администраторских (обе группы имели одинаковые настройки) — под админом создается, под user — нет =(
          Rimas Kudelis
          26 февраля 2014, 14:02
          0
          Делаю вроде всё по инструкций:
          $response = $modx->runProcessor('security/login', array('username' => $username, 'password' => $password, 'login_context' => 'mgr'));
          if ($response->isError()) {
          	$modx->log(modX::LOG_LEVEL_ERROR, 'Could not log in, will exit now: '.$response->getMessage());
          	exit;
          }
          $user_data = $modx->user->toArray();
          if ($user_data['id'] == 0) {
          	$modx->log(modX::LOG_LEVEL_ERROR, 'Failed to log in, will exit now: '.$response->getMessage());
          	exit;		
          }
          Первый блок срабатывает, второй – нет. Включив дебаг, при попытке авторизации выводится вот что:

          There was an error retrieving or creating session id: jkrdurgorih6im1m9pa0r1ol42
          и дальнейший скрипт не срабатывает, так как юзер, оказывается, аноним… пробовал гуглить, но ничего полезного не нашёл. Может подскажите, в чем может быть дело?

          Кстати, при обращении к скрипту, сессия в БД создаётся, нот с другим ИД.
            Aртур Чикин
            26 февраля 2014, 22:02
            0
            Закрой сессию перед тем как открывать новую.
              Rimas Kudelis
              27 февраля 2014, 11:12
              0
              А это как делается? Я сессию вообще в своём скрипте не трогаю.
                Rimas Kudelis
                27 февраля 2014, 14:48
                0
                Вот уж как интересно…
                Ошибки с сессией избавился. Похоже, контекст не совпадал.
                Но другая штука вылезла: авторизация проходит успешно, а вот $modx->user остаётся тот самый, как и был (т.е. там и дальше хранятся данные, что наш юзер – аноним). Вообще-то это мне не мешает (правда, жаль что в БД не записывается информация о том, какой юзер создал импортированные товары), но странно всё-таки… Или всё так и должно быть?
                Константин Ильин
                23 июня 2022, 17:44
                0
                Подскажите пожалуйста, столкнулся примерно с такой же проблемой.
                <?php
                define('MODX_API_MODE', true);
                require_once $_SERVER['DOCUMENT_ROOT'].'/index.php';
                
                $resp = $modx->runProcessor('/security/login', array(
                    'username' => 'admin',
                    'password' => '123123',
                    'rememberme' => true,
                    'login_context' => 'mgr',
                ));
                Пробовал session_abort или session_destroy, но мне кажется тут не все так просто из-за метода подключения API.

                Как правильно залогиниться под админом, например в login.php с «примерно» вышеуказанным кодом?
                  Николай Савин
                  23 июня 2022, 20:12
                  +1
                  $response = $modx->runProcessor('security/login', $data);
                          if ($response->isError()) {
                              $modx->log(modX::LOG_LEVEL_ERROR, print_r($response->response, 1));
                          } else {
                              //User отдельно необходим потому-что процессор не возвращает юзера и не присваивает его автоматом объекту $modx->user
                              //В данном случае нет смысла дополнительно проверять права, потому что процессор уже все проверки провел.
                              $user = $modx->getObject('modUser', array('username' => $username));
                              if ($user) {
                                  $modx->user = $user;
                                  $modx->initialize('mgr');
                              }
                          }
                    Константин Ильин
                    23 июня 2022, 22:04
                    0
                    Спасибо большое Николай, сколько гуглил не на нашел такого.

                    для поиска: Авторизация админа api
                Дмитрий
                01 августа 2015, 00:21
                0
                Подскажите, пожалуйста, как правильно передать дату создания документа. Т.е. если нужно именно указать НЕ текущую дату. Прописываю

                ,'publishedon' => $next_date

                где $next_date вида 21.07.15
                Не получается, вставляется текущая дата и всё. Думал надо в UNIX формате указывать. Сделал, стали прописываться какие-то совершенно левые даты… Не пойму в чём дело.
                Дмитрий
                03 августа 2015, 11:19
                0
                Парни, спасибо большое! Василий, действительно в том формате, что вы указали надо выставлять дату. При этом настройки системы на это не влияют. Они только для вывода даты в админке нужны по всей видимости.
                  Евгений
                  24 июля 2017, 16:49
                  0
                  Что за ошибка?


                  Fatal error: require(): Failed opening required '/home/mesial1/www/test.mymilena.ru/core/cache/includes/elements/index.php' (include_path='.:/opt/php54/pear') in /home/mesial1/www/test.mymilena.ru/core/cache/includes/elements/modsnippet/92.include.cache.php on line 3

                  Вот код
                  <?php
                  define('MODX_API_MODE', true);
                  require dirname(dirname(__FILE__)).'/index.php';
                  
                  $response = $modx->runProcessor('security/login', array('username' => $username, 'password' => $password));
                  if ($response->isError()) {
                      $modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
                      return;
                  }
                  $modx->initialize('mgr');
                    Воеводский Михаил
                    24 июля 2017, 17:24
                    1
                    +1
                    В сниппете объявлять MODX_API_MODE и подключать основной index.php — давно я подобного не встречал.

                    Указанный код необходимо размещать в каком-либо подкаталоге корня сайта, тогда и подключение корректно произойдет, и от MODX_API_MODE будет толк.
                      Сергей Шлоков
                      25 июля 2017, 07:16
                      +1
                      Вы сами пишете код или откуда-то просто копируете? Вы понимаете, что эта конструкция значит?
                      require dirname(dirname(__FILE__)).'/index.php';
                      Она значит — подняться на одну директорию выше текущего файла и там найти файл index.php. PHP ищет этот файл в директории elements и не находит. Об этом и сообщается в ошибке. Файл index.php находится в корне. Поэтому, чтобы его подключить, нужно ещё 4 раза вызвать функцию dirname().
                        wissem
                        28 мая 2019, 15:16
                        0
                        А как правильно подключить этот код? Я так понимаю, что создавать сниппет с кодом это не правильно. А как тогда?
                      Евгений
                      24 июля 2017, 17:44
                      0
                      С этим понятно, спасибо.
                      define('MODX_API_MODE', true);
                      require dirname(dirname(__FILE__)).'/index.php';
                      Как быть с остальным кодом, при добавлении товара через процессор, в кроне получаю:
                      Array
                      (
                          [success] => 
                          [message] => permission_denied
                          [total] => 0
                          [errors] => Array
                              (
                              )
                          [object] => Array
                              (
                              )
                      )
                        Воеводский Михаил
                        24 июля 2017, 18:06
                        0
                        Необходимо добавить получение пользователя и его авторизацию, чтобы исключить такую ошибку.
                        В сообществе уже обсуждалось, поищите.
                        Евгений
                        25 июля 2017, 00:21
                        0
                        Нашел ответ.
                        В этой статье afres.ru/blog/working-with-modx-revolution-api
                        Нужно перед авторизацией включить сессии!
                        // Включаем сессии MODX и инициализируем контекст web
                        require_once 'config.core.php';
                        require_once MODX_CORE_PATH.'model/modx/modx.class.php';
                        $modx = new modX();
                        $modx->initialize('web');
                        
                        $response = $modx->runProcessor('security/login', ['username' => 'admin', 'password' => '123456']);
                                    if ($response->isError()) {
                                        $modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
                                        return;
                                    }
                                    $modx->initialize('mgr');
                        Как то так у меня получилось…
                          Сергей Шлоков
                          25 июля 2017, 07:17
                          +1
                          Сессии здесь совершенно не причем. Читайте мой комментарий выше.
                          Евгений
                          25 июля 2017, 11:33
                          0
                          С конструкцией
                          require dirname(dirname(__FILE__)).'/index.php';
                          я разобрался. Но при этом получал ошибку
                          Array
                          (
                              [success] => 
                              [message] => permission_denied
                              [total] => 0
                              [errors] => Array
                                  (
                                  )
                              [object] => Array
                                  (
                                  )
                          )
                          И вот тут то меня выручили сессии…
                            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                            26