<?php
/**
  * Ahead WebSoft Technologies Pvt Ltd.
  * @copyright  Copyright 2006-2026 Ahead WebSoft Technologies Pvt Ltd.
  * @license    https://www.socialengine.com/policies
*/
class Core_Api_Mail extends Core_Api_Abstract
{
  protected $_enabled;

  protected $_queueing;

  protected $_transport;

  protected $_log;
  public function __construct()
  {
    $this->_enabled = (bool) Engine_Api::_()->getApi('settings', 'core')->getSetting('core.mail.enabled', true);
    $this->_queueing = (bool) Engine_Api::_()->getApi('settings', 'core')->getSetting('core.mail.queueing', true);
  }

  // Options

  public function getTransport()
  {
    if (null === $this->_transport) {

      // Get config
      $mailConfig = array();
      $mailConfigFile = APPLICATION_PATH . '/application/settings/mail.php';
      if (file_exists($mailConfigFile)) {
        $mailConfig = include $mailConfigFile;
      } else {
        $mailConfig = array(
          'class' => 'Zend_Mail_Transport_Sendmail',
          'args' => array(),
        );
      }

      // Get transport
      try {
        $args = (!empty($mailConfig['args']) ? $mailConfig['args'] : array());
        $r = new ReflectionClass($mailConfig['class']);
        $transport = $r->newInstanceArgs($args);
        if (!($transport instanceof Zend_Mail_Transport_Abstract)) {
          $this->_transport = false;
        } else {
          $this->_transport = $transport;
        }
      } catch (Exception $e) {
        $this->_transport = false;
        throw $e;
      }
    }

    if (!($this->_transport instanceof Zend_Mail_Transport_Abstract)) {
      return null;
    }

    return $this->_transport;
  }

  public function getCharset()
  {
    return 'utf-8';
  }

  /**
   * @return Zend_Log
   */
  public function getLog()
  {
    if (null === $this->_log) {
      if (@is_file(APPLICATION_PATH . '/temporary/log/mail.log')) {
        @chmod(APPLICATION_PATH . '/temporary/log/mail.log', 0777);
        $log = new Zend_Log();
        $log->addWriter(new Zend_Log_Writer_Stream(APPLICATION_PATH . '/temporary/log/mail.log', 'a'));
        if ('development' == APPLICATION_ENV) {
          $log->addWriter(new Zend_Log_Writer_Firebug());
        }
      }
      $this->_log = @$log;
    }
    return $this->_log;
  }


  // Doing things

  public function create()
  {
    return new Zend_Mail($this->getCharset());
  }

  public function send(Zend_Mail $mail)
  {
    if ($this->_enabled) {

      if ($this->_queueing) {

        // Single
        if (engine_count($mail->getRecipients()) <= 1) {
          $mailTable = Engine_Api::_()->getDbtable('mail', 'core');
          $mailTable->insert(
            array(
              'type' => 'zend',
              'body' => serialize($mail),
              'recipient_count' => engine_count($mail->getRecipients()),
            )
          );
        }

        // Multi
        else {
          $recipients = $mail->getRecipients();
          $mailClone = clone $mail;
          $mailClone->clearRecipients();

          // Insert main
          $mailTable = Engine_Api::_()->getDbtable('mail', 'core');
          $mail_id = $mailTable->insert(
            array(
              'type' => 'zend',
              'body' => serialize($mailClone),
              'recipient_count' => engine_count($recipients),
              'recipient_total' => engine_count($recipients),
              'creation_time' => date("Y-m-d H:i:s"),
            )
          );

          // Insert recipients
          $mailRecipientsTable = Engine_Api::_()->getDbtable('mailRecipients', 'core');
          foreach ($recipients as $oneRecipient) {
            if ($oneRecipient instanceof Core_Model_Item_Abstract) {
              $mailRecipientsTable->insert(
                array(
                  'mail_id' => $mail_id,
                  'user_id' => $oneRecipient->user_id,
                )
              );
            } else if (is_string($oneRecipient)) {
              $mailRecipientsTable->insert(
                array(
                  'mail_id' => $mail_id,
                  'email' => $oneRecipient,
                )
              );
            }
          }
        }

      } else {

        $mailClone = clone $mail;
        $mailClone->clearRecipients();
        $mailClone->addTo($mailClone->getFrom());
        foreach ($mail->getRecipients() as $oneRecipient) {
          if ($oneRecipient instanceof Core_Model_Item_Abstract && !empty($oneRecipient->email)) {
            $mailClone->addBcc($oneRecipient->email);
          } else if (is_string($oneRecipient)) {
            $mailClone->addBcc($oneRecipient);
          }
          // send in batches of 30
          if (30 <= engine_count($mailClone->getRecipients())) {
            $this->sendRaw($mailClone);
            $mailClone->clearRecipients();
            $mailClone->addTo($mailClone->getFrom());
          }
        }
        if (1 <= engine_count($mailClone->getRecipients())) {
          $this->sendRaw($mailClone);

          // Logging in dev mode
          if ('development' == APPLICATION_ENV) {
            if ($this->getLog()) {
              $this->getLog()->log(sprintf('[%s] %s <- %s', 'Zend', join(', ', $mailClone->getRecipients()), $mailClone->getFrom()), Zend_Log::DEBUG);
            }
          }
        }
      }
    }

    return $this;
  }

  public function sendRaw(Zend_Mail $mail)
  {
    if ($this->_enabled) {
      try {

        $mail->send($this->getTransport());
      } catch (Exception $e) {
        // Silence? Note: Engine_Exception 's are already logged
        if (!($e instanceof Engine_Exception) && Zend_Registry::isRegistered('Zend_Log')) {
          $log = Zend_Registry::get('Zend_Log');
          $log->log($e, Zend_Log::ERR);
        }
      }

      // Logging in dev mode
      if ('development' == APPLICATION_ENV) {
        if ($this->getLog()) {
          $this->getLog()->log(sprintf('[%s] %s <- %s', 'Zend', join(', ', $mail->getRecipients()), $mail->getFrom()), Zend_Log::DEBUG);
        }
      }

      // Track emails
      Engine_Api::_()->getDbtable('statistics', 'core')->increment('core.emails');
    }

    return $this;
  }

  // System
  public function sendSystem($recipient, $type, array $params = array())
  {
    // Just send
    if (!$this->_queueing || (isset($params['queue']) && $params['queue'] === false)) {
      $this->sendSystemRaw($recipient, $type, $params);
    }
    // Queue
    else {
      if (!is_array($recipient) && !($recipient instanceof Zend_Db_Table_Rowset_Abstract)) {
        $recipient = array($recipient);
      }
      $recipients = array();
      // Pre-process recpients
      foreach ($recipient as $oneRecipient) {
        if (!$this->_validateRecipient($oneRecipient)) {
          throw new Exception(get_class($this) . '::sendSystem() requires an item, an array of items with an email, or a string email address.');
        }
        $recipients[] = $oneRecipient;
      }

      // Insert main row
      $mailTable = Engine_Api::_()->getDbtable('mail', 'core');
      $mailRecipientsTable = Engine_Api::_()->getDbtable('mailRecipients', 'core');
      $mail_id = $mailTable->insert(array(
        'type' => 'system',
        'body' => serialize(array(
          'type' => $type,
          'params' => $params,
        )),
        'recipient_count' => engine_count($recipients),
        'creation_time' => date('Y-m-d H:i:s'),
      ));

      // Insert recipients
      foreach ($recipients as $oneRecipient) {
        if ($oneRecipient instanceof Core_Model_Item_Abstract) {
          if (!empty($oneRecipient->disable_email) && $oneRecipient->user_id && $type != "core_lostpassword") {
            continue;
          }

          //If member is not verifed then do not send email
          if (!engine_in_array($type, array('user_otp', 'core_welcome', 'core_verification', 'notify_admin_user_signup')) && empty($oneRecipient->verified)) return;

          $mailRecipientsTable->insert(array(
            'mail_id' => $mail_id,
            'user_id' => $oneRecipient->user_id,
          ));
        } else if (is_string($oneRecipient)) {
          $mailRecipientsTable->insert(array(
            'mail_id' => $mail_id,
            'email' => $oneRecipient,
          ));
        } else if (is_numeric($oneRecipient)) {
          $mailRecipientsTable->insert(array(
            'mail_id' => $mail_id,
            'user_id' => $oneRecipient,
          ));
        }
      }
    }
    return $this;
  }
  public function sendSystemRaw($recipient, $type, array $params = array())
  {
    // Verify mail template type
    $mailTemplateTable = Engine_Api::_()->getDbtable('MailTemplates', 'core');
    $mailTemplate = $mailTemplateTable->fetchRow($mailTemplateTable->select()->where('type = ?', $type));

    if (null === $mailTemplate) {
      return;
    }

    //Don't send email when admin disable from admin panel.
    if (empty($mailTemplate->default)) {
      return;
    }

    // Verify recipient(s)
    if (!is_array($recipient) && !($recipient instanceof Zend_Db_Table_Rowset_Abstract)) {
      $recipient = array($recipient);
    }
    $recipients = array();
    foreach ($recipient as $oneRecipient) {
      if (!$this->_validateRecipient($oneRecipient)) {
        return;
        //throw new Engine_Exception(get_class($this) . '::sendSystem() requires an item, an array of items with an email, or a string email address.');
      }
      $recipients[] = $oneRecipient;
    }

    // Send
    // Get admin info
    $fromAddress = Engine_Api::_()->getApi('settings', 'core')->getSetting('core.mail.from', 'admin@' . $_SERVER['HTTP_HOST']);
    $fromName = Engine_Api::_()->getApi('settings', 'core')->getSetting('core.mail.name', 'Site Admin');

    $params['admin_email'] = $fromAddress;
    $params['admin_title'] = $fromName;

    // Build subject/body
    $translate = Zend_Registry::get('Zend_Translate');

    $subjectKey = strtoupper('_EMAIL_' . $mailTemplate->type . '_SUBJECT');
    $bodyTextKey = strtoupper('_EMAIL_' . $mailTemplate->type . '_BODY');
    $bodyHtmlKey = strtoupper('_EMAIL_' . $mailTemplate->type . '_BODYHTML');

    $settings = Engine_Api::_()->getApi('settings', 'core');
		$emailadmin = ($settings->getSetting('user.signup.adminemail', 0) == 1);
		$super_adminEmail = $settings->getSetting('user.signup.adminemailaddress', null);

    // Send to each recipient
    foreach ($recipients as $recipient) {

      // Copy params
      $rParams = $params;

      // See if they're actually a member
      if( is_string($recipient) ) {
        $user = Engine_Api::_()->getItemTable('user')->fetchRow(array('email LIKE ?' => $recipient));
        if( null !== $user ) {
            $enabledEmailTypes = Engine_Api::_()->getDbtable('emailSettings', 'user')->checkEnabledEmail($user, $type);
            if(empty($enabledEmailTypes)) continue;
            $recipient = $user;
        }
      } else if(!empty($recipient->disable_email) && $recipient->user_id && $type != "core_lostpassword") {
          continue;
      }

      // Check recipient
      if ($recipient instanceof Core_Model_Item_Abstract) {
        $isMember = true;

        //If member is not verifed then do not send email
        if(!engine_in_array($type, array('user_otp', 'core_welcome', 'core_verification', 'notify_admin_user_signup','core_lostpassword', 'user_account_approved')) && empty($recipient->verified)) return;

        // Detect email and name
        $recipientEmail = $recipient->email;
        $recipientName = $recipient->getTitle(false);

        // Detect language
        if (!empty($rParams['language'])) {
          $recipientLanguage = $rParams['language'];
        } else if (!empty($recipient->language)) {
          $recipientLanguage = $recipient->language;
        } else {
          $recipientLanguage = $translate->getLocale();
        }
        if (!Zend_Locale::isLocale($recipientLanguage) ||
          $recipientLanguage == 'auto' ||
          !engine_in_array($recipientLanguage, $translate->getList())
        ) {
          $recipientLanguage = $translate->getLocale();
        }

        // add automatic params
        $rParams['email'] = $recipientEmail;
        $rParams['language'] = $recipientLanguage;
        $rParams['recipient_email'] = $recipientEmail;
        $rParams['recipient_title'] = $recipientName;
        $rParams['recipient_link'] = $recipient->getHref();

        $photoUrl = $recipient->getPhotoUrl('thumb.normal');
        $view = Zend_Registry::get('Zend_View');
        $photoUrl = $view->absoluteUrl($photoUrl);
        $recipientImg = $view->htmlImage($photoUrl,'',array(
            'max-width' => '100px',
          ));
        $rParams['recipient_photo'] = $recipientImg;
      } else if (is_string($recipient)) {
        $isMember = false;

        // Detect email and name
        if (strpos($recipient, ' ') !== false) {
          $parts = explode(' ', $recipient, 2);
          $recipientEmail = $parts[0];
          $recipientName = trim($parts[1], ' <>');
        } else {
          $recipientEmail = $recipient;
          $recipientName = '';
        }

        // Detect language
        if (!empty($rParams['language'])) {
          $recipientLanguage = $rParams['language'];
          //} else if( !empty($recipient->language) ) {
          //  $recipientLanguage = $recipient->language;
        } else {
          $recipientLanguage = $translate->getLocale();
        }
        if (!Zend_Locale::isLocale($recipientLanguage) ||
          $recipientLanguage == 'auto' ||
          !engine_in_array($recipientLanguage, $translate->getList())) {
          $recipientLanguage = $translate->getLocale();
        }

        // add automatic params
        $rParams['email'] = $recipientEmail;
        $rParams['recipient_email'] = $recipientEmail;
        $rParams['recipient_title'] = $recipientName;
        $rParams['recipient_link'] = '';
        $rParams['recipient_photo'] = '';

      } else {
        continue;
      }


      if($recipient instanceof Core_Model_Item_Abstract ) {
        if(!is_null($mailTemplate->member_level) && !engine_in_array($recipient->level_id,explode(",", $mailTemplate->member_level))){
            return false;
        }
      }

      // Get subject and body
      $subjectTemplate = (string) $this->_translate($subjectKey, $recipientLanguage);
      $bodyTextTemplate = (string) $this->_translate($bodyTextKey, $recipientLanguage);
      $bodyHtmlTemplate = (string) $this->_translate($bodyHtmlKey, $recipientLanguage);

      if (!($subjectTemplate)) {
        throw new Engine_Exception(sprintf('No subject translation available for system email "%s"', $type));
      }
      if (!$bodyHtmlTemplate && !$bodyTextTemplate) {
        throw new Engine_Exception(sprintf('No body translation available for system email "%s"', $type));
      }

      if (!$bodyHtmlTemplate) {
        $bodyHtmlTemplate = nl2br($bodyTextTemplate);
      }
      // Get headers and footers
      $headerPrefix = '_EMAIL_HEADER_' . ($isMember ? 'MEMBER_' : '');
      $footerPrefix = '_EMAIL_FOOTER_' . ($isMember ? 'MEMBER_' : '');

      $subjectHeader = (string) $this->_translate($headerPrefix . 'SUBJECT', $recipientLanguage);
      $subjectFooter = (string) $this->_translate($footerPrefix . 'SUBJECT', $recipientLanguage);
      $bodyTextHeader = (string) $this->_translate($headerPrefix . 'BODY', $recipientLanguage);
      $bodyTextFooter = (string) $this->_translate($footerPrefix . 'BODY', $recipientLanguage);
      $bodyHtmlHeader = (string) $this->_translate($headerPrefix . 'BODYHTML', $recipientLanguage);
      $bodyHtmlFooter = (string) $this->_translate($footerPrefix . 'BODYHTML', $recipientLanguage);

      if (!$bodyHtmlHeader) {
        $bodyHtmlHeader = nl2br($bodyTextHeader);
      }

      if (!$bodyHtmlFooter) {
        $bodyHtmlFooter = nl2br($bodyTextFooter);
      }

      // Do replacements
      foreach ($rParams as $var => $val) {
        $raw = trim($var, '[]');
        $var = '[' . $var . ']';
        //if( !$val ) {
        //  $val = $var;
        //}
        // Fix nbsp
        $val = str_replace('&amp;nbsp;', ' ', $val);
        $val = str_replace('&nbsp;', ' ', $val);
        // Replace
        $subjectTemplate = str_replace($var, $val, $subjectTemplate);
        $bodyTextTemplate = str_replace($var, $val, $bodyTextTemplate);
        $bodyHtmlTemplate = str_replace($var, $val, $bodyHtmlTemplate);
        $subjectHeader = str_replace($var, $val, $subjectHeader);
        $subjectFooter = str_replace($var, $val, $subjectFooter);
        $bodyTextHeader = str_replace($var, $val, $bodyTextHeader);
        $bodyTextFooter = str_replace($var, $val, $bodyTextFooter);
        $bodyHtmlHeader = str_replace($var, $val, $bodyHtmlHeader);
        $bodyHtmlFooter = str_replace($var, $val, $bodyHtmlFooter);
      }

      // Do header/footer replacements
      $subjectTemplate = str_replace('[header]', $subjectHeader, $subjectTemplate);
      $subjectTemplate = str_replace('[footer]', $subjectFooter, $subjectTemplate);
      $bodyTextTemplate = str_replace('[header]', $bodyTextHeader, $bodyTextTemplate);
      $bodyTextTemplate = str_replace('[footer]', $bodyTextFooter, $bodyTextTemplate);
      $bodyHtmlTemplate = str_replace('[header]', $bodyHtmlHeader, $bodyHtmlTemplate);
      $bodyHtmlTemplate = str_replace('[footer]', $bodyHtmlFooter, $bodyHtmlTemplate);
      // Check for missing text or html
      if (!$bodyHtmlTemplate) {
        $bodyHtmlTemplate = nl2br($bodyTextTemplate);
      }
      if (!$bodyTextTemplate) {
        $bodyTextTemplate = $bodyHtmlTemplate;
      }
      $bodyTextTemplate = $bodyHtmlTemplate; //strip_tags($bodyTextTemplate);
      $adminEmails = array();

      $templateTable = Engine_Api::_()->getItemTable('core_emailtemplate');
      $templateTableName = $templateTable->info('name');

      if ($type == 'core_test_mailtemplate') {
        $bodyTextTemplate = '<p><span style="font-weight: 400;">Hello,</span></p><p><span style="font-weight: 400;">' . $bodyTextTemplate . '</span></p><p>&nbsp;</p><p><span style="font-weight: 400;">Thank You</span></p>';
      }

      $view = Zend_Registry::isRegistered('Zend_View') ? Zend_Registry::get('Zend_View') : null;
      $finalbodyTextTemplate = $view->partial('_emailhtml.tpl', 'core', array('body' => nl2br($bodyTextTemplate), 'id' => $recipient->user_id, 'template_id' => @$params['template_id']));

      // Send
      if(empty($emailadmin) && $subjectKey == '_EMAIL_NOTIFY_ADMIN_USER_SIGNUP_SUBJECT' ) {
        // the signup notification is emailed to the first SuperAdmin by default
        $usersTable = Engine_Api::_()->getDbtable('users', 'user');
        $usersSelect = $usersTable->select()
          ->where('level_id = ?', 1)
          ->where('enabled >= ?', 1);
        $superAdmins = $usersTable->fetchAll($usersSelect);

        foreach ($superAdmins as $superAdmin) {
          $adminEmails[$superAdmin->displayname] = $superAdmin->email;
        }
        $recipientEmail = $adminEmails;
        $recipientName = '';
      }

      $mail = $this->create()
        ->addTo($recipientEmail, $recipientName)
        ->setFrom($fromAddress, $fromName)
        ->setSubject($subjectTemplate)
        ->setBodyHtml($finalbodyTextTemplate)
        ->setBodyText($finalbodyTextTemplate);

      $this->sendRaw($mail);

      // Logging in dev mode
      if( 'development' == APPLICATION_ENV ) {
        if($this->getLog()) {
          $this->getLog()->log(sprintf('[%s] (%s) %s <- %s', 'System', $type, join(', ', $mail->getRecipients()), $mail->getFrom()), Zend_Log::DEBUG);
        }
      }
    }
    return $this;
  }

  protected function _validateRecipient($recipient)
  {
    if ($recipient instanceof Core_Model_Item_Abstract && !empty($recipient->email)) {
      return true;
    } else if (is_string($recipient) && strpos($recipient, '@') >= 1) {
      return true;
    }
    return false;
  }

  protected function _translate($key, $locale, $noDefault = false)
  {
    $translate = Zend_Registry::get('Zend_Translate');
    $value = $translate->translate($key, $locale);
    if ($value == $key || '' == trim($value)) {
      if ($noDefault) {
        return false;
      } else {
        $value = $translate->translate($key);
        if ($value == $key || '' == trim($value)) {
          $value = $translate->translate($key, 'en');
          if ($value == $key || '' == trim($value)) {
            return false;
          }
        }
      }
    }
    return $value;
  }
}
