Кастомизация minishop'a
Доброго дня!
Стоит задача изменить исходник файла живущего по адресу:
/core/components/minishop2/model/minishop2/minishop2.class.php
По сути, что может быть проще, поменять код и дело с концом, но при первом же обновлении, все это канет в лету, а это не корпоративно!
Как можно подцепить свой файл?
Стоит задача изменить исходник файла живущего по адресу:
/core/components/minishop2/model/minishop2/minishop2.class.php
По сути, что может быть проще, поменять код и дело с концом, но при первом же обновлении, все это канет в лету, а это не корпоративно!
Как можно подцепить свой файл?
Комментарии: 10
Никак. Если расскажешь задачу, возможно, подскажут другое решение.
- Расширяешь класс msOrderHandler (поключение)
- Копируете из старого submit
- Заменяешь там
на$user_id = $this->ms2->getCustomerId();$user_id = $this->getReceiverId(); - Добавляешь новый метод getReceiverId в новообразованный класс и меняешь его как хочешь
хм… хочу что бы при формировании заказа минишоп генерировал username не email пользователя, а номер телефона
Версия минишопа какая?
minishop2-4.4.2-pl
Во, вот так хочу, что бы было
public function getCustomerId() {
$customer = null;
$response = $this->invokeEvent('msOnBeforeGetOrderCustomer', [
'order' => $this->order,
'customer' => $customer,
]);
if (!$response['success']) {
return $response['message'];
}
if (!$customer) {
$data = $this->order->get();
$email = $data['email'] ?? '';
$receiver = $data['receiver'] ?? '';
$phone = $data['phone'] ?? '';
// Функция для приведения телефона к международному формату +КодСтраныНомер
$formatPhone = function($phone) {
if (empty($phone)) return '';
// Удаляем все нецифровые символы
$phone = preg_replace('/[^0-9]/', '', $phone);
// Определяем код страны по умолчанию (Россия)
$defaultCountryCode = '7';
// Если номер начинается с 8 (Россия)
if (substr($phone, 0, 1) == '8') {
$phone = $defaultCountryCode . substr($phone, 1);
}
// Если номер без кода (10 цифр) - добавляем код по умолчанию
elseif (strlen($phone) == 10) {
$phone = $defaultCountryCode . $phone;
}
// Если номер начинается с 7 (уже есть код России)
elseif (substr($phone, 0, 1) == '7' && strlen($phone) == 11) {
// Оставляем как есть
}
// Если номер с другим кодом страны
elseif (strlen($phone) > 11 || (strlen($phone) == 11 && substr($phone, 0, 1) != '7')) {
// Оставляем как есть (уже содержит код страны)
}
// Добавляем знак + в начало
return '+' . $phone;
};
// Приводим телефон к единому формату
$formattedPhone = $formatPhone($phone);
// Обновляем телефон в данных заказа
if ($formattedPhone !== $phone) {
$data['phone'] = $formattedPhone;
$this->order->set($data);
$phone = $formattedPhone;
}
// Формируем receiver, если он пустой
if (empty($receiver)) {
if (!empty($phone)) {
$receiver = preg_replace('/[^0-9]/', '', $phone);
} elseif (!empty($email)) {
$receiver = substr($email, 0, strpos($email, '@'));
} else {
$receiver = uniqid('user_', false);
}
}
// Формируем email, если он пустой
if (empty($email)) {
if (!empty($phone)) {
$cleanPhone = preg_replace('/[^0-9]/', '', $phone);
$email = 'user_' . $cleanPhone . '@' . $this->modx->getOption('http_host');
} else {
$email = $receiver . '@' . $this->modx->getOption('http_host');
}
}
// Если пользователь авторизован
if ($this->modx->user->isAuthenticated()) {
$profile = $this->modx->user->Profile;
if (!$profile->get('email')) {
$profile->set('email', $email);
}
if (!empty($phone) && $profile->get('mobilephone') != $phone) {
$profile->set('mobilephone', $phone);
}
if (!empty($receiver) && $profile->get('fullname') != $receiver) {
$profile->set('fullname', $receiver);
}
$profile->save();
$customer = $this->modx->user;
} else {
// Поиск существующего пользователя
$c = $this->modx->newQuery('modUser');
$c->leftJoin('modUserProfile', 'Profile');
$filter = [];
if (!empty($phone)) {
$filter['modUser.username'] = $phone;
$filter['OR:Profile.mobilephone:='] = $phone;
}
if (!empty($email)) {
$filter['OR:Profile.email:='] = $email;
}
$c->where($filter);
$c->select('modUser.id');
// Пытаемся найти пользователя
if (!$customer = $this->modx->getObject('modUser', $c)) {
// Создаем нового пользователя
$userData = [
'username' => !empty($phone) ? $phone : $email,
'password' => md5(rand()),
'active' => 1
];
$customer = $this->modx->newObject('modUser', $userData);
$profileData = [
'fullname' => $receiver,
];
if (!empty($email)) {
$profileData['email'] = $email;
}
if (!empty($phone)) {
$profileData['mobilephone'] = $phone;
}
$profile = $this->modx->newObject('modUserProfile', $profileData);
$customer->addOne($profile);
// Добавляем настройку языка
$setting = $this->modx->newObject('modUserSetting');
$setting->fromArray([
'key' => 'cultureKey',
'value' => $this->modx->getOption('cultureKey', null, 'en', true),
], '', true);
$customer->addMany($setting);
if (!$customer->save()) {
$customer = null;
} elseif ($groups = $this->modx->getOption('ms2_order_user_groups', null, false)) {
$groupRoles = array_map('trim', explode(',', $groups));
foreach ($groupRoles as $groupRole) {
$groupRole = explode(':', $groupRole);
$roleId = null;
if (count($groupRole) > 1 && !empty($groupRole[1])) {
$roleId = is_numeric($groupRole[1]) ? (int)$groupRole[1] : $groupRole[1];
}
$customer->joinGroup($groupRole[0], $roleId);
}
}
} else {
// Пользователь найден - обновляем данные
$profile = $customer->getOne('Profile');
if ($profile) {
$changed = false;
if (!empty($phone) && $profile->get('mobilephone') != $phone) {
$profile->set('mobilephone', $phone);
$changed = true;
}
if (!empty($email) && $profile->get('email') != $email) {
$profile->set('email', $email);
$changed = true;
}
if (!empty($receiver) && $profile->get('fullname') != $receiver) {
$profile->set('fullname', $receiver);
$changed = true;
}
if ($changed) {
$profile->save();
}
}
}
}
}
$response = $this->invokeEvent('msOnGetOrderCustomer', [
'order' => $this->order,
'customer' => $customer,
]);
if (!$response['success']) {
return $response['message'];
}
return $customer instanceof modUser ? $customer->get('id') : 0;
}
Спасибо! Но есть ряд вопросов, в рамках того, что я сильно не сведущ…
я уже как-то подключал свой обработчик доставки.
имеет ли значение в какой папке будет лежать новый файл my_msOrderHandler
метод это когда начинается с «public function»?
Т.е. посути в новом файле должно остаться метод submit с теми изменениями что вы написали и мой метод, который я постил в предыдущем комментарии?
я уже как-то подключал свой обработчик доставки.
имеет ли значение в какой папке будет лежать новый файл my_msOrderHandler
метод это когда начинается с «public function»?
Т.е. посути в новом файле должно остаться метод submit с теми изменениями что вы написали и мой метод, который я постил в предыдущем комментарии?
и вот еще какой вопрос…
в документации прописано вот так:
ИИ говорит мне, что интерфейс не нужно подключать для msOrderHandler
т.е. этот кусок получается лишний в моем случае?
в документации прописано вот так:
if (!class_exists('msDeliveryInterface')) {
require_once dirname(dirname(dirname(__FILE__))) . '/model/minishop2/msdeliveryhandler.class.php';
}
class msDeliveryHandlerMsk extends msDeliveryHandler implements msDeliveryInterface {пример подключения собственного класса доставки.ИИ говорит мне, что интерфейс не нужно подключать для msOrderHandler
т.е. этот кусок получается лишний в моем случае?
if (!class_exists('msDeliveryInterface')) {
require_once dirname(dirname(dirname(__FILE__))) . '/model/minishop2/msdeliveryhandler.class.php';
}
В общем убил целый день, но… так у меня ничего и не вышло.
не могу зарегистрировать класс.
содержание самого файла my_msorderhandler.class.php:
согласно священописанию в консоле делаю так:
Из чего делаю вывод, что класс мой не зарегистрировался.
Дальше меняю настройку ms2_services.
она у меня выглядела так:
{«cart»:[],«order»:[«my_OrderHandler»],«payment»:[],«delivery»:{«mydelivery»:"{core_path}components\/minishop2\/custom\/delivery\/my_msdeliveryhandler.class.php"}}
т.к. я уже ранее подрубал собственную службу доставки, и она вроде как исправно работает, делаю по образу и подобию с order, хотя ИИ визжит, что так делать нельзя, и у этой настройки должно быть только название класса.
В логах живет вот такая ошибка:
Вообщем, итог такой, что либо ничего не меняется, либо не работает вовсе.
Что и где я делаю не так?
не могу зарегистрировать класс.
содержание самого файла my_msorderhandler.class.php:
<?php
if (!class_exists('msOrderHandler')) { // проверяем интерфейс заказа
require_once MODX_CORE_PATH . 'components/minishop2/handlers/msorderhandler.class.php';
}
class my_OrderHandler extends msOrderHandler { // implements msOrderInterface не нужен
public function submit($data = [])
{
$response = $this->ms2->invokeEvent('msOnSubmitOrder', [
'data' => $data,
'order' => $this,
]);
if (!$response['success']) {
return $this->error($response['message']);
}
if (!empty($response['data']['data'])) {
$this->set($response['data']['data']);
}
$response = $this->getDeliveryRequiresFields();
if ($this->ms2->config['json_response']) {
$response = json_decode($response, true);
}
if (!$response['success']) {
return $this->error($response['message']);
}
$requires = $response['data']['requires'];
$errors = [];
foreach ($requires as $v) {
if (!empty($v) && empty($this->order[$v])) {
$errors[] = $v;
}
}
if (!empty($errors)) {
return $this->error('ms2_order_err_requires', $errors);
}
$user_id = $this->getReceiverId();
if (empty($user_id) || !is_int($user_id)) {
return $this->error(is_string($user_id) ? $user_id : 'ms2_err_user_nf');
}
$cart_status = $this->ms2->cart->status();
if (empty($cart_status['total_count'])) {
return $this->error('ms2_order_err_empty');
}
$delivery_cost = $this->getCost(false, true);
$cart_cost = $this->getCost(true, true) - $delivery_cost;
$num = $this->getNewOrderNum();
/** @var msOrder $msOrder */
$msOrder = $this->storageHandler->getForSubmit(
compact('user_id', 'num', 'cart_cost', 'cart_status', 'delivery_cost')
);
$response = $this->ms2->invokeEvent('msOnBeforeCreateOrder', [
'msOrder' => $msOrder,
'order' => $this,
]);
if (!$response['success']) {
return $this->error($response['message']);
}
if ($msOrder->save()) {
$response = $this->ms2->invokeEvent('msOnCreateOrder', [
'msOrder' => $msOrder,
'order' => $this,
]);
if (!$response['success']) {
return $this->error($response['message']);
}
if ($this->storage === 'session') {
$this->ms2->cart->clean();
$this->clean();
}
if (empty($_SESSION['minishop2']['orders'])) {
$_SESSION['minishop2']['orders'] = [];
}
$_SESSION['minishop2']['orders'][] = $msOrder->get('id');
// Trying to set status "new"
$status_new = $this->modx->getOption('ms2_status_new', null, 1);
$response = $this->ms2->changeOrderStatus($msOrder->get('id'), $status_new);
if ($response !== true) {
return $this->error($response, ['msorder' => $msOrder->get('id')]);
}
// Reload order object after changes in changeOrderStatus method
/** @var msOrder $msOrder */
$msOrder = $this->modx->getObject('msOrder', ['id' => $msOrder->get('id')]);
/** @var msPayment $payment */
$payment = $this->modx->getObject(
'msPayment',
['id' => $msOrder->get('payment'), 'active' => 1]
);
if ($payment) {
$response = $payment->send($msOrder);
if ($this->config['json_response']) {
@session_write_close();
echo is_array($response) ? json_encode($response) : $response;
die();
}
if (!empty($response['data']['redirect'])) {
$this->modx->sendRedirect($response['data']['redirect']);
}
if (!empty($response['data']['msorder'])) {
$redirect = $this->modx->context->makeUrl(
$this->modx->resource->id,
['msorder' => $response['data']['msorder']]
);
$this->modx->sendRedirect($redirect);
}
$this->modx->sendRedirect($this->modx->context->makeUrl($this->modx->resource->id));
} else {
if ($this->config['json_response']) {
return $this->success('', ['msorder' => $msOrder->get('id')]);
}
$redirect = $this->modx->context->makeUrl(
$this->modx->resource->id,
['msorder' => $msOrder->get('id')]
);
$this->modx->sendRedirect($redirect);
}
return $this->success();
}
return $this->error();
}
public function getCustomerId() {
error_log("🔥🔥🔥 getCustomerId() НАЧАЛО 🔥🔥🔥");
$customer = null;
$response = $this->invokeEvent('msOnBeforeGetOrderCustomer', [
'order' => $this->order,
'customer' => $customer,
]);
if (!$response['success']) {
return $response['message'];
}
if (!$customer) {
$data = $this->order->get();
$email = $data['email'] ?? '';
$receiver = $data['receiver'] ?? '';
$phone = $data['phone'] ?? '';
// Функция для приведения телефона к международному формату +КодСтраныНомер
$formatPhone = function($phone) {
if (empty($phone)) return '';
// Удаляем все нецифровые символы
$phone = preg_replace('/[^0-9]/', '', $phone);
// Определяем код страны по умолчанию (Россия)
$defaultCountryCode = '7';
// Если номер начинается с 8 (Россия)
if (substr($phone, 0, 1) == '8') {
$phone = $defaultCountryCode . substr($phone, 1);
}
// Если номер без кода (10 цифр) - добавляем код по умолчанию
elseif (strlen($phone) == 10) {
$phone = $defaultCountryCode . $phone;
}
// Если номер начинается с 7 (уже есть код России)
elseif (substr($phone, 0, 1) == '7' && strlen($phone) == 11) {
// Оставляем как есть
}
// Если номер с другим кодом страны
elseif (strlen($phone) > 11 || (strlen($phone) == 11 && substr($phone, 0, 1) != '7')) {
// Оставляем как есть (уже содержит код страны)
}
// Добавляем знак + в начало
return '+' . $phone;
};
// Приводим телефон к единому формату
$formattedPhone = $formatPhone($phone);
// Обновляем телефон в данных заказа
if ($formattedPhone !== $phone) {
$data['phone'] = $formattedPhone;
$this->order->set($data);
$phone = $formattedPhone;
}
// Формируем receiver, если он пустой
if (empty($receiver)) {
if (!empty($phone)) {
$receiver = preg_replace('/[^0-9]/', '', $phone);
} elseif (!empty($email)) {
$receiver = substr($email, 0, strpos($email, '@'));
} else {
$receiver = uniqid('user_', false);
}
}
// Формируем email, если он пустой
if (empty($email)) {
if (!empty($phone)) {
$cleanPhone = preg_replace('/[^0-9]/', '', $phone);
$email = 'user_' . $cleanPhone . '@' . $this->modx->getOption('http_host');
} else {
$email = $receiver . '@' . $this->modx->getOption('http_host');
}
}
// Если пользователь авторизован
if ($this->modx->user->isAuthenticated()) {
$profile = $this->modx->user->Profile;
if (!$profile->get('email')) {
$profile->set('email', $email);
}
if (!empty($phone) && $profile->get('mobilephone') != $phone) {
$profile->set('mobilephone', $phone);
}
if (!empty($receiver) && $profile->get('fullname') != $receiver) {
$profile->set('fullname', $receiver);
}
$profile->save();
$customer = $this->modx->user;
} else {
// Поиск существующего пользователя
$c = $this->modx->newQuery('modUser');
$c->leftJoin('modUserProfile', 'Profile');
$filter = [];
if (!empty($phone)) {
$filter['modUser.username'] = $phone;
$filter['OR:Profile.mobilephone:='] = $phone;
}
if (!empty($email)) {
$filter['OR:Profile.email:='] = $email;
}
$c->where($filter);
$c->select('modUser.id');
// Пытаемся найти пользователя
if (!$customer = $this->modx->getObject('modUser', $c)) {
// Создаем нового пользователя
$userData = [
'username' => !empty($phone) ? $phone : $email,
'password' => md5(rand()),
'active' => 1
];
$customer = $this->modx->newObject('modUser', $userData);
$profileData = [
'fullname' => $receiver,
];
if (!empty($email)) {
$profileData['email'] = $email;
}
if (!empty($phone)) {
$profileData['mobilephone'] = $phone;
}
$profile = $this->modx->newObject('modUserProfile', $profileData);
$customer->addOne($profile);
// Добавляем настройку языка
$setting = $this->modx->newObject('modUserSetting');
$setting->fromArray([
'key' => 'cultureKey',
'value' => $this->modx->getOption('cultureKey', null, 'en', true),
], '', true);
$customer->addMany($setting);
if (!$customer->save()) {
$customer = null;
} elseif ($groups = $this->modx->getOption('ms2_order_user_groups', null, false)) {
$groupRoles = array_map('trim', explode(',', $groups));
foreach ($groupRoles as $groupRole) {
$groupRole = explode(':', $groupRole);
$roleId = null;
if (count($groupRole) > 1 && !empty($groupRole[1])) {
$roleId = is_numeric($groupRole[1]) ? (int)$groupRole[1] : $groupRole[1];
}
$customer->joinGroup($groupRole[0], $roleId);
}
}
} else {
// Пользователь найден - обновляем данные
$profile = $customer->getOne('Profile');
if ($profile) {
$changed = false;
if (!empty($phone) && $profile->get('mobilephone') != $phone) {
$profile->set('mobilephone', $phone);
$changed = true;
}
if (!empty($email) && $profile->get('email') != $email) {
$profile->set('email', $email);
$changed = true;
}
if (!empty($receiver) && $profile->get('fullname') != $receiver) {
$profile->set('fullname', $receiver);
$changed = true;
}
if ($changed) {
$profile->save();
}
}
}
}
}
$response = $this->invokeEvent('msOnGetOrderCustomer', [
'order' => $this->order,
'customer' => $customer,
]);
if (!$response['success']) {
return $response['message'];
}
return $customer instanceof modUser ? $customer->get('id') : 0;
}
}согласно священописанию в консоле делаю так:
<?php
if ($miniShop2 = $modx->getService('miniShop2')) {
$miniShop2->addService('order', 'my_OrderHandler',
'{core_path}components/minishop2/custom/order/my_msorderhandler.class.php');
}Пробую, и ничего не меняется. На пару с ИИ добрел до системной настройки, с ключем ms2_order_handler_class и там указал свой класс. Перестало работать вообще. Т.е. тыкаю на кнопку «сделать заказ» на самом сайте и ничего не происходит.Из чего делаю вывод, что класс мой не зарегистрировался.
Дальше меняю настройку ms2_services.
она у меня выглядела так:
{«cart»:[],«order»:[«my_OrderHandler»],«payment»:[],«delivery»:{«mydelivery»:"{core_path}components\/minishop2\/custom\/delivery\/my_msdeliveryhandler.class.php"}}
т.к. я уже ранее подрубал собственную службу доставки, и она вроде как исправно работает, делаю по образу и подобию с order, хотя ИИ визжит, что так делать нельзя, и у этой настройки должно быть только название класса.
В логах живет вот такая ошибка:
(ERROR @ /home/c/cz42644/test-iflower/public_html/core/components/minishop2/model/minishop2/minishop2.class.php: 484) [miniShop2] Could not load custom class at "/home/c/cz42644/test-iflower/public_html/my_OrderHandler"Т.е. я так понимаю, он ищет файл с моей службой почему-то не так где надо, по сути в корне. И как ему указать, где искать — не ведаю.
Вообщем, итог такой, что либо ничего не меняется, либо не работает вовсе.
Что и где я делаю не так?
Етот кусок кода отвечает за то что бы менялась настройка ms2_services
В зависимости от версии minishopа может быть разный путь к msOrderHandler, убедись что етот файл существует
<?php
if ($miniShop2 = $modx->getService('miniShop2')) {
$miniShop2->addService('order', 'my_OrderHandler',
'{core_path}components/minishop2/custom/order/my_msorderhandler.class.php');
}После чего у тебя ms2_services должен быть таким{"cart":[],"order":{"my_OrderHandler":"{core_path}components\/minishop2\/custom\/order\/my_msorderhandler.class.php"},"payment":[],"delivery":{"mydelivery":"{core_path}components\/minishop2\/custom\/delivery\/my_msdeliveryhandler.class.php"}}Тебе надо делать только одно из двух либо регистировать клас через консоль либо в сис. настройках.В зависимости от версии minishopа может быть разный путь к msOrderHandler, убедись что етот файл существует
require_once MODX_CORE_PATH . 'components/minishop2/handlers/msorderhandler.class.php';А еще в submit ты поменял $user_id = $this->ms2->getCustomerId(); на $user_id = $this->getReceiverId(); Но новый метод ты не назвал getReceiverId
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.