Skip to content

Instantly share code, notes, and snippets.

@stefanheimes
Created August 6, 2014 15:32
Show Gist options
  • Save stefanheimes/897396bbfb0c2f19254d to your computer and use it in GitHub Desktop.
Save stefanheimes/897396bbfb0c2f19254d to your computer and use it in GitHub Desktop.
<?php
/**
* PHP version 5
*
* @copyright MEN AT WORK 2014
* @license LGPL-3.0+
* @filesource
*/
/**
* Initialize the system
*/
define('TL_MODE', 'FE');
require_once('../../initialize.php');
use Avisota\Contao\Entity\MailingList;
use Avisota\Contao\Entity\Recipient;
use Avisota\Contao\Subscription\SubscriptionManager;
use Contao\Doctrine\ORM\EntityHelper;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\Query;
class AvisotaCsvRecipientImporter
{
/**
* Import file
*/
const strImportFile = 'files/standard/import/recipients.csv';
/**
* Mapping from CSV to intern.
*/
protected $arrCsvMapping = array
(
self::LIST_EMAIL => 'email',
self::LIST_FORENAME => 'forename',
self::LIST_SURNAME => 'surname',
self::LIST_GENDER => 'gender',
self::LIST_LANGUAGE => '',
);
/**
* Name of the adder of the new rows.
* @var string
*/
protected $strAddedBy = 'Importer';
/**
* Set the auto refresh html markup.
* @var bool
*/
protected $blnAutoRefresh = true;
/**
* If a mail is already in the list try to add it to the given
* mailing list.
*
* @var bool
*/
protected $blnAddExistingMailToList = true;
// OptIn -----------------------------------------------------------------------------------------------------------
/**
* Send opt out.
* @var bool
*/
protected $sendOptOut = false;
/**
* Mailer for the opt mails.
* @var string
*/
protected $transportId = '05f247db-1cad-11e4-9cc8-e69d0c26f1ba'; //default swift mailer
/**
* ID of the opt mail.
* @var string
*/
protected $mailId = ''; //OptIn Mail DE
// Language --------------------------------------------------------------------------------------------------------
/**
* Use a custom language and not from the import file.
* @var bool
*/
protected $useCustomLanguage = true;
/**
* Use this language tag for everyone.
* @var string
*/
protected $customLanguage = 'de';
/**
* If there is no language use this one.
* @var string
*/
protected $defaultLanguage = 'en';
// Mail lists ------------------------------------------------------------------------------------------------------
/**
* Use this mailing list.
* @var string
*/
protected $usedMailingList = 'default';
/**
* Mapping for the mailing lists.
* @var array
*/
public $arrMailingLists = array(
'default' => array(
'de' => '3e515e54-3ca6-11e3-8066-1ab841b66e32'
),
);
/**
* Jump to urls.
* @var array
*/
protected $mailUrl = array(
'de' => '',
'en' => '',
);
// Limits ----------------------------------------------------------------------------------------------------------
/**
* Insert pe run.
* @var int
*/
protected $limit = 4;
// Converting ------------------------------------------------------------------------------------------------------
/**
* Converting language.
* @var array
*/
public $arrLanConvert = array(
'D' => 'de',
'E' => 'en'
);
/**
* Mapping for the gender.
* @var array
*/
protected $arrGender = array(
// Male
'Herr' => 'male',
'Herr.' => 'male',
'Herren' => 'male',
'Herrn' => 'male',
'Mr.' => 'male',
'Mr' => 'male',
'Mister' => 'male',
'male' => 'male',
// Female
'Frau' => 'female',
'Frauen' => 'female',
'Mrs.' => 'female',
'Mrs' => 'female',
'female' => 'female',
);
// Const -----------------------------------------------------------------------------------------------------------
/**
* Vars for the intern mapping, don't touch this.
*/
const LIST_EMAIL = 'email';
const LIST_FORENAME = 'forename';
const LIST_SURNAME = 'surname';
const LIST_GENDER = 'gender';
const LIST_LANGUAGE = 'language';
// Vars ------------------------------------------------------------------------------------------------------------
/**
* Swift_Mime_Grammar.
* @var null|Swift_Mime_Grammar
*/
protected $objTester = null;
/**
* Mailing list id's.
* @var array
*/
protected $arrLang2Mailing = array();
/**
* Entity Accessor for doctrine.
* @var \Contao\Doctrine\ORM\EntityAccessor $entityAccessor
*/
protected $objEntityAccessor = null;
/**
* The subscription manager from avisota.
* @var \Avisota\Contao\Subscription\SubscriptionManager $subscriptionManager
*/
protected $objSubscriptionManager = null;
/**
* A list with all mailing list for the current use.
*
* @var array
*/
protected $arrAvisotaMailingList = array();
/**
* __construct
*/
public function __construct()
{
// Check if we have a mailing list.
if (!isset($this->arrMailingLists[$this->usedMailingList]))
{
throw new \Exception('Unknown mailing list:' . $this->usedMailingList);
}
// Set the default mailing lists.
$this->arrLang2Mailing = $this->arrMailingLists[$this->usedMailingList];
// Setup some vars.
$this->objTester = new Swift_Mime_Grammar();
$this->objEntityAccessor = $GLOBALS['container']['doctrine.orm.entityAccessor'];
$this->objSubscriptionManager = $GLOBALS['container']['avisota.subscription'];
\System::loadLanguageFile('avisota_subscription');
}
/**
* Echo something on the screen.
*
* @param string $strMsg
*/
protected function echoMsg($strMsg)
{
echo "<pre>";
var_dump($strMsg);
echo "</pre>";
}
/**
* @param $arrSubscriptions
*/
protected function echoSubscriptions($arrSubscriptions)
{
}
/**
* Check if the email is valid.
*
* @param string $strMail
*
* @return bool True is || False is not.
*/
protected function isValidEMail($strMail)
{
if (!preg_match('/^' . $this->objTester->getDefinition('addr-spec') . '$/D', $strMail))
{
$this->echoMsg('Invalid email: ' . $strMail);
\System::log('Invalid email: ' . $strMail, __CLASS__ . ' | ' . __FUNCTION__, TL_ERROR);
return false;
}
return true;
}
/**
* Check if the user is already in the database.
*
* @param string $strMail Email for checking
*
* @return boolean True is in DB || False nope not found.
*/
protected function isMailInDb($strMail)
{
// Check if the email already exists
$queryBuilder = EntityHelper::getEntityManager()->createQueryBuilder();
$queryBuilder
->select('COUNT(r.id)')
->from('Avisota\Contao:Recipient', 'r')
->where('r.email=?1')
->setParameter(1, $strMail);
$query = $queryBuilder->getQuery();
if ($query->getResult(Query::HYDRATE_SINGLE_SCALAR) < 1)
{
return false;
}
else
{
return true;
}
}
/**
* Get the recipient based on the email.
*
* @param string $strMail
*
* @return \Avisota\Contao\Entity\Recipient
*/
protected function getRecipientByMail($strMail)
{
// Check if the email already exists
$repository = EntityHelper::getEntityManager()->getRepository('Avisota\Contao:Recipient');
$queryBuilder = $repository->createQueryBuilder('r');
$expr = $queryBuilder->expr();
$queryBuilder
->where($expr->eq('r.email', ':mail'))
->setParameter('mail', $strMail);
$query = $queryBuilder->getQuery();
try
{
return $query->getSingleResult();
}
catch (NoResultException $e)
{
return null;
}
}
/**
* Get a list with the given mailing list.
*
* @param $arrIds
*
* @return MailingList[] A list with all searched mailing lists.
*/
protected function getMailingLists($arrIds)
{
$arrReturn = array();
foreach ($arrIds as $strID)
{
// Check if global is given.
if ($strID == 'global')
{
continue;
}
// get the data.
if (!isset($this->arrAvisotaMailingList[$strID]))
{
// Check if the email already exists
$repository = EntityHelper::getEntityManager()->getRepository('Avisota\Contao:MailingList');
$queryBuilder = $repository->createQueryBuilder('m');
$expr = $queryBuilder->expr();
$queryBuilder
->where($expr->eq('m.id', ':mailingListId'))
->setParameter('mailingListId', $strID);
$query = $queryBuilder->getQuery();
try
{
$arrReturn[$strID] = $query->getSingleResult();
}
catch (NoResultException $e)
{
continue;
}
}
// Add to the array.
$arrReturn[] = $this->arrAvisotaMailingList[$strID];
}
// Return the result.
return $arrReturn;
}
/**
* Show the end.
*
* @return array
*/
protected function showEnd()
{
// echo "<pre>";
// var_dump($objSteps);
// var_dump($csvSource->getAllData($arrImport));
// echo "</pre>";
$this->echoMsg('FINISHED');
exit();
// return array
// (
// 'result' => true, // true or false
// 'details' => 'Import succsessfull' // status for logging
// );
}
/**
* Show the next page content.
*
* @param int $turn Turn ID
*/
protected function showNextStep($turn)
{
$parameters = array
(
'turn' => $turn + 1,
);
$url = sprintf
(
// TODO: Add path.
'%ssystem/modules/newsletter-addon/AvisotaCsvImporter.php?%s',
Environment::get('base'),
http_build_query($parameters)
);
if ($this->blnAutoRefresh)
{
echo '<html><head><meta http-equiv="refresh" content="8; URL=' . $url . '"></head><body>Still importing...</body></html>';
}
else
{
echo '<html><head></head><body> Still importing... <a href=' . $url . '>NEXT</a></body></html>';
}
exit();
}
/**
* Read the CSV and return the array.
*
* @param int $intOffset Start at ....
*
* @param int $intLimit Get only ....
*
* @return array|bool
*/
protected function readCSV($intOffset = 0, $intLimit = 0)
{
$csvSource = new TabimporterSource_csv();
// Setting for the importer.
$arrImport = array
(
'sourceFile' => self::strImportFile,
'fieldDelimiter' => 'semicolon',
'hasFieldnames' => true
);
// Get the data from the csv
$arrData = $csvSource->getAllData($arrImport);
// If no limit is set return all.
if ($intLimit == 0)
{
return $arrData;
}
// Only get the data for this turn.
else
{
return array_slice($arrData, $intOffset, $intLimit);
}
}
/**
* Get the data from the data array and try to resolve some special cases.
*
* @param array $arrRow The data row.
*
* @param string $strField Name of the intern field.
*
* @return string The value.
*/
protected function getDataFromArray($arrRow, $strField)
{
// Get the name of the field from the csv.
$strCsvField = $this->arrCsvMapping[$strField];
// Get the value from the CSV.
$strValue = $arrRow[$strCsvField];
// Make something with it.
switch ($strField)
{
case self::LIST_GENDER:
return $this->arrGender[$strValue];
case self::LIST_LANGUAGE:
if ($this->useCustomLanguage)
{
return $this->customLanguage;
}
else
{
return ($this->arrLanConvert[$strValue]) ? $this->arrLanConvert[$strValue] : $this->defaultLanguage;
}
default:
return $strValue;
}
}
/**
* Add a new recipient to the database.
*
* @param array $arrRecipient A list with all information.
*
* @return \Avisota\Contao\Entity\Recipient The new recipient.
*/
protected function addNewRecipient($arrRecipient)
{
// Create a new recipient object.
$objNewRecipient = new Recipient();
$objNewRecipient->setEmail($this->getDataFromArray($arrRecipient, self::LIST_EMAIL));
$objNewRecipient->setSurname($this->getDataFromArray($arrRecipient, self::LIST_SURNAME));
$objNewRecipient->setForename($this->getDataFromArray($arrRecipient, self::LIST_FORENAME));
$objNewRecipient->setGender($this->getDataFromArray($arrRecipient, self::LIST_GENDER));
$objNewRecipient->setAddedByName($this->strAddedBy);
// Save to the database.
EntityHelper::getEntityManager()->persist($objNewRecipient);
EntityHelper::getEntityManager()->flush();
// Echo the data.
$this->echoMsg($this->objEntityAccessor->getRawProperties($objNewRecipient, array('email', 'surname', 'forename', 'gender', 'addedByName')));
return $objNewRecipient;
}
/**
* Add a user to a mailing list.
*
* @param \Avisota\Contao\Entity\Recipient $objRecipient Recipient object.
*
* @param string $strLanguage Language.
*
* @param mixed $options Options for avisota.
*
* @return \Avisota\Contao\Entity\Subscription[]
*/
protected function addSubscriptionFor($objRecipient, $strLanguage, $options)
{
// Get the mailing lists.
$arrMailingLists = array($this->arrLang2Mailing[$strLanguage]);
$arrAvisotaMailingLists = $this->getMailingLists($arrMailingLists);
// Add to the global one.
$this->objSubscriptionManager->subscribe($objRecipient, null, $options);
// Add to the given mailing lists.
$subscriptions = $this->objSubscriptionManager->subscribe($objRecipient, $arrAvisotaMailingLists, $options);
return $subscriptions;
}
/**
*
* @return type
*/
public function importRecipients()
{
global $container;
// Set up everything.
$turn = \Input::get('turn');
$offset = $turn * $this->limit;
$limit = $this->limit;
$options = ($this->sendOptOut) ? SubscriptionManager::OPT_IGNORE_BLACKLIST : SubscriptionManager::OPT_ACTIVATE;
$arrRecipients = $this->readCSV($offset, $limit);
// Get the entity and subscription managers
$entityManager = EntityHelper::getEntityManager();
$repository = $entityManager->getRepository('Avisota\Contao\Entity\Recipient');
// If we have no data end here.
if (count($arrRecipients) == 0)
{
$this->showEnd();
}
foreach ($arrRecipients as $arrRecipient)
{
// Check email.
if (!$this->isValidEMail($this->getDataFromArray($arrRecipient, self::LIST_EMAIL)))
{
continue;
}
// Get the language.
$strLang = $this->getDataFromArray($arrRecipient, self::LIST_LANGUAGE);
// Check if we have the email.
if (!$this->isMailInDb($this->getDataFromArray($arrRecipient, self::LIST_EMAIL)))
{
// Add a new recipient and subscription.
$objRecipient = $this->addNewRecipient($arrRecipient);
$objSubscriptions = $this->addSubscriptionFor($objRecipient, $strLang, $options);
// Send opt-in if flag is set.
if ($this->sendOptOut && $objSubscriptions)
{
$this->sendOptIn($objRecipient, $objSubscriptions, $strLang);
}
}
else
{
// Add a log.
$this->echoMsg('Already in DB: ' . $this->getDataFromArray($arrRecipient, self::LIST_EMAIL));
\System::log('Already in DB: ' . $this->getDataFromArray($arrRecipient, self::LIST_EMAIL), __CLASS__ . ' | ' . __FUNCTION__, TL_ERROR);
// Check if we should add it to the list.
if (!$this->blnAddExistingMailToList)
{
continue;
}
// Get the recipient from the database.
$objRecipient = $this->getRecipientByMail($this->getDataFromArray($arrRecipient, self::LIST_EMAIL));
// Echo the data.
$this->echoMsg($this->objEntityAccessor->getRawProperties($objRecipient, array('email', 'surname', 'forename', 'gender', 'addedByName')));
// Set the mailing lists.
$objSubscriptions = $this->addSubscriptionFor($objRecipient, $strLang, $options);
}
}
$this->showNextStep($turn);
}
/**
* Send opt in mail.
*
* @param \Avisota\Contao\Entity\Recipient $objRecipient
*
* @param \Avisota\Contao\Entity\Subscription[] $objSubscriptions
*
* @param string $strLang The language to use.
*/
protected function sendOptIn($objRecipient, $objSubscriptions, $strLang)
{
$tokens = array();
foreach ($objSubscriptions as $objSubscription)
{
$tokens[] = $objSubscription->getToken();
}
$parameters = array(
'email' => $objRecipient->getEmail(),
'token' => implode(',', $tokens),
);
$url = \Environment::get('base') . $this->mailUrl[$strLang];
$url .= (strpos($url, '?') === false ? '?' : '&');
$url .= http_build_query($parameters);
// ToDo: Check if we need this. We have already the recipient object?
// $objSubscription = $objSubscription[0];
// $recipient = $objSubscription->getRecipient();
// TODO
$newsletterData = array();
$newsletterData['link'] = (object)array(
'url' => $url,
'text' => $GLOBALS['TL_LANG']['avisota_subscription']['confirmSubscription'],
);
$this->sendMessage($objRecipient, $this->mailId, $this->transportId, $newsletterData);
}
/**
* Get the templates and information and send the option.
*
* @param \Avisota\Contao\Entity\Recipient $objRecipient
*
* @param string $mailBoilerplateId
*
* @param string $transportId
*
* @param string $newsletterData
*
* @throws \RuntimeException
*/
protected function sendMessage($objRecipient, $mailBoilerplateId, $transportId, $newsletterData)
{
// Last check if we send a msg.
if ($this->sendOptOut == false)
{
return;
}
$this->echoMsg('SEND MSG');
$messageRepository = EntityHelper::getRepository('Avisota\Contao:Message');
$messageEntity = $messageRepository->find($mailBoilerplateId);
if (!$messageEntity)
{
throw new \RuntimeException('Could not find message id ' . $mailBoilerplateId);
}
/** @var MessagePreRendererInterface $renderer */
$renderer = $GLOBALS['container']['avisota.renderer'];
$preRenderedMessage = $renderer->renderMessage($messageEntity);
$message = $preRenderedMessage->render($objRecipient, $newsletterData);
/** @var TransportInterface $transport */
$transport = $GLOBALS['container']['avisota.transport.' . $transportId];
$transport->send($message);
}
}
$objImporter = new AvisotaCsvRecipientImporter();
$objImporter->importRecipients();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment