Page MenuHomeIn-Portal Phabricator

in-commerce
No OneTemporary

File Metadata

Created
Fri, Jun 13, 8:57 PM

in-commerce

Index: branches/5.0.x/units/gateways/gw_classes/atosorigin.php
===================================================================
--- branches/5.0.x/units/gateways/gw_classes/atosorigin.php (revision 13261)
+++ branches/5.0.x/units/gateways/gw_classes/atosorigin.php (revision 13262)
@@ -1,191 +1,192 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
require_once GW_CLASS_PATH.'/gw_base.php';
$class_name = 'kAtosOriginGW'; // for automatic installation
class kAtosOriginGW extends kGWBase
{
function InstallData()
{
$data = array(
'Gateway' => Array('Name' => 'Atos Origin', 'ClassName' => 'kAtosOriginGW', 'ClassFile' => 'atosorigin.php', 'RequireCCFields' => 0),
'ConfigFields' => Array(
'request_binary' => Array('Name' => 'API Request Executable', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'response_binary' => Array('Name' => 'API Response Executable', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'pathfile' => Array('Name' => 'Pathfile', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'merchant_id' => Array('Name' => 'Merchant ID', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'merchant_country' => Array('Name' => 'Merchant Country Code', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'currency_code' => Array('Name' => 'Currency Code', 'Type' => 'text', 'ValueList' => '', 'Default' => '978'),
'shipping_control' => Array('Name' => 'Shipping Control', 'Type' => 'select', 'ValueList' => '3=la_CreditDirect,4=la_CreditPreAuthorize', 'Default' => '3'),
)
);
return $data;
}
/**
* Returns payment form submit url
*
* @param Array $gw_params gateway params from payment type config
* @return string
*/
function getFormAction($gw_params)
{
return $gw_params['submit_url'];
}
/**
* Processed input data and convets it to fields understandable by gateway
*
* @param Array $item_data
* @param Array $tag_params additional params for gateway passed through tag
* @param Array $gw_params gateway params from payment type config
* @return Array
*/
function getHiddenFields($item_data, $tag_params, $gw_params)
{
$params['pathfile'] = $gw_params['pathfile'];
$params['merchant_id'] = $gw_params['merchant_id'];
$params['merchant_country'] = $gw_params['merchant_country'];
$params['currency_code'] = $gw_params['currency_code'];
$params['currency_code'] = $gw_params['currency_code'];
$params['normal_return_url'] = $this->Application->HREF($tag_params['return_template'],'',Array('pass'=>'m'));
$params['cancel_return_url'] = $this->Application->HREF($tag_params['cancel_template'],'',Array('pass'=>'m'));
$params['automatic_response_url'] = $this->Application->BaseURL('/in-commerce/units/gateways/gw_classes/notify_scripts').'atosorigin_notify.php';
$txt_amount = sprintf("%.2f", $item_data['TotalAmount']);
- $params['amount'] = eregi_replace("[.,]", '', $txt_amount);
- $params['caddie'] = $this->Application->GetSID().','.MD5($item_data['OrderId']);
+
+ $params['amount'] = str_replace( Array('.', ','), '', $txt_amount);
+ $params['caddie'] = $this->Application->GetSID() . ',' . MD5($item_data['OrderId']);
$params['order_id'] = $item_data['OrderId'];
$params['customer_ip_address'] = $_SERVER['REMOTE_ADDR'];
$params['customer_id'] = $item_data['PortalUserId'];
$billing_email = $item_data['BillingEmail'];
if (!$billing_email) {
$billing_email = $this->Conn->GetOne(' SELECT Email FROM '.$this->Application->getUnitOption('u', 'TableName').'
WHERE PortalUserId = '.$this->Application->RecallVar('user_id'));
}
$params['customer_email'] = $billing_email;
$params_str = '';
foreach ($params as $key => $val) {
$params_str .= ' '.$key . '="'.$val.'"';
}
$run_line = $gw_params['request_binary'].' '.$params_str;
// $run_line = escapeshellcmd($run_line);
// echo $run_line;
exec ($run_line, $rets);
$ret = $rets[0];
- $ret = eregi_replace("^.*\!\!", '', $ret);
- $ret = chop($ret, '!');
+ $ret = preg_replace('/^(.*)!!/is', '', $ret);
+ $ret = rtrim($ret, '!');
return '</form>'.$ret.'<form>';
}
function NeedPlaceButton($item_data, $tag_params, $gw_params)
{
return false;
}
function processNotification($gw_params)
{
$params['pathfile'] = $gw_params['pathfile'];
$params['message'] = $_POST['DATA'];
$params_str = '';
foreach ($params as $key => $val) {
$params_str .= ' '.$key . '="'.$val.'"';
}
$run_line = $gw_params['response_binary'].' '.$params_str;
exec ($run_line, $rets);
$ret = $rets[0];
$result = $this->parseGWResponce($ret);
list ($sid, $auth_code) = explode(',', $result['caddie']);
$session =& $this->Application->recallObject('Session');
$session->SID = $sid;
$order_id = $this->Conn->GetOne('SELECT OrderId FROM '.TABLE_PREFIX.'Orders WHERE md5(OrderId) = '.$this->Conn->qstr($auth_code));
$this->Application->SetVar('ord_id', $order_id);
$order =& $this->Application->recallObject('ord');
$order->Load($order_id);
return $result['response_code'] === '00' ? 1 : 0;
}
function parseGWResponce($str)
{
$response = explode ("!", $str);
$result = Array (
'code' => $response[1],
'error' => $response[2],
'merchant_id' => $response[3],
'merchant_country' => $response[4],
'amount' => $response[5],
'transaction_id' => $response[6],
'payment_means' => $response[7],
'transmission_date' => $response[8],
'payment_time' => $response[9],
'payment_date' => $response[10],
'response_code' => $response[11],
'payment_certificate' => $response[12],
'authorisation_id' => $response[13],
'currency_code' => $response[14],
'card_number' => $response[15],
'cvv_flag' => $response[16],
'cvv_response_code' => $response[17],
'bank_response_code' => $response[18],
'complementary_code' => $response[19],
'complementary_info' => $response[20],
'return_context' => $response[21],
'caddie' => $response[22],
'receipt_complement' => $response[23],
'merchant_language' => $response[24],
'language' => $response[25],
'customer_id' => $response[26],
'order_id' => $response[27],
'customer_email' => $response[28],
'customer_ip_address' => $response[29],
'capture_day' => $response[30],
'capture_mode' => $response[31],
'data' => $response[32],
);
$this->parsed_responce = $result;
return $result;
}
function getGWResponce()
{
return serialize($this->parsed_responce);
}
function getErrorMsg()
{
$msg = $this->parsed_responce['error'];
if (!$msg) {
if ($this->parsed_responce['response_code'] != '00') {
$msg = 'Transaction failed';
}
}
return $msg;
}
}
\ No newline at end of file
Index: branches/5.0.x/units/gateways/gw_classes/paybox.php
===================================================================
--- branches/5.0.x/units/gateways/gw_classes/paybox.php (revision 13261)
+++ branches/5.0.x/units/gateways/gw_classes/paybox.php (revision 13262)
@@ -1,182 +1,182 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
require_once GW_CLASS_PATH.'/gw_base.php';
$class_name = 'kPayboxGW'; // for automatic installation
class kPayboxGW extends kGWBase
{
function InstallData()
{
$data = array(
'Gateway' => Array('Name' => 'Paybox.com', 'ClassName' => 'kPayboxGW', 'ClassFile' => 'paybox.php', 'RequireCCFields' => 0),
'ConfigFields' => Array(
'binary' => Array('Name' => 'API Executable', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'params_file' => Array('Name' => 'OPT Params File', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'site_number' => Array('Name' => 'Site Number', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'rank_number' => Array('Name' => 'Rank Number', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'identity_number' => Array('Name' => 'Identity Number', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'currency_code' => Array('Name' => 'Currency Code', 'Type' => 'text', 'ValueList' => '', 'Default' => '978'),
'shipping_control' => Array('Name' => 'Shipping Control', 'Type' => 'select', 'ValueList' => '3=la_CreditDirect,4=la_CreditPreAuthorize', 'Default' => '3'),
)
);
return $data;
}
/**
* Returns payment form submit url
*
* @param Array $gw_params gateway params from payment type config
* @return string
*/
function getFormAction($gw_params)
{
return $gw_params['submit_url'];
}
/**
* Processed input data and convets it to fields understandable by gateway
*
* @param Array $item_data
* @param Array $tag_params additional params for gateway passed through tag
* @param Array $gw_params gateway params from payment type config
* @return Array
*/
function getHiddenFields($item_data, $tag_params, $gw_params)
{
$params['PBX_MODE'] = $gw_params['params_file'] ? '34' : '4';
$params['PBX_OUTPUT'] = 'B';
$params['PBX_SITE'] = $gw_params['site_number'];
$params['PBX_RANG'] = $gw_params['rank_number'];
$params['PBX_IDENTIFIANT'] = $gw_params['identity_number'];
$params['PBX_OPT'] = $gw_params['params_file'];
$params['PBX_DEVISE'] = $gw_params['currency_code']; // 978 for the euro. 840 for the US dollar.
$params['PBX_RETOUR'] = 'amount:M;reference:R;trans:T;autorization:A;subscription:B;payment:P;card:C;trans_id:S;country:Y;error:E;expiration:D';
$params['PBX_EFFECTUE'] = $this->Application->HREF($tag_params['return_template'],'',Array('pass'=>'m'));
$params['PBX_REFUSE'] = $this->Application->HREF($tag_params['cancel_template'],'',Array('pass'=>'m'));
$txt_amount = sprintf("%.2f", $item_data['TotalAmount']);
- $params['PBX_TOTAL'] = eregi_replace("[.,]", '', $txt_amount);
+ $params['PBX_TOTAL'] = str_replace( Array('.', ','), '', $txt_amount);
$params['PBX_CMD'] = $this->Application->GetSID().','.MD5($item_data['OrderId']);
/*$params['order_id'] = $item_data['OrderId'];
$params['customer_ip_address'] = $_SERVER['REMOTE_ADDR'];
$params['customer_id'] = $item_data['PortalUserId'];*/
$billing_email = $item_data['BillingEmail'];
if (!$billing_email) {
$billing_email = $this->Conn->GetOne(' SELECT Email FROM '.$this->Application->getUnitOption('u', 'TableName').'
WHERE PortalUserId = '.$this->Application->RecallVar('user_id'));
}
$params['PBX_PORTEUR'] = $billing_email;
$params_str = '';
foreach ($params as $key => $val) {
$params_str .= ' '.$key . '="'.$val.'"';
}
$run_line = $gw_params['binary'].' '.$params_str;
// $run_line = escapeshellcmd($run_line);
// echo escapeshellcmd($run_line);
exec ($run_line, $rets);
$ret = implode("\n", $rets);
- $ret = eregi_replace("^.*\!\!", '', $ret);
- $ret = chop($ret, '!');
+ $ret = preg_replace('/^(.*)!!/is', '', $ret);
+ $ret = rtrim($ret, '!');
return '</form>'.$ret.'<form>';
}
function NeedPlaceButton($item_data, $tag_params, $gw_params)
{
return false;
}
function processNotification($gw_params)
{
$result = $this->Application->HttpQuery->GetParams();
$this->parsed_responce = $result;
list ($sid, $auth_code) = explode(',', $result['reference']);
$session =& $this->Application->recallObject('Session');
$session->SID = $sid;
$order_id = $this->Conn->GetOne('SELECT OrderId FROM '.TABLE_PREFIX.'Orders WHERE md5(OrderId) = '.$this->Conn->qstr($auth_code));
$this->Application->SetVar('ord_id', $order_id);
$order =& $this->Application->recallObject('ord');
$order->Load($order_id);
return $result['error'] === '00000' ? 1 : 0;
}
function parseGWResponce($str)
{
$response = explode ("!", $str);
$result = Array (
'code' => $response[1],
'error' => $response[2],
'merchant_id' => $response[3],
'merchant_country' => $response[4],
'amount' => $response[5],
'transaction_id' => $response[6],
'payment_means' => $response[7],
'transmission_date' => $response[8],
'payment_time' => $response[9],
'payment_date' => $response[10],
'response_code' => $response[11],
'payment_certificate' => $response[12],
'authorisation_id' => $response[13],
'currency_code' => $response[14],
'card_number' => $response[15],
'cvv_flag' => $response[16],
'cvv_response_code' => $response[17],
'bank_response_code' => $response[18],
'complementary_code' => $response[19],
'complementary_info' => $response[20],
'return_context' => $response[21],
'caddie' => $response[22],
'receipt_complement' => $response[23],
'merchant_language' => $response[24],
'language' => $response[25],
'customer_id' => $response[26],
'order_id' => $response[27],
'customer_email' => $response[28],
'customer_ip_address' => $response[29],
'capture_day' => $response[30],
'capture_mode' => $response[31],
'data' => $response[32],
);
$this->parsed_responce = $result;
return $result;
}
function getGWResponce()
{
return serialize($this->parsed_responce);
}
function getErrorMsg()
{
$msg = '';
if ($this->parsed_responce['response_code'] != '00000') {
$msg = 'Transaction failed';
}
return $msg;
}
}
\ No newline at end of file
Index: branches/5.0.x/units/gateways/gw_classes/ideal_nl.php
===================================================================
--- branches/5.0.x/units/gateways/gw_classes/ideal_nl.php (revision 13261)
+++ branches/5.0.x/units/gateways/gw_classes/ideal_nl.php (revision 13262)
@@ -1,159 +1,159 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
/* http://www.ideal.nl/ gateway class */
require_once GW_CLASS_PATH.'/gw_base.php';
$class_name = 'kGWiDEALnl'; // for automatic installation
class kGWiDEALnl extends kGWBase
{
function InstallData()
{
$data = array(
'Gateway' => Array('Name' => 'iDEAL.nl', 'ClassName' => 'kGWiDEALnl', 'ClassFile' => 'ideal_nl.php', 'RequireCCFields' => 0),
'ConfigFields' => Array(
'partner_id' => Array('Name' => 'Partner ID', 'Type' => 'text', 'ValueList' => '', 'Default' => ''),
'request_url' => Array('Name' => 'Request URL', 'Type' => 'text', 'ValueList' => '', 'Default' => 'http://www.mollie.nl/xml/ideals'),
'shipping_control' => Array('Name' => 'Shipping Control', 'Type' => 'select', 'ValueList' => '3=la_CreditDirect,4=la_CreditPreAuthorize', 'Default' => '3'),
)
);
return $data;
}
/**
* Processed input data and convets it to fields understandable by gateway
*
* @param Array $item_data
* @param Array $tag_params additional params for gateway passed through tag
* @param Array $gw_params gateway params from payment type config
* @return Array
*/
function getHiddenFields($item_data, $tag_params, $gw_params)
{
$this->Application->StoreVar('gw_success_template',$tag_params['return_template']);
$this->Application->StoreVar('gw_cancel_template',$tag_params['cancel_template']);
$banks_query = $gw_params['request_url'].'?a=banklist';
$banks = curl_post($banks_query, null, null, 'GET');
$parser =& $this->Application->recallObject('kXMLHelper');
/* @var $parser kXMLHelper */
$bank_data =& $parser->Parse($banks);
$bank_data->FindChild('response');
$banks = array();
foreach ($bank_data->Children as $a_child) {
if ($a_child->Name != 'BANK') continue;
$banks[$a_child->FindChildValue('bank_id')] = $a_child->FindChildValue('bank_name');
}
$ret = $this->Application->Phrase('lu_Select_iDEAL_bank').': <select name="ideal_nl_bank_id">';
foreach ($banks as $id => $name) {
$ret .= '<option value="'.$id.'">'.$name.'</option>';
}
$ret .= '</select>';
$ret .= '<input type="hidden" name="events[ord]" value="OnCompleteOrder" />'."\n";
return $ret;
}
function DirectPayment($item_data, $gw_params)
{
$fields = array();
$fields['a'] = 'fetch';
$fields['partnerid'] = $gw_params['partner_id'];
$txt_amount = sprintf("%.2f", $item_data['TotalAmount']);
- $fields['amount'] = eregi_replace("[.,]", '', $txt_amount);
+ $fields['amount'] = str_replace( Array('.', ','), '', $txt_amount);
$fields['bank_id'] = $this->Application->GetVar('ideal_nl_bank_id');
$fields['description'] = 'Invoice #'.$item_data['OrderNumber'];
$fields['returnurl'] = $this->Application->BaseURL('/in-commerce').'gw_notify.php?order_id='.$item_data['OrderId'];
$fields['reporturl'] = $this->Application->BaseURL('/in-commerce').'gw_notify.php?mode=report&order_id='.$item_data['OrderId'];
$transaction_xml = curl_post($gw_params['request_url'], $fields, null, 'GET');
$parser =& $this->Application->recallObject('kXMLHelper');
/* @var $parser kXMLHelper */
$trans_data =& $parser->Parse($transaction_xml);
$transaction_id = $trans_data->FindChildValue('transaction_id');
$url = $trans_data->FindChildValue('url');
if ($transaction_id && $url) {
$this->Application->Redirect('external:'.$url);
}
else {
$error_msg = $trans_data->FindChildValue('message');
$this->parsed_responce['XML'] = $transaction_xml;
$this->Application->SetVar('failure_template', $this->Application->RecallVar('gw_cancel_template'));
$this->parsed_responce['MESSAGE'] = $error_msg ? $error_msg : 'Unknown gateway error ('.htmlspecialchars($transaction_xml).')';
return false;
}
}
function getErrorMsg()
{
return $this->parsed_responce['MESSAGE'];
}
function getGWResponce()
{
return serialize($this->parsed_responce);
}
function processNotification($gw_params)
{
// silent mode
if ($this->Application->GetVar('mode') == 'report') {
$fields = array();
$fields['a'] = 'check';
$fields['partnerid'] = $gw_params['partner_id'];
$fields['transaction_id'] = $this->Application->GetVar('transaction_id');
$fields['bank_id'] = $this->Application->GetVar('ideal_nl_bank_id');
$check_xml = curl_post($gw_params['request_url'], $fields, null, 'GET');
$parser =& $this->Application->recallObject('kXMLHelper');
/* @var $parser kXMLHelper */
$trans_data =& $parser->Parse($check_xml);
$response = $trans_data->FindChild('order');
foreach ($response->Children as $a_child) {
$this->parsed_responce[$a_child->Name] = $a_child->Data;
}
$this->parsed_responce['XML'] = $check_xml;
$result = $trans_data->FindChildValue('payed') == 'true' ? 1:0;
return $result;
}
else {
$order =& $this->Application->recallObject('ord');
if ($order->GetDBField('Status') == ORDER_STATUS_INCOMPLETE) {
// error
$t = $this->Application->RecallVar('gw_cancel_template');
$this->parsed_responce = unserialize($order->GetDBField('GWResult1'));
$this->Application->StoreVar('gw_error', $this->getErrorMsg());
$this->Application->Redirect($t, array('pass'=>'m', 'm_cat_id'=>0));
}
else {
// ok
$t = $this->Application->RecallVar('gw_success_template');
$this->Application->Redirect($t, array('pass'=>'m', 'm_cat_id'=>0));
}
}
}
}
\ No newline at end of file
Index: branches/5.0.x/units/shipping_quote_engines/usps.php
===================================================================
--- branches/5.0.x/units/shipping_quote_engines/usps.php (revision 13261)
+++ branches/5.0.x/units/shipping_quote_engines/usps.php (revision 13262)
@@ -1,1193 +1,1195 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
define('MODULE_SHIPPING_USPS_TEXT_TITLE', 'United States Postal Service');
define('MODULE_SHIPPING_USPS_TEXT_DESCRIPTION', 'You will need to have registered an account with USPS. Click <a target="_blank" href="https://secure.shippingapis.com/registration/"><strong>HERE</strong></a> for registration details. USPS expects you to use pounds as weight measure for your products.');
define('MODULE_SHIPPING_USPS_TEXT_ERROR', 'An error occured with the USPS shipping calculations.<br>If you prefer to use USPS as your shipping method, please contact the store owner.');
define('MODULE_SHIPPING_USPS_TEXT_DAY', 'Day');
define('MODULE_SHIPPING_USPS_TEXT_DAYS', 'Days');
define('MODULE_SHIPPING_USPS_TEXT_WEEKS', 'Weeks');
define('MODULE_SHIPPING_USPS_STATUS', 'True'); // Do you want to offer USPS shipping?
define('MODULE_SHIPPING_USPS_SERVER', 'production'); // An account at USPS is needed to use the Production server // production othervise value may be 'test'
define('MODULE_SHIPPING_USPS_HANDLING', '0'); // Handling fee for this shipping method
define('MODULE_SHIPPING_USPS_TAX_CLASS', '0'); // Use the following tax class on the shipping fee
define('MODULE_SHIPPING_USPS_ZONE', '0'); // If a zone is selected, only enable this shipping method for that zone.
define('MODULE_SHIPPING_USPS_SORT_ORDER', '0'); // Sort order of display.
define('MODULE_SHIPPING_USPS_TYPES', 'PRIORITY, PARCEL'); // EXPRESS, FIRST CLASS, BMP, MEDIA 'Select the domestic services to be offered:
define('MODULE_SHIPPING_USPS_TYPES_INTL', 'EXPRESS MAIL INTERNATIONAL (EMS), EXPRESS MAIL INT, EXPRESS MAIL INT FLAT RATE ENV, PRIORITY MAIL INT, PRIORITY MAIL INT FLAT RATE ENV, PRIORITY MAILINT FLAT RATE BOX, FIRST-CLASS MAIL INT');// 'GLOBAL EXPRESS, GLOBAL EXPRESS NON-DOC RECT, GLOBAL EXPRESS NON-DOC NON-RECT, Select the international services to be offered:
define('MODULE_SHIPPING_USPS_OPTIONS', 'Display weight, Display transit time'); //
//configuration values for insurance
define('MODULE_SHIPPING_USPS_INS1', '1.65');// 'US/Canada insurance for totals $.01-$50.00
define('MODULE_SHIPPING_USPS_INS2', '2.05');// 'US/Canada insurance for totals $50.01-$100
define('MODULE_SHIPPING_USPS_INS3', '2.45');// 'US/Canada insurance for totals $100.01-$200
define('MODULE_SHIPPING_USPS_INS4', '4.60');// 'US/Canada insurance for totals $200.01-$300
define('MODULE_SHIPPING_USPS_INS5', '.90');// 'US/Canada insurance for every $100 over $300 (add)
define('MODULE_SHIPPING_USPS_INS6', '2.40');// 'International insurance for totals $.01-$50.00
define('MODULE_SHIPPING_USPS_INS7', '3.30');// 'International insurance for totals $50.01-$100
define('MODULE_SHIPPING_USPS_INS8', '4.20');// 'International insurance for totals $100.01-$200
define('MODULE_SHIPPING_USPS_INS9', '5.10');// 'International insurance for totals $200.01-$300
define('MODULE_SHIPPING_USPS_INS10', '.90');// 'International insurance for every $100 over $300 (add)
define('MODULE_SHIPPING_USPS_INSURE', 'True');// 'Insure packages shipped by USPS?
define('MODULE_SHIPPING_USPS_INSURE_TAX', 'True');// 'Insure tax on packages shipped by USPS?
define('USPS_LOG_FILE', WRITEABLE .'/user_files/usps.log');
class USPS extends ShippingQuoteEngine
{
var $countries, $pounds, $ounces, $insurance_cost = 0, $shipping_origin_country, $store_first_name, $store_last_name, $company_name, $store_name, $store_address1, $store_address2, $store_city, $store_state, $store_zip5, $store_zip4, $store_phone, $usps_userid;
var $order = Array();
var $types = Array();
var $intl_types = Array();
function USPS()
{
parent::kBase();
// EXPRESS, FIRST CLASS, PRIORITY, PARCEL, BMP, MEDIA
$this->types = Array(
'EXPRESS' => 'Express Mail',
'FIRST CLASS' => 'First Class Mail',
'PRIORITY' => 'Priority Mail',
'PARCEL' => 'Parcel Post',
'BPM' => 'Bound Printed Matter',
'MEDIA' => 'Media Mail'
);
$this->intl_types = Array(
// 'GLOBAL EXPRESS' => 'Global Express Guaranteed',
// 'GLOBAL EXPRESS NON-DOC RECT' => 'Global Express Guaranteed Non-Document Rectangular',
// 'GLOBAL EXPRESS NON-DOC NON-RECT' => 'Global Express Guaranteed Non-Document Non-Rectangular',
'EXPRESS MAIL INT' => 'Express Mail International (EMS)',
'EXPRESS MAIL INT FLAT RATE ENV' => 'Express Mail International (EMS) Flat Rate Envelope',
'PRIORITY MAIL INT' => 'Priority Mail International',
'PRIORITY MAIL INT FLAT RATE ENV' => 'Priority Mail International Flat Rate Envelope',
'PRIORITY MAIL INT FLAT RATE BOX' => 'Priority Mail International Flat Rate Box',
'FIRST-CLASS MAIL INT' => 'First-Class Mail International'
);
// get 2-symbol country code
$country = $this->Application->ConfigValue('Comm_Shipping_Country');
if ($country != '') {
$db =& $this->Application->GetADODBConnection();
$this->shipping_origin_country = $db->GetOne(
'SELECT DestAbbr2
FROM '.TABLE_PREFIX.'StdDestinations
WHERE
DestAbbr = '.$db->qstr($country).'
AND destType = 1
'
);
}
$contact_name = trim($this->_prepare_xml_param($this->Application->ConfigValue('Comm_Contacts_Name')));
$split_pos = strpos($contact_name, ' ');
if ($split_pos === false) {
$this->store_first_name = $contact_name;
$this->store_last_name = '';
} else {
$this->store_first_name = substr($contact_name, 0, $split_pos);
$this->store_last_name = trim(substr($contact_name, $split_pos));
}
$this->company_name = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_CompanyName'));
$this->store_name = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_StoreName'));
$this->store_address1 = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_Shipping_AddressLine1'));
$this->store_address2 = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_Shipping_AddressLine2'));
if ($this->store_address2 == '') {
$this->store_address2 = $this->store_address1;
$this->store_address1 = '';
}
$this->store_city = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_Shipping_City'));
$this->store_state = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_Shipping_State'));
$zip = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_Shipping_ZIP'));
$this->store_zip5 = substr($zip, 0, 5);
$this->store_zip4 = trim(substr($zip, 6), '-');
$this->store_phone = $this->_prepare_xml_param($this->Application->ConfigValue('Comm_Contacts_Phone'));
// get username and password fron config.
$a_params = $this->LoadParams();
$this->usps_userid = $a_params['AccountLogin'];
// Note by Erik: DO NOT CHANGE THIS ARRAY. It's values are sent to USPS service and any changes may impact class main functionality.
$this->countries = array(
'AF' => 'Afghanistan',
'AL' => 'Albania',
'DZ' => 'Algeria',
'AD' => 'Andorra',
'AO' => 'Angola',
'AI' => 'Anguilla',
'AG' => 'Antigua and Barbuda',
'AR' => 'Argentina',
'AM' => 'Armenia',
'AW' => 'Aruba',
'AU' => 'Australia',
'AT' => 'Austria',
'AZ' => 'Azerbaijan',
'BS' => 'Bahamas',
'BH' => 'Bahrain',
'BD' => 'Bangladesh',
'BB' => 'Barbados',
'BY' => 'Belarus',
'BE' => 'Belgium',
'BZ' => 'Belize',
'BJ' => 'Benin',
'BM' => 'Bermuda',
'BT' => 'Bhutan',
'BO' => 'Bolivia',
'BA' => 'Bosnia-Herzegovina',
'BW' => 'Botswana',
'BR' => 'Brazil',
'VG' => 'British Virgin Islands',
'BN' => 'Brunei Darussalam',
'BG' => 'Bulgaria',
'BF' => 'Burkina Faso',
'MM' => 'Burma',
'BI' => 'Burundi',
'KH' => 'Cambodia',
'CM' => 'Cameroon',
'CA' => 'Canada',
'CV' => 'Cape Verde',
'KY' => 'Cayman Islands',
'CF' => 'Central African Republic',
'TD' => 'Chad',
'CL' => 'Chile',
'CN' => 'China',
'CX' => 'Christmas Island (Australia)',
'CC' => 'Cocos Island (Australia)',
'CO' => 'Colombia',
'KM' => 'Comoros',
'CG' => 'Congo (Brazzaville),Republic of the',
'ZR' => 'Congo, Democratic Republic of the',
'CK' => 'Cook Islands (New Zealand)',
'CR' => 'Costa Rica',
'CI' => 'Cote d\'Ivoire (Ivory Coast)',
'HR' => 'Croatia',
'CU' => 'Cuba',
'CY' => 'Cyprus',
'CZ' => 'Czech Republic',
'DK' => 'Denmark',
'DJ' => 'Djibouti',
'DM' => 'Dominica',
'DO' => 'Dominican Republic',
'TP' => 'East Timor (Indonesia)',
'EC' => 'Ecuador',
'EG' => 'Egypt',
'SV' => 'El Salvador',
'GQ' => 'Equatorial Guinea',
'ER' => 'Eritrea',
'EE' => 'Estonia',
'ET' => 'Ethiopia',
'FK' => 'Falkland Islands',
'FO' => 'Faroe Islands',
'FJ' => 'Fiji',
'FI' => 'Finland',
'FR' => 'France',
'GF' => 'French Guiana',
'PF' => 'French Polynesia',
'GA' => 'Gabon',
'GM' => 'Gambia',
'GE' => 'Georgia, Republic of',
'DE' => 'Germany',
'GH' => 'Ghana',
'GI' => 'Gibraltar',
'GB' => 'Great Britain and Northern Ireland',
'GR' => 'Greece',
'GL' => 'Greenland',
'GD' => 'Grenada',
'GP' => 'Guadeloupe',
'GT' => 'Guatemala',
'GN' => 'Guinea',
'GW' => 'Guinea-Bissau',
'GY' => 'Guyana',
'HT' => 'Haiti',
'HN' => 'Honduras',
'HK' => 'Hong Kong',
'HU' => 'Hungary',
'IS' => 'Iceland',
'IN' => 'India',
'ID' => 'Indonesia',
'IR' => 'Iran',
'IQ' => 'Iraq',
'IE' => 'Ireland',
'IL' => 'Israel',
'IT' => 'Italy',
'JM' => 'Jamaica',
'JP' => 'Japan',
'JO' => 'Jordan',
'KZ' => 'Kazakhstan',
'KE' => 'Kenya',
'KI' => 'Kiribati',
'KW' => 'Kuwait',
'KG' => 'Kyrgyzstan',
'LA' => 'Laos',
'LV' => 'Latvia',
'LB' => 'Lebanon',
'LS' => 'Lesotho',
'LR' => 'Liberia',
'LY' => 'Libya',
'LI' => 'Liechtenstein',
'LT' => 'Lithuania',
'LU' => 'Luxembourg',
'MO' => 'Macao',
'MK' => 'Macedonia, Republic of',
'MG' => 'Madagascar',
'MW' => 'Malawi',
'MY' => 'Malaysia',
'MV' => 'Maldives',
'ML' => 'Mali',
'MT' => 'Malta',
'MQ' => 'Martinique',
'MR' => 'Mauritania',
'MU' => 'Mauritius',
'YT' => 'Mayotte (France)',
'MX' => 'Mexico',
'MD' => 'Moldova',
'MC' => 'Monaco (France)',
'MN' => 'Mongolia',
'MS' => 'Montserrat',
'MA' => 'Morocco',
'MZ' => 'Mozambique',
'NA' => 'Namibia',
'NR' => 'Nauru',
'NP' => 'Nepal',
'NL' => 'Netherlands',
'AN' => 'Netherlands Antilles',
'NC' => 'New Caledonia',
'NZ' => 'New Zealand',
'NI' => 'Nicaragua',
'NE' => 'Niger',
'NG' => 'Nigeria',
'KP' => 'North Korea (Korea, Democratic People\'s Republic of)',
'NO' => 'Norway',
'OM' => 'Oman',
'PK' => 'Pakistan',
'PA' => 'Panama',
'PG' => 'Papua New Guinea',
'PY' => 'Paraguay',
'PE' => 'Peru',
'PH' => 'Philippines',
'PN' => 'Pitcairn Island',
'PL' => 'Poland',
'PT' => 'Portugal',
'QA' => 'Qatar',
'RE' => 'Reunion',
'RO' => 'Romania',
'RU' => 'Russia',
'RW' => 'Rwanda',
'SH' => 'Saint Helena',
'KN' => 'Saint Kitts (St. Christopher and Nevis)',
'LC' => 'Saint Lucia',
'PM' => 'Saint Pierre and Miquelon',
'VC' => 'Saint Vincent and the Grenadines',
'SM' => 'San Marino',
'ST' => 'Sao Tome and Principe',
'SA' => 'Saudi Arabia',
'SN' => 'Senegal',
'YU' => 'Serbia-Montenegro',
'SC' => 'Seychelles',
'SL' => 'Sierra Leone',
'SG' => 'Singapore',
'SK' => 'Slovak Republic',
'SI' => 'Slovenia',
'SB' => 'Solomon Islands',
'SO' => 'Somalia',
'ZA' => 'South Africa',
'GS' => 'South Georgia (Falkland Islands)',
'KR' => 'South Korea (Korea, Republic of)',
'ES' => 'Spain',
'LK' => 'Sri Lanka',
'SD' => 'Sudan',
'SR' => 'Suriname',
'SZ' => 'Swaziland',
'SE' => 'Sweden',
'CH' => 'Switzerland',
'SY' => 'Syrian Arab Republic',
'TW' => 'Taiwan',
'TJ' => 'Tajikistan',
'TZ' => 'Tanzania',
'TH' => 'Thailand',
'TG' => 'Togo',
'TK' => 'Tokelau (Union) Group (Western Samoa)',
'TO' => 'Tonga',
'TT' => 'Trinidad and Tobago',
'TN' => 'Tunisia',
'TR' => 'Turkey',
'TM' => 'Turkmenistan',
'TC' => 'Turks and Caicos Islands',
'TV' => 'Tuvalu',
'UG' => 'Uganda',
'UA' => 'Ukraine',
'AE' => 'United Arab Emirates',
'UY' => 'Uruguay',
'UZ' => 'Uzbekistan',
'VU' => 'Vanuatu',
'VA' => 'Vatican City',
'VE' => 'Venezuela',
'VN' => 'Vietnam',
'WF' => 'Wallis and Futuna Islands',
'WS' => 'Western Samoa',
'YE' => 'Yemen',
'ZM' => 'Zambia',
'ZW' => 'Zimbabwe'
);
$this->countryinsure = array(
'AF' => 0,
'AL' => 0,
'DZ' => 2185,
'AD' => 5000,
'AO' => 0,
'AI' => 415,
'AG' => 60,
'AR' => 5000,
'AM' => 1350,
'AW' => 830,
'AU' => 3370,
'AT' => 5000,
'AZ' => 5000,
'BS' => 2795,
'BH' => 0,
'BD' => 5000,
'BB' => 220,
'BY' => 1323,
'BE' => 5000,
'BZ' => 1600,
'BJ' => 170,
'BM' => 440,
'BT' => 440,
'BO' => 0,
'BA' => 5000,
'BW' => 145,
'BR' => 5000,
'VG' => 165,
'BN' => 4405,
'BG' => 1030,
'BF' => 530,
'MM' => 4045,
'BI' => 790,
'KH' => 0,
'CM' => 5000,
'CA' => 675,
'CV' => 0,
'KY' => 0,
'CF' => 4405,
'TD' => 440,
'CL' => 0,
'CN' => 1130,
'CX' => 3370,
'CC' => 3370,
'CO' => 0,
'KM' => 690,
'CG' => 1685,
'ZR' => 0,
'CK' => 980,
'CR' => 0,
'CI' => 5000,
'HR' => 5000,
'CU' => 0,
'CY' => 5000,
'CZ' => 5000,
'DK' => 5000,
'DJ' => 880,
'DM' => 0,
'DO' => 0,
'TP' => 0,
'EC' => 0,
'EG' => 1685,
'SV' => 0,
'GQ' => 0,
'ER' => 0,
'EE' => 2020,
'ET' => 1000,
'FK' => 510,
'FO' => 5000,
'FJ' => 600,
'FI' => 5000,
'FR' => 5000,
'GF' => 5000,
'PF' => 1015,
'GA' => 485,
'GM' => 2575,
'GE' => 1350,
'DE' => 5000,
'GH' => 5000,
'GI' => 5000,
'GB' => 857,
'GR' => 5000,
'GL' => 5000,
'GD' => 350,
'GP' => 5000,
'GT' => 0,
'GN' => 875,
'GW' => 21,
'GY' => 10,
'HT' => 0,
'HN' => 0,
'HK' => 5000,
'HU' => 5000,
'IS' => 5000,
'IN' => 2265,
'ID' => 0,
'IR' => 0,
'IQ' => 0,
'IE' => 5000,
'IL' => 0,
'IT' => 5000,
'JM' => 0,
'JP' => 5000,
'JO' => 0,
'KZ' => 5000,
'KE' => 815,
'KI' => 0,
'KW' => 1765,
'KG' => 1350,
'LA' => 0,
'LV' => 1350,
'LB' => 440,
'LS' => 440,
'LR' => 440,
'LY' => 0,
'LI' => 5000,
'LT' => 5000,
'LU' => 5000,
'MO' => 4262,
'MK' => 2200,
'MG' => 675,
'MW' => 50,
'MY' => 1320,
'MV' => 0,
'ML' => 950,
'MT' => 5000,
'MQ' => 5000,
'MR' => 635,
'MU' => 270,
'YT' => 5000,
'MX' => 0,
'MD' => 1350,
'MC' => 5000,
'MN' => 440,
'MS' => 2200,
'MA' => 5000,
'MZ' => 0,
'NA' => 4405,
'NR' => 220,
'NP' => 0,
'NL' => 5000,
'AN' => 830,
'NC' => 1615,
'NZ' => 980,
'NI' => 440,
'NE' => 810,
'NG' => 205,
'KP' => 0,
'NO' => 0,
'OM' => 575,
'PK' => 270,
'PA' => 0,
'PG' => 445,
'PY' => 0,
'PE' => 0,
'PH' => 270,
'PN' => 0,
'PL' => 1350,
'PT' => 5000,
'QA' => 2515,
'RE' => 5000,
'RO' => 5000,
'RU' => 5000,
'RW' => 0,
'SH' => 170,
'KN' => 210,
'LC' => 400,
'PM' => 5000,
'VC' => 130,
'SM' => 5000,
'ST' => 440,
'SA' => 0,
'SN' => 865,
'YU' => 5000,
'SC' => 0,
'SL' => 0,
'SG' => 4580,
'SK' => 5000,
'SI' => 4400,
'SB' => 0,
'SO' => 440,
'ZA' => 1760,
'GS' => 510,
'KR' => 5000,
'ES' => 5000,
'LK' => 35,
'SD' => 0,
'SR' => 535,
'SZ' => 560,
'SE' => 5000,
'CH' => 5000,
'SY' => 3080,
'TW' => 1350,
'TJ' => 1350,
'TZ' => 230,
'TH' => 1350,
'TG' => 2190,
'TK' => 295,
'TO' => 515,
'TT' => 930,
'TN' => 2200,
'TR' => 880,
'TM' => 675,
'TC' => 0,
'TV' => 4715,
'UG' => 0,
'UA' => 5000,
'AE' => 5000,
'UY' => 0,
'UZ' => 5000,
'VU' => 0,
'VA' => 5000,
'VE' => 0,
'VN' => 0,
'WF' => 1615,
'WS' => 295,
'YE' => 0,
'ZM' => 540,
'ZW' => 600,
'US' => 5000
);
}
function SetInsurance()
{
$this->insurance_cost = 0;
// Insurance module by Kevin Shelton
// divide the value of the order among the packages based on the order total or subtotal depending on whether or not you have configured to insure tax
$shipping_weight = $this->order['ShippingWeight'];
$shipping_num_boxes = $this->order['ShippingNumBoxes'];
$costperpkg = $this->order['SubTotal'] / $shipping_num_boxes;
// retrieve the maximum allowed insurance for the destination country and if the package value exceeds it then set package value to the maximum allowed
$maxins = $this->countryinsure[$this->order['ShippingCountry']];
if ($costperpkg > $maxins) $costperpkg = $maxins;
// if insurance not allowed for destination or insurance is turned off add nothing to shipping cost
if (($maxins == 0) || (MODULE_SHIPPING_USPS_INSURE == 'False')) {
$insurance = 0;
}
// US and Canada share the same insurance calculation (though not the same maximum)
else if (($this->order['ShippingCountry'] == 'US') || ($this->order['ShippingCountry'] == 'CA'))
{
if ($costperpkg<=50) {
$insurance=MODULE_SHIPPING_USPS_INS1;
}
else if ($costperpkg<=100) {
$insurance=MODULE_SHIPPING_USPS_INS2;
}
else if ($costperpkg<=200) {
$insurance=MODULE_SHIPPING_USPS_INS3;
}
else if ($costperpkg<=300) {
$insurance=MODULE_SHIPPING_USPS_INS4;
}
else {
$insurance = MODULE_SHIPPING_USPS_INS4 + ((ceil($costperpkg/100) -3) * MODULE_SHIPPING_USPS_INS5);
}
}
// if insurance allowed and is not US or Canada then calculate international insurance
else {
if ($costperpkg<=50) {
$insurance=MODULE_SHIPPING_USPS_INS6;
}
else if ($costperpkg<=100) {
$insurance=MODULE_SHIPPING_USPS_INS7;
}
else if ($costperpkg<=200) {
$insurance=MODULE_SHIPPING_USPS_INS8;
}
else if ($costperpkg<=300) {
$insurance=MODULE_SHIPPING_USPS_INS9;
}
else {
$insurance = MODULE_SHIPPING_USPS_INS9 + ((ceil($costperpkg/100) - 3) * MODULE_SHIPPING_USPS_INS10);
}
}
// usps doesnt accept zero weight
$shipping_weight = ($shipping_weight < 0.1 ? 0.1 : $shipping_weight);
$shipping_pounds = floor ($shipping_weight);
$shipping_ounces = round(16 * ($shipping_weight - floor($shipping_weight)));
$this->_setWeight($shipping_pounds, $shipping_ounces);
// Added by Kevin Chen (kkchen@uci.edu); Fixes the Parcel Post Bug July 1, 2004
// Refer to http://www.usps.com/webtools/htm/Domestic-Rates.htm documentation
// Thanks Ryan
if($shipping_pounds > 35 || ($shipping_pounds == 0 && $shipping_ounces < 6)){
$this->_setMachinable('False');
}
else{
$this->_setMachinable('True');
}
$this->insurance_cost = $insurance;
// End Kevin Chen July 1, 2004
}
function _setService($service)
{
$this->service = $service;
}
function _setWeight($pounds, $ounces=0)
{
$this->pounds = $pounds;
$this->ounces = $ounces;
}
function _setContainer($container)
{
$this->container = $container;
}
function _setSize($size)
{
$this->size = $size;
}
function _setMachinable($machinable)
{
$this->machinable = $machinable;
}
function PhoneClean($phone)
{
- $res = ereg_replace("[(]|[)]|[\-]|[ ]|[#]|[\.]|[a-z](.*)|[A-Z](.*)", "", $phone);
- if ( strlen($res) > 10 ) $res = substr($res, 0, 10);
+ $res = preg_replace('/[(]|[)]|[\-]|[ ]|[#]|[\.]|[a-z](.*)|[A-Z](.*)/g', '', $phone);
+ if ( strlen($res) > 10 ) {
+ $res = substr($res, 0, 10);
+ }
return $res != '' ? $res : $phone;
}
function GetQuote($method = '')
{
if ( isset($this->types[$method]) || in_array($method, $this->intl_types)) {
$this->_setService($method);
}
$this -> _setContainer('None');
$this -> _setSize('REGULAR');
$this -> SetInsurance(); // ???
if ($this->order['ShippingCountry'] == $this->shipping_origin_country) {
$request='<?xml version="1.0"?>';
// PASSWORD="'.$this->usps_password.'"
$request.= '<RateV3Request USERID="'.$this->usps_userid.'">';
$services_count = 0;
if (isset($this->service)) {
$this->types = array($this->service => $this->types[$this->service]);
}
$dest_zip = str_replace(' ', '', $this->order['ShippingZip']);
$dest_zip = substr($dest_zip, 0, 5);
reset($this->types);
$allowed_types = explode(", ", MODULE_SHIPPING_USPS_TYPES);
while (list($key, $value) = each($this->types))
{
if ( !in_array($key, $allowed_types) ) continue;
$request .= '<Package ID="'.$services_count.'">'.
'<Service>'.$key.'</Service>'.
'<ZipOrigination>'.$this->store_zip5.'</ZipOrigination>'.
'<ZipDestination>'.$dest_zip.'</ZipDestination>'.
'<Pounds>'.$this->pounds.'</Pounds>'.
'<Ounces>'.$this->ounces.'</Ounces>'.
'<Size>'.$this->size.'</Size>'.
'<Machinable>'.$this->machinable.'</Machinable>'.
'</Package>';
$services_count++;
}
$request .= '</RateV3Request>';
$api_query = 'RateV3';
}
else {
$request = '<IntlRateRequest USERID="'.$this->usps_userid.'">'.
'<Package ID="0">'.
'<Pounds>'.$this->pounds.'</Pounds>'.
'<Ounces>'.$this->ounces.'</Ounces>'.
'<MailType>Package</MailType>'.
'<Country>'.$this->countries[$this->order['ShippingCountry']].'</Country>'.
'</Package>'.
'</IntlRateRequest>';
$api_query = 'IntlRate';
}
$request = 'API='.$api_query.'&XML=' . urlencode($request);
$body = $this->PostQuery($request);
$body = str_replace(chr(146), '', $body); // for bad `
// check for errors
if (strpos($body, '<Error>') !== false) {
$errors = Array ();
preg_match_all('/<Number>(.*?)<\/Number>/s', $body, $error_numbers);
preg_match_all('/<Description>(.*?)<\/Description>/s', $body, $error_descriptions);
foreach ($error_numbers[1] as $index => $error_number) {
$errors[$index] = $error_descriptions[1][$index];
if ($this->Application->isDebugMode()) {
$errors[$index] .= ' (' . $error_number . ')';
}
}
$errors = array_unique($errors); // we may have same errors on many packages, so don't show duplicates
return Array('error' => implode('<br/>', $errors));
}
// parse response
$xml_helper =& $this->Application->recallObject('kXMLHelper');
/* @var $xml_helper kXMLHelper */
$root_node =& $xml_helper->Parse($body);
/* @var $root_node kXMLNode */
$rates = Array();
// Domestic shipping
if ($this->order['ShippingCountry'] == $this->shipping_origin_country) {
$i = 0;
$postage_node =& $root_node->FindChild('Package');
do {
// $parcel_node =& $postage_node->firstChild;
$service = $postage_node->FindChildValue('MailService');
if ( $service != '' ) {
$i++;
$rates[$i] = Array();
$rates[$i]['Title'] = $service;
$rates[$i]['Rate'] = $this->insurance_cost + $postage_node->FindChildValue('Rate');
}
}
while ( $postage_node =& $postage_node->NextSibling());
}
else {
// for International Rates !!!
$allowed_types = array();
foreach( explode(", ", MODULE_SHIPPING_USPS_TYPES_INTL) as $value ) {
$allowed_types[$value] = $this->intl_types[$value];
}
$i = 0;
$service_node =& $root_node->FindChild('Service');
do {
$service = trim($service_node->FindChildValue('SvcDescription'));
if( !in_array($service, $allowed_types) ) continue;
$i++;
if ( $service_node->FindChildValue('MaxWeight') >= $this->pounds ) {
$rates[$i] = Array();
$rates[$i]['Title'] = $service;
$rates[$i]['MaxDimensions'] = $service_node->FindChildValue('MaxDimensions');
$rates[$i]['MaxWeight'] = $service_node->FindChildValue('MaxWeight');
$rates[$i]['SvcCommitments'] = $service_node->FindChildValue('SvcCommitments');
$rates[$i]['Rate'] = $this->insurance_cost + $service_node->FindChildValue('Postage');
}
}
while ( $service_node =& $service_node->NextSibling());
}
// print_r($rates);
// die('here');
return $rates;
}
function PostOrder()
{
$request='';
$base_request = '';
$this->SetInsurance();
// $this->order['ShippingCountry'] = $this->GetUSPSCountry($this->order['ShippingCountry']);
// Domestic Order
if ($this->order['ShippingCountry'] == $this->shipping_origin_country) {
// $dest_zip = str_replace(' ', '', $this->order['ShippingZip5']);
$this->order['ShippingZip5'] = substr($this->order['ShippingZip5'], 0, 5);
$WeightInOunces = floor($this->pounds * 16 + $this->ounces);
$base_request ='
<Option>1</Option>
<ImageParameters></ImageParameters>
<FromName>'.$this->store_name.'</FromName>
<FromFirm>'.$this->company_name.'</FromFirm>
<FromAddress1>'.$this->store_address1.'</FromAddress1>
<FromAddress2>'.$this->store_address2.'</FromAddress2>
<FromCity>'.$this->store_city.'</FromCity>
<FromState>'.$this->store_state.'</FromState>
<FromZip5>'.$this->store_zip5.'</FromZip5>
<FromZip4>'.$this->store_zip4.'</FromZip4>
<ToName>'.$this->order['FirstName'].' '.$this->order['LastName'].'</ToName>
<ToFirm>'.$this->order['ShippingCompany'].'</ToFirm>
<ToAddress1>'.$this->order['ShippingAddress2'].'</ToAddress1>
<ToAddress2>'.$this->order['ShippingAddress1'].'</ToAddress2>
<ToCity>'.$this->order['ShippingCity'].'</ToCity>
<ToState>'.$this->order['ShippingState'].'</ToState>
<ToZip5>'.$this->order['ShippingZip5'].'</ToZip5>
<ToZip4>'.$this->order['ShippingZip4'].'</ToZip4>
<WeightInOunces>'.$WeightInOunces.'</WeightInOunces>
<ServiceType>'.$this->order['ShippingService'].'</ServiceType>
<ImageType>PDF</ImageType>
<LabelDate>'.date('m/d/Y',time()).'</LabelDate>
<CustomerRefNo></CustomerRefNo>
<AddressServiceRequested></AddressServiceRequested>
<SenderName></SenderName><SenderEMail></SenderEMail>
<RecipientName></RecipientName>
<RecipientEMail></RecipientEMail>
';
$api_query = 'DeliveryConfirmationV3';
$xml_request = 'DeliveryConfirmationV3.0Request';
}
else {
// International Order(s)
$shipping_service = strtolower($this->order['ShippingService']);
$base_request = '<Option/>
<ImageParameters/>
<FromFirstName>'.$this->store_first_name.'</FromFirstName>
<FromLastName>'.$this->store_last_name.'</FromLastName>
<FromFirm>'.$this->company_name.'</FromFirm>
<FromAddress1>'.$this->store_address1.'</FromAddress1>
<FromAddress2>'.$this->store_address2.'</FromAddress2>
<FromCity>'.$this->store_city.'</FromCity>
<FromState>'.$this->store_state.'</FromState>
<FromZip5>'.$this->store_zip5.'</FromZip5>
<FromPhone>'.$this->PhoneClean($this->store_phone).'</FromPhone>
<ToName>'.$this->order['FirstName'].' '.$this->order['LastName'].'</ToName>
<ToFirm>'.$this->order['ShippingCompany'].'</ToFirm>
<ToAddress1></ToAddress1>
<ToAddress2>'.$this->order['ShippingAddress2'].'</ToAddress2>
<ToAddress3>'.$this->order['ShippingAddress1'].'</ToAddress3>
<ToCity>'.$this->order['ShippingCity'].'</ToCity>';
if ( $this->order['ShippingProvince'] != '' ) {
$base_request.='
<ToProvince>'.$this->order['ShippingProvince'].'</ToProvince>';
}
$base_request.='
<ToCountry>'.$this->countries[$this->order['ShippingCountry']].'</ToCountry>
<ToPostalCode>'.$this->order['ShippingZip'].'</ToPostalCode>
<ToPOBoxFlag>N</ToPOBoxFlag>
<ToPhone>'.$this->PhoneClean($this->order['ShippingPhone']).'</ToPhone>
<ToFax>'.$this->PhoneClean($this->order['ShippingFax']).'</ToFax>
<ToEmail>'.$this->order['Email'].'</ToEmail>
<ShippingContents>';
// add items
foreach ( $this->order['Items'] as $k => $value ) {
$base_request.='
<ItemDetail>
<Description>Computer Parts</Description>
<Quantity>'.$value['Qty'].'</Quantity>
<Value>'.($value['Price'] * $value['Qty']).'</Value>
<NetPounds>'.$value['NetPounds'].'</NetPounds>
<NetOunces>'.$value['NetOunces'].'</NetOunces>
<HSTariffNumber>123456</HSTariffNumber>
<CountryOfOrigin>United States</CountryOfOrigin>
</ItemDetail>';
}
// end add items
$base_request.='
</ShippingContents>
<GrossPounds>'.$this->pounds.'</GrossPounds>
<GrossOunces>'.$this->ounces.'</GrossOunces>
<ContentType>MERCHANDISE</ContentType>
<Agreement>Y</Agreement>
<InvoiceNumber>'.$this->order['InvoiceNumber'].'</InvoiceNumber>
<ImageType>PDF</ImageType>
<ImageLayout>ALLINONEFILE</ImageLayout>
<LabelDate>'.date('m/d/Y',time()).'</LabelDate>
';
if (strpos($shipping_service, 'express') !== false) {
$xml_request = 'ExpressMailIntlRequest';
$api_query = 'ExpressMailIntl';
}
elseif (strpos($shipping_service, 'priority') !== false) {
$xml_request = 'PriorityMailIntlRequest';
$api_query = 'PriorityMailIntl';
}
else {
$xml_request = 'FirstClassMailIntlRequest';
$api_query = 'FirstClassMailIntl';
}
}
$request.= '<'.$xml_request.' USERID="'.$this->usps_userid.'">';
$request.= $base_request;
$request.= '</'.$xml_request.'>';
// die($request);
$request = 'API='.$api_query.'&XML='.urlencode($request);
$body = $this->PostQuery($request, 1);
// check for errors
if (strpos($body, '<Error>') !== false) {
$errors = Array ();
preg_match_all('/<Number>(.*?)<\/Number>/s', $body, $error_numbers);
preg_match_all('/<Description>(.*?)<\/Description>/s', $body, $error_descriptions);
foreach ($error_numbers[1] as $index => $error_number) {
$errors[$index] = Array ('error_number' => $error_number, 'error_description' => $error_descriptions[1][$index]);
}
// TODO: find a way to return other error messages in same package as well
return $errors[0];
}
// parse response
$xml_helper =& $this->Application->recallObject('kXMLHelper');
$root_node =& $xml_helper->Parse($body);
/* @var $root_node kXMLNode */
$Postage = 0;
$label_file = $TrackingNumber = $PostnetBarCode = '';
// Domestic shipping
if ($this->order['ShippingCountry'] == $this->shipping_origin_country ) {
$delivery_node =& $root_node->FindChild('DeliveryConfirmationV3.0Response');
do {
$TrackingNumber = $delivery_node->FindChildValue('DeliveryConfirmationNumber');
$PostnetBarCode = $delivery_node->FindChildValue('Postnet');
$DeliveryConfirmationLabel = base64_decode($delivery_node->FindChildValue('DeliveryConfirmationLabel'));
}
while ( $delivery_node =& $delivery_node->NextSibling());
}
else {
if (strpos($shipping_service, 'express') !== false) {
$node_title = 'ExpressMailIntlResponse';
}
elseif (strpos($shipping_service, 'priority') !== false) {
$node_title = 'PriorityMailIntlResponse';
}
else {
$node_title = 'FirstClassMailIntlResponse';
}
$delivery_node =& $root_node->FindChild($node_title);
$PostnetBarCode = $delivery_node->FindChildValue('BarcodeNumber');
$Postage = $delivery_node->FindChildValue('Postage');
$DeliveryConfirmationLabel = base64_decode($delivery_node->FindChildValue('LabelImage'));
}
if ( $TrackingNumber != '' ) {
$label_file = USPS_LABEL_FOLDER.$TrackingNumber.".pdf";
}
elseif ( $PostnetBarCode != '' ) {
$label_file = USPS_LABEL_FOLDER.$PostnetBarCode.".pdf";
}
if ( $label_file != '' ) {
if (!$handle = fopen($label_file, 'a')) echo "Cannot open file ($label_file)";
if ( @fwrite($handle, $DeliveryConfirmationLabel) === FALSE) echo "Cannot write to file ($label_file)";
}
return array('TrackingNumber' => $TrackingNumber, 'PostnetBarCode' => $PostnetBarCode, 'Postage' => $Postage);
}
function GetUSPSCountry($country)
{
$country = $this->Application->Conn->GetOne('SELECT DestAbbr2 FROM '.TABLE_PREFIX.'StdDestinations WHERE DestAbbr = '.$this->Application->Conn->qstr($country));
if ( $country == '' ) $country = 'US';
return $country;
}
function GetShippingQuotes($params = null)
{
$weights = Kg2Pounds($params['packages']['0']['weight']);
$weight = '';
$weight = $weights[0];
if ( $weights[1] != '' ) {
$weight.='.'.$weights[1];
}
$country = $this->GetUSPSCountry($params['dest_country']);
$this->order = Array();
$this->order['ShippingWeight'] = $weight;
$this->order['ShippingNumBoxes'] = 1;
$this->order['ShippingZip'] = $params['dest_postal'];
$this->order['SubTotal'] = $params['amount'];
$this->order['ShippingCountry'] = $country;
$shipping_types = Array();
$rates = $this->GetQuote();
if ( !isset($rates['error']) ) {
$this->Application->RemoveVar('usps_errors');
$i = 1;
foreach ($rates as $k => $rate ) {
$shipping_types['USPS_'.$i] = Array(
'ShippingId' => 'USPS_'.$i,
'TotalCost' => $rate['Rate'],
'ShippingName' => $rate['Title'],
'Type' => '1',
'CODFlat' => '0',
'CODPercent' => '0',
'PortalGroups' => ',15,',
'InsuranceFee' => '',
'COD' => '0',
'SelectedOnly' => '0',
'Code' => $rate['Title']
);
$i++;
}
}
else {
// for Front-End (shipping screen) and Admin (Shipping Tab on editing order)
$this->Application->StoreVar('usps_errors', $rates['error']);
}
$this->Application->StoreVar('current_usps_shipping_types', serialize($shipping_types));
return $shipping_types;
}
function TrackOrder($TrackingNumber='')
{
if ( $TrackingNumber != '' ) {
// http://testing.shippingapis.com/ShippingAPITest.dll?API=TrackV2&XML=<TrackFieldRequest USERID="402INTEC7634"><TrackID ID="EJ958083578US"></TrackID></TrackFieldRequest>
$request = '<TrackRequest USERID="'.$this->usps_userid.'"><TrackID ID="'.$TrackingNumber.'"></TrackID></TrackRequest>';
$api_query = 'TrackV2';
$request = 'API='.$api_query.'&XML='.urlencode($request);
$body = $this->PostQuery($request);
// check for errors
if (strpos($body, '<Error>') !== false) {
$errors = Array ();
preg_match_all('/<Number>(.*?)<\/Number>/s', $body, $error_numbers);
preg_match_all('/<Description>(.*?)<\/Description>/s', $body, $error_descriptions);
foreach ($error_numbers[1] as $index => $error_number) {
$errors[$index] = $error_descriptions[1][$index];
if ($this->Application->isDebugMode()) {
$errors[$index] .= ' (' . $error_number . ')';
}
}
$errors = array_unique($errors); // we may have same errors on many packages, so don't show duplicates
return Array('error' => implode('<br/>', $errors));
}
$xml_helper =& $this->Application->recallObject('kXMLHelper');
$root_node =& $xml_helper->Parse($body);
/* @var $root_node kXMLNode */
// Tracking Shipping
$delivery_node =& $root_node->FindChild('TrackInfo');
$TrackSummary = $delivery_node->FindChildValue('TrackSummary');
// echo ' TrackSummary ('.$TrackingNumber.') = '.$TrackSummary.'<br>';
return strpos($TrackSummary, 'delivered') !== false ? 1 : 0;
}
else
return false;
}
function ProcessTrackOrders()
{
$sql = sprintf('SELECT `OrderId`, `ShippingTracking` FROM %s WHERE `Status` > 3 AND `Delivered` = 0', TABLE_PREFIX.'Orders');
$orders = $this->Application->Conn->Query($sql);
foreach ( $orders as $k => $order ) {
// try to track order
if ( $order['ShippingTracking'] != '' && $this->TrackOrder($order['ShippingTracking']) ) {
$update_order = sprintf("UPDATE %s SET `Delivered` = 1 WHERE %s = %s",
TABLE_PREFIX.'Orders',
$this->Application->getUnitOption('ord', 'IDField'),
$order[$this->Application->getUnitOption('ord', 'IDField')]
);
$this->Application->Conn->Query($update_order);
}
}
}
function PostQuery($request, $secure=0)
{
switch (MODULE_SHIPPING_USPS_SERVER) {
case 'production':
$usps_server = $secure > 0 ? 'https://secure.shippingapis.com' : 'http://production.shippingapis.com' ;
$api_dll = 'ShippingAPI.dll';
break;
case 'test':
$usps_server = $secure > 0 ? 'https://secure.shippingapis.com' : 'http://testing.shippingapis.com';
$api_dll = 'ShippingAPITest.dll';
break;
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $usps_server.'/'.$api_dll.'?'.$request);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$body = curl_exec($curl);
curl_close($curl);
if (defined('USPS_LOG_FILE')) {
$filename = USPS_LOG_FILE;
if ( !$fp = fopen($filename, "a") ) echo("Failed opening file $filename");
}
$request_url = sprintf("Date %s : IP %s\n\nPost\n\n%s\n\nReplay\n\n%s\n\n",
date("m/d/Y H:i:s",time()),
$_SERVER['REMOTE_ADDR'],
$usps_server.'/'.$api_dll.'?'.urldecode($request),
$body
);
if (defined('USPS_LOG_FILE')) {
if (!fwrite($fp, $request_url)) echo("Failed writing to file $filename");
fclose($fp);
}
return $body;
}
function GetAvailableTypes()
{
return array();
$conn =& $this->Application->GetADODBConnection();
$types = $conn->Query('SELECT * FROM '.TABLE_PREFIX.'ShippingType');
$ret = array();
foreach ($types as $a_type) {
$a_type['_ClassName'] = get_class($this);
$a_type['_Id'] = 'CUST_'.$a_type['ShippingID'];
$a_type['_Name'] = '(Custom) '.$a_type['Name'];
$ret[] = $a_type;
}
return $ret;
}
function LoadParams()
{
$sql = 'SELECT Properties FROM '.$this->Application->getUnitOption('sqe', 'TableName').'
WHERE ClassName="USPS"';
$db =& $this->Application->GetADODBConnection();
return unserialize($db->GetOne($sql));
}
function _prepare_xml_param($value) {
return strip_tags($value);
}
}
\ No newline at end of file
Index: branches/5.0.x/units/orders/orders_item.php
===================================================================
--- branches/5.0.x/units/orders/orders_item.php (revision 13261)
+++ branches/5.0.x/units/orders/orders_item.php (revision 13262)
@@ -1,502 +1,502 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class OrdersItem extends kDBItem
{
function OrdersItem()
{
parent::kDBItem();
$this->ErrorMsgs['credit_card_validation_error'] = $this->Application->Phrase('lu_cc_validation_error');
$this->ErrorMsgs['credit_card_expired'] = $this->Application->Phrase('lu_cc_expired');
}
/**
* Return error message for field
*
* @param string $field
* @return string
* @access public
*/
function GetErrorMsg($field)
{
if( $field != 'OrderNumber' ) return parent::GetErrorMsg($field);
$number['error'] = parent::GetErrorMsg('Number');
$number['pseudo'] = getArrayValue($this->FieldErrors['Number'], 'pseudo');
$subnumber['error'] = parent::GetErrorMsg('SubNumber');
$subnumber['pseudo'] = getArrayValue($this->FieldErrors['SubNumber'], 'pseudo');
// if pseudo match & not empty -> return 1st
// if one of pseudos not empty -> return it
// if we got one pseudo "bad_type" and other pseudo "required", then return "bad_type" error message
if( $number['pseudo'] && ($number['pseudo'] == $subnumber['pseudo']) )
{
return $number['error'];
}
if( $number['pseudo'] && !$subnumber['pseudo'] )
{
return $number['error'];
}
if( !$number['pseudo'] && $subnumber['pseudo'] )
{
return $subnumber['error'];
}
if( $number['pseudo'] == 'bad_type' )
{
return $number['error'];
}
if( $subnumber['pseudo'] == 'bad_type' )
{
return $subnumber['error'];
}
// $msg = '['.$number_error.'('.$number_pseudo.')] ['.$subnumber_error.'] ('.$subnumber_pseudo.')';
//
// return $msg;
}
function SetFieldsFromHash($hash, $set_fields=null)
{
parent::SetFieldsFromHash($hash, $set_fields);
$options = $this->GetFieldOptions('PaymentCCExpDate');
if( $this->GetDirtyField($options['month_field']) || $this->GetDirtyField($options['year_field']) )
{
$this->SetDirtyField('PaymentCCExpDate', 0);
$this->SetField('PaymentCCExpDate', 0);
}
}
/**
* Returns gateway data based on payment type used in order
*
* @return Array
*/
function getGatewayData($pt_id=null)
{
// get Gateway fields
if (!isset($pt_id) || !$pt_id) {
$pt_id = $this->GetDBField('PaymentType');
}
$pt_table = $this->Application->getUnitOption('pt','TableName');
$sql = 'SELECT GatewayId FROM %s WHERE PaymentTypeId = %s';
$gw_id = $this->Conn->GetOne( sprintf($sql, $pt_table, $pt_id) );
$sql = 'SELECT * FROM %s WHERE GatewayId = %s';
$ret = $this->Conn->GetRow( sprintf($sql, TABLE_PREFIX.'Gateways', $gw_id) );
// get Gateway parameters based on payment type
$gwf_table = $this->Application->getUnitOption('gwf','TableName');
$gwfv_table = $this->Application->getUnitOption('gwfv','TableName');
$sql = 'SELECT gwfv.Value, gwf.SystemFieldName
FROM %s gwf
LEFT JOIN %s gwfv ON gwf.GWConfigFieldId = gwfv.GWConfigFieldId
WHERE gwfv.PaymentTypeId = %s AND gwf.GatewayId = %s';
$ret['gw_params'] = $this->Conn->GetCol( sprintf($sql, $gwf_table, $gwfv_table, $pt_id, $gw_id), 'SystemFieldName' );
$ret['gw_params']['gateway_id'] = $gw_id;
if ($this->GetDBField('IsRecurringBilling') && $this->Application->ConfigValue('Comm_AutoProcessRecurringOrders')) {
if (isset($ret['gw_params']['shipping_control'])) {
$ret['gw_params']['shipping_control'] = SHIPPING_CONTROL_DIRECT;
}
}
return $ret;
}
/**
* Checks if tangible items are present in order
*
* @return bool
*/
function HasTangibleItems()
{
$sql = 'SELECT COUNT(*)
FROM '.TABLE_PREFIX.'OrderItems orditems
LEFT JOIN '.TABLE_PREFIX.'Products p ON p.ProductId = orditems.ProductId
WHERE (orditems.OrderId = '.$this->GetID().') AND (p.Type = '.PRODUCT_TYPE_TANGIBLE.')';
return $this->Conn->GetOne($sql) ? true : false;
}
/**
* Calculates tax value of order items based on billing & shipping country specified
*
* @return double
*/
function getTaxPercent()
{
$sql = 'SELECT DestId FROM '.TABLE_PREFIX.'StdDestinations WHERE DestType = %s AND DestAbbr = %s';
$shipping_country_id = (int) $this->Conn->GetOne( sprintf($sql, 1, $this->Conn->qstr($this->GetDBField('ShippingCountry') ) ) );
$shipping_state_id = (int) $this->Conn->GetOne( sprintf($sql, 2, $this->Conn->qstr($this->GetDBField('ShippingState') ) ) );
$shipping_zip = (string) $this->GetDBField('ShippingZip');
$billing_country_id = (int) $this->Conn->GetOne( sprintf($sql, 1, $this->Conn->qstr($this->GetDBField('BillingCountry') ) ) );
$billing_state_id = (int) $this->Conn->GetOne( sprintf($sql, 2, $this->Conn->qstr($this->GetDBField('BillingState') ) ) );
$billing_zip = (string) $this->GetDBField('BillingZip');
/*
$dest_ids = array_diff( array_unique( Array( $shipping_country_id, $shipping_state_id, $billing_country_id, $billing_state_id ) ), Array(0) );
$dest_values = array_diff( array_unique( Array( $this->Conn->qstr($shipping_zip), $this->Conn->qstr($billing_zip) ) ), Array('\'\'') );
*/
$tax = false;
$sql = 'SELECT tx.*
FROM '.$this->Application->getUnitOption('tax', 'TableName').' tx
LEFT JOIN '.$this->Application->getUnitOption('taxdst', 'TableName').' txd ON tx.TaxZoneId = txd.TaxZoneId
WHERE
( txd.StdDestId IN ('.$shipping_country_id.','.$shipping_state_id.')
AND
( (txd.DestValue = "" OR txd.DestValue IS NULL)
OR
txd.DestValue = '.$this->Conn->qstr($shipping_zip).'
)
)
OR
( txd.StdDestId IN ('.$billing_country_id.','.$billing_state_id.')
AND
( (txd.DestValue = "" OR txd.DestValue IS NULL)
OR
txd.DestValue = '.$this->Conn->qstr($billing_zip).'
)
)
ORDER BY tx.TaxValue DESC';
$tax = $this->Conn->GetRow($sql);
if ($tax == false) {
$tax['TaxValue'] = 0;
$tax['ApplyToShipping'] = 0;
$tax['ApplyToProcessing'] = 0;
}
return $tax;
}
function RecalculateTax()
{
$tax = $this->getTaxPercent();
$this->SetDBField( 'VATPercent', $tax['TaxValue'] );
$this->SetDBField( 'ShippingTaxable', $tax['ApplyToShipping']);
$this->SetDBField( 'ProcessingTaxable', $tax['ApplyToProcessing']);
$this->UpdateTotals();
$subtotal = $this->GetDBField('AmountWithoutVAT');
$query = 'SELECT SUM(Quantity * Price) FROM '.TABLE_PREFIX.'OrderItems AS oi
LEFT JOIN '.TABLE_PREFIX.'Products AS p
ON p.ProductId = oi.ProductId
WHERE p.Type = 6 AND oi.OrderId = '.$this->GetDBField('OrderId');
$tax_exempt = $this->Conn->GetOne($query);
if ($tax_exempt) $subtotal -= $tax_exempt;
$this->SetDBField( 'VAT', round($subtotal * $tax['TaxValue'] / 100, 2) );
$this->UpdateTotals();
}
function UpdateTotals()
{
$total = 0;
$total += $this->GetDBField('SubTotal');
if ($this->GetDBField('ShippingTaxable')) $total += $this->GetDBField('ShippingCost');
if ($this->GetDBField('ProcessingTaxable')) $total += $this->GetDBField('ProcessingFee');
$this->SetDBField('AmountWithoutVAT', $total);
$total += $this->GetDBField('VAT');
if (!$this->GetDBField('ShippingTaxable')) $total += $this->GetDBField('ShippingCost');
if (!$this->GetDBField('ProcessingTaxable')) $total += $this->GetDBField('ProcessingFee');
$total += $this->GetDBField('InsuranceFee');
$this->SetDBField('TotalAmount', $total);
}
function getTotalAmount()
{
return $this->GetDBField('SubTotal') +
$this->GetDBField('ShippingCost') +
$this->GetDBField('VAT') +
$this->GetDBField('ProcessingFee') +
$this->GetDBField('InsuranceFee') -
$this->GetDBField('GiftCertificateDiscount');
}
/**
* Check field value by user-defined alghoritm
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
*/
function CustomValidation($field, $params)
{
$res = true;
$res = $res && $this->ValidateCCNumber($field, $params);
$res = $res && $this->ValidateCCExpiration($field, $params);
return $res;
}
function requireCreditCard()
{
$pt_table = $this->Application->getUnitOption('pt', 'TableName');
$sql = 'SELECT RequireCCFields
FROM '.$pt_table.' pt
LEFT JOIN '.TABLE_PREFIX.'Gateways gw ON gw.GatewayId = pt.GatewayId
WHERE pt.PaymentTypeId = '.$this->GetDBField('PaymentType');
return $this->Conn->GetOne($sql);
}
/**
* Check if field value is valid credit card number against credit card type specified
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
* @access private
*/
function ValidateCCNumber($field, $params)
{
$cardtype_field = getArrayValue($params, 'cardtype_field');
$value = $this->GetDBField($field);
if( !$cardtype_field || !$value || !$this->requireCreditCard() ) return true;
if ($this->Application->ConfigValue('Comm_MaskProcessedCreditCards')) {
$mask_found = strpos($value, str_repeat('X', 4)) !== false;
if ($this->Application->isAdminUser && $mask_found) {
// masked card numbers always appear valid in admin
return true;
}
}
if (defined('DEBUG_MODE') && constOn('DBG_PAYMENT_GW')) {
$gw_data = $this->getGatewayData();
$this->Application->registerClass( $gw_data['ClassName'], GW_CLASS_PATH.'/'.$gw_data['ClassFile'] );
$gateway_object =& $this->Application->recallObject( $gw_data['ClassName'] );
$test_numbers = $gateway_object->GetTestCCNumbers();
if (in_array($value, $test_numbers)) return true;
}
$error_field = isset($params['error_field']) ? $params['error_field'] : $field;
// '1' => 'Visa','2' => 'Mastercard', '3' => 'Amex', '4' => 'Discover', 5 => 'Diners Club', 6 => 'JBC'
// Innocent until proven guilty
$cc_valid = true;
- // Get rid of any non-digits
- $value = ereg_replace("[^[:digit:]]", '', $value);
+ // Get rid of any non-digits
+ $value = preg_replace('/[^\d]/', '', $value);
// Perform card-specific checks, if applicable
switch( $this->GetDBField($cardtype_field) )
{
case 2: // MasterCard
- $cc_valid = ereg("^5[1-5].{14}$", $value);
+ $cc_valid = preg_match('/^5[1-5].{14}$/', $value);
break;
case 1: // Visa
- $cc_valid = ereg("^4.{15}$|^4.{12}$", $value);
+ $cc_valid = preg_match('/^4.{15}$|^4.{12}$/', $value);
break;
case 3: // American Express
- $cc_valid = ereg("^3[47].{13}$", $value);
+ $cc_valid = preg_match('/^3[47].{13}$/', $value);
break;
case 4: // Discover
- $cc_valid = ereg("^6011.{12}$", $value);
+ $cc_valid = preg_match('/^6011.{12}$/', $value);
break;
case 5: // Diners Club
- $cc_valid = ereg("^30[0-5].{11}$|^3[68].{12}$", $value);
+ $cc_valid = preg_match('/^30[0-5].{11}$|^3[68].{12}$/', $value);
break;
case 6: // JBC
- $cc_valid = ereg("^3.{15}$|^2131|1800.{11}$", $value);
+ $cc_valid = preg_match('/^3.{15}$|^2131|1800.{11}$/', $value);
break;
default:
$this->FieldErrors[$error_field]['pseudo'] = 'credit_card_validation_error';
return false;
break;
}
// The Luhn formula works right to left, so reverse the number.
$value = strrev($value);
$total = 0;
for($x = 0; $x < strlen($value); $x++)
{
$digit = substr($value, $x, 1);
// If it's an odd digit, double it
if( $x / 2 != floor($x/2) )
{
$digit *= 2;
// If the result is two digits, add them
if( strlen($digit) == 2 )
{
$digit = substr($digit, 0, 1) + substr($digit, 1, 1);
}
}
// Add the current digit, doubled and added if applicable, to the Total
$total += $digit;
}
// If it passed (or bypassed) the card-specific check and the Total is
// evenly divisible by 10, it's cool!
if ($cc_valid && $total % 10 == 0)
{
return true;
}
else
{
$this->FieldErrors[$error_field]['pseudo'] = 'credit_card_validation_error';
return false;
}
}
/**
* Check if field value is non-expired credit card expiration date
*
* @param string $field field name
* @param Array $params field options from config
* @return bool
* @access private
*/
function ValidateCCExpiration($field, $params)
{
$formatter = getArrayValue($params, 'formatter');
if( ($formatter != 'kCCDateFormatter') || !$this->requireCreditCard() ) return true;
if(!$this->Application->isAdminUser) {
// validate expiration date only for front
if (preg_match('/([\d]{2})\/([\d]{2})/', $this->GetDBField($field), $rets)) {
$month = $rets[1];
$year = $rets[2];
$now_date = adodb_mktime(0, 0, 0, adodb_date('m'), adodb_date('d'), adodb_date('Y') );
$day_count = adodb_date('t', adodb_mktime(0, 0, 0, $month, 1, $year) );
$cc_date = adodb_mktime(23, 59, 59, $month, $day_count, $year);
if ($cc_date < $now_date) {
$error_field = isset($params['error_field']) ? $params['error_field'] : $field;
$this->FieldErrors[$error_field]['pseudo'] = 'credit_card_expired';
return false;
}
}
}
return true;
}
function getNextSubNumber()
{
$table = $this->Application->GetLiveName($this->TableName);
$sql = 'SELECT MAX(SubNumber) FROM '.$table.' WHERE Number = '.$this->GetDBField('Number');
return $this->Conn->GetOne($sql) + 1;
}
function ResetAddress($prefix)
{
$fields = Array('To','Company','Phone','Fax','Email','Address1','Address2','City','State','Zip','Country');
foreach($fields as $field)
{
$this->SetDBField($prefix.$field, $this->Fields[$prefix.$field]['default']);
}
}
function IsProfileAddress($address_type)
{
return $this->Application->GetVar($this->Prefix.'_IsProfileAddress');
}
// ===== Gift Certificates Related =====
function RecalculateGift(&$event)
{
$gc_id = $this->GetDBField('GiftCertificateId');
if ($gc_id < 1) {
return;
}
$gc =& $this->Application->recallObject('gc', null, Array('skip_autoload' => true));
/* @var $gc kDBItem */
$gc->Load($gc_id);
if ($gc->GetDBField('Status') == gcDISABLED) {
// disabled GC
$this->SetDBField('GiftCertificateId', 0);
$this->SetDBField('GiftCertificateDiscount', 0);
// disabled
return;
}
$debit = $gc->GetDBField('Debit') + $this->GetDBField('GiftCertificateDiscount');
$this->UpdateTotals();
$total = $this->GetDBField('TotalAmount');
$gift_certificate_discount = $debit >= $total ? $total : $debit;
$this->SetDBField('TotalAmount', $total - $gift_certificate_discount);
$this->GetDBField('GiftCertificateDiscount', $gift_certificate_discount);
$debit -= $gift_certificate_discount;
$gc->SetDBField('Debit', $debit);
$gc->SetDBField('Status', $debit > 0 ? gcENABLED : gcUSED);
$gc->Update();
if ($gift_certificate_discount == 0) {
$this->RemoveGiftCertificate($object);
$event->SetRedirectParam('checkout_error', 108);
}
$this->SetDBField('GiftCertificateDiscount', $gift_certificate_discount);
}
function RemoveGiftCertificate()
{
$gc_id = $this->GetDBField('GiftCertificateId');
$gc =& $this->Application->recallObject('gc', null, Array('skip_autoload' => true));
/* @var $gc kDBItem */
$gc->Load($gc_id);
$debit = $gc->GetDBField('Debit') + $this->GetDBField('GiftCertificateDiscount');
if ($gc->isLoaded() && ($debit > 0)) {
$gc->SetDBField('Debit', $debit);
$gc->SetDBField('Status', gcENABLED);
$gc->Update();
}
$this->SetDBField('GiftCertificateId', 0);
$this->SetDBField('GiftCertificateDiscount', 0);
}
}
\ No newline at end of file
Index: branches/5.0.x/units/products/products_event_handler.php
===================================================================
--- branches/5.0.x/units/products/products_event_handler.php (revision 13261)
+++ branches/5.0.x/units/products/products_event_handler.php (revision 13262)
@@ -1,1293 +1,1292 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class ProductsEventHandler extends kCatDBEventHandler {
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
// front
'OnCancelAction' => Array('self' => true),
'OnRateProduct' => Array('self' => true),
'OnClearRecent' => Array('self' => true),
'OnRecommendProduct' => Array('self' => true),
// admin
'OnQtyAdd' => Array('self' => 'add|edit'),
'OnQtyRemove' => Array('self' => 'add|edit'),
'OnQtyOrder' => Array('self' => 'add|edit'),
'OnQtyReceiveOrder' => Array('self' => 'add|edit'),
'OnQtyCancelOrder' => Array('self' => 'add|edit'),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
function mapEvents()
{
parent::mapEvents(); // ensure auto-adding of approve/decine and so on events
$product_events = Array( 'OnQtyAdd'=>'InventoryAction',
'OnQtyRemove'=>'InventoryAction',
'OnQtyOrder'=>'InventoryAction',
'OnQtyReceiveOrder'=>'InventoryAction',
'OnQtyCancelOrder'=>'InventoryAction',);
$this->eventMethods = array_merge($this->eventMethods, $product_events);
}
/**
* Sets default processing data for subscriptions
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$object =& $event->getObject();
$product_approve_events = Array(2 => 'p:OnSubscriptionApprove',
4 => 'p:OnDownloadableApprove',
5 => 'p:OnPackageApprove');
$product_type = $object->GetDBField('Type');
$type_found = in_array($product_type, array_keys($product_approve_events) );
if($type_found && !$object->GetDBField('ProcessingData') )
{
$processing_data = Array('ApproveEvent' => $product_approve_events[$product_type] );
$object->SetDBField( 'ProcessingData', serialize($processing_data) );
}
}
/**
* Process product count manipulations
*
* @param kEvent $event
* @access private
*/
function InventoryAction(&$event)
{
$object =& $event->getObject();
$object->SetFieldsFromHash( $this->getSubmittedFields($event) );
if ($object->GetDBField('InventoryStatus') == 2) {
// inventory by options (use first selected combination in grid)
$combination_id = array_shift( array_keys( $this->Application->GetVar('poc_grid') ) );
}
else {
// inventory by product
$combination_id = 0;
}
// save id of selected option combination & preselect it in grid
$this->Application->SetVar('combination_id', $combination_id);
$this->ScheduleInventoryAction($event->Name, $object->GetId(), $object->GetDBField('Qty'), $combination_id);
$object->Validate();
if (!isset($object->FieldErrors['Qty']['pseudo'])){
$this->modifyInventory($event->Name, $object, $object->GetDBField('Qty'), $combination_id);
}
$object->SetDBField('Qty', null);
$event->redirect = false;
}
/**
* Perform inventory action on supplied object
*
* @param string $action event name which is actually called by user
* @param ProductsItem $product
* @param int $qty
* @param int $combination_id
*/
function modifyInventory($action, &$product, $qty, $combination_id)
{
if ($product->GetDBField('InventoryStatus') == 2) {
// save inventory changes to option combination instead of product
$object =& $this->Application->recallObject('poc.-item', null, Array('skip_autoload' => true));
$object->Load($combination_id);
}
elseif ($combination_id > 0) {
// combination id present, but not inventory by combinations => skip
return false;
}
elseif ($product->GetDBField('InventoryStatus') == 1) {
// save inventory changes to product
$object =& $product;
}
else {
// product has inventory actions, but don't use inventory => skip
return false;
}
if (!$object->isLoaded()) {
// product/combination in action doesn't exist in database by now
return false;
}
switch ($action) {
case 'OnQtyAdd':
$object->SetDBField('QtyInStock', $object->GetDBField('QtyInStock') + $qty);
break;
case 'OnQtyRemove':
if ($object->GetDBField('QtyInStock') < $qty) {
$qty = $object->GetDBField('QtyInStock');
}
$object->SetDBField('QtyInStock', $object->GetDBField('QtyInStock') - $qty);
break;
case 'OnQtyOrder':
$object->SetDBField('QtyOnOrder', $object->GetDBField('QtyOnOrder') + $qty);
break;
case 'OnQtyReceiveOrder':
$object->SetDBField('QtyOnOrder', $object->GetDBField('QtyOnOrder') - $qty);
$object->SetDBField('QtyInStock', $object->GetDBField('QtyInStock') + $qty);
break;
case 'OnQtyCancelOrder':
$object->SetDBField('QtyOnOrder', $object->GetDBField('QtyOnOrder') - $qty);
break;
}
return $object->Update();
}
function ScheduleInventoryAction($action, $prod_id, $qty, $combination_id = 0)
{
$inv_actions = $this->Application->RecallVar('inventory_actions');
if (!$inv_actions) {
$inv_actions = Array();
}
else {
$inv_actions = unserialize($inv_actions);
}
array_push($inv_actions, Array('action' => $action, 'product_id' => $prod_id, 'combination_id' => $combination_id, 'qty' => $qty));
$this->Application->StoreVar('inventory_actions', serialize($inv_actions));
}
function RealInventoryAction($action, $prod_id, $qty, $combination_id)
{
$product =& $this->Application->recallObject('p.liveitem', null, Array('skip_autoload' => true));
$product->SwitchToLive();
$product->Load($prod_id);
$this->modifyInventory($action, $product, $qty, $combination_id);
}
function RunScheduledInventoryActions(&$event)
{
$inv_actions = $this->Application->GetVar('inventory_actions');
if (!$inv_actions) {
return;
}
$inv_actions = unserialize($inv_actions);
$products = array();
foreach($inv_actions as $an_action) {
$this->RealInventoryAction($an_action['action'], $an_action['product_id'], $an_action['qty'], $an_action['combination_id']);
array_push($products, $an_action['product_id'].'_'.$an_action['combination_id']);
}
$products = array_unique($products);
if ($products) {
$product_obj =& $this->Application->recallObject('p.liveitem', null, Array('skip_autoload' => true));
$product_obj->SwitchToLive();
foreach ($products as $product_key) {
list($prod_id, $combination_id) = explode('_', $product_key);
$product_obj->Load($prod_id);
$this->FullfillBackOrders($product_obj, $combination_id);
}
}
}
/**
* In case if products arrived into inventory and they are required by old (non processed) orders, then use them (products) in that orders
*
* @param ProductsItem $product
* @param int $combination_id
*/
function FullfillBackOrders(&$product, $combination_id)
{
if ( !$this->Application->ConfigValue('Comm_Process_Backorders_Auto') ) return;
if ($combination_id && ($product->GetDBField('InventoryStatus') == 2)) {
// if combination id present and inventory by combinations
$poc_idfield = $this->Application->getUnitOption('poc', 'IDField');
$poc_tablename = $this->Application->getUnitOption('poc', 'TableName');
$sql = 'SELECT QtyInStock
FROM '.$poc_tablename.'
WHERE '.$poc_idfield.' = '.$combination_id;
$stock_qty = $this->Conn->GetOne($sql);
}
else {
// inventory by product
$stock_qty = $product->GetDBField('QtyInStock');
}
$qty = (int) $stock_qty - $product->GetDBField('QtyInStockMin');
$prod_id = $product->GetID();
if ($prod_id <= 0 || !$prod_id || $qty <= 0) return;
//selecting up to $qty backorders with $prod_id where full qty is not reserved
$query = 'SELECT '.TABLE_PREFIX.'Orders.OrderId
FROM '.TABLE_PREFIX.'OrderItems
LEFT JOIN '.TABLE_PREFIX.'Orders ON '.TABLE_PREFIX.'Orders.OrderId = '.TABLE_PREFIX.'OrderItems.OrderId
WHERE (ProductId = '.$prod_id.') AND (Quantity > QuantityReserved) AND (Status = '.ORDER_STATUS_BACKORDERS.')
GROUP BY '.TABLE_PREFIX.'Orders.OrderId
ORDER BY OrderDate ASC
LIMIT 0,'.$qty; //assuming 1 item per order - minimum possible
$orders = $this->Conn->GetCol($query);
if (!$orders) return;
$order =& $this->Application->recallObject('ord.-inv', null, Array('skip_autoload' => true));
foreach ($orders as $ord_id) {
$order->Load($ord_id);
$email_event_admin =& $this->Application->EmailEventAdmin('BACKORDER.FULLFILL');
//reserve what's possible in any case
$this->Application->HandleEvent( $event, 'ord:OnReserveItems' );
if ($event->status == erSUCCESS) { //
//in case the order is ready to process - process it
$this->Application->HandleEvent( $event, 'ord:OnOrderProcess' );
}
}
}
function OnBeforeDeleteFromLive(&$event)
{
$id = $event->getEventParam('id');
$product =& $this->Application->recallObject($event->Prefix.'.itemlive', null, Array('skip_autoload' => true));
$product->SwitchToLive();
if (!$product->Load($id)) return ; // this will make sure New product will not be overwritten with empty data
$temp =& $this->Application->recallObject($event->Prefix.'.itemtemp', null, Array('skip_autoload' => true));
$temp->SwitchToTemp();
$temp->Load($id);
$temp->SetDBFieldsFromHash($product->FieldValues, Array('QtyInStock','QtyReserved','QtyBackOrdered','QtyOnOrder'));
$temp->Update();
}
function clearSelectedIDs(&$event)
{
parent::clearSelectedIDs($event);
$this->Application->SetVar('inventory_actions', $this->Application->RecallVar('inventory_actions'));
$this->Application->RemoveVar('inventory_actions');
}
function OnSave(&$event)
{
$res = parent::OnSave($event);
if ($event->status == erSUCCESS) {
$this->RunScheduledInventoryActions($event);
}
return $res;
}
function OnPreCreate(&$event)
{
parent::onPreCreate($event);
$object =& $event->GetObject();
$object->SetDBField('Type', $this->Application->GetVar( $event->getPrefixSpecial(true).'_new_type' ));
}
function OnPreSaveAndGo(&$event) {
$event->CallSubEvent('OnPreSave');
$this->LoadItem($event);
$object =& $event->getObject();
$from_type = $object->GetDBField('Type');
if ($event->status==erSUCCESS) {
$this->Application->SetVar($event->Prefix_Special.'_id', $this->Application->GetVar($event->getPrefixSpecial(true).'_GoId'));
$this->LoadItem($event);
$to_type = $object->GetDBField('Type');
if ($from_type != $to_type) {
$from_tabs = $this->GetTabs($from_type);
$from_tab_i = array_search($this->Application->GetVar('t'), $from_tabs);
$to_tabs = $this->GetTabs($to_type);
$to_tab = $this->Application->GetVar('t');
$found = false;
while ( !isset($to_tabs[$from_tab_i]) && $from_tab_i < count($to_tabs)) {
$from_tab_i++;
}
if ( !isset($to_tabs[$from_tab_i]) ) $from_tab_i = 0;
$to_tab = $to_tabs[$from_tab_i];
$event->redirect = $to_tab;
}
}
}
function GetTabs($type)
{
switch($type)
{
case 1:
return Array(
0 => 'in-commerce/products/products_edit',
1 => 'in-commerce/products/products_inventory',
2 => 'in-commerce/products/products_pricing',
3 => 'in-commerce/products/products_categories',
4 => 'in-commerce/products/products_images',
5 => 'in-commerce/products/products_reviews',
6 => 'in-commerce/products/products_custom',
);
case 2:
return Array(
0 => 'in-commerce/products/products_edit',
1 => 'in-commerce/products/products_access',
/*2 => 'in-commerce/products/products_access_pricing',*/
3 => 'in-commerce/products/products_categories',
4 => 'in-commerce/products/products_images',
5 => 'in-commerce/products/products_reviews',
6 => 'in-commerce/products/products_custom',
);
case 3:
return Array(
0 => 'in-commerce/products/products_edit',
2 => 'in-commerce/products/products_access_pricing',
3 => 'in-commerce/products/products_categories',
4 => 'in-commerce/products/products_images',
5 => 'in-commerce/products/products_reviews',
6 => 'in-commerce/products/products_custom',
);
case 4:
return Array(
0 => 'in-commerce/products/products_edit',
2 => 'in-commerce/products/products_files',
3 => 'in-commerce/products/products_categories',
4 => 'in-commerce/products/products_images',
5 => 'in-commerce/products/products_reviews',
6 => 'in-commerce/products/products_custom',
);
}
}
/**
* Return type clauses for list bulding on front
*
* @param kEvent $event
* @return Array
*/
function getTypeClauses(&$event)
{
$types=$event->getEventParam('types');
$except_types=$event->getEventParam('except');
$object =& $event->getObject();
$type_clauses = parent::getTypeClauses($event);
$type_clauses['featured']['include']='%1$s.Featured=1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['featured']['except']='%1$s.Featured!=1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['featured']['having_filter']=false;
$type_clauses['onsale']['include']='%1$s.OnSale=1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['onsale']['except']='%1$s.OnSale!=1 AND '.TABLE_PREFIX.'CategoryItems.PrimaryCat = 1';
$type_clauses['onsale']['having_filter']=false;
// products from selected manufacturer: begin
$manufacturer = $event->getEventParam('manufacturer');
if ( !$manufacturer ) {
$manufacturer = $this->Application->GetVar('manuf_id');
}
if ( $manufacturer ) {
$type_clauses['manufacturer']['include'] = '%1$s.ManufacturerId='.$manufacturer.' AND PrimaryCat = 1';
$type_clauses['manufacturer']['except'] = '%1$s.ManufacturerId!='.$manufacturer.' AND PrimaryCat = 1';
$type_clauses['manufacturer']['having_filter'] = false;
}
// products from selected manufacturer: end
// recent products: begin
$recent = $this->Application->RecallVar('recent_products');
if ($recent) {
$recent = unserialize($recent);
$type_clauses['recent']['include'] = '%1$s.ProductId IN ('.implode(',', $recent).') AND PrimaryCat = 1';
$type_clauses['recent']['except'] = '%1$s.ProductId NOT IN ('.implode(',', $recent).') AND PrimaryCat = 1';
}
else {
$type_clauses['recent']['include']='0';
$type_clauses['recent']['except']='1';
}
$type_clauses['recent']['having_filter']=false;
// recent products: end
// products already in shopping cart: begin
if (strpos($types, 'in_cart') !== false || strpos($except_types, 'in_cart') !== false) {
$order_id = $this->Application->RecallVar('ord_id');
if ($order_id) {
$in_cart = $this->Conn->GetCol('SELECT ProductId FROM '.TABLE_PREFIX.'OrderItems WHERE OrderId = '.$order_id);
if ($in_cart) {
$type_clauses['in_cart']['include'] = '%1$s.ProductId IN ('.implode(',', $in_cart).') AND PrimaryCat = 1';
$type_clauses['in_cart']['except'] = '%1$s.ProductId NOT IN ('.implode(',', $in_cart).') AND PrimaryCat = 1';
}
else {
$type_clauses['in_cart']['include']='0';
$type_clauses['in_cart']['except']='1';
}
}
else {
$type_clauses['in_cart']['include']='0';
$type_clauses['in_cart']['except']='1';
}
$type_clauses['in_cart']['having_filter']=false;
}
// products already in shopping cart: end
// my downloadable products: begin
if (strpos($types, 'my_downloads') !== false || strpos($except_types, 'my_downloads') !== false)
{
$user_id = $this->Application->RecallVar('user_id');
$my_downloads = ($user_id > 0) ? $this->Conn->GetCol('SELECT ProductId FROM '.TABLE_PREFIX.'UserFileAccess WHERE PortalUserId = '.$user_id) : false;
if ($my_downloads)
{
$type_clauses['my_downloads']['include'] = '%1$s.ProductId IN ('.implode(',', $my_downloads).') AND PrimaryCat = 1';
$type_clauses['my_downloads']['except'] = '%1$s.ProductId NOT IN ('.implode(',', $my_downloads).') AND PrimaryCat = 1';
}
else
{
$type_clauses['my_downloads']['include'] = '0';
$type_clauses['my_downloads']['except'] = '1';
}
$type_clauses['my_downloads']['having_filter'] = false;
}
// my downloadable products: end
// my favorite products: begin
if (strpos($types, 'wish_list') !== false || strpos($except_types, 'wish_list') !== false) {
$sql = 'SELECT ResourceId FROM '.$this->Application->getUnitOption('fav', 'TableName').'
WHERE PortalUserId = '.(int)$this->Application->RecallVar('user_id');
$wishlist_ids = $this->Conn->GetCol($sql);
if ($wishlist_ids) {
$type_clauses['wish_list']['include'] = '%1$s.ResourceId IN ('.implode(',', $wishlist_ids).') AND PrimaryCat = 1';
$type_clauses['wish_list']['except'] = '%1$s.ResourceId NOT IN ('.implode(',', $wishlist_ids).') AND PrimaryCat = 1';
}
else {
$type_clauses['wish_list']['include']='0';
$type_clauses['wish_list']['except']='1';
}
$type_clauses['wish_list']['having_filter']=false;
}
// my favorite products: end
// products from package: begin
if (strpos($types, 'content') !== false) {
$object->removeFilter('category_filter');
$object->AddGroupByField('%1$s.ProductId');
$item_type = $this->Application->getUnitOption('p', 'ItemType');
$object_product = &$this->Application->recallObject($event->Prefix);
$content_ids_array = $object_product->GetPackageContentIds();
if (sizeof($content_ids_array)==0) {
$content_ids_array = array('-1');
}
if (sizeof($content_ids_array)>0) {
$type_clauses['content']['include'] = '%1$s.ProductId IN ('.implode(',', $content_ids_array).')';
}
else {
$type_clauses['content']['include']='0';
}
$type_clauses['related']['having_filter']=false;
}
// products from package: end
$object->addFilter('not_virtual', '%1$s.Virtual = 0');
if (!$this->Application->isAdminUser) {
$object->addFilter('expire_filter', '%1$s.Expire IS NULL OR %1$s.Expire > UNIX_TIMESTAMP()');
}
return $type_clauses;
}
function OnClearRecent(&$event)
{
$this->Application->RemoveVar('recent_products');
}
/**
* Occurs, when user rates a product
*
* @param kEvent $event
*/
function OnRateProduct(&$event)
{
$event->redirect_params = Array('pass' => 'all,p');
$event->redirect = $this->Application->GetVar('success_template');
$object =& $event->getObject();
$user_id = ($this->Application->RecallVar('user_id') == 0) ? -2 : $this->Application->RecallVar('user_id');
$sql = ' SELECT * FROM '.TABLE_PREFIX.'SpamControl
WHERE ItemResourceId='.$object->GetDBField('ResourceId').'
AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'"
AND PortalUserId='.$user_id.'
AND DataType="Rating"';
$res = $this->Conn->GetRow($sql);
if( $res && $res['Expire'] < adodb_mktime() )
{
$sql = ' DELETE FROM '.TABLE_PREFIX.'SpamControl
WHERE ItemResourceId='.$object->GetDBField('ResourceId').'
AND IPaddress="'.$_SERVER['REMOTE_ADDR'].'"
AND PortalUserId='.$user_id.'
AND DataType="Rating"';
$this->Conn->Query($sql);
unset($res);
}
$new_rating = $this->Application->GetVar('rating');
if($new_rating !== false && !$res)
{
$rating = $object->GetDBField('CachedRating');
$votes = $object->GetDBField('CachedVotesQty');
$new_votes = $votes + 1;
$rating = (($rating * $votes) + $new_rating) / $new_votes;
$object->SetDBField('CachedRating', $rating);
$object->SetDBField('CachedVotesQty', $new_votes);
$object->Update();
$expire = adodb_mktime() + $this->Application->ConfigValue('product_ReviewDelay_Value') * $this->Application->ConfigValue('product_ReviewDelay_Interval');
$sql = ' INSERT INTO '.TABLE_PREFIX.'SpamControl
(ItemResourceId, IPaddress, PortalUserId, DataType, Expire)
VALUES ('.$object->GetDBField('ResourceId').',
"'.$_SERVER['REMOTE_ADDR'].'",
'.$user_id.',
"Rating",
'.$expire.')';
$this->Conn->Query($sql);
}
else
{
$event->status == erFAIL;
$event->redirect=false;
$object->FieldErrors['CachedRating']['pseudo'] = 'too_frequent';
$object->ErrorMsgs['too_frequent'] = $this->Application->Phrase('lu_ferror_rate_duplicate');
}
}
function OnCancelAction(&$event)
{
$event->redirect_params = Array('pass' => 'all,p');
$event->redirect = $this->Application->GetVar('cancel_template');
}
function OnRecommendProduct(&$event)
{
// used for error reporting only -> rewrite code + theme (by Alex)
$object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true)); // TODO: change theme too
$friend_email = $this->Application->GetVar('friend_email');
$friend_name = $this->Application->GetVar('friend_name');
$my_email = $this->Application->GetVar('your_email');
$my_name = $this->Application->GetVar('your_name');
$my_message = $this->Application->GetVar('your_message');
$send_params = array();
$send_params['to_email']=$friend_email;
$send_params['to_name']=$friend_name;
$send_params['from_email']=$my_email;
$send_params['from_name']=$my_name;
$send_params['message']=$my_message;
- if (eregi("^[a-z0-9]+([-_\.]?[a-z0-9])+@[a-z0-9]+([-_\.]?[a-z0-9])+\.[a-z]{2,4}", $friend_email))
- {
+ if (preg_match('/'.REGEX_EMAIL_USER.'@'.REGEX_EMAIL_DOMAIN.'/', $friend_email)) {
$user_id = $this->Application->RecallVar('user_id');
$email_event = &$this->Application->EmailEventUser('PRODUCT.SUGGEST', $user_id, $send_params);
$email_event = &$this->Application->EmailEventAdmin('PRODUCT.SUGGEST');
if ($email_event->status == erSUCCESS){
$event->redirect_params = array('opener' => 's', 'pass' => 'all');
$event->redirect = $this->Application->GetVar('template_success');
}
else {
// $event->redirect_params = array('opener' => 's', 'pass' => 'all');
// $event->redirect = $this->Application->GetVar('template_fail');
$object->ErrorMsgs['send_error'] = $this->Application->Phrase('lu_email_send_error');
$object->FieldErrors['Email']['pseudo'] = 'send_error';
$event->status = erFAIL;
}
}
else {
$object->ErrorMsgs['invalid_email'] = $this->Application->Phrase('lu_InvalidEmail');
$object->FieldErrors['Email']['pseudo'] = 'invalid_email';
$event->status = erFAIL;
}
}
/**
* Creates/updates virtual product based on listing type data
*
* @param kEvent $event
*/
function OnSaveVirtualProduct(&$event)
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$listing_type =& $this->Application->recallObject('lst', null, Array('skip_autoload' => true));
$listing_type->Load($event->MasterEvent->getEventParam('id'));
$product_id = $listing_type->GetDBField('VirtualProductId');
if ($product_id) {
$object->Load($product_id);
}
if (!$listing_type->GetDBField('EnableBuying')) {
if ($product_id) {
// delete virtual product here
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$temp_handler->DeleteItems($event->Prefix, $event->Special, Array($product_id));
$listing_type->SetDBField('VirtualProductId', 0);
$listing_type->Update();
}
return true;
}
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
$object->SetDBField($ml_formatter->LangFieldName('Name'), $listing_type->GetDBField('ShopCartName') );
$object->SetDBField($ml_formatter->LangFieldName('Description'), $listing_type->GetDBField('Description'));
$object->SetDBField('SKU', 'ENHANCE_LINK_'.abs( crc32( $listing_type->GetDBField('Name') ) ) );
if ($product_id) {
$object->Update();
}
else {
$object->SetDBField('Type', 2);
$object->SetDBField('Status', 1);
$object->SetDBField('HotItem', 0);
$object->SetDBField('PopItem', 0);
$object->SetDBField('NewItem', 0);
$object->SetDBField('Virtual', 1);
// $processing_data = Array('ApproveEvent' => 'ls:EnhanceLinkAfterOrderApprove', 'ExpireEvent' => 'ls:ExpireLink');
$processing_data = Array( 'ApproveEvent' => 'ls:EnhanceLinkAfterOrderApprove',
'DenyEvent' => 'ls:EnhanceLinkAfterOrderDeny',
'CompleteOrderEvent' => 'ls:EnhancedLinkOnCompleteOrder',
'ExpireEvent' => 'ls:ExpireLink',
'HasNewProcessing' => 1);
$object->SetDBField('ProcessingData', serialize($processing_data));
$object->Create();
$listing_type->SetDBField('VirtualProductId', $object->GetID());
$listing_type->Update();
}
$additiona_fields = Array( 'AccessDuration' => $listing_type->GetDBField('Duration'),
'AccessUnit' => $listing_type->GetDBField('DurationType'),
);
$this->setPrimaryPrice($object->GetID(), (double)$listing_type->GetDBField('Price'), $additiona_fields);
}
/**
* [HOOK] Deletes virtual product when listing type is deleted
*
* @param kEvent $event
*/
function OnDeleteListingType(&$event)
{
$listing_type = $event->MasterEvent->getObject();
$product_id = $listing_type->GetDBField('VirtualProductId');
if ($product_id) {
$temp_handler =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
$temp_handler->DeleteItems($event->Prefix, $event->Special, Array($product_id));
}
}
/**
* Extends user membership in group when his order is approved
*
* @param kEvent $event
*/
function OnSubscriptionApprove(&$event)
{
$field_values = $event->getEventParam('field_values');
$item_data = unserialize($field_values['ItemData']);
if (!getArrayValue($item_data,'PortalGroupId')) {
// is subscription product, but no group defined in it's properties
trigger_error('Invalid product <b>'.$field_values['ProductName'].'</b> (id: '.$field_values['ProductId'].')');
return false;
}
$order_table = $this->Application->getUnitOption('ord', 'TableName');
$order_idfield = $this->Application->getUnitOption('ord', 'IDField');
$sql = 'SELECT PortalUserId FROM %s WHERE %s = %s';
$user_id = $this->Conn->GetOne( sprintf($sql, $order_table, $order_idfield, $field_values['OrderId']) );
$group_id = $item_data['PortalGroupId'];
$duration = $item_data['Duration'];
$sql = 'SELECT * FROM '.TABLE_PREFIX.'UserGroup WHERE PortalUserId = %s';
$user_groups = $this->Conn->Query( sprintf($sql, $user_id), 'GroupId' );
$sql = 'REPLACE INTO '.TABLE_PREFIX.'UserGroup (PortalUserId,GroupId,MembershipExpires,PrimaryGroup) VALUES (%s,%s,%s,%s)';
if( !isset($user_groups[$group_id]) )
{
$primary_group = count($user_groups) == 0 ? 1 : 0;
$expire = adodb_mktime() + $duration;
}
else {
$primary_group = $user_groups[$group_id]['PrimaryGroup'];
$expire = $user_groups[$group_id]['MembershipExpires'];
$expire = $expire < adodb_mktime() ? adodb_mktime() + $duration : $expire + $duration;
}
/*
// Customization healtheconomics.org
if ($item_data['DurationType'] == 2) {
$expire = $item_data['AccessExpiration'];
}
// Customization healtheconomics.org --
*/
$this->Conn->Query( sprintf($sql, $user_id, $group_id, $expire, $primary_group) );
$sub_order =& $this->Application->recallObject('ord.-sub'.$event->getEventParam('next_sub_number'), 'ord');
$sub_order->SetDBField('IsRecurringBilling', getArrayValue($item_data, 'IsRecurringBilling') ? 1 : 0);
$sub_order->SetDBField('GroupId', $group_id);
$sub_order->SetDBField('NextCharge_date', $expire);
$sub_order->SetDBField('NextCharge_time', $expire);
}
function OnDownloadableApprove(&$event)
{
$field_values = $event->getEventParam('field_values');
$product_id = $field_values['ProductId'];
$sql = 'SELECT PortalUserId FROM '.$this->Application->getUnitOption('ord', 'TableName').'
WHERE OrderId = '.$field_values['OrderId'];
$user_id = $this->Conn->GetOne($sql);
$sql = 'INSERT INTO '.TABLE_PREFIX.'UserFileAccess VALUES("", '.$product_id.', '.$user_id.')';
$this->Conn->Query($sql);
}
function OnPackageApprove(&$event){
$field_values = $event->getEventParam('field_values');
$item_data = unserialize($field_values['ItemData']);
$package_content_ids = $item_data['PackageContent'];
$object_item = &$this->Application->recallObject('p.packageitem', null, array('skip_autoload'=>true));
foreach ($package_content_ids as $package_item_id) {
$object_field_values = array();
// query processing data from product and run approve event
$sql = 'SELECT ProcessingData FROM '.TABLE_PREFIX.'Products WHERE ProductId = '.$package_item_id;
$processing_data = $this->Conn->GetOne($sql);
if($processing_data)
{
$processing_data = unserialize($processing_data);
$approve_event = new kEvent($processing_data['ApproveEvent']);
//$order_item_fields = $this->Conn->GetRow('SELECT * FROM '.TABLE_PREFIX.'OrderItems WHERE OrderItemId = '.$grouping_data[1]);
$object_item->Load($package_item_id);
$object_field_values['OrderId'] = $field_values['OrderId'];
$object_field_values['ProductId'] = $package_item_id;
$object_field_values['ItemData'] = serialize($item_data['PackageItemsItemData'][$package_item_id]);
$approve_event->setEventParam('field_values', $object_field_values);
$this->Application->HandleEvent($approve_event);
}
}
}
/**
* Checks, that all required product options are filled in before product is saved
*
* @param kEvent $event
*/
function OnPreSave(&$event)
{
$this->CheckRequiredOptions($event);
parent::OnPreSave($event);
}
/**
* Set new price to ProductsPricing
*
* @param kEvent $event
*/
function OnAfterItemCreate(&$event)
{
parent::OnAfterItemCreate($event);
$this->_updateProductPrice($event);
}
/**
* Set new price to ProductsPricing
*
* @param kEvent $event
*/
function OnAfterItemUpdate(&$event)
{
parent::OnAfterItemUpdate($event);
$this->_updateProductPrice($event);
}
/**
* Updates product's primary price based on Price virtual field value
*
* @param kEvent $event
*/
function _updateProductPrice(&$event)
{
$object =& $event->getObject();
/* @var $object kDBItem */
$price = $object->GetDBField('Price');
// always create primary pricing, to show on Pricing tab (in admin) for tangible products
$force_create = ($object->GetDBField('Type') == PRODUCT_TYPE_TANGIBLE) && is_null($price);
if ($force_create || ($price != $object->GetOriginalField('Price'))) {
// new product OR price was changed in virtual field
$this->setPrimaryPrice($object->GetID(), (float)$price);
}
}
function CheckRequiredOptions(&$event)
{
$object =& $event->getObject();
if ($object->GetDBField('ProductId') == '') return ; // if product does not have ID - it's not yet created
$opt_object =& $this->Application->recallObject('po', null, Array('skip_autoload' => true) );
$has_required = $this->Conn->GetOne('SELECT COUNT(*) FROM '.$opt_object->TableName.' WHERE Required = 1 AND ProductId = '.$object->GetDBField('ProductId'));
//we need to imitate data sumbit, as parent' PreSave sets object values from $items_info
$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );
$items_info[$object->GetDBField('ProductId')]['HasRequiredOptions'] = $has_required ? 1:0;
$this->Application->SetVar($event->getPrefixSpecial(true), $items_info);
$object->SetDBField('HasRequiredOptions', $has_required ? 1:0);
}
/**
* Sets required price in primary price backed, if it's missing, then create it
*
* @param int $product_id
* @param double $price
* @param Array $additional_fields
* @return bool
*/
function setPrimaryPrice($product_id, $price, $additional_fields = Array())
{
$pr_object =& $this->Application->recallObject('pr.-item', null, Array('skip_autoload' => true) );
/* @var $pr_object kDBItem */
$pr_object->Load( Array('ProductId' => $product_id, 'IsPrimary' => 1) );
$sql = 'SELECT COUNT(*) FROM '.$pr_object->TableName.' WHERE ProductId = '.$product_id;
$has_pricings = $this->Conn->GetOne($sql);
if ($additional_fields) {
$pr_object->SetDBFieldsFromHash($additional_fields);
}
if( ($price === false) && $has_pricings ) return false;
if( $pr_object->isLoaded() )
{
$pr_object->SetField('Price', $price);
return $pr_object->Update();
}
else
{
$group_id = $this->Application->ConfigValue('User_LoggedInGroup');
$field_values = Array('ProductId' => $product_id, 'IsPrimary' => 1, 'MinQty' => 1, 'MaxQty' => -1, 'GroupId'=>$group_id);
$pr_object->SetDBFieldsFromHash($field_values);
$pr_object->SetField('Price', $price);
$ret = $pr_object->Create();
if ($pr_object->mode == 't') {
$pr_object->setTempID();
}
return $ret;
}
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnAfterItemDelete(&$event)
{
$product_id = $event->getEventParam('id');
if(!$product_id)
{
return;
}
$sql = 'DELETE FROM '.TABLE_PREFIX.'UserFileAccess
WHERE ProductId = '.$product_id;
$this->Conn->Query($sql);
}
/**
* Load price from temp table if product mode is temp table
*
* @param kEvent $event
*/
function OnAfterItemLoad(&$event)
{
parent::OnAfterItemLoad($event);
$object =& $event->getObject();
/* @var $object kDBItem */
$a_pricing = $object->getPrimaryPricing();
if (!$a_pricing) {
// pricing doesn't exist for new products
$price = $cost = null;
}
else {
$price = (float)$a_pricing['Price'];
$cost = (float)$a_pricing['Cost'];
}
// set original fields to use them in OnAfterItemCreate/OnAfterItemUpdate later
$object->SetDBField('Price', $price);
$object->SetOriginalField('Price', $price);
$object->SetDBField('Cost', $cost);
$object->SetOriginalField('Cost', $cost);
}
/**
* Allows to add products to package besides all that parent method does
*
* @param kEvent $event
*/
function OnProcessSelected(&$event)
{
$dst_field = $this->Application->RecallVar('dst_field');
if ($dst_field == 'PackageContent') {
$this->OnAddToPackage($event);
}
elseif ($dst_field == 'AssignedCoupon') {
$coupon_id = $this->Application->GetVar('selected_ids');
$object =& $event->getObject();
$object->SetDBField('AssignedCoupon', $coupon_id);
$this->RemoveRequiredFields($object);
$object->Update();
}
else {
parent::OnProcessSelected($event);
}
$this->finalizePopup($event);
}
/**
* Called when some products are selected in products selector for this prefix
*
* @param kEvent $event
*/
function OnAddToPackage(&$event)
{
$selected_ids = $this->Application->GetVar('selected_ids');
// update current package content with selected products
$object =& $event->getObject();
/* @var $object ProductsItem */
$product_ids = $selected_ids['p'] ? explode(',', $selected_ids['p']) : Array();
if ($product_ids) {
$current_ids = $object->GetPackageContentIds();
$current_ids = array_unique(array_merge($current_ids, $product_ids));
// remove package product from selected list
$this_product = array_search($object->GetID(), $current_ids);
if ($this_product !== false) {
unset($current_ids[$this_product]);
}
$dst_field = $this->Application->RecallVar('dst_field');
$object->SetDBField($dst_field, '|'.implode('|', $current_ids).'|');
$object->Update();
$this->ProcessPackageItems($event);
}
$this->finalizePopup($event);
}
function ProcessPackageItems(&$event)
{
//$this->Application->SetVar('p_mode', 't');
$object =& $event->getObject();
/* @var $object ProductsItem */
$content_ids = $object->GetPackageContentIds();
if (sizeof($content_ids) > 0) {
$total_weight = $this->Conn->GetOne('SELECT SUM(Weight) FROM '.TABLE_PREFIX.'Products WHERE ProductId IN ('.implode(', ', $content_ids).') AND Type=1');
if (!$total_weight) $total_weight = 0;
$this->Conn->Query('UPDATE '.$object->TableName.' SET Weight='.$total_weight.' WHERE ProductId='.$object->GetID());
}
/*
$this->Application->SetVar('p_mode', false);
$list = &$this->Application->recallObject('p.content', 'p_List', array('types'=>'content'));
$this->Application->SetVar('p_mode', 't');
$list->Query();
$total_weight_a = 0;
$total_weight_b = 0;
$list->GoFirst();
while (!$list->EOL())
{
if ($list->GetDBField('Type')==1){
$total_weight_a += $list->GetField('Weight_a');
$total_weight_b += $list->GetField('Weight_b');
}
$list->GoNext();
}
$object->SetField('Weight_a', $total_weight_a);
$object->SetField('Weight_b', $total_weight_b);
*/
//$object->Update();
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnSaveItems(&$event)
{
//$event->CallSubEvent('OnUpdate');
$event->redirect = false;
//$event->redirect_params = Array('opener'=>'s','pass'=>'all,p');
}
/**
* Removes product from package
*
* @param kEvent $event
*/
function OnRemovePackageItem(&$event) {
$this->Application->SetVar('p_mode', 't');
$object =& $event->getObject();
$items_info = $this->Application->GetVar('p_content');
if($items_info)
{
$product_ids = array_keys($items_info);
$current_ids = $object->GetPackageContentIds();
$current_ids_flip = array_flip($current_ids);
foreach($product_ids as $key=>$val){
unset($current_ids_flip[$val]);
}
$current_ids = array_keys($current_ids_flip);
$current_ids_str = '|'.implode('|', array_unique($current_ids)).'|';
$object->SetDBField('PackageContent', $current_ids_str);
}
$object->Update();
$this->ProcessPackageItems($event);
}
/**
* Enter description here...
*
* @param kEvent $event
*/
function OnBeforeItemDelete(&$event){
$object = &$event->getObject();
$product_includes_in = $this->Conn->GetOne('SELECT COUNT(*) FROM '.TABLE_PREFIX.'Products WHERE PackageContent LIKE "%|'.$object->GetID().'%"');
if ($product_includes_in > 0){
$event->status=erFAIL;
}
}
/**
* Returns specific to each item type columns only
*
* @param kEvent $event
* @return Array
*/
function getCustomExportColumns(&$event)
{
$columns = parent::getCustomExportColumns($event);
$new_columns = Array(
'__VIRTUAL__Price' => 'Price',
'__VIRTUAL__Cost' => 'Cost',
);
return array_merge_recursive2($columns, $new_columns);
}
/**
* Sets non standart virtual fields (e.g. to other tables)
*
* @param kEvent $event
*/
function setCustomExportColumns(&$event)
{
parent::setCustomExportColumns($event);
$object =& $event->getObject();
$this->setPrimaryPrice($object->GetID(), (double)$object->GetDBField('Price'), Array('Cost' => (double)$object->GetDBField('Cost')) );
}
function OnPreSaveAndOpenPopup(&$event)
{
$object =& $event->getObject();
$this->RemoveRequiredFields($object);
$event->CallSubEvent('OnPreSave');
$event->redirect = $this->Application->GetVar('t');
// pass ID too, in case if product is created by OnPreSave call to ensure proper editing
$event->redirect_params = Array(
'pass' => 'all',
$event->getPrefixSpecial(true).'_id' => $object->GetID(),
);
}
function getPassedID(&$event)
{
$event->setEventParam('raise_warnings', 0);
$passed = parent::getPassedID($event);
if ($passed) {
return $passed;
}
if ($this->Application->isAdminUser) {
// we may get product id out of OrderItem, if it exists
$ord_item =& $this->Application->recallObject('orditems', null, Array ('raise_warnings' => 0));
if ($ord_item->GetDBField('ProductId')) {
$passed = $ord_item->GetDBField('ProductId');
}
}
return $passed;
}
function OnAfterConfigRead(&$event)
{
parent::OnAfterConfigRead($event);
if (!$this->Application->LoggedIn()) {
return ;
}
$user_id = $this->Application->RecallVar('user_id');
$calculated_fields = $this->Application->getUnitOption($event->Prefix, 'CalculatedFields');
$sql = 'SELECT GroupId
FROM ' . TABLE_PREFIX . 'UserGroup
WHERE PrimaryGroup = 1 AND PortalUserId = ' . $user_id;
$primary_group = $this->Conn->GetOne($sql);
if (!$primary_group) {
return;
}
$sub_select = ' SELECT pp.Price
FROM ' . TABLE_PREFIX . 'ProductsPricing AS pp
WHERE pp.ProductId = %1$s.ProductId AND GroupId = ' . $primary_group . '
ORDER BY MinQty
LIMIT 0,1';
$calculated_fields['']['Price'] = 'IFNULL((' . $sub_select . '), ' . $calculated_fields['']['Price'] . ')';
$this->Application->setUnitOption($event->Prefix, 'CalculatedFields', $calculated_fields);
}
/**
* Starts product editing, remove any pending inventory actions
*
* @param kEvent $event
*/
function OnEdit(&$event)
{
$this->Application->RemoveVar('inventory_actions');
parent::OnEdit($event);
}
/**
* Adds "Shop Cart" tab on paid listing type editing tab
*
* @param kEvent $event
*/
function OnModifyPaidListingConfig(&$event)
{
$edit_tab_presets = $this->Application->getUnitOption($event->MasterEvent->Prefix, 'EditTabPresets');
$edit_tab_presets['Default']['shopping_cart'] = Array ('title' => 'la_tab_ShopCartEntry', 't' => 'in-commerce/paid_listings/paid_listing_type_shopcart', 'priority' => 2);
$this->Application->setUnitOption($event->MasterEvent->Prefix, 'EditTabPresets', $edit_tab_presets);
}
}
\ No newline at end of file

Event Timeline