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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Читайте также:
Программы на заказ
Отзывы
Контакты