[miniShop2] Как тестировать письма без оформления заказа


Иногда приходится тестировать внешний вид писем, отсылаемых при оформлении заказа. Чтобы не оформлять постоянно заказ для просмотра внешнего вида, написал сниппет. Подробности под катом.

Код сниппета


Создаём сниппет msEmail:
<?php
$sp = &$scriptProperties;
if (!$ms2 = $modx->getService('miniShop2')) {
    return 'Class `miniShop2` not found.';
}
$sp['type'] = empty($sp['type']) ? 'user' : $sp['type'];
$sp['order'] = (int)(empty($sp['order']) ? 0 : $sp['order']);
$sp['status'] = (int)(empty($sp['status']) ? 0 : $sp['status']);
if (!in_array($sp['type'], ['user', 'admin'])) {
    return 'Bad type.';
}

/** @var msOrder $order */
if (!$order = $modx->getObject('msOrder', array('id' => $sp['order']))) {
    return $modx->lexicon('ms2_err_order_nf');
}
if (!$status = $modx->getObject('msOrderStatus', array('id' => $sp['status']))) {
    return $modx->lexicon('ms2_err_status_nf');
}

// Load user/context language
$lang = $modx->getOption('cultureKey', null, 'en', true);
if ($tmp = $modx->getObject('modUserSetting', array('key' => 'cultureKey', 'user' => $order->get('user_id')))) {
    $lang = $tmp->get('value');
} else if ($tmp = $modx->getObject('modContextSetting', array('key' => 'cultureKey', 'context_key' => $order->get('context')))) {
    $lang = $tmp->get('value');
}
$modx->setOption('cultureKey', $lang);
$modx->lexicon->load($lang . ':minishop2:default', $lang . ':minishop2:cart');
unset($tmp);

// Placeholders
$pls = $order->toArray();
$pls['status'] = $sp['status'];
$pls['cost'] = $ms2->formatPrice($pls['cost']);
$pls['cart_cost'] = $ms2->formatPrice($pls['cart_cost']);
$pls['delivery_cost'] = $ms2->formatPrice($pls['delivery_cost']);
$pls['weight'] = $ms2->formatWeight($pls['weight']);
$pls['payment_link'] = '';
if ($payment = $order->getOne('Payment')) {
    if ($class = $payment->get('class')) {
        $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;
            }
        }
    }
}

//
$output = [];
if ($type == 'user') {
    if (!$profile = $modx->getObject('modUserProfile', array('internalKey' => $pls['user_id']))) {
        return;
    }
    $emails = [$profile->get('email')];
} elseif ($type == 'manager') {
    $emails = array_map('trim', explode(',',
        $modx->getOption('ms2_email_manager', null, $modx->getOption('emailsender')))
    );
}
$tpl = '';
$subject = $ms2->pdoTools->getChunk('@INLINE ' . $status->get('subject_' . $type), $pls);
if ($chunk = $modx->getObject('modChunk', array('id' => $status->get('body_' . $type)))) {
    $tpl = $chunk->get('name');
}
$body = $modx->runSnippet('msGetOrder', array_merge($pls, array('tpl' => $tpl)));
if (!empty($subject)) {
    $output = $body;
}

return $output;

Как вызывать


Создаём ресурс с пустым шаблоном и кодом:
[[!msEmail?
    &type=`user`
    &order=`1`
    &status=`1`
]]

Параметры сниппета


  • type — тип письма, принимает user или manager,
  • order — ID заказа,
  • status — ID статуса.
Павел Гвоздь
25 ноября 2018, 15:48
modx.pro
36
3 513
+13
Поблагодарить автора Отправить деньги

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

Василий Наумкин
25 ноября 2018, 15:53
4
+8
На всякий случай, тестировать можно и без создания дополнительных сниппетов.
[[!msGetOrder?
    &id=`2404`
    &tpl=`tpl.msEmail.new.user`
]]

Вызвать в ресурсе с пустым шаблоном:
    Павел Гвоздь
    25 ноября 2018, 16:27
    1
    +1
    Это я понял, когда писал сниппет. Однако мне проще вызвать вот в таком виде:
    [[!msEmail?
        &type=`user`
        &order=`1`
        &status=`1`
    ]]
    У статуса может быть и не стандартный шаблон указан, не хочется лезть и смотреть, какой шаблон подтягивает статус. Проще указать ID статуса.
      Николай Савин
      26 ноября 2018, 06:23
      +1
      Етить колотить. Так можно было? А почему тогда письма не отправляются каждый раз при обновлении страницы со сниппетом? Сессия?
        Василий Наумкин
        26 ноября 2018, 06:40
        0
        Так это сниппет оформляет письмо, но не отправляет.

        Для отправки или используй сниппет из поста, или просто оформи заказ.
          Николай Савин
          26 ноября 2018, 06:47
          +2
          Да сейчас перечитал — понял что ты имел ввиду показ письма на экране просто, без отправки.
          Но это так себе решение с точки зрения Email верстки. Не поймешь какие стили сработают, а какие нет.
          Разве что вставку данных проверить.
            Павел Гвоздь
            26 ноября 2018, 06:59
            1
            0
            А почему не сработают? Вроде на мыло главное стили в атрибут style помещать, не?
              Николай Савин
              26 ноября 2018, 07:02
              +2
              Не. Работают только те стили, которые были в эпоху табличной верстки. Все новое будет вырезано. Но это еще от сервиса к сервису. Gmail еще ничего относительно свежие стили рендерит, а вот mail.ru совсем плохо.
              Василий Наумкин
              26 ноября 2018, 07:29
              6
              +4
              У меня все письма перед отправкой проходят через pelago/emogrifier — так что на расхождений в отображении почти нет.

              Грузим свой почтовый класс раньше всех:
              $modx->getService('mail', 'extraMail', 'path/to/class');

              А в классе extraMail добавляем свою обработку:
              <?php
              if (!class_exists('modPHPMailer')) {
                  /** @noinspection PhpIncludeInspection */
                  require MODX_CORE_PATH . 'model/modx/mail/modphpmailer.class.php';
              }
              
              class extraMail extends modPHPMailer
              {
                  /** @var PHPMailer $mailer */
                  public $mailer;
                  
                  /**
                   * @param string $key
                   * @param mixed $value
                   */
                  public function set($key, $value)
                  {
                      if ($key == modMail::MAIL_BODY) {
                          $emogrifier = new \Pelago\Emogrifier($value);
                          $value = $emogrifier->emogrify();
                          $this->set(modMail::MAIL_BODY_TEXT, $this->mailer->html2text(nl2br($value)));
                      }
                      parent::set($key, $value);
                  }
        Stepan
        09 августа 2022, 04:33
        0
        я еще добавил в ваш сниппет событие чтобы подтянуть кастомные переводы(это вообще для любителей странного)
        /** check event*/
        $response = $ms2->invokeEvent('msOnChangeOrderStatus', array(
            'order' => $order,
            'status' => $order->get('status'),
        ));
        а в плагине прям кусок из минишопа
        case 'msOnChangeOrderStatus':
            	if ($tmp = $modx->getObject('modUserSetting', array('key' => 'cultureKey', 'user' => $order->get('user_id')))) {
                    $lang = $tmp->get('value');
        			$modx->setOption('cultureKey', $lang);
        			$modx->lexicon->load($lang.':***:ext');
        
                }
                break;
          Николай Савин
          09 августа 2022, 08:18
          0
          Тогда уж нужно добавить просто код из события, а не вызов самого события.
            Stepan
            09 августа 2022, 15:00
            0
            Ну сам код события пригодится еще при отправке письма, а тут только тест
          Александр Мельник
          09 августа 2022, 08:35
          0
          мне кажется есть огромная разница через что «смотреть» на письмо.
          Внешний вид письма, на который мы сморим через браузер, может сильно отличаться от вида этого же письма в почтовой системе и разительно отличаться от просмотра в какой то программе, например в Thunderbird.

          Поэтому если хотим увидеть, как реальные наши клиенты будут видеть — нужно все-же отправлять на почту.
          А для верстки письма, чтобы быстренько глянуть, да — удобно и в браузер вывести.
            Stepan
            19 ноября 2022, 17:07
            +1
            нашел ошибку
            if (!in_array($sp['type'], ['user', 'admin'])) {
                return 'Bad type.';
            }
            тут admin нужно на manager поменять
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              13