name = 'referralprogram';
$this->tab = 'Tools';
$this->version = '1.4';
parent::__construct();
$this->confirmUninstall = $this->l('All sponsor and friends would be deleted. Do you really want to uninstall this module ?');
$this->displayName = $this->l('Customer referral program');
$this->description = $this->l('Integrate a referral program system to your shop.');
$this->_configuration = Configuration::getMultiple(array(
'REFERRAL_NB_FRIENDS',
'REFERRAL_ORDER_QUANTITY',
'REFERRAL_DISCOUNT_TYPE',
'REFERRAL_DISCOUNT_VALUE'
));
$this->_configuration['REFERRAL_DISCOUNT_DESCRIPTION'] = Configuration::getInt('REFERRAL_DISCOUNT_DESCRIPTION');
$path = dirname(__FILE__);
if (strpos(__FILE__, 'Module.php') !== false)
$path .= '/../modules/'.$this->name;
$this->_xmlFile = $path.'/referralprogram.xml';
include_once($path.'/ReferralProgramModule.php');
}
public function install()
{
$langs = Language::getLanguages(false);
foreach ($langs AS $lang)
$desc[$lang['id_lang']] = 'ReferralProgram';
if (!parent::install()
OR !$this->installDB()
OR !Configuration::updateValue('REFERRAL_DISCOUNT_DESCRIPTION', $desc)
OR !Configuration::updateValue('REFERRAL_ORDER_QUANTITY', 1)
OR !Configuration::updateValue('REFERRAL_DISCOUNT_TYPE', 2)
OR !Configuration::updateValue('REFERRAL_NB_FRIENDS', 5)
OR !$this->registerHook('shoppingCart')
OR !$this->registerHook('orderConfirmation')
OR !$this->registerHook('updateOrderStatus')
OR !$this->registerHook('adminCustomers')
OR !$this->registerHook('createAccount')
OR !$this->registerHook('createAccountForm')
OR !$this->registerHook('customerAccount')
)
return false;
foreach (Currency::getCurrencies() as $currency)
Configuration::updateValue('REFERRAL_DISCOUNT_VALUE_'.intval($currency['id_currency']), 5);
/* This hook is optional */
$this->registerHook('myAccountBlock');
return true;
}
public function installDB()
{
return Db::getInstance()->Execute('
CREATE TABLE `'._DB_PREFIX_.'referralprogram` (
`id_referralprogram` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`id_sponsor` INT UNSIGNED NOT NULL,
`email` VARCHAR(255) NOT NULL,
`lastname` VARCHAR(128) NOT NULL,
`firstname` VARCHAR(128) NOT NULL,
`id_customer` INT UNSIGNED DEFAULT NULL,
`id_discount` INT UNSIGNED DEFAULT NULL,
`id_discount_sponsor` INT UNSIGNED DEFAULT NULL,
`date_add` DATETIME NOT NULL,
`date_upd` DATETIME NOT NULL,
PRIMARY KEY (`id_referralprogram`),
UNIQUE KEY `index_unique_referralprogram_email` (`email`)
) DEFAULT CHARSET=utf8 ;');
}
public function uninstall()
{
if (!parent::uninstall()
OR !$this->uninstallDB()
OR !$this->removeMail()
)
return false;
return true;
}
public function uninstallDB()
{
return Db::getInstance()->Execute('DROP TABLE `'._DB_PREFIX_.'referralprogram`;');
}
public function removeMail()
{
$langs = Language::getLanguages(false);
foreach ($langs as $lang)
foreach ($this->_mails['name'] as $name)
foreach ($this->_mails['ext'] as $ext)
{
$file = _PS_MAIL_DIR_.$lang['iso_code'].'/'.$name.'.'.$ext;
if (file_exists($file) AND !@unlink($file))
$this->_errors[] = $this->l('Cannot delete this file:').' '.$file;
}
return true;
}
private function _postProcess()
{
Configuration::updateValue('REFERRAL_ORDER_QUANTITY', intval(Tools::getValue('order_quantity')));
foreach (Tools::getValue('discount_value') as $id_currency => $discount_value)
Configuration::updateValue('REFERRAL_DISCOUNT_VALUE_'.intval($id_currency), floatval($discount_value));
Configuration::updateValue('REFERRAL_DISCOUNT_TYPE', intval(Tools::getValue('discount_type')));
Configuration::updateValue('REFERRAL_NB_FRIENDS', intval(Tools::getValue('nb_friends')));
Configuration::updateValue('REFERRAL_DISCOUNT_DESCRIPTION', Tools::getValue('discount_description'));
$this->_html .= $this->displayConfirmation($this->l('Configuration updated.'));
}
private function _postValidation()
{
$this->_errors = array();
if (!intval(Tools::getValue('order_quantity')) OR Tools::getValue('order_quantity') < 0)
$this->_errors[] = $this->displayError($this->l('Order quantity is required/invalid.'));
if (!is_array(Tools::getValue('discount_value')))
$this->_errors[] = $this->displayError($this->l('Discount value is invalid.'));
foreach (Tools::getValue('discount_value') as $id_currency => $discount_value)
if ($discount_value == '')
$this->_errors[] = $this->displayError($this->l('Discount value for the currency #').$id_currency.$this->l(' is empty.'));
elseif (!Validate::isUnsignedFloat($discount_value))
$this->_errors[] = $this->displayError($this->l('Discount value for the currency #').$id_currency.$this->l(' is invalid.'));
if (!intval(Tools::getValue('discount_type')) OR Tools::getValue('discount_type') < 1 OR Tools::getValue('discount_type') > 2)
$this->_errors[] = $this->displayError($this->l('Discount type is required/invalid.'));
if (!intval(Tools::getValue('nb_friends')) OR Tools::getValue('nb_friends') < 0)
$this->_errors[] = $this->displayError($this->l('Number of friends is required/invalid.'));
}
private function _writeXml()
{
$forbiddenKey = array('submitUpdate'); // Forbidden key
// Generate new XML data
$newXml = '<'.'?xml version=\'1.0\' encoding=\'utf-8\' ?>'."\n";
$newXml .= ''."\n";
$newXml .= "\t".'';
// Making body data
foreach ($_POST AS $key => $field)
{
if ($line = $this->putContent($newXml, $key, $field, $forbiddenKey, 'body'))
$newXml .= $line;
}
$newXml .= "\n\t".''."\n";
$newXml .= ''."\n";
/* write it into the editorial xml file */
if ($fd = @fopen($this->_xmlFile, 'w'))
{
if (!@fwrite($fd, $newXml))
$this->_html .= $this->displayError($this->l('Unable to write to the xml file.'));
if (!@fclose($fd))
$this->_html .= $this->displayError($this->l('Can\'t close the xml file.'));
}
else
$this->_html .= $this->displayError($this->l('Unable to update the xml file. Please check the xml file\'s writing permissions.'));
}
public function putContent($xml_data, $key, $field, $forbidden, $section)
{
foreach ($forbidden AS $line)
if ($key == $line)
return 0;
if (!preg_match('/^'.$section.'_/i', $key))
return 0;
$key = preg_replace('/^'.$section.'_/i', '', $key);
$field = Tools::htmlentitiesDecodeUTF8(htmlspecialchars($field));
if (!$field)
return 0;
return ("\n\t\t".'<'.$key.'>'.$key.'>');
}
public function getContent()
{
if (Tools::isSubmit('submitReferralProgram'))
{
$this->_postValidation();
if (!sizeof($this->_errors))
$this->_postProcess();
else
foreach ($this->_errors AS $err)
$this->_html .= '
'.$err.'
';
}
elseif (Tools::isSubmit('submitText'))
{
foreach ($_POST AS $key => $value)
if (!Validate::isString(Tools::getValue($key)))
{
$this->_html .= $this->displayError($this->l('Invalid html field, javascript is forbidden'));
$this->_displayForm();
return $this->_html;
}
$this->_writeXml();
}
$this->_html .= ''.$this->displayName.'
';
$this->_displayForm();
$this->_displayFormRules();
return $this->_html;
}
private function _displayForm()
{
$divLangName = 'cpara¤dd';
$currencies = Currency::getCurrencies();
$this->_html .= '
';
}
private function _displayFormRules()
{
global $cookie;
// Languages preliminaries
$defaultLanguage = intval(Configuration::get('PS_LANG_DEFAULT'));
$languages = Language::getLanguages();
$iso = Language::getIsoById($defaultLanguage);
$divLangName = 'cpara¤dd';
// xml loading
$xml = false;
if (file_exists($this->_xmlFile))
{
if (!$xml = @simplexml_load_file($this->_xmlFile))
$this->_html .= $this->displayError($this->l('Your text is empty.'));
}
$this->_html .= '
';
}
/**
* Hook call when cart created and updated
* Display the discount name if the sponsor friend have one
*/
public function hookShoppingCart($params)
{
$cart = $params['cart'];
if (!isset($cart->id_customer))
return false;
if (!($id_referralprogram = ReferralProgramModule::isSponsorised(intval($cart->id_customer), true)))
return false;
$referralprogram = new ReferralProgramModule($id_referralprogram);
if (!Validate::isLoadedObject($referralprogram))
return false;
$discount = new Discount($referralprogram->id_discount);
if (!Validate::isLoadedObject($discount))
return false;
if ($cart->checkDiscountValidity($discount, $cart->getDiscounts(), $cart->getOrderTotal(true, 1), $cart->getProducts())===false)
{
global $smarty;
$smarty->assign(array(
'discount_display' => Discount::display($discount->value, $discount->id_discount_type, new Currency($params['cookie']->id_currency)),
'discount' => $discount
));
return $this->display(__FILE__, 'shopping-cart.tpl');
}
return false;
}
/**
* Hook display on customer account page
* Display an additional link on my-account and block my-account
*/
public function hookCustomerAccount($params)
{
return $this->display(__FILE__, 'my-account.tpl');
}
public function hookMyAccountBlock($params)
{
return $this->hookCustomerAccount($params);
}
/**
* Hook display on form create account
* Add an additional input on bottom for fill the sponsor's e-mail address
*/
public function hookCreateAccountForm($params)
{
global $smarty;
$blowfish = new Blowfish(_COOKIE_KEY_, _COOKIE_IV_);
$explodeResult = explode('|', $blowfish->decrypt(urldecode(Tools::getValue('sponsor'))));
if ($explodeResult AND count($explodeResult) > 1 AND list($id_referralprogram, $email) = $explodeResult AND intval($id_referralprogram) AND Validate::isEmail($email) AND $id_referralprogram == ReferralProgramModule::isEmailExists($email))
{
$referralprogram = new ReferralProgramModule($id_referralprogram);
if (Validate::isLoadedObject($referralprogram))
{
/* hack for display referralprogram information in form */
$_POST['customer_firstname'] = $referralprogram->firstname;
$_POST['firstname'] = $referralprogram->firstname;
$_POST['customer_lastname'] = $referralprogram->lastname;
$_POST['lastname'] = $referralprogram->lastname;
$_POST['email'] = $referralprogram->email;
$_POST['email_create'] = $referralprogram->email;
$sponsor = new Customer($referralprogram->id_sponsor);
$_POST['referralprogram'] = $sponsor->email;
}
}
return $this->display(__FILE__, 'authentication.tpl');
}
/**
* Hook called on creation customer account
* Create a discount for the customer if sponsorised
*/
public function hookCreateAccount($params)
{
global $cookie;
$newCustomer = $params['newCustomer'];
if (!Validate::isLoadedObject($newCustomer))
return false;
$postVars = $params['_POST'];
if (empty($postVars) OR !isset($postVars['referralprogram']) OR empty($postVars['referralprogram']))
return false;
$sponsorEmail = $postVars['referralprogram'];
if (!Validate::isEmail($sponsorEmail) OR $sponsorEmail == $newCustomer->email)
return false;
$sponsor = new Customer();
if ($sponsor = $sponsor->getByEmail($sponsorEmail))
{
if ($id_referralprogram = ReferralProgramModule::isEmailExists($newCustomer->email, true, false))
{
$referralprogram = new ReferralProgramModule($id_referralprogram);
if ($referralprogram->id_sponsor == $sponsor->id)
{
$referralprogram->id_customer = $newCustomer->id;
$referralprogram->save();
if ($referralprogram->registerDiscountForSponsored(intval($params['cookie']->id_currency)))
{
$discount = new Discount(intval($referralprogram->id_discount));
if (Validate::isLoadedObject($discount))
{
$data = array(
'{firstname}' => $newCustomer->firstname,
'{lastname}' => $newCustomer->lastname,
'{voucher_num}' => $discount->name,
'{voucher_amount}' => Tools::displayPrice(floatval(Configuration::get('REFERRAL_DISCOUNT_VALUE_'.intval($cookie->id_currency))), intval(Configuration::get('PS_CURRENCY_DEFAULT'))));
Mail::Send(intval($cookie->id_lang), 'referralprogram-voucher', $this->l('Congratulations!'), $data, $newCustomer->email, $newCustomer->firstname.' '.$newCustomer->lastname, strval(Configuration::get('PS_SHOP_EMAIL')), strval(Configuration::get('PS_SHOP_NAME')), NULL, NULL, dirname(__FILE__).'/mails/');
}
}
return true;
}
}
}
return false;
}
/**
* Hook display in tab AdminCustomers on BO
* Data table with all sponsors informations for a customer
*/
public function hookAdminCustomers($params)
{
$customer = new Customer(intval($params['id_customer']));
if (!Validate::isLoadedObject($customer))
die (Tools::displayError('Incorrect object Customer.'));
global $cookie;
$friends = ReferralProgramModule::getSponsorFriend($customer->id);
if ($id_referralprogram = ReferralProgramModule::isSponsorised(intval($customer->id), true))
{
$referralprogram = new ReferralProgramModule($id_referralprogram);
$sponsor = new Customer($referralprogram->id_sponsor);
}
$html = ''.$this->l('Referral program').'
';
// link to the detail of the sponsor
$html.= ''.(isset($sponsor) ? $this->l('Customer\'s sponsor:').' '.$sponsor->firstname.' '.$sponsor->lastname.'' : $this->l('No one has sponsored this customer.')).'
';
if ($friends AND sizeof($friends))
{
$html.= ''.sizeof($friends).' '.(sizeof($friends) > 1 ? $this->l('sponsored customers:') : $this->l('sponsored customer:')).'
';
$html.= '
| '.$this->l('ID').' |
'.$this->l('Name').' |
'.$this->l('Email').' |
'.$this->l('Registration date').' |
'.$this->l('Sponsored customers').' |
'.$this->l('Placed orders').' |
'.$this->l('Inscribed').' |
';
foreach ($friends AS $key => $friend)
{
$orders = Order::getCustomerOrders($friend['id_customer']);
$html.= '
| '.(intval($friend['id_customer']) ? $friend['id_customer'] : '--').' |
'.$friend['firstname'].' '.$friend['lastname'].' |
'.$friend['email'].' |
'.Tools::displayDate($friend['date_add'], intval($cookie->id_lang), true).' |
'.sizeof(ReferralProgramModule::getSponsorFriend($friend['id_customer'])).' |
'.($orders ? sizeof($orders) : 0).' |
'.(intval($friend['id_customer']) ? ' ' : ' ').' |
';
}
$html.= '
';
}
else
$html.= $customer->firstname.' '.$customer->lastname.' '.$this->l('has not sponsored any friends yet.');
return $html.'
';
}
/**
* Hook called when a order is confimed
* display a message to customer about sponsor discount
*/
public function hookOrderConfirmation($params)
{
$order = $params['objOrder'];
if ($order AND !Validate::isLoadedObject($order))
return die (Tools::displayError('Incorrect object Order.'));
$customer = new Customer($order->id_customer);
$stats = $customer->getStats();
$nbOrdersCustomer = intval($stats['nb_orders']) + 1; // hack to count current order
$referralprogram = new ReferralProgramModule(ReferralProgramModule::isSponsorised(intval($customer->id), true));
if (!Validate::isLoadedObject($referralprogram))
return false;
$sponsor = new Customer($referralprogram->id_sponsor);
if (intval($nbOrdersCustomer) == intval($this->_configuration['REFERRAL_ORDER_QUANTITY']))
{
$discount = new Discount($referralprogram->id_discount_sponsor);
if (!Validate::isLoadedObject($discount))
return false;
$discount_display = $discount->display($discount->value, $discount->id_discount_type, new Currency($order->id_currency));
global $smarty;
$smarty->assign(array(
'discount' => $discount_display,
'sponsor_firstname' => $sponsor->firstname,
'sponsor_lastname' => $sponsor->lastname
));
return $this->display(__FILE__, 'order-confirmation.tpl');
}
return false;
}
/**
* Hook called when order status changed
* register a discount for sponsor and send him an e-mail
*/
public function hookUpdateOrderStatus($params)
{
if (!Validate::isLoadedObject($params['newOrderStatus']))
die (Tools::displayError('Some parameters are missing.'));
$orderState = $params['newOrderStatus'];
$order = new Order(intval($params['id_order']));
if ($order AND !Validate::isLoadedObject($order))
die (Tools::displayError('Incorrect object Order.'));
$customer = new Customer($order->id_customer);
$stats = $customer->getStats();
$nbOrdersCustomer = intval($stats['nb_orders']) + 1; // hack to count current order
$referralprogram = new ReferralProgramModule(ReferralProgramModule::isSponsorised(intval($customer->id), true));
if (!Validate::isLoadedObject($referralprogram))
return false;
$sponsor = new Customer($referralprogram->id_sponsor);
if (intval($orderState->logable) AND $nbOrdersCustomer >= intval($this->_configuration['REFERRAL_ORDER_QUANTITY']) AND $referralprogram->registerDiscountForSponsor(intval($order->id_currency)))
{
$discount = new Discount($referralprogram->id_discount_sponsor);
$currency = new Currency($order->id_currency);
$discount_display = $discount->display($discount->value, $discount->id_discount_type, $currency);
$data = array(
'{sponsored_firstname}' => $customer->firstname,
'{sponsored_lastname}' => $customer->lastname,
'{discount_display}' => $discount_display,
'{discount_name}' => $discount->name
);
Mail::Send(intval($order->id_lang), 'referralprogram-congratulations', $this->l('Congratulations!'), $data, $sponsor->email, $sponsor->firstname.' '.$sponsor->lastname, strval(Configuration::get('PS_SHOP_EMAIL')), strval(Configuration::get('PS_SHOP_NAME')), NULL, NULL, dirname(__FILE__).'/mails/');
return true;
}
return false;
}
}
?>