Joomla и имитация админа
Мне
- Цель
- Декомпозиция
- Попытка номер 1
- Попытка номер 2
- Реализация
- Итог
Необходимо сделать так, чтобы в Joomla 3 выполнялись автоматически действия с некоторыми заказами из компонента Jshopping в определенное время. Пройтись по заказам, найти с необходимым статусом, узнать трек-номер из СДЭК, затем изменить статус и отправить сообщение покупателю.
Звучит просто, верно? Ну если просто, то сразу делаем декомпозицию задачи.
Декомпозиция
Делим задачу на подзадачи
- Авторизация
- Получение заказов
- Получение трек номера от сдэк
- Изменение статуса и отправка комментария
Сделал, дальше авторизовался админом и начал делать изменение статуса. Получение всех заказов по статусу оставил на конец – тут можно реализовать прямо через базу, даже не трогая джумлу.
Так что научимся менять статус заказа и всё можно будет собирать.
Попытка номер 1
Для начала авторизация, тут все оказалось очень просто, вариантов масса, например вот так
define('_JEXEC', 1); define('JPATH_BASE', realpath(dirname(__FILE__))); require_once JPATH_BASE . '/includes/defines.php'; require_once JPATH_BASE . '/includes/framework.php'; // Инициализация приложения $app = JFactory::getApplication('site'); $app->initialise(); // Авторизация под администратором $credentials = array( 'username' => $username, 'password' => $pass ); $app->login($credentials); // Проверка, авторизован ли пользователь if (!JFactory::getUser()->authorise('core.manage')) { echo "Ошибка: Пользователь не авторизован как администратор.\n"; exit; }А вот что дальше? А дальше нам надо подключить нужный файл, создать экземпляр класса и вызвать нужную функцию. Потом повторить это для всех действий. Это на самом деле просто, но не в джумле.
Самый правильный способ – это подключить нужные пространства имен и классы, затем вызвать – и всё через встроенные функции джумлы 3. Пробуем
//подключаем компонент $component = JComponentHelper::getComponent('com_jshopping'); // Путь к компоненту $componentPath = JPATH_BASE . '/components/com_jshopping'; // Подключаем автозагрузчик классов Joomla JLoader::registerNamespace('Joomla\\Component\\Jshopping', $componentPath . ''); // Подключаем файл с классом, если он не подключен автоматически JLoader::register('jshopOrderChangeStatus', $componentPath . '/models/orderchangestatus.php'); // Создаем экземпляр класса $model = new jshopOrderChangeStatus(); // Вызываем метод класса //$result = $model->someMethod();В итоге – ошибка 404. Я подключал по-разному, пробовал в CLI (так в общем и надо) – не получается. Если вот так
define('JPATH_COMPONENT_SITE', JPATH_BASE."/ components/com_jshopping"); require_once JPATH_BASE . '/administrator/components/com_jshopping/jshopping.php'; require_once JPATH_BASE . '/administrator/components/com_jshopping/controllers/orders.php'; $controller = new JshoppingControllerOrders(); $controller->cront();Тоже куча разных ошибок.
Скорее всего тут надо до подключения основного класса (в котором предполагалось работать) – надо подключить кучу дополнительных. Но проблема в том, что файлы с классами называются как угодно, а не как классы – то есть пройтись по всем рекурсивно зависимостям также не получится.
Тут мне надоело разгребать ошибки и я отложил решение задачи на следующий день.
Попытка номер 2
После множество попыток и совещаний с LLM, я не выдержал и просто решил отказаться от этой идеи – работы внутри. И стал делать снаружи.
Сначала опять же авторизуемся, переходим на страницу нужную и отправляем запрос имитируя форму, благо есть подобный инструмент у джумлы – JHttp. Набросал простейший пример
// Переход к определенной странице в админке $url = 'index.php?option=com_yourcomponent&view=yourview&layout=edit&id=1'; $app->redirect($url); // Заполнение формы $http = new JHttp(); $postData = array( 'jform[field1]' => 'value1', 'jform[field2]' => 'value2', // Добавьте остальные поля формы 'task' => 'yourtask.save', // Замените на нужный таск JSession::getFormToken() => 1 // Добавьте токен формы ); $response = $http->post($url, $postData); if ($response->code == 200) { echo "Форма успешно заполнена и сохранена.\n"; } else { echo "Ошибка: Не удалось заполнить форму.\n"; }И… нет. После перехода на страницу все обрывается. В общем, логично, после редиректа – прерывает работу. Оставляем только авторизацию и потом сразу отправляем запрос. И … и ничего.
Реализация
Тут я окончательно не выдержал и набросал свой код отправки через curl php (после авторизации)
$url = 'http://домен /administrator/index.php?option=com_jshopping&controller=orders'; $postData = array( 'order_id' => $order_id, 'order_status' => $order_status, 'comments' => $comment, 'task' => 'update_one_status', 'js_nolang' => '1' ); $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_COOKIE, session_name() . '=' . session_id()); $response = curl_exec($ch); curl_close($ch);И всё заработало
Итог
Да, я знаю, что так как я сделал – это не самый профессиональный путь, по учебнику надо было добиваться первого пути, но работает же?
Бесплатный совет – не заводите сайт на джумле, если в дальнейшем планируете свою кастомизацию. Или запасайтесь терпением при изменениях или ищите хорошего программиста.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Читайте также:
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.