getObject($params); $type = getArrayValue($params,'type'); if($type == 'Company') { return $this->PrintCompanyLocation($params); } $fields = Array('City','State','Zip','Country'); $ret = ''; foreach($fields as $field) { $value = $object->GetField($type.$field); if ($field == 'Country' && $value) $ret .= '
'; if($value) $ret .= $value.', '; } return rtrim($ret,', '); } function PrintCompanyLocation($params) { $ret = ''; $fields = Array ('City','State','ZIP','Country'); foreach ($fields as $field) { $value = $this->Application->ConfigValue('Comm_'.$field); if ($field == 'Country') { $current_language = $this->Application->GetVar('m_lang'); $primary_language = $this->Application->GetDefaultLanguageId(); $sql = 'SELECT IF(l' . $current_language . '_Name = "", l' . $primary_language . '_Name, l' . $current_language . '_Name) FROM ' . TABLE_PREFIX . 'CountryStates WHERE IsoCode = ' . $this->Conn->qstr($value); $value = $this->Conn->GetOne($sql); } if ($field == 'Country' && $value) { $ret .= '
'; } if ($value) { $ret .= $value.', '; } } return rtrim($ret,', '); } function Orditems_LinkRemoveFromCart($params) { $params['m_cat_id'] = 0; $params['ord_event'] = 'OnRemoveFromCart'; if ( !isset($params['pass']) ) { $params['pass'] = 'm,orditems,ord'; } // Remove parameters, that indicate from where this aggregated tag was called. unset($params['PrefixSpecial'], $params['original_tag']); return $this->Application->ProcessParsedTag('m', 'Link', $params); } function Orderitems_ProductLink($params) { $object = $this->Application->recallObject('orditems'); $url_params = Array ( 'p_id' => $object->GetDBField('ProductId'), 'pass' => 'm,p', ); return $this->Application->HREF($params['template'], '', $url_params); } function Orderitems_ProductExists($params) { $object = $this->Application->recallObject('orditems'); return $object->GetDBField('ProductId') > 0; } function PrintCart($params) { $o = ''; $params['render_as'] = $params['item_render_as']; $tag_params = array_merge($params, Array ('per_page' => -1)); $o_items = $this->Application->ProcessParsedTag(rtrim('orditems.' . $this->Special, '.'), 'PrintList', $tag_params); if ( $o_items ) { if ( isset($params['header_render_as']) ) { $cart_params = array ('name' => $params['header_render_as']); $o .= $this->Application->ParseBlock($cart_params); } $o .= $o_items; if ( isset($params['footer_render_as']) ) { $cart_params = array ('name' => $params['footer_render_as']); $o .= $this->Application->ParseBlock($cart_params); } } elseif ( isset($params['empty_cart_render_as']) ) { $cart_params = array ('name' => $params['empty_cart_render_as']); $o = $this->Application->ParseBlock($cart_params); } return $o; } function ShopCartForm($params) { return $this->Application->ProcessParsedTag('m', 'ParseBlock', array_merge($params, Array( 'name' => 'kernel_form', 'PrefixSpecial'=>'ord' )) ); } function BackOrderFlag($params) { $object = $this->Application->recallObject('orditems'); return $object->GetDBField('BackOrderFlag'); } function OrderIcon($params) { $object = $this->Application->recallObject('orditems'); if ($object->GetDBField('BackOrderFlag') == 0) { return $params['ordericon']; } else { return $params['backordericon']; } } function Status($params) { $status_map = Array( 'incomplete' => ORDER_STATUS_INCOMPLETE, 'pending' => ORDER_STATUS_PENDING, 'backorder' => ORDER_STATUS_BACKORDERS, 'toship' => ORDER_STATUS_TOSHIP, 'processed' => ORDER_STATUS_PROCESSED, 'denied' => ORDER_STATUS_DENIED, 'archived' => ORDER_STATUS_ARCHIVED, ); $object = $this->getObject($params); $status = $object->GetDBField('Status'); $result = true; if (isset($params['is'])) { $result = $result && ($status == $status_map[$params['is']]); } if (isset($params['is_not'])) { $result = $result && ($status != $status_map[$params['is_not']]); } return $result; } function ItemsInCart($params) { $object = $this->getObject($params); /* @var $object kDBItem */ if ( $object->GetDBField('Status') != ORDER_STATUS_INCOMPLETE || $object->GetID() == FAKE_ORDER_ID ) { return 0; } $object = $this->Application->recallObject('orditems', 'orditems_List'); /* @var $object kDBList */ $object->Query(); return array_sum($object->GetCol('Quantity')); // $object->GetRecordsCount(); } function CartNotEmpty($params) { $object = $this->getObject($params); if ($object->GetDBField('Status') != ORDER_STATUS_INCOMPLETE || $object->GetID() == FAKE_ORDER_ID) { return 0; } $order_id = $this->Application->RecallVar('ord_id'); if ($order_id) { $sql = 'SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'OrderItems WHERE OrderId = ' . $order_id; return $this->Conn->GetOne($sql); } return 0; } function CartIsEmpty($params) { return $this->CartNotEmpty($params) ? false : true; } function CartHasBackorders($params = Array ()) { $object = $this->getObject($params); $sql = 'SELECT COUNT(*) FROM ' . TABLE_PREFIX . 'OrderItems WHERE OrderId = ' . $object->GetID() . ' GROUP BY BackOrderFlag'; $different_types = $this->Conn->GetCol($sql); return count($different_types) > 1; } function PrintShippings($params) { $o = ''; $limitations_cache = Array (); $object = $this->getObject($params); /* @var $object kDBItem */ $ord_id = $object->GetID(); $oi_table = $this->Application->getUnitOption('orditems', 'TableName'); if ( $object->IsTempTable() ) { $oi_table = $this->Application->GetTempName($oi_table, 'prefix:' . $object->Prefix); } list ($split_shipments, $limit_types) = $this->GetShippingLimitations($ord_id); foreach ($split_shipments as $group => $data) { $sql = 'UPDATE ' . $oi_table . ' SET SplitShippingGroup = ' . $group . ' WHERE ProductId IN (' . implode(',', $data['Products']) . ')'; $this->Conn->Query($sql); $limitations_cache[$group] = $data['Types']; } $shipping_group_option = $object->GetDBField('ShippingGroupOption'); $shipping_group_select = $shipping_group_option == ORDER_GROUP_SHIPPMENTS_AUTO ? '0' : 'oi.SplitShippingGroup'; if ( count($split_shipments) > 1 ) { // different shipping limitations apply $this->Application->SetVar('shipping_limitations_apply', 1); if ( $limit_types == 'NONE' ) { // order can't be shipped with single shipping type $shipping_group_option = ORDER_GROUP_SHIPPMENTS_MANUAL; $shipping_group_select = 'oi.SplitShippingGroup'; $this->Application->SetVar('shipping_limitations_apply', 2); } } else { $this->Application->SetVar('shipping_limitations_apply', 0); } $shipping_option = $object->GetDBField('ShippingOption'); $weight_sql = 'IF(oi.Weight IS NULL, 0, oi.Weight * oi.Quantity)'; $sql = 'SELECT ' . ($shipping_option == ORDER_SHIP_ALL_TOGETHER ? '0' : 'oi.BackOrderFlag') . ' AS BackOrderFlagCalc, oi.ProductName, oi.ShippingTypeId, SUM(oi.Quantity) AS TotalItems, SUM(' . $weight_sql . ') AS TotalWeight, SUM(oi.Price * oi.Quantity) AS TotalAmount, SUM(oi.Quantity) - SUM(IF(p.MinQtyFreePromoShipping > 0 AND p.MinQtyFreePromoShipping <= oi.Quantity, oi.Quantity, 0)) AS TotalItemsPromo, SUM(' . $weight_sql . ') - SUM(IF(p.MinQtyFreePromoShipping > 0 AND p.MinQtyFreePromoShipping <= oi.Quantity, ' . $weight_sql . ', 0)) AS TotalWeightPromo, SUM(oi.Price * oi.Quantity) - SUM(IF(p.MinQtyFreePromoShipping > 0 AND p.MinQtyFreePromoShipping <= oi.Quantity, oi.Price * oi.Quantity, 0)) AS TotalAmountPromo, ' . $shipping_group_select . ' AS SplitShippingGroupCalc FROM ' . $oi_table . ' oi LEFT JOIN ' . TABLE_PREFIX . 'Products p ON oi.ProductId = p.ProductId WHERE oi.OrderId = ' . $ord_id . ' AND p.Type = ' . PRODUCT_TYPE_TANGIBLE . ' GROUP BY BackOrderFlagCalc, SplitShippingGroupCalc ORDER BY BackOrderFlagCalc ASC, SplitShippingGroupCalc ASC'; $shipments = $this->Conn->Query($sql); $block_params = Array (); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $block_params['user_country_id'] = $object->GetDBField('ShippingCountry'); $block_params['user_state_id'] = $object->GetDBField('ShippingState'); $block_params['user_zip'] = $object->GetDBField('ShippingZip'); $block_params['user_city'] = $object->GetDBField('ShippingCity'); $block_params['user_addr1'] = $object->GetDBField('ShippingAddress1'); $block_params['user_addr2'] = $object->GetDBField('ShippingAddress2'); $block_params['user_name'] = $object->GetDBField('ShippingTo'); $group = 1; foreach ($shipments as $shipment) { $where = Array ('OrderId = ' . $ord_id); if ( $shipping_group_option == ORDER_GROUP_SHIPPMENTS_MANUAL ) { $where[] = 'SplitShippingGroup = ' . $shipment['SplitShippingGroupCalc']; } if ( $shipping_option != ORDER_SHIP_ALL_TOGETHER ) { $where[] = 'BackOrderFlag = ' . $shipment['BackOrderFlagCalc']; } $sql = 'UPDATE ' . $oi_table . ' SET PackageNum = ' . $group . ' WHERE ' . implode(' AND ', $where); $this->Conn->Query($sql); $group++; } $group = 1; $this->Application->RemoveVar('LastShippings'); $this->Application->SetVar('ShipmentsExists', 1); foreach ($shipments as $shipment) { $block_params['package_num'] = $group; $block_params['limit_types'] = $shipping_group_option == ORDER_GROUP_SHIPPMENTS_AUTO ? $limit_types : $limitations_cache[ $shipment['SplitShippingGroupCalc'] ]; $this->Application->SetVar('ItemShipmentsExists', 1); // also set from Order_PrintShippingTypes tag switch ( $shipment['BackOrderFlagCalc'] ) { case 0: if ( $this->CartHasBackOrders() && $shipping_option == ORDER_SHIP_ALL_TOGETHER ) { $block_params['shipment'] = $this->Application->Phrase('lu_all_available_backordered'); } else { $block_params['shipment'] = $this->Application->Phrase('lu_ship_all_available');; } break; case 1: $block_params['shipment'] = $this->Application->Phrase('lu_ship_all_backordered');; break; default: $block_params['shipment'] = $this->Application->Phrase('lu_ship_backordered'); break; } $block_params['promo_weight_metric'] = $shipment['TotalWeightPromo']; $block_params['promo_amount'] = $shipment['TotalAmountPromo']; $block_params['promo_items'] = $shipment['TotalItemsPromo']; $block_params['weight_metric'] = $shipment['TotalWeight']; $block_params['weight'] = $shipment['TotalWeight']; if ( $block_params['weight_metric'] == '' ) { $block_params['weight'] = $this->Application->Phrase('lu_NotAvailable'); } else { $block_params['weight'] = $this->_formatWeight( $block_params['weight'] ); } $block_params['items'] = $shipment['TotalItems']; $amount = $this->ConvertCurrency($shipment['TotalAmount'], $this->GetISO( $params['currency'] )); $amount = sprintf("%.2f", $amount); $block_params['amount'] = $shipment['TotalAmount']; $block_params['field_name'] = $this->InputName( Array('field' => 'ShippingTypeId') ) . '[' . $group . ']'; $parsed_block = $this->Application->ParseBlock($block_params); if ( $this->Application->GetVar('ItemShipmentsExists') ) { $o .= $parsed_block; } else { $this->Application->SetVar('ShipmentsExists', 0); if ( getArrayValue($params, 'no_shipments_render_as') ) { $block_params['name'] = $params['no_shipments_render_as']; return $this->Application->ParseBlock($block_params); } } $group++; } if ( getArrayValue($params, 'table_header_render_as') ) { $o = $this->Application->ParseBlock(Array ('name' => $params['table_header_render_as'])) . $o; } if ( getArrayValue($params, 'table_footer_render_as') ) { $o .= $this->Application->ParseBlock(Array ('name' => $params['table_footer_render_as'])); } return $o; } /** * Checks, that all given address fields are valid * * @param Array $params * @return bool */ function AddressValid($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $address_type = isset($params['type']) ? strtolower($params['type']) : 'shipping'; $address_type = ucfirst($address_type); $check_fields = Array ('Address1', 'City', 'Zip', 'Country'); foreach ($check_fields as $check_field) { if ( $object->GetDBField($address_type . $check_field) == '' ) { return false; } } return true; } function GetShippingLimitations($ord_id) { $limit_types = false; $types_index = $split_shipments = $cat_limitations = Array (); $sql = 'SELECT p.ShippingLimitation, p.ShippingMode, oi.ProductId AS ProductId FROM ' . TABLE_PREFIX . 'Products p LEFT JOIN ' . TABLE_PREFIX . 'OrderItems AS oi ON oi.ProductId = p.ProductId WHERE oi.OrderId = ' . $ord_id . ' AND p.Type = ' . PRODUCT_TYPE_TANGIBLE; $limitations = $this->Conn->Query($sql, 'ProductId'); // group products by shipping type range and calculate intersection of all types available for ALL products // the intersection calculation is needed to determine if the order can be shipped with single type or not if ($limitations) { foreach ($limitations as $product_id => $row) { // if shipping types are limited - get the types $types = $row['ShippingLimitation'] != '' ? explode('|', substr($row['ShippingLimitation'], 1, -1)) : Array ('ANY'); // if shipping is NOT limited to selected types (default - so products with no limitations at all also counts) if ($row['ShippingMode'] == PRODUCT_SHIPPING_MODE_ANY_AND_SELECTED) { array_push($types, 'ANY'); // can be shipped with ANY (literally) type $types = array_unique($types); } //adding product id to split_shipments group by types range $i = array_search(serialize($types), $types_index); if ($i === false) { $types_index[] = serialize($types); $i = count($types_index) - 1; } $split_shipments[$i]['Products'][] = $product_id; $split_shipments[$i]['Types'] = serialize($types); if ($limit_types === false) { // it is false only when we process first item with limitations $limit_types = $types; // initial scope } // this is to avoid ANY intersect CUST_1 = (), but allows ANY intersect CUST_1,ANY = (ANY) if ( in_array('ANY', $limit_types) && !in_array('ANY', $types) ) { array_splice($limit_types, array_search('ANY', $limit_types), 1, $types); } // this is to avoid CUST_1 intersect ANY = (), but allows CUST_1 intersect CUST_1,ANY = (ANY) if ( !in_array('ANY', $limit_types) && in_array('ANY', $types) ) { array_splice($types, array_search('ANY', $types), 1, $limit_types); } $limit_types = array_intersect($limit_types, $types); } $limit_types = count($limit_types) > 0 ? serialize(array_unique($limit_types)) : 'NONE'; } return Array ($split_shipments, $limit_types); } function PaymentTypeForm($params) { $object = $this->getObject($params); $payment_type_id = $object->GetDBField('PaymentType'); if($payment_type_id) { $this->Application->SetVar('pt_id', $payment_type_id); $block_params['name'] = $this->SelectParam($params, $this->UsingCreditCard($params) ? 'cc_render_as,block_cc' : 'default_render_as,block_default' ); return $this->Application->ParseBlock($block_params); } return ''; } /** * Returns true in case if credit card was used as payment type for order. * * @param array $params Tag params. * * @return boolean * @throws Exception When payment type not found. */ protected function UsingCreditCard(array $params) { static $payment_types; if ( !isset($payment_types) ) { $pt_table = $this->Application->getUnitOption('pt', 'TableName'); $sql = 'SELECT g.RequireCCFields, pt.PaymentTypeId FROM ' . $pt_table . ' pt JOIN ' . TABLE_PREFIX . 'Gateways g ON g.GatewayId = pt.GatewayId'; $payment_types = $this->Conn->GetCol($sql, 'PaymentTypeId'); } /** @var kDBItem $object */ $object = $this->getObject($params); $payment_type = $object->GetDBField('PaymentType'); if ( !$payment_type ) { $payment_type = $this->getPrimaryPaymentType(); $object->SetDBField('PaymentType', $payment_type); } if ( !isset($payment_types[$payment_type]) ) { throw new Exception('Unknown payment type: ' . $payment_type); } return $payment_types[$payment_type]; } /** * Get primary payment type. * * @return string */ protected function getPrimaryPaymentType() { static $primary_payment_type; if ( !isset($primary_payment_type) ) { $pt_table = $this->Application->getUnitOption('pt', 'TableName'); $sql = 'SELECT PaymentTypeId FROM ' . $pt_table . ' WHERE IsPrimary = 1'; $primary_payment_type = $this->Conn->GetOne($sql); } return $primary_payment_type; } function PaymentTypeDescription($params) { return $this->Application->ProcessParsedTag('pt', 'Field', array_merge($params, Array( 'field' => 'Description' )) ); } function PaymentTypeInstructions($params) { return $this->Application->ProcessParsedTag('pt', 'Field', array_merge($params, Array( 'field' => 'Instructions' )) ); } function PrintMonthOptions($params) { $object = $this->getObject($params); $date = explode('/', $object->GetDBField($params['date_field_name'])); if (!$date || sizeof($date) != 2) { $date=array("", ""); } $o = ''; $params['name'] = $params['block']; for ($i = 1; $i <= 12; $i++) { $month_str = str_pad($i, 2, "0", STR_PAD_LEFT); if ($date[0] == $month_str) { $params['selected'] = ' selected'; }else { $params['selected'] = ''; } $params['mm'] = $month_str; $o .= $this->Application->ParseBlock($params); } return $o; } function PrintYearOptions($params) { $object = $this->getObject($params); $value = $object->GetDBField( $params['field'] ); $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $o = ''; $this_year = adodb_date('y'); for($i = $this_year; $i <= $this_year + 10; $i++) { $year_str = str_pad($i, 2, '0', STR_PAD_LEFT); $block_params['selected'] = ($value == $year_str) ? $params['selected'] : ''; $block_params['key'] = $year_str; $block_params['option'] = $year_str; $o .= $this->Application->ParseBlock($block_params); } return $o; } function PrintMyOrders($params) { } /** * Checks, that order data can be editied based on it's status * * @param Array $params * @return bool */ function OrderEditable($params) { $id_field = $this->Application->getUnitOption($this->Prefix, 'IDField'); $table_name = $this->Application->getUnitOption($this->Prefix, 'TableName'); if ($this->Application->IsTempMode($this->Prefix, $this->Special)) { $table_name = $this->Application->GetTempName($table_name, 'prefix:' . $this->Prefix); } // use direct select here (not $this->getObject) because this tag is // used even before "combined_header" block is used (on "orders_edit_items" template) $sql = 'SELECT Status, PaymentType FROM ' . $table_name . ' WHERE ' . $id_field . ' = ' . $this->Application->GetVar( $this->getPrefixSpecial() . '_id' ); $order_data = $this->Conn->GetRow($sql); if (!$order_data) { // new order adding, when even not in database return true; } switch ($order_data['Status']) { case ORDER_STATUS_INCOMPLETE: $ret = true; break; case ORDER_STATUS_PENDING: case ORDER_STATUS_BACKORDERS: $sql = 'SELECT PlacedOrdersEdit FROM ' . $this->Application->getUnitOption('pt', 'TableName') . ' WHERE ' . $this->Application->getUnitOption('pt', 'IDField') . ' = ' . $order_data['PaymentType']; $ret = $this->Conn->GetOne($sql); break; default: $ret = false; break; } return $ret; } function CheckoutSteps($params) { $steps = explode(',', $params['steps']); foreach ($steps as $key => $item) { $templates[$key] = trim($item); } $templates = explode(',', $params['templates']); foreach ($templates as $key => $item) { $templates[$key] = trim($item); } $total_steps = count($templates); $t = $this->Application->GetVar('t'); $o = ''; $block_params = array(); $i = 0; $passed_current = preg_match("/".preg_quote($templates[count($templates)-1], '/')."/", $t); foreach ($steps as $step => $name) { if (preg_match("/".preg_quote($templates[$step], '/')."/", $t)) { $block_params['name'] = $this->SelectParam($params, 'current_step_render_as,block_current_step'); $passed_current = true; } else { $block_params['name'] = $passed_current ? $this->SelectParam($params, 'render_as,block') : $this->SelectParam($params, 'passed_step_render_as,block_passed_step'); } $block_params['title'] = $this->Application->Phrase($name); $block_params['template'] = $templates[$i]; $block_params['template_link'] = $this->Application->HREF($templates[$step], '', Array('pass'=>'m')); $block_params['next_step_template'] = isset($templates[$i + 1]) ? $templates[$i + 1] : ''; $block_params['number'] = $i + 1; $i++; $o.= $this->Application->ParseBlock($block_params, 1); } return $o; } function ShowOrder($params) { $order_params = $this->prepareTagParams($params); // $order_params['Special'] = 'myorders'; // $order_params['PrefixSpecial'] = 'ord.myorders'; $order_params['name'] = $this->SelectParam($order_params, 'render_as,block'); // $this->Application->SetVar('ord.myorders_id', $this->Application->GetVar('ord_id')); $object = $this->getObject($params); if (!$object->GetDBField('OrderId')) { return; } return $this->Application->ParseBlock($order_params); } function BuildListSpecial($params) { if ($this->Special != '') { return $this->Special; } $list_unique_key = $this->getUniqueListKey($params); if ($list_unique_key == '') { return parent::BuildListSpecial($params); } return crc32($list_unique_key); } function ListOrders($params) { $o = ''; $params['render_as'] = $params['item_render_as']; $o_orders = $this->PrintList2($params); if ($o_orders) { $orders_params = array('name' => $params['header_render_as']); $o = $this->Application->ParseBlock($orders_params); $o .= $o_orders; } else { $orders_params = array('name' => $params['empty_myorders_render_as']); $o = $this->Application->ParseBlock($orders_params); } return $o; } function HasRecentOrders($params) { $per_page = $this->SelectParam($params, 'per_page,max_items'); if ($per_page !== false) { $params['per_page'] = $per_page; } return (int)$this->TotalRecords($params) > 0 ? 1 : 0; } function ListOrderItems($params) { $prefix_special = rtrim('orditems.'.$this->Special, '.'); return $this->Application->ProcessParsedTag($prefix_special, 'PrintList', array_merge($params, Array( 'per_page' => -1 )) ); } function OrdersLink(){ $params['pass']='m,ord'; $main_processor = $this->Application->recallObject('m_TagProcessor'); return $main_processor->Link($params); } function PrintAddresses($params) { $object = $this->getObject($params); $address_list = $this->Application->recallObject('addr','addr_List', Array('per_page'=>-1, 'skip_counting'=>true) ); $address_list->Query(); $address_id = $this->Application->GetVar($params['type'].'_address_id'); if (!$address_id) { $sql = 'SELECT '.$address_list->IDField.' FROM '.$address_list->TableName.' WHERE PortalUserId = '.$object->GetDBField('PortalUserId').' AND LastUsedAs'.ucfirst($params['type']).' = 1'; $address_id = (int)$this->Conn->GetOne($sql); } $ret = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $this->SelectParam($params, 'render_as,block'); $address_list->GoFirst(); while (!$address_list->EOL()) { $selected = ($address_list->GetID() == $address_id); if ($selected && $address_list->GetDBField('IsProfileAddress')) { $this->Application->SetVar($this->Prefix.'_IsProfileAddress', true); } $block_params['key'] = $address_list->GetID(); $block_params['value'] = $address_list->GetDBField('ShortAddress'); $block_params['selected'] = $selected ? ' selected="selected"' : ''; $ret .= $this->Application->ParseBlock($block_params, 1); $address_list->GoNext(); } return $ret; } function PrefillRegistrationFields($params) { if ( $this->Application->GetVar('fields_prefilled') ) { return false; } if ( isset($params['user_prefix']) ) { $user = $this->Application->recallObject($params['user_prefix']); /* @var $user kDBItem */ } else { $user = $this->Application->recallObject('u', null, Array ('skip_autoload' => true)); /* @var $user kDBItem */ } $order = $this->Application->recallObject($this->Prefix . '.last'); /* @var $order OrdersItem */ $order_helper = $this->Application->recallObject('OrderHelper'); /* @var $order_helper OrderHelper */ $user_fields = $order_helper->getUserFields($order, $params['type'] == 'billing' ? 'Billing' : 'Shipping'); foreach ($user_fields as $field => $value) { if ( !$user->GetDBField($field) ) { $user->SetDBField($field, $value); } } $cs_helper = $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ $cs_helper->PopulateStates(new kEvent('u:OnBuild'), 'State', 'Country'); } function UserLink($params) { $object = $this->getObject($params); $user_id = $object->GetDBField( $params['user_field'] ); if ($user_id) { $url_params = Array ( 'm_opener' => 'd', 'u_mode' => 't', 'u_event' => 'OnEdit', 'u_id' => $user_id, 'pass' => 'all,u', 'no_pass_through' => 1, ); return $this->Application->HREF($params['edit_template'], '', $url_params); } } function UserFound($params) { $virtual_users = Array(USER_ROOT, USER_GUEST, 0); $object = $this->getObject($params); return !in_array( $object->GetDBField( $params['user_field'] ) , $virtual_users ); } /** * Returns a link for editing order * * @param Array $params * @return string */ function OrderLink($params) { $object = $this->getObject($params); $url_params = Array ( 'm_opener' => 'd', $this->Prefix.'_mode' => 't', $this->Prefix.'_event' => 'OnEdit', $this->Prefix.'_id' => $object->GetID(), 'pass' => 'all,'.$this->Prefix, 'no_pass_through' => 1, ); return $this->Application->HREF($params['edit_template'], '', $url_params); } function HasOriginalAmount($params) { $object = $this->getObject($params); $original_amount = $object->GetDBField('OriginalAmount'); return $original_amount && ($original_amount != $object->GetDBField('TotalAmount') ); } /** * Returns true, when order has tangible items * * @param Array $params * @return bool * * @todo This is copy from OrdersItem::HasTangibleItems. Copy to helper (and create it) and use here. */ function OrderHasTangibleItems($params) { $object = $this->getObject($params); if ($object->GetID() == FAKE_ORDER_ID) { return false; } $sql = 'SELECT COUNT(*) FROM '.TABLE_PREFIX.'OrderItems orditems LEFT JOIN '.TABLE_PREFIX.'Products p ON p.ProductId = orditems.ProductId WHERE (orditems.OrderId = '.$object->GetID().') AND (p.Type = '.PRODUCT_TYPE_TANGIBLE.')'; return $this->Conn->GetOne($sql) ? true : false; } function ShipmentsExists($params) { return $this->Application->GetVar('ShipmentsExists') ? 1 : 0; } function Field($params) { $value = parent::Field($params); $field = $this->SelectParam($params,'name,field'); if( ($field == 'PaymentAccount') && getArrayValue($params,'masked') ) { $value = str_repeat('X',12).substr($value,-4); } return $value; } function CartHasError($params) { return $this->Application->RecallVar('checkout_errors'); } function CheckoutError($params) { $errors = $this->Application->RecallVar('checkout_errors'); if ( !$errors ) { return ''; } $this->Application->RemoveVar('checkout_errors'); $errors = unserialize($errors); if ( isset($errors[OrderCheckoutErrorType::COUPON]) ) { $mapping = Array ( OrderCheckoutError::COUPON_APPLIED => 'coupon_applied', OrderCheckoutError::COUPON_REMOVED => 'code_removed', OrderCheckoutError::COUPON_REMOVED_AUTOMATICALLY => 'code_removed_automatically', OrderCheckoutError::COUPON_CODE_INVALID => 'invalid_code', OrderCheckoutError::COUPON_CODE_EXPIRED => 'code_expired', ); $error_phrase = $mapping[ $errors[OrderCheckoutErrorType::COUPON] ]; } elseif ( isset($errors[OrderCheckoutErrorType::GIFT_CERTIFICATE]) ) { $mapping = Array ( OrderCheckoutError::GC_APPLIED => 'gift_certificate_applied', OrderCheckoutError::GC_REMOVED => 'gc_code_removed', OrderCheckoutError::GC_REMOVED_AUTOMATICALLY => 'gc_code_removed_automatically', OrderCheckoutError::GC_CODE_INVALID => 'invalid_gc_code', OrderCheckoutError::GC_CODE_EXPIRED => 'gc_code_expired', ); $error_phrase = $mapping[ $errors[OrderCheckoutErrorType::GIFT_CERTIFICATE] ]; } else { $mapping = Array ( OrderCheckoutError::QTY_UNAVAILABLE => 'qty_unavailable', OrderCheckoutError::QTY_OUT_OF_STOCK => 'outofstock', OrderCheckoutError::QTY_CHANGED_TO_MINIMAL => 'min_qty', ); foreach ($errors as $error_type => $error_code) { if ( isset($mapping[$error_code]) ) { $error_phrase = $mapping[$error_code]; break; } } if ( !isset($error_phrase) ) { $error_phrase = 'state_changed'; // 'changed_after_login' } } return $this->Application->Phrase( $params[$error_phrase] ); } /** * Returns checkout errors in JSON format * * @param Array $params * @return string */ function PrintOrderInfo($params) { $order_helper = $this->Application->recallObject('OrderHelper'); /* @var $order_helper OrderHelper */ $object = $this->getObject($params); /* @var $object kDBItem */ $currency = isset($params['currency']) ? $params['currency'] : 'selected'; return json_encode( $order_helper->getOrderInfo($object, $currency) ); } /** * Returns currency mark (%s is $amount placemark) * * @param Array $params * @return string */ function CurrencyMask($params) { $iso = $this->GetISO( $params['currency'] ); return $this->AddCurrencySymbol('%s', $iso); } function CheckoutErrorNew($params) { $errors = $this->Application->RecallVar('checkout_errors'); if ( !$errors ) { return ''; } // $this->Application->RemoveVar('checkout_errors'); $errors = unserialize($errors); $reflection = new ReflectionClass('OrderCheckoutErrorType'); $error_types = $reflection->getConstants(); $reflection = new ReflectionClass('OrderCheckoutError'); $error_codes = $reflection->getConstants(); $ret = Array (); foreach ($errors as $error_type => $error_code) { $error_type = explode(':', $error_type); $error_explained = '' . array_search($error_type[0], $error_types) . ''; if ( $error_type[0] == OrderCheckoutErrorType::PRODUCT ) { $error_explained .= ' (ProductId = ' . $error_type[1] . '; OptionsSalt: ' . $error_type[2] . '; BackOrderFlag: ' . $error_type[3] . '; Field: ' . $error_type[4] . ')'; } $error_explained .= ' - ' . array_search($error_code, $error_codes) . ''; $ret[] = $error_explained; } return implode('
', $ret); } function GetFormAction($params) { $object = $this->getObject($params); /* @var $object OrdersItem */ $gw_data = $object->getGatewayData( isset($params['payment_type_id']) ? $params['payment_type_id'] : null ); /** @var kGWBase $gateway_object */ $gateway_object = $this->Application->recallObject($gw_data['ClassName']); return $gateway_object->getFormAction($gw_data['gw_params']); } function GetFormHiddenFields($params) { $object = $this->getObject($params); /* @var $object OrdersItem */ $gw_data = $object->getGatewayData( isset($params['payment_type_id']) ? $params['payment_type_id'] : null ); /** @var kGWBase $gateway_object */ $gateway_object = $this->Application->recallObject($gw_data['ClassName']); $tpl = ''."\n"; $hidden_fields = $gateway_object->getHiddenFields($object->GetFieldValues(), $params, $gw_data['gw_params']); if ( !is_array($hidden_fields) ) { return $hidden_fields; } $ret = ''; foreach ($hidden_fields as $hidden_name => $hidden_value) { $ret .= sprintf($tpl, $hidden_name, $hidden_value); } return $ret; } function NeedsPlaceButton($params) { $object = $this->getObject($params); /* @var $object OrdersItem */ $gw_data = $object->getGatewayData( isset($params['payment_type_id']) ? $params['payment_type_id'] : null ); /** @var kGWBase $gateway_object */ $gateway_object = $this->Application->recallObject($gw_data['ClassName']); return $gateway_object->NeedPlaceButton($object->GetFieldValues(), $params, $gw_data['gw_params']); } function HasGatewayError($params) { return $this->Application->RecallVar('gw_error'); } function ShowGatewayError($params) { $ret = $this->Application->RecallVar('gw_error'); $this->Application->RemoveVar('gw_error'); return $ret; } function ShippingType($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $shipping_info = unserialize($object->GetDBField('ShippingInfo')); if ( count($shipping_info) > 1 ) { return $this->Application->Phrase('lu_MultipleShippingTypes'); } if ( $shipping_info ) { $shipping_info = array_shift($shipping_info); return $shipping_info['ShippingName']; } return ''; } function DiscountHelpLink($params) { $params['pass'] = 'all,orditems'; $params['m_cat_id'] = 0; $m_tag_processor = $this->Application->recallObject('m_TagProcessor'); return $m_tag_processor->Link($params); } function DiscountField($params) { $orditems = $this->Application->recallObject( 'orditems' ); $item_data = $orditems->GetDBField('ItemData'); if(!$item_data) return ''; $item_data = unserialize($item_data); $discount_prefix = ($item_data['DiscountType'] == 'coupon') ? 'coup' : 'd'; $discount = $this->Application->recallObject($discount_prefix, null, Array('skip_autoload' => true)); if(!$discount->isLoaded()) { $discount->Load($item_data['DiscountId']); } return $discount->GetField( $this->SelectParam($params, 'field,name') ); } function HasDiscount($params) { $object = $this->getObject($params); return (float)$object->GetDBField('DiscountTotal') ? 1 : 0; } /** * Allows to check if required product types are present in order * * @param Array $params */ function HasProductType($params) { $product_types = Array('tangible' => 1, 'subscription' => 2, 'service' => 3, 'downloadable' => 4, 'package' => 5, 'gift' => 6); $object = $this->getObject($params); $sql = 'SELECT COUNT(*) FROM '.TABLE_PREFIX.'OrderItems oi LEFT JOIN '.TABLE_PREFIX.'Products p ON p.ProductId = oi.ProductId WHERE (oi.OrderId = '.$object->GetID().') AND (p.Type = '.$product_types[ $params['type'] ].')'; return $this->Conn->GetOne($sql); } function PrintSerializedFields($params) { $object = $this->getObject($params); $field = $this->SelectParam($params, 'field'); if (!$field) $field = $this->Application->GetVar('field'); $data = unserialize($object->GetDBField($field)); $o = ''; $block_params['name'] = $params['render_as']; foreach ($data as $field => $value) { $block_params['field'] = $field; $block_params['value'] = $value; $o .= $this->Application->ParseBlock($block_params); } return $o; } /** * Prints order totals * * @param Array $params * @return string * @access protected */ protected function PrintTotals($params) { $object = $this->getObject($params); /* @var $object OrdersItem */ if ( isset($params['element_order']) ) { // TODO: implement } else { // default element order $element_order = Array ( 'products' => 1, 'return' => 4, 'sub_total' => 5, 'discount' => 6, 'vat' => 7, 'shipping' => 8, 'processing' => 9, ); // show shipping & processing costs before tax, when they are taxable if ( $object->GetDBField('ShippingTaxable') ) { $element_order['shipping'] = 2; } if ( $object->GetDBField('ProcessingTaxable') ) { $element_order['processing'] = 3; } } $totals = Array (); if ( abs($object->GetDBField('SubTotal') - $object->GetDBField('AmountWithoutVAT')) > 0.01 ) { $totals[] = 'products'; } if ( $this->OrderHasTangibleItems($params) ) { $totals[] = 'shipping'; } if ( $object->GetDBField('ProcessingFee') > 0 ) { $totals[] = 'processing'; } if ( $object->GetDBField('ReturnTotal') > 0 ) { $totals[] = 'return'; } if ( $this->HasDiscount($params) ) { $totals[] = 'discount'; } $totals[] = 'sub_total'; if ( $object->GetDBField('VAT') > 0 ) { $totals[] = 'vat'; } $o = ''; asort($element_order, SORT_NUMERIC); $block_params = $this->prepareTagParams($params); foreach ($element_order as $type => $order) { $element = getArrayValue($params, $type . '_render_as'); if ( !in_array($type, $totals) || !$element ) { continue; } $block_params['name'] = $element; $o .= $this->Application->ParseBlock($block_params); } return $o; } function ShowDefaultAddress($params) { $address_type = ucfirst($params['type']); if ($this->Application->GetVar('check_'.strtolower($address_type).'_address')) { // form type doesn't match check type, e.g. shipping check on billing form return ''; } // for required field highlighting on form when no submit made $this->Application->SetVar('check_'.strtolower($address_type).'_address', 'true'); /*if ((strtolower($address_type) == 'billing') && $this->UsingCreditCard($params)) { $this->Application->SetVar('check_credit_card', 'true'); }*/ $this->Application->HandleEvent(new kEvent('ord:SetStepRequiredFields')); $user_id = $this->Application->RecallVar('user_id'); $sql = 'SELECT AddressId FROM '.TABLE_PREFIX.'Addresses WHERE PortalUserId = '.$user_id.' AND LastUsedAs'.$address_type.' = 1'; $address_id = $this->Conn->GetOne($sql); if (!$address_id) { return ''; } $addr_list = $this->Application->recallObject('addr', 'addr_List', Array('per_page'=>-1, 'skip_counting'=>true) ); $addr_list->Query(); $object = $this->getObject(); if (!$addr_list->CheckAddress($object->GetFieldValues(), $address_type)) { $addr_list->CopyAddress($address_id, $address_type); } } function IsProfileAddress($params) { $object = $this->getObject($params); $address_type = ucfirst($params['type']); return $object->IsProfileAddress($address_type); } function HasPayPalSubscription($params) { $object = $this->getObject($params); $sql = 'SELECT COUNT(*) FROM '.TABLE_PREFIX.'OrderItems oi LEFT JOIN '.TABLE_PREFIX.'Products p ON p.ProductId = oi.ProductId WHERE (oi.OrderId = '.$object->GetID().') AND (p.PayPalRecurring = 1)'; return $this->Conn->GetOne($sql); } function GetPayPalSubscriptionForm($params) { $object = $this->getObject($params); $gw_data = $object->getGatewayData($params['payment_type_id']); /** @var kGWBase $gateway_object */ $gateway_object = $this->Application->recallObject($gw_data['ClassName']); $sql = 'SELECT oi.* FROM '.TABLE_PREFIX.'OrderItems oi LEFT JOIN '.TABLE_PREFIX.'Products p ON p.ProductId = oi.ProductId WHERE (oi.OrderId = '.$object->GetID().') AND (p.PayPalRecurring = 1)'; $order_item = $this->Conn->GetRow($sql); $order_item_data = unserialize($order_item['ItemData']); $cycle = ceil($order_item_data['Duration'] / 86400); $cycle_units = 'D'; $item_data = $object->GetFieldValues(); $item_data['item_name'] = $order_item['ProductName']; $item_data['item_number'] = $order_item['OrderItemId']; $item_data['custom'] = $order_item['OrderId']; $item_data['a1'] = ''; $item_data['p1'] = ''; $item_data['t1'] = ''; $item_data['a2'] = ''; $item_data['p2'] = ''; $item_data['t2'] = ''; $item_data['a3'] = $order_item['Price']; //rate $item_data['p3'] = $cycle; //cycle $item_data['t3'] = $cycle_units; //cycle units D (days), W (weeks), M (months), Y (years) $item_data['src'] = '1'; // Recurring payments. If set to 1, the payment will recur unless your customer cancels the subscription before the end of the billing cycle. $item_data['sra'] = '1'; // Reattempt on failure. If set to 1, and the payment fails, the payment will be reattempted two more times. After the third failure, the subscription will be cancelled. $item_data['srt'] = ''; // Recurring Times. This is the number of payments which will occur at the regular rate. $hidden_fields = $gateway_object->getSubscriptionFields($item_data, $params, $gw_data['gw_params']); $ret = ''; if (!is_array($hidden_fields)) { return $hidden_fields; } $tpl = ''."\n"; foreach($hidden_fields as $hidden_name => $hidden_value) { $ret .= sprintf($tpl, $hidden_name, $hidden_value); } return $ret; } function UserHasPendingOrders($params) { $sql = 'SELECT OrderId FROM '.$this->Application->getUnitOption($this->Prefix, 'TableName').' WHERE PortalUserId = '.$this->Application->RecallVar('user_id').' AND Status = '.ORDER_STATUS_PENDING; return $this->Conn->GetOne($sql) ? 1 : 0; } function AllowAddAddress($params) { $user = $this->Application->recallObject('u.current'); if ($user->GetDBField('cust_shipping_addr_block')) return false; $address_list = $this->Application->recallObject('addr','addr_List', Array('per_page'=>-1, 'skip_counting'=>true) ); $address_list->Query(); $max = $this->Application->ConfigValue('MaxAddresses'); return $max <= 0 ? true : $address_list->GetRecordsCount() < $max; } /** * Creates link for removing coupon or gift certificate * * @param Array $params * @return string */ function RemoveCouponLink($params) { if ( !isset($params['pass']) ) { $params['pass'] = 'm,ord'; } $params['m_cat_id'] = 0; $link_type = $params['type']; unset($params['type']); $params['ord_event'] = strtolower($link_type) == 'coupon' ? 'OnRemoveCoupon' : 'OnRemoveGiftCertificate'; return $this->ItemLink($params); } /** * Calculates total weight of items in shopping cart * * @param Array $params * @return float */ function TotalOrderWeight($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $sql = 'SELECT SUM( IF(oi.Weight IS NULL, 0, oi.Weight * oi.Quantity) ) FROM '.TABLE_PREFIX.'OrderItems oi WHERE oi.OrderId = '.$object->GetID(); $total_weight = $this->Conn->GetOne($sql); if ($total_weight == '') { // zero weight -> return text about it return $this->Application->Phrase('lu_NotAvailable'); } return $this->_formatWeight($total_weight); } function _formatWeight($weight) { $regional = $this->Application->recallObject('lang.current'); /* @var $regional kDBItem */ switch ( $regional->GetDBField('UnitSystem') ) { case 1: // metric system -> add kg sign $weight .= ' ' . $this->Application->Phrase('lu_kg'); break; case 2: // uk system -> convert to pounds list ($pounds, $ounces) = kUtil::Kg2Pounds($weight); $weight = $pounds . ' ' . $this->Application->Phrase('lu_pounds') . ' ' . $ounces . ' ' . $this->Application->Phrase('lu_ounces'); break; } return $weight; } function InitCatalogTab($params) { $tab_params['mode'] = $this->Application->GetVar('tm'); // single/multi selection possible $tab_params['special'] = $this->Application->GetVar('ts'); // use special for this tab $tab_params['dependant'] = $this->Application->GetVar('td'); // is grid dependant on categories grid // set default params (same as in catalog) if ($tab_params['mode'] === false) $tab_params['mode'] = 'multi'; if ($tab_params['special'] === false) $tab_params['special'] = ''; if ($tab_params['dependant'] === false) $tab_params['dependant'] = 'yes'; // pass params to block with tab content $params['name'] = $params['render_as']; $params['prefix'] = trim($this->Prefix.'.'.($tab_params['special'] ? $tab_params['special'] : $this->Special), '.'); $params['cat_prefix'] = trim('c.'.($tab_params['special'] ? $tab_params['special'] : $this->Special), '.'); $params['tab_mode'] = $tab_params['mode']; $params['grid_name'] = ($tab_params['mode'] == 'multi') ? $params['default_grid'] : $params['radio_grid']; $params['tab_dependant'] = $tab_params['dependant']; $params['show_category'] = $tab_params['special'] == 'showall' ? 1 : 0; // this is advanced view -> show category name // use $pass_params to be able to pass 'tab_init' parameter from m_ModuleInclude tag return $this->Application->ParseBlock($params, 1); } /** * Checks if required payment method is available * * @param Array $params * @return bool */ function HasPaymentGateway($params) { static $payment_types = Array (); $gw_name = $params['name']; if (!array_key_exists($gw_name, $payment_types)) { $sql = 'SELECT pt.PaymentTypeId, pt.PortalGroups FROM '.TABLE_PREFIX.'PaymentTypes pt LEFT JOIN '.TABLE_PREFIX.'Gateways g ON pt.GatewayId = g.GatewayId WHERE (g.Name = '.$this->Conn->qstr($params['name']).') AND (pt.Status = '.STATUS_ACTIVE.')'; $payment_types[$gw_name] = $this->Conn->GetRow($sql); } if (!$payment_types[$gw_name]) { return false; } $pt_groups = explode(',', substr($payment_types[$gw_name]['PortalGroups'], 1, -1)); $user_groups = explode(',', $this->Application->RecallVar('UserGroups')); return array_intersect($user_groups, $pt_groups) ? $payment_types[$gw_name]['PaymentTypeId'] : false; } function DisplayPaymentGateway($params) { $payment_type_id = $this->HasPaymentGateway($params); if (!$payment_type_id) { return ''; } $object = $this->getObject($params); /* @var $object OrdersItem */ $gw_data = $object->getGatewayData($payment_type_id); $block_params = $gw_data['gw_params']; $block_params['name'] = $params['render_as']; $block_params['payment_type_id'] = $payment_type_id; return $this->Application->ParseBlock($block_params); } /** * Checks, that USPS returned valid label * * @param Array $params * @return bool */ function USPSLabelFound($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $full_path = USPS_LABEL_FOLDER . $object->GetDBField( $params['field'] ) . '.pdf'; return file_exists($full_path) && is_file($full_path); } /** * Prints SQE errors from session * * @param Array $params * @return string */ function PrintSQEErrors($params) { $sqe_errors = $this->Application->RecallVar('sqe_errors'); if (!$sqe_errors) { return ''; } $o = ''; $block_params = $this->prepareTagParams($params); $block_params['name'] = $params['render_as']; $sqe_errors = unserialize($sqe_errors); foreach ($sqe_errors as $order_number => $error_description) { $block_params['order_number'] = $order_number; $block_params['error_description'] = $error_description; $o .= $this->Application->ParseBlock($block_params); } $this->Application->RemoveVar('sqe_errors'); return $o; } /** * Creates a continue shopping link * * @param Array $params * @return string * @access protected */ protected function ContinueShoppingLink($params) { $order_helper = $this->Application->recallObject('OrderHelper'); /* @var $order_helper OrderHelper */ if ( isset($params['template']) ) { $template = $params['template']; unset($params['template']); } else { $template = ''; } return $this->Application->HREF($order_helper->getContinueShoppingTemplate($template), '', $params); } /** * Checks that billing address and shipping address are the same * * @param Array $params * @return string * @access protected */ protected function AddressesTheSame($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $address_fields = Array ('To', 'Company', 'Address1', 'Address2', 'City', 'Country', 'State', 'Zip'); foreach ($address_fields as $address_field) { if ( $object->GetDBField('Shipping' . $address_field) != $object->GetDBField('Billing' . $address_field) ) { return false; } } return true; } }