Недавно наткнулся на платный компонент msCustomerAutoReg (490 руб.), который позволяет регистрировать пользователей после оформления заказа. Сказать, что я удивился, это не сказать ничего. Мало того, что компонент платный, так и способ реализации задачи достаточно некорректный, с моей точки зрения. На вопрос: можно сделать лучше и штатными средствами? Я отвечу: можно! И даже нужно!
Начнем с того, что после оформления заказа miniShop2 автоматически регистрирует пользователя на сайте, только данные пользователя на почту не высылаются. В сети предлагают кучу решений данной задачи, но все они сводятся к тому, что после оформления заказа пользователю отсылается второе письмо с данными от личного кабинета. Не считаю, что два письма отсылать корректно. Поэтому делюсь своими наработками в данном направлении.
Компонент miniShop2 обладает широкими возможностями для масштабирования, за что разработчику огромное спасибо. В частности, мы можем переопределить стандартные методы классов. Что и послужит нам отличным инструментом для решения данной задачи. Нам нужно переопределить всего один метод changeOrderStatus, для этого создаем файл orderCustomHandler.class.php в директории /core/components/minishop2/custom/order/ со следующим содержимым:
<?php class orderCustomHandler extends msOrderHandler{ /** * Switch order status * * @param integer $order_id The id of msOrder * @param integer $status_id The id of msOrderStatus * * @return boolean|string */ public function changeOrderStatus($order_id, $status_id) { /** @var msOrder $order */ if (!$order = $this->modx->getObject('msOrder', array('id' => $order_id), false)) { return $this->modx->lexicon('ms2_err_order_nf'); } $ctx = $order->get('context'); $this->modx->switchContext($ctx); $this->initialize($ctx); // This method could be overwritten from custom order handler if (is_object($this->order) && method_exists($this->order, 'changeOrderStatus')) { return $this->order->changeOrderStatus($order_id, $status_id); } $error = ''; /** @var msOrderStatus $status */ if (!$status = $this->modx->getObject('msOrderStatus', array('id' => $status_id, 'active' => 1))) { $error = 'ms2_err_status_nf'; } /** @var msOrderStatus $old_status */ else { if ($old_status = $this->modx->getObject('msOrderStatus', array('id' => $order->get('status'), 'active' => 1)) ) { if ($old_status->get('final')) { $error = 'ms2_err_status_final'; } else { if ($old_status->get('fixed')) { if ($status->get('rank') <= $old_status->get('rank')) { $error = 'ms2_err_status_fixed'; } } } } } if ($order->get('status') == $status_id) { $error = 'ms2_err_status_same'; } if (!empty($error)) { return $this->modx->lexicon($error); } $response = $this->ms2->invokeEvent('msOnBeforeChangeOrderStatus', array( 'order' => $order, 'status' => $order->get('status'), )); if (!$response['success']) { return $response['message']; } $order->set('status', $status_id); if ($order->save()) { $this->ms2->orderLog($order->get('id'), 'status', $status_id); $response = $this->ms2->invokeEvent('msOnChangeOrderStatus', array( 'order' => $order, 'status' => $status_id, )); if (!$response['success']) { return $response['message']; } $lang = $this->modx->getOption('cultureKey', null, 'en', true); if ($tmp = $this->modx->getObject('modUserSetting', array('key' => 'cultureKey', 'user' => $order->get('user_id')))) { $lang = $tmp->get('value'); } else if ($tmp = $this->modx->getObject('modContextSetting', array('key' => 'cultureKey', 'context_key' => $order->get('context')))) { $lang = $tmp->get('value'); } $this->modx->setOption('cultureKey', $lang); $this->modx->lexicon->load($lang . ':minishop2:default', $lang . ':minishop2:cart'); $pls = $order->toArray(); $pls['cost'] = $this->ms2->formatPrice($pls['cost']); $pls['cart_cost'] = $this->ms2->formatPrice($pls['cart_cost']); $pls['delivery_cost'] = $this->ms2->formatPrice($pls['delivery_cost']); $pls['weight'] = $this->ms2->formatWeight($pls['weight']); $pls['payment_link'] = ''; if ($payment = $order->getOne('Payment')) { if ($class = $payment->get('class')) { $this->ms2->loadCustomClasses('payment'); if (class_exists($class)) { /** @var msPaymentHandler|PayPal $handler */ $handler = new $class($order); if (method_exists($handler, 'getPaymentLink')) { $link = $handler->getPaymentLink($order); $pls['payment_link'] = $link; } } } } $userId = $pls["user_id"]; $user = $this->modx->getObject("modUser", $userId); if($user){ $time = time(); $newUser = 10; $username = $user->get("username"); $createdon = strtotime($user->get("createdon")) + $newUser; if($createdon > $time){ $length = 8; $pass = $this->modx->user->generatePassword($length); $user->set("password", $pass); $user->save(); $pls["userdata"] = array( "username" => $username, "password" => $pass, ); $user->addSessionContext("web"); } } if ($status->get('email_manager')) { $subject = $this->ms2->pdoTools->getChunk('@INLINE ' . $status->get('subject_manager'), $pls); $tpl = ''; if ($chunk = $this->modx->getObject('modChunk', array('id' => $status->get('body_manager')))) { $tpl = $chunk->get('name'); } $body = $this->modx->runSnippet('msGetOrder', array_merge($pls, array('tpl' => $tpl))); $emails = array_map('trim', explode(',', $this->modx->getOption('ms2_email_manager', null, $this->modx->getOption('emailsender'))) ); if (!empty($subject)) { foreach ($emails as $email) { if (preg_match('#.*?@.*#', $email)) { $this->ms2->sendEmail($email, $subject, $body); } } } } if ($status->get('email_user')) { if ($profile = $this->modx->getObject('modUserProfile', array('internalKey' => $pls['user_id']))) { $subject = $this->ms2->pdoTools->getChunk('@INLINE ' . $status->get('subject_user'), $pls); $tpl = ''; if ($chunk = $this->modx->getObject('modChunk', array('id' => $status->get('body_user')))) { $tpl = $chunk->get('name'); } $body = $this->modx->runSnippet('msGetOrder', array_merge($pls, array('tpl' => $tpl))); $email = $profile->get('email'); if (!empty($subject) && preg_match('#.*?@.*#', $email)) { $this->ms2->sendEmail($email, $subject, $body); } } } } return true; } }
Как видите, мы просто добавили небольшой блок, который позволяет нам вывести данные по личному кабинету прямо в письме о новом заказе. Что чертовски круто. Теперь переходим в системные настройки в разде miniShop2 и меняем значение настройки ms2_order_handler_class на orderCustomHandler.
Далее просто редактируем стандартный чанк tpl.msEmail, добавляя блок с данными о заказе (всегда мучал вопрос почему из коробки этого нет) и данными от личного кабинета:
<div style="width:90%;margin:auto;"> {if $user.fullname}<p><strong>Ф.И.О.:</strong> {$user.fullname}</p>{/if} {if $user.email}<p><strong>E-mail:</strong> {$user.email}</p>{/if} {if $address.phone}<p><strong>Телефон:</strong> {$address.phone}</p>{/if} {if $address.city}<p><strong>Город:</strong> {$address.city}</p>{/if} {if $address.street}<p><strong>Адрес:</strong> {$address.street}{/if} {if $address.building} {$address.building}{/if} {if $address.room} {$address.room}</p>{/if} {if $address.comment}<p><strong>Комментарии:</strong> {$address.comment}</p>{/if} {if $delivery.name}<p><strong>Доставка:</strong> {$delivery.name}</p>{/if} {if $payment.name}<p><strong>Оплата:</strong> {$payment.name}</p>{/if} {if $userdata} <h3 style="{$style.h}{$style.h3}">Данные для входа в личный кабинет:</h3> <div style="padding: 0 20px;"> <strong>Логин:</strong> {$userdata.username}<br/> <strong>Пароль:</strong> {$userdata.password} </div> {/if} </div>
Вот и все! Несколько минут работы, сэкономленные 490 руб. и полученные новые навыки. Неплохо правда?
Сейчас мне надо модифицировать sendEmail в minishop.class.php, делаю так же по вашему примеру и ничего не происходит, запускается старый метод. Подскажите куда копать