Payflow Pro Settings
@@ -1407,6 +1441,156 @@
+
+
+ Payflow Link Settings
+ text
+ 80
+ 1
+ 1
+ 1
+
+
+ paypal/adminhtml_system_config_payflowlink_info
+ 1
+ 1
+ 1
+ 22
+
+
+ Title
+ It is recommended to set this value to "Debit or Credit Card" per store views.
+ payment/payflow_link/title
+ text
+ 5
+ 1
+ 1
+ 1
+
+
+ Sort Order
+ payment/payflow_link/sort_order
+ text
+ 10
+ 1
+ 1
+ 1
+
+
+ Payment Action
+ payment/payflow_link/payment_action
+ select
+ paypal/config::getPaymentActions
+ 15
+ 1
+ 1
+
+
+ Payment Applicable From
+ payment/payflow_link/allowspecific
+ select
+ adminhtml/system_config_source_payment_allspecificcountries
+ 20
+ 1
+ 1
+
+
+ Countries Payment Applicable From
+ payment/payflow_link/specificcountry
+ multiselect
+ paypal/system_config_source_buyerCountry
+ 25
+ 1
+ 1
+ 1
+
+
+ Debug Mode
+ payment/payflow_link/debug
+ select
+ adminhtml/system_config_source_yesno
+ 30
+ 1
+ 1
+
+
+ API/Integration
+ adminhtml/system_config_form_field_heading
+ 35
+ 1
+ 1
+
+
+ Partner
+ payment/payflow_link/partner
+ text
+ 40
+ 1
+ 1
+
+
+ User
+ text
+ payment/payflow_link/user
+ 45
+ 1
+ 1
+
+
+ Vendor
+ payment/payflow_link/vendor
+ text
+ 50
+ 1
+ 1
+
+
+ Password
+ payment/payflow_link/pwd
+ obscure
+ adminhtml/system_config_backend_encrypted
+ 55
+ 1
+ 1
+
+
+ Test Mode
+ payment/payflow_link/sandbox_flag
+ select
+ adminhtml/system_config_source_yesno
+ 60
+ 1
+ 1
+
+
+ Use Proxy
+ payment/payflow_link/use_proxy
+ select
+ adminhtml/system_config_source_yesno
+ 65
+ 1
+ 1
+
+
+ Proxy Host
+ payment/payflow_link/proxy_host
+ text
+ 70
+ 1
+ 1
+ 1
+
+
+ Proxy Port
+ payment/payflow_link/proxy_port
+ text
+ 75
+ 1
+ 1
+ 1
+
+
+
diff --git a/app/code/core/Mage/Paypal/sql/paypal_setup/mysql4-upgrade-1.4.0.1-1.4.0.2.php b/app/code/core/Mage/Paypal/sql/paypal_setup/mysql4-upgrade-1.4.0.1-1.4.0.2.php
new file mode 100644
index 0000000000..131a494833
--- /dev/null
+++ b/app/code/core/Mage/Paypal/sql/paypal_setup/mysql4-upgrade-1.4.0.1-1.4.0.2.php
@@ -0,0 +1,47 @@
+run("
+CREATE TABLE `{$installer->getTable('paypal/cert')}` (
+ `cert_id` SMALLINT(5) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `website_id` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
+ `content` MEDIUMBLOB NOT NULL,
+ `updated_at` datetime default NULL,
+ PRIMARY KEY (`cert_id`),
+ KEY `IDX_PAYPAL_CERT_WEBSITE` (`website_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+");
+
+$installer->getConnection()->addConstraint(
+ 'FK_PAYPAL_CERT_WEBSITE',
+ $this->getTable('paypal/cert'),
+ 'website_id',
+ $this->getTable('core/website'),
+ 'website_id'
+);
diff --git a/app/code/core/Mage/PaypalUk/Model/Api/Nvp.php b/app/code/core/Mage/PaypalUk/Model/Api/Nvp.php
index 3d8db9dcc8..fda8583acd 100644
--- a/app/code/core/Mage/PaypalUk/Model/Api/Nvp.php
+++ b/app/code/core/Mage/PaypalUk/Model/Api/Nvp.php
@@ -280,6 +280,15 @@ class Mage_PaypalUk_Model_Api_Nvp extends Mage_Paypal_Model_Api_Nvp
'PAYMENTSTATUS', 'PENDINGREASON', 'PROTECTIONELIGIBILITY', 'EMAIL',
);
+ /**
+ * Required fields in the response
+ *
+ * @var array
+ */
+ protected $_requiredResponseParams = array(
+ self::DO_DIRECT_PAYMENT => array('RESULT', 'PNREF', 'PPREF')
+ );
+
/**
* API endpoint getter
*
diff --git a/app/code/core/Mage/PaypalUk/Model/Express.php b/app/code/core/Mage/PaypalUk/Model/Express.php
index 27bc796dc0..b24c6477c1 100644
--- a/app/code/core/Mage/PaypalUk/Model/Express.php
+++ b/app/code/core/Mage/PaypalUk/Model/Express.php
@@ -62,10 +62,10 @@ public function isAvailable($quote = null)
if (!$this->_ecInstance) {
$this->_ecInstance = Mage::helper('payment')->getMethodInstance(Mage_Paypal_Model_Config::METHOD_WPP_EXPRESS);
}
- if ($quote) {
+ if ($quote && $this->_ecInstance) {
$this->_ecInstance->setStore($quote->getStoreId());
}
- return !$this->_ecInstance->isAvailable();
+ return $this->_ecInstance ? !$this->_ecInstance->isAvailable() : false;
}
/**
diff --git a/app/code/core/Mage/Reports/Block/Product/Abstract.php b/app/code/core/Mage/Reports/Block/Product/Abstract.php
index d5f077e0e6..6256af0ac3 100644
--- a/app/code/core/Mage/Reports/Block/Product/Abstract.php
+++ b/app/code/core/Mage/Reports/Block/Product/Abstract.php
@@ -113,6 +113,10 @@ public function getItemsCollection()
->addUrlRewrite()
->setPageSize($this->getPageSize())
->setCurPage(1);
+
+ /* Price data is added to consider item stock status using price index */
+ $this->_collection->addPriceData();
+
$ids = $this->getProductIds();
if (empty($ids)) {
$this->_collection->addIndexFilter();
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Accounts/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Accounts/Collection.php
index a9c02549f3..f00ec187bd 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Accounts/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Accounts/Collection.php
@@ -51,13 +51,17 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter to collection
+ *
+ * @param array $setStoreIds
+ * @return Mage_Reports_Model_Mysql4_Accounts_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->addAttributeToFilter('store_id', array('in' => (array)$storeIds));
}
-
return $this;
}
}
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Customer/Orders/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Customer/Orders/Collection.php
index f3f67d30ae..fec272e53f 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Customer/Orders/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Customer/Orders/Collection.php
@@ -50,10 +50,15 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter to collection
+ *
+ * @param array $setStoreIds
+ * @return Mage_Reports_Model_Mysql4_Customer_Orders_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->addAttributeToFilter('store_id', array('in' => (array)$storeIds));
$this->addSumAvgTotals(1)
->orderByOrdersCount();
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Customer/Totals/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Customer/Totals/Collection.php
index 0024cecad0..a2b7a92a33 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Customer/Totals/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Customer/Totals/Collection.php
@@ -50,10 +50,14 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter collection
+ * @param array $storeIds
+ * @return Mage_Reports_Model_Mysql4_Customer_Totals_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->addAttributeToFilter('store_id', array('in' => (array)$storeIds));
$this->addSumAvgTotals(1)
->orderByTotalAmount();
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php
index 6319575301..e94ebd34ae 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Invoiced/Collection.php
@@ -52,10 +52,14 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter collection
+ * @param array $storeIds
+ * @return Mage_Reports_Model_Mysql4_Invoiced_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->addAttributeToFilter('store_id', array('in' => (array)$storeIds))
->addExpressionAttributeToSelect(
'invoiced',
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php
index dccbcc6b7a..e305b2a272 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Order/Collection.php
@@ -423,10 +423,14 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter collection
+ * @param array $storeIds
+ * @return Mage_Reports_Model_Mysql4_Order_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->getSelect()->columns(array(
'subtotal' => 'SUM(main_table.base_subtotal)',
'tax' => 'SUM(main_table.base_tax_amount)',
@@ -523,8 +527,17 @@ public function addSumAvgTotals($storeId = 0)
* calculate average and total amount
*/
$expr = ($storeId == 0)
- ? '(main_table.base_subtotal-IFNULL(main_table.base_subtotal_refunded,0)-IFNULL(main_table.base_subtotal_canceled,0))*main_table.base_to_global_rate'
- : 'main_table.base_subtotal-IFNULL(main_table.base_subtotal_canceled,0)-IFNULL(main_table.base_subtotal_refunded,0)';
+ ? '(main_table.base_subtotal
+ - IFNULL(main_table.base_subtotal_refunded, 0)
+ - IFNULL(main_table.base_subtotal_canceled, 0)
+ - ABS(main_table.base_discount_amount)
+ - IFNULL(main_table.base_discount_canceled, 0)
+ ) * main_table.base_to_global_rate'
+ : 'main_table.base_subtotal
+ - IFNULL(main_table.base_subtotal_canceled, 0)
+ - IFNULL(main_table.base_subtotal_refunded, 0)
+ - ABS(main_table.base_discount_amount)
+ - IFNULL(main_table.base_discount_canceled, 0)';
$this->getSelect()
->columns(array("orders_avg_amount" => "AVG({$expr})"))
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Product/Sold/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Product/Sold/Collection.php
index bd57e3f50a..356cec5764 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Product/Sold/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Product/Sold/Collection.php
@@ -52,18 +52,40 @@ public function setDateRange($from, $to)
}
/**
- * Set Store filter to collection
+ * Set store filter to collection
*
* @param array $storeIds
* @return Mage_Reports_Model_Mysql4_Product_Sold_Collection
*/
public function setStoreIds($storeIds)
{
- if (!empty($storeIds[0])) {
- $storeIds = array_values($storeIds);
- $this->getSelect()->where('order_items.store_id IN(?)', $storeIds);
+ if ($storeIds) {
+ $this->getSelect()->where('order_items.store_id IN (?)', (array)$storeIds);
}
-
+ return $this;
+ }
+
+ /**
+ * Add website product limitation
+ *
+ * @return Mage_Reports_Model_Mysql4_Product_Sold_Collection
+ */
+ protected function _productLimitationJoinWebsite()
+ {
+ $filters = $this->_productLimitationFilters;
+ $conditions = array(
+ 'product_website.product_id=e.entity_id'
+ );
+ if (isset($filters['website_ids'])) {
+ $conditions[] = $this->getConnection()
+ ->quoteInto('product_website.website_id IN(?)', $filters['website_ids']);
+
+ $subQuery = $this->getConnection()->select()
+ ->from(array('product_website' => $this->getTable('catalog/product_website')), array('product_website.product_id'))
+ ->where(join(' AND ', $conditions));
+ $this->getSelect()->where('e.entity_id IN( '.$subQuery.' )');
+ }
+
return $this;
}
}
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Refunded/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Refunded/Collection.php
index c0ba7a919e..1e81e9d2b7 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Refunded/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Refunded/Collection.php
@@ -50,10 +50,15 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter to collection
+ *
+ * @param array $setStoreIds
+ * @return Mage_Reports_Model_Mysql4_Refunded_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->addAttributeToFilter('store_id', array('in' => (array)$storeIds))
->addExpressionAttributeToSelect(
'refunded',
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Shipping/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Shipping/Collection.php
index 3b11c55956..91f527d0a4 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Shipping/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Shipping/Collection.php
@@ -49,10 +49,15 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter to collection
+ *
+ * @param array $setStoreIds
+ * @return Mage_Reports_Model_Mysql4_Shipping_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->addAttributeToFilter('store_id', array('in' => (array)$storeIds));
$this->addExpressionAttributeToSelect('total',
'SUM({{base_shipping_amount}})',
diff --git a/app/code/core/Mage/Reports/Model/Mysql4/Tax/Collection.php b/app/code/core/Mage/Reports/Model/Mysql4/Tax/Collection.php
index 5fe36d6eae..49e6b63c12 100644
--- a/app/code/core/Mage/Reports/Model/Mysql4/Tax/Collection.php
+++ b/app/code/core/Mage/Reports/Model/Mysql4/Tax/Collection.php
@@ -55,10 +55,15 @@ public function setDateRange($from, $to)
return $this;
}
+ /**
+ * Set store filter to collection
+ *
+ * @param array $setStoreIds
+ * @return Mage_Reports_Model_Mysql4_Tax_Collection
+ */
public function setStoreIds($storeIds)
{
- $vals = array_values($storeIds);
- if (count($storeIds) >= 1 && $vals[0] != '') {
+ if ($storeIds) {
$this->getSelect()
->where('e.store_id in (?)', (array)$storeIds)
->columns(array('tax'=>'SUM(tax_table.base_real_amount)'));
diff --git a/app/code/core/Mage/Review/Block/Product/View.php b/app/code/core/Mage/Review/Block/Product/View.php
index 1cb66ac719..79d6b15968 100644
--- a/app/code/core/Mage/Review/Block/Product/View.php
+++ b/app/code/core/Mage/Review/Block/Product/View.php
@@ -35,6 +35,11 @@ class Mage_Review_Block_Product_View extends Mage_Catalog_Block_Product_View
{
protected $_reviewsCollection;
+ /**
+ * Render block HTML
+ *
+ * @return string
+ */
protected function _toHtml()
{
$this->getProduct()->setShortDescription(null);
diff --git a/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php b/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php
index 45ed47e254..58ac97475e 100644
--- a/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php
+++ b/app/code/core/Mage/Review/Model/Mysql4/Review/Product/Collection.php
@@ -237,18 +237,22 @@ public function addAttributeToFilter($attribute, $condition=null, $joinType='inn
break;
case 'type':
if($condition == 1) {
- $this->getSelect()->where('rdt.customer_id = 0');
+ $this->getSelect()
+ ->where('rdt.customer_id IS NULL AND rdt.store_id = ?', Mage_Core_Model_App::ADMIN_STORE_ID);
} elseif ($condition == 2) {
$this->getSelect()->where('rdt.customer_id > 0');
} else {
- $this->getSelect()->where('rdt.customer_id IS NULL');
+ $this->getSelect()
+ ->where('rdt.customer_id IS NULL AND rdt.store_id <> ?', Mage_Core_Model_App::ADMIN_STORE_ID);
}
+
return $this;
break;
default:
parent::addAttributeToFilter($attribute, $condition, $joinType);
}
+
return $this;
}
diff --git a/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php b/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php
index fc6c61a0f1..206bc6bbfe 100644
--- a/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php
+++ b/app/code/core/Mage/Rss/Block/Catalog/NotifyStock.php
@@ -58,16 +58,16 @@ protected function _toHtml()
$rssObj = Mage::getModel('rss/rss');
$data = array('title' => $title,
- 'description' => $title,
- 'link' => $newurl,
- 'charset' => 'UTF-8',
- );
+ 'description' => $title,
+ 'link' => $newurl,
+ 'charset' => 'UTF-8',
+ );
$rssObj->_addHeader($data);
$_configManageStock = (int)Mage::getStoreConfigFlag(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_MANAGE_STOCK);
$stockItemWhere = "({{table}}.low_stock_date is not null) "
. " and ({{table}}.low_stock_date>'0000-00-00') "
- . " and IF({{table}}.use_config_manage_stock=1," . $_configManageStock . ",{{table}}.manage_stock) <= 1";
+ . " and IF({{table}}.use_config_manage_stock=1," . $_configManageStock . ",{{table}}.manage_stock) = 1";
$product = Mage::getModel('catalog/product');
$collection = $product->getCollection()
@@ -76,6 +76,9 @@ protected function _toHtml()
->joinTable('cataloginventory/stock_item', 'product_id=entity_id', array('qty'=>'qty', 'notify_stock_qty'=>'notify_stock_qty', 'use_config' => 'use_config_notify_stock_qty','low_stock_date' => 'low_stock_date'), $stockItemWhere, 'inner')
->setOrder('low_stock_date')
;
+ $collection->addAttributeToFilter('status', array('in' => Mage::getSingleton('catalog/product_status')->getVisibleStatusIds()));
+ $collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
+
$_globalNotifyStockQty = (float) Mage::getStoreConfig(Mage_CatalogInventory_Model_Stock_Item::XML_PATH_NOTIFY_STOCK_QTY);
Mage::dispatchEvent('rss_catalog_notify_stock_collection_select', array('collection' => $collection));
diff --git a/app/code/core/Mage/Rss/Block/Catalog/Special.php b/app/code/core/Mage/Rss/Block/Catalog/Special.php
index f07a7b0ffb..9511db1b36 100644
--- a/app/code/core/Mage/Rss/Block/Catalog/Special.php
+++ b/app/code/core/Mage/Rss/Block/Catalog/Special.php
@@ -45,7 +45,7 @@ protected function _construct()
/*
* setting cache to save the rss for 10 minutes
*/
- $this->setCacheKey('rss_catalog_special_'.$this->getStoreId().'_'.$this->_getCustomerGroupId());
+ $this->setCacheKey('rss_catalog_special_'.$this->_getStoreId().'_'.$this->_getCustomerGroupId());
$this->setCacheLifetime(600);
}
diff --git a/app/code/core/Mage/Rss/Block/Order/Status.php b/app/code/core/Mage/Rss/Block/Order/Status.php
index e52104163c..67cb5b7c02 100644
--- a/app/code/core/Mage/Rss/Block/Order/Status.php
+++ b/app/code/core/Mage/Rss/Block/Order/Status.php
@@ -63,7 +63,8 @@ protected function _toHtml()
if($type && $type!='order'){
$urlAppend = $type;
}
- $title = Mage::helper('rss')->__('Details for %s #%s', ucwords($type), $result['increment_id']);
+ $type = Mage::helper('rss')->__(ucwords($type));
+ $title = Mage::helper('rss')->__('Details for %s #%s', $type, $result['increment_id']);
$description = ''.
Mage::helper('rss')->__('Notified Date: %s ',$this->formatDate($result['created_at'])).
diff --git a/app/code/core/Mage/Rule/Model/Condition/Abstract.php b/app/code/core/Mage/Rule/Model/Condition/Abstract.php
index 54e872204c..a702b1ba93 100644
--- a/app/code/core/Mage/Rule/Model/Condition/Abstract.php
+++ b/app/code/core/Mage/Rule/Model/Condition/Abstract.php
@@ -80,7 +80,7 @@ public function getDefaultOperatorInputByType()
'date' => array('==', '>=', '<='),
'select' => array('==', '!='),
'boolean' => array('==', '!='),
- 'multiselect' => array('==', '!=', '{}', '!{}'),
+ 'multiselect' => array('{}', '!{}', '()', '!()'),
'grid' => array('()', '!()'),
);
}
@@ -254,7 +254,7 @@ public function getValueParsed()
$value = $this->getData('value');
$op = $this->getOperator();
- if (($op==='()' || $op==='!()') && is_string($value)) {
+ if (($op === '{}' || $op === '!{}' || $op==='()' || $op==='!()') && is_string($value)) {
$value = preg_split('#\s*[,;]\s*#', $value, null, PREG_SPLIT_NO_EMPTY);
$this->setValue($value);
}
@@ -511,8 +511,13 @@ public function validateAttribute($validatedValue)
$op = $this->getOperator();
// if operator requires array and it is not, or on opposite, return false
- if ((($op=='()' || $op=='!()') && !is_array($value))
- || (!($op=='()' || $op=='!()' || $op=='!=' || $op=='==' || $op=='{}' || $op=='!{}') && is_array($value))) {
+ if ((
+ ($op == '()' || $op == '!()' || $op == '{}' || $op == '!{}')
+ && !is_array($value)
+ ) || (
+ !($op == '()' || $op == '!()' || $op == '{}' || $op == '!{}')
+ && is_array($value)
+ )) {
return false;
}
@@ -520,19 +525,10 @@ public function validateAttribute($validatedValue)
switch ($op) {
case '==': case '!=':
- if (is_array($value)) {
- if (is_array($validatedValue)) {
- $result = array_diff($validatedValue, $value);
- $result = empty($result) && (sizeof($validatedValue) == sizeof($value));
- } else {
- return false;
- }
+ if (is_array($validatedValue)) {
+ $result = in_array($value, $validatedValue);
} else {
- if (is_array($validatedValue)) {
- $result = in_array($value, $validatedValue);
- } else {
- $result = $validatedValue==$value;
- }
+ $result = $validatedValue == $value;
}
break;
@@ -555,8 +551,8 @@ public function validateAttribute($validatedValue)
case '{}': case '!{}':
if (is_array($value)) {
if (is_array($validatedValue)) {
- $result = array_diff($value, $validatedValue);
- $result = empty($result);
+ $result = array_intersect($value, $validatedValue);
+ $result = !empty($result);
} else {
return false;
}
diff --git a/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php b/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php
index 8820bb8407..c7ca136b3d 100644
--- a/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php
+++ b/app/code/core/Mage/Sales/Block/Order/Item/Renderer/Default.php
@@ -165,4 +165,14 @@ public function getSku()
}*/
return $this->getItem()->getSku();
}
+
+ /**
+ * Return product additional information block
+ *
+ * @return Mage_Core_Block_Abstract
+ */
+ public function getProductAdditionalInformationBlock()
+ {
+ return $this->getLayout()->getBlock('additional.product.info');
+ }
}
diff --git a/app/code/core/Mage/Sales/Block/Order/Print/Shipment.php b/app/code/core/Mage/Sales/Block/Order/Print/Shipment.php
index 517250521d..2b6340793d 100644
--- a/app/code/core/Mage/Sales/Block/Order/Print/Shipment.php
+++ b/app/code/core/Mage/Sales/Block/Order/Print/Shipment.php
@@ -133,7 +133,7 @@ public function getShipmentsCollection()
*/
public function getShipmentTracks($shipment)
{
- return $this->_tracks[$shipment->getId()];
+ return isset($this->_tracks[$shipment->getId()]) ? $this->_tracks[$shipment->getId()] : null;
}
/**
diff --git a/app/code/core/Mage/Sales/Block/Reorder/Sidebar.php b/app/code/core/Mage/Sales/Block/Reorder/Sidebar.php
index 08f4f80e12..34b4bb4d42 100644
--- a/app/code/core/Mage/Sales/Block/Reorder/Sidebar.php
+++ b/app/code/core/Mage/Sales/Block/Reorder/Sidebar.php
@@ -63,6 +63,7 @@ public function getItems()
$items = array();
$order = $this->getLastOrder();
$limit = 5;
+
if ($order) {
$website = Mage::app()->getStore()->getWebsiteId();
foreach ($order->getParentItemsRandomCollection($limit) as $item) {
@@ -71,6 +72,7 @@ public function getItems()
}
}
}
+
return $items;
}
diff --git a/app/code/core/Mage/Sales/Model/Billing/Agreement.php b/app/code/core/Mage/Sales/Model/Billing/Agreement.php
index ba73a38dbc..46dda00047 100644
--- a/app/code/core/Mage/Sales/Model/Billing/Agreement.php
+++ b/app/code/core/Mage/Sales/Model/Billing/Agreement.php
@@ -208,13 +208,14 @@ public function importOrderPayment(Mage_Sales_Model_Order_Payment $payment)
$this->_paymentMethodInstance = (isset($baData['method_code']))
? Mage::helper('payment')->getMethodInstance($baData['method_code'])
- ->setStore($payment->getMethodInstance()->getStore())
: $payment->getMethodInstance();
-
- $this->setCustomerId($payment->getOrder()->getCustomerId())
- ->setMethodCode($this->_paymentMethodInstance->getCode())
- ->setReferenceId($baData['billing_agreement_id'])
- ->setStatus(self::STATUS_ACTIVE);
+ if ($this->_paymentMethodInstance) {
+ $this->_paymentMethodInstance->setStore($payment->getMethodInstance()->getStore());
+ $this->setCustomerId($payment->getOrder()->getCustomerId())
+ ->setMethodCode($this->_paymentMethodInstance->getCode())
+ ->setReferenceId($baData['billing_agreement_id'])
+ ->setStatus(self::STATUS_ACTIVE);
+ }
return $this;
}
diff --git a/app/code/core/Mage/Sales/Model/Mysql4/Order/Grid/Collection.php b/app/code/core/Mage/Sales/Model/Mysql4/Order/Grid/Collection.php
index e0fd7af9f3..5a84cd7839 100644
--- a/app/code/core/Mage/Sales/Model/Mysql4/Order/Grid/Collection.php
+++ b/app/code/core/Mage/Sales/Model/Mysql4/Order/Grid/Collection.php
@@ -33,6 +33,13 @@ class Mage_Sales_Model_Mysql4_Order_Grid_Collection extends Mage_Sales_Model_Mys
protected $_eventPrefix = 'sales_order_grid_collection';
protected $_eventObject = 'order_grid_collection';
+ /**
+ * Customer mode flag
+ *
+ * @var bool
+ */
+ protected $_customerModeFlag = false;
+
protected function _construct()
{
parent::_construct();
@@ -60,4 +67,26 @@ public function getSelectCountSql()
return $countSelect;
}
+
+ /**
+ * Set customer mode flag value
+ *
+ * @param bool $value
+ * @return Mage_Sales_Model_Mysql4_Order_Grid_Collection
+ */
+ public function setIsCustomerMode($value)
+ {
+ $this->_customerModeFlag = (bool)$value;
+ return $this;
+ }
+
+ /**
+ * Get customer mode flag value
+ *
+ * @return bool
+ */
+ public function getIsCustomerMode()
+ {
+ return $this->_customerModeFlag;
+ }
}
diff --git a/app/code/core/Mage/Sales/Model/Mysql4/Order/Status.php b/app/code/core/Mage/Sales/Model/Mysql4/Order/Status.php
new file mode 100644
index 0000000000..ea31a265c0
--- /dev/null
+++ b/app/code/core/Mage/Sales/Model/Mysql4/Order/Status.php
@@ -0,0 +1,203 @@
+_init('sales/order_status', 'status');
+ $this->_isPkAutoIncrement = false;
+ $this->_labelsTable = $this->getTable('sales/order_status_label');
+ $this->_stateTable = $this->getTable('sales/order_status_state');
+ }
+
+ /**
+ * Retrieve select object for load object data
+ *
+ * @param string $field
+ * @param mixed $value
+ * @return Zend_Db_Select
+ */
+ protected function _getLoadSelect($field, $value, $object)
+ {
+ if ($field == 'default_state') {
+ $select = $this->_getReadAdapter()->select()
+ ->from($this->getMainTable())
+ ->join(array('state_table'=>$this->_stateTable), $this->getMainTable().'.status=state_table.status', 'status')
+ ->where('state_table.state=?', $value)
+ ->order('state_table.is_default DESC')
+ ->limit(1);
+ } else {
+ $select = parent::_getLoadSelect($field, $value, $object);
+ }
+ return $select;
+ }
+
+ /**
+ * Store labels getter
+ *
+ * @param Mage_Core_Model_Abstract $status
+ * @return array
+ */
+ public function getStoreLabels(Mage_Core_Model_Abstract $status)
+ {
+ $select = $this->_getWriteAdapter()->select()
+ ->from($this->_labelsTable, array('store_id', 'label'))
+ ->where('status=?', $status->getStatus());
+ return $this->_getReadAdapter()->fetchPairs($select);
+ }
+
+ /**
+ * Save status labels per store
+ *
+ * @param Mage_Core_Model_Abstract $object
+ * @return Mage_Sales_Model_Mysql4_Order_Status
+ */
+ protected function _afterSave(Mage_Core_Model_Abstract $object)
+ {
+ if ($object->hasStoreLabels()) {
+ $labels = $object->getStoreLabels();
+ $this->_getWriteAdapter()->delete(
+ $this->_labelsTable,
+ array('status = ?' => $object->getStatus())
+ );
+ $data = array();
+ foreach ($labels as $storeId => $label) {
+ if (empty($label)) {
+ continue;
+ }
+ $data[] = array(
+ 'status' => $object->getStatus(),
+ 'store_id' => $storeId,
+ 'label' => $label
+ );
+ }
+ if (!empty($data)) {
+ $this->_getWriteAdapter()->insertMultiple($this->_labelsTable, $data);
+ }
+ }
+ return parent::_afterSave($object);
+ }
+
+ /**
+ * Assign order status to order state
+ *
+ * @param string $status
+ * @param string $state
+ * @param bool $isDefault
+ * @return Mage_Sales_Model_Mysql4_Order_Status
+ */
+ public function assignState($status, $state, $isDefault)
+ {
+ if ($isDefault) {
+ $this->_getWriteAdapter()->update(
+ $this->_stateTable,
+ array('is_default' => 0),
+ array('state=?' => $state)
+ );
+ }
+ $this->_getWriteAdapter()->insertOnDuplicate(
+ $this->_stateTable,
+ array(
+ 'status' => $status,
+ 'state' => $state,
+ 'is_default'=> (int) $isDefault
+ )
+ );
+ return $this;
+ }
+
+ /**
+ * Unassign order status from order state
+ *
+ * @param string $status
+ * @param string $state
+ * @return Mage_Sales_Model_Mysql4_Order_Status
+ */
+ public function unassignState($status, $state)
+ {
+ $select = $this->_getWriteAdapter()->select()
+ ->from($this->_stateTable, 'count(*)')
+ ->where('state=?', $state);
+ if ($this->_getWriteAdapter()->fetchOne($select) == 1) {
+ throw new Mage_Core_Exception(
+ Mage::helper('sales')->__('Last status can\'t be unassigned from state.')
+ );
+ }
+ $select = $this->_getWriteAdapter()->select()
+ ->from($this->_stateTable, 'is_default')
+ ->where('state=?', $state)
+ ->where('status=?', $status)
+ ->limit(1);
+ $isDefault = $this->_getWriteAdapter()->fetchOne($select);
+ $this->_getWriteAdapter()->delete(
+ $this->_stateTable,
+ array(
+ 'state=?' => $state,
+ 'status=?' => $status
+ )
+ );
+
+ if ($isDefault) {
+ $select = $this->_getWriteAdapter()->select()
+ ->from($this->_stateTable, 'status')
+ ->where('state=?', $state)
+ ->limit(1);
+ $defaultStatus = $this->_getWriteAdapter()->fetchOne($select);
+ if ($defaultStatus) {
+ $this->_getWriteAdapter()->update(
+ $this->_stateTable,
+ array('is_default'=>1),
+ array(
+ 'state=?' => $state,
+ 'status=?' => $defaultStatus
+ )
+ );
+ }
+ }
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/Sales/Model/Mysql4/Order/Status/Collection.php b/app/code/core/Mage/Sales/Model/Mysql4/Order/Status/Collection.php
new file mode 100644
index 0000000000..a115a782d9
--- /dev/null
+++ b/app/code/core/Mage/Sales/Model/Mysql4/Order/Status/Collection.php
@@ -0,0 +1,100 @@
+_init('sales/order_status');
+ }
+
+ /**
+ * Get collection data as options array
+ *
+ * @return array
+ */
+ public function toOptionArray()
+ {
+ return $this->_toOptionArray('status', 'label');
+ }
+
+ /**
+ * Get collection data as options hash
+ *
+ * @return array
+ */
+ public function toOptionHash()
+ {
+ return $this->_toOptionHash('status', 'label');
+ }
+
+ /**
+ * Join order states table
+ */
+ public function joinStates()
+ {
+ if (!$this->getFlag('states_joined')) {
+ $this->_idFieldName = 'status_state';
+ $this->getSelect()->joinLeft(
+ array('state_table' => $this->getTable('sales/order_status_state')),
+ 'main_table.status=state_table.status',
+ array('state', 'is_default')
+ );
+ $this->setFlag('states_joined', true);
+ }
+ return $this;
+ }
+
+ /**
+ * add state code filter to collection
+ *
+ * @param string $state
+ */
+ public function addStateFilter($state)
+ {
+ $this->joinStates();
+ $this->getSelect()->where('state_table.state=?', $state);
+ return $this;
+ }
+
+ /**
+ * Define label order
+ *
+ * @param string $dir
+ * @return Mage_Sales_Model_Mysql4_Order_Status_Collection
+ */
+ public function orderByLabel($dir = 'ASC')
+ {
+ $this->getSelect()->order('main_table.label '.$dir);
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/Sales/Model/Mysql4/Report/Order.php b/app/code/core/Mage/Sales/Model/Mysql4/Report/Order.php
index c2d2493c38..2d789efa05 100644
--- a/app/code/core/Mage/Sales/Model/Mysql4/Report/Order.php
+++ b/app/code/core/Mage/Sales/Model/Mysql4/Report/Order.php
@@ -99,6 +99,7 @@ public function aggregate($from = null, $to = null)
'total_qty_invoiced' => 'SUM(qty_invoiced)',
);
$selectOrderItem->from($this->getTable('sales/order_item'), $cols)
+ ->where('parent_item_id IS NULL')
->group('order_id');
if ($subSelect !== null) {
//$selectOrderItem->where($this->_makeConditionFromDateRangeSelect($subSelect, 'created_at'));
@@ -108,8 +109,7 @@ public function aggregate($from = null, $to = null)
->join(array('oi' => $selectOrderItem), 'oi.order_id = o.entity_id', array())
->where('o.state NOT IN (?)', array(
Mage_Sales_Model_Order::STATE_PENDING_PAYMENT,
- Mage_Sales_Model_Order::STATE_NEW,
- Mage_Sales_Model_Order::STATE_CANCELED,
+ Mage_Sales_Model_Order::STATE_NEW
));
if ($subSelect !== null) {
diff --git a/app/code/core/Mage/Sales/Model/Mysql4/Report/Order/Updatedat/Collection.php b/app/code/core/Mage/Sales/Model/Mysql4/Report/Order/Updatedat/Collection.php
index 6a8c604b67..6f300b276d 100644
--- a/app/code/core/Mage/Sales/Model/Mysql4/Report/Order/Updatedat/Collection.php
+++ b/app/code/core/Mage/Sales/Model/Mysql4/Report/Order/Updatedat/Collection.php
@@ -157,6 +157,7 @@ protected function _initSelect()
'total_qty_ordered' => 'SUM(qty_ordered - IFNULL(qty_canceled, 0))',
'total_qty_invoiced' => 'SUM(qty_invoiced)',
))
+ ->where('parent_item_id IS NULL')
->group('order_id');
$select = $this->getSelect()
@@ -164,8 +165,7 @@ protected function _initSelect()
->join(array('oi' => $selectOrderItem), 'oi.order_id = e.entity_id', array())
->where('e.state NOT IN (?)', array(
Mage_Sales_Model_Order::STATE_PENDING_PAYMENT,
- Mage_Sales_Model_Order::STATE_NEW,
- Mage_Sales_Model_Order::STATE_CANCELED,
+ Mage_Sales_Model_Order::STATE_NEW
));
$this->_applyStoresFilter();
diff --git a/app/code/core/Mage/Sales/Model/Order.php b/app/code/core/Mage/Sales/Model/Order.php
index 5b12677b8a..ea9120b0e6 100644
--- a/app/code/core/Mage/Sales/Model/Order.php
+++ b/app/code/core/Mage/Sales/Model/Order.php
@@ -67,6 +67,11 @@ class Mage_Sales_Model_Order extends Mage_Sales_Model_Abstract
const STATE_HOLDED = 'holded';
const STATE_PAYMENT_REVIEW = 'payment_review';
+ /**
+ * Order statuses
+ */
+ const STATUS_FRAUD = 'fraud';
+
/**
* Order flags
*/
@@ -109,6 +114,13 @@ class Mage_Sales_Model_Order extends Mage_Sales_Model_Abstract
*/
protected $_actionFlag = array();
+ /**
+ * Flag: if after order placing we can send new email to the customer.
+ *
+ * @var bool
+ */
+ protected $_canSendNewEmailFlag = true;
+
/**
* Initialize resource model
*/
@@ -159,6 +171,28 @@ public function setActionFlag($action, $flag)
return $this;
}
+ /**
+ * Return flag for order if it can sends new email to customer.
+ *
+ * @return bool
+ */
+ public function getCanSendNewEmailFlag()
+ {
+ return $this->_canSendNewEmailFlag;
+ }
+
+ /**
+ * Set flag for order if it can sends new email to customer.
+ *
+ * @param bool $flag
+ * @return Mage_Sales_Model_Order
+ */
+ public function setCanSendNewEmailFlag($flag)
+ {
+ $this->_canSendNewEmailFlag = (boolean) $flag;
+ return $this;
+ }
+
/**
* Load order by system increment identifier
*
@@ -433,18 +467,35 @@ public function canReorder()
foreach ($this->getItemsCollection() as $item) {
$products[] = $item->getProductId();
}
- $productsCollection = Mage::getModel('catalog/product')->getCollection()
- ->setStoreId($this->getStoreId());
if (!empty($products)) {
- $productsCollection->addIdFilter($products)
+ /*
+ * @TODO ACPAOC: Use product collection here, but ensure that product is loaded with order store id, otherwise there'll be problems with isSalable()
+ * for configurables, bundles and other composites
+ *
+ */
+ /*
+ $productsCollection = Mage::getModel('catalog/product')->getCollection()
+ ->setStoreId($this->getStoreId())
+ ->addIdFilter($products)
->addAttributeToSelect('status')
->load();
+
foreach ($productsCollection as $product) {
if (!$product->isSalable()) {
return false;
}
}
+ */
+
+ foreach ($products as $productId) {
+ $product = Mage::getModel('catalog/product')
+ ->setStoreId($this->getStoreId())
+ ->load($productId);
+ if (!$product->getId() || !$product->isSalable()) {
+ return false;
+ }
+ }
}
if ($this->getActionFlag(self::ACTION_FLAG_REORDER) === false) {
@@ -1091,13 +1142,11 @@ protected function _getItemsRandomCollection($limit, $nonChildrenOnly = false)
{
$collection = Mage::getModel('sales/order_item')->getCollection()
->setOrderFilter($this)
- ->setRandomOrder()
- ->setPageSize($limit);
+ ->setRandomOrder();
if ($nonChildrenOnly) {
$collection->filterByParent();
}
-
$products = array();
foreach ($collection as $item) {
$products[] = $item->getProductId();
@@ -1106,11 +1155,17 @@ protected function _getItemsRandomCollection($limit, $nonChildrenOnly = false)
$productsCollection = Mage::getModel('catalog/product')
->getCollection()
->addIdFilter($products)
+ ->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInSiteIds())
+ /* Price data is added to consider item stock status using price index */
+ ->addPriceData()
+ ->setPageSize($limit)
->load();
- Mage::getSingleton('catalog/product_visibility')
- ->addVisibleInSiteFilterToCollection($productsCollection);
+
foreach ($collection as $item) {
- $item->setProduct($productsCollection->getItemById($item->getProductId()));
+ $product = $productsCollection->getItemById($item->getProductId());
+ if ($product) {
+ $item->setProduct($product);
+ }
}
return $collection;
diff --git a/app/code/core/Mage/Sales/Model/Order/Address.php b/app/code/core/Mage/Sales/Model/Order/Address.php
index 29744ed061..ccf75d53cc 100644
--- a/app/code/core/Mage/Sales/Model/Order/Address.php
+++ b/app/code/core/Mage/Sales/Model/Order/Address.php
@@ -45,6 +45,9 @@ public function setOrder(Mage_Sales_Model_Order $order)
public function getOrder()
{
+ if (!$this->_order) {
+ $this->_order = Mage::getModel('sales/order')->load($this->getParentId());
+ }
return $this->_order;
}
diff --git a/app/code/core/Mage/Sales/Model/Order/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Api/V2.php
index 86ba322cc5..39b40d5995 100644
--- a/app/code/core/Mage/Sales/Model/Order/Api/V2.php
+++ b/app/code/core/Mage/Sales/Model/Order/Api/V2.php
@@ -74,15 +74,23 @@ public function items($filters = null)
$preparedFilters = array();
if (isset($filters->filter)) {
foreach ($filters->filter as $_filter) {
- $preparedFilters[$_filter->key] = $_filter->value;
+ $preparedFilters[][$_filter->key] = $_filter->value;
}
}
if (isset($filters->complex_filter)) {
foreach ($filters->complex_filter as $_filter) {
$_value = $_filter->value;
- $preparedFilters[][$_filter->key] = array(
- $_value->key => $_value->value
- );
+ if(is_object($_value)) {
+ $preparedFilters[][$_filter->key] = array(
+ $_value->key => $_value->value
+ );
+ } elseif(is_array($_value)) {
+ $preparedFilters[][$_filter->key] = array(
+ $_value['key'] => $_value['value']
+ );
+ } else {
+ $preparedFilters[][$_filter->key] = $_value;
+ }
}
}
diff --git a/app/code/core/Mage/Sales/Model/Order/Config.php b/app/code/core/Mage/Sales/Model/Order/Config.php
index b4a7f8925e..f67295a9f4 100644
--- a/app/code/core/Mage/Sales/Model/Order/Config.php
+++ b/app/code/core/Mage/Sales/Model/Order/Config.php
@@ -33,6 +33,13 @@
*/
class Mage_Sales_Model_Order_Config extends Mage_Core_Model_Config_Base
{
+ /**
+ * Statuses per state array
+ *
+ * @var array
+ */
+ protected $_stateStatuses;
+
private $_states;
public function __construct()
@@ -60,18 +67,9 @@ public function getStateDefaultStatus($state)
{
$status = false;
if ($stateNode = $this->_getState($state)) {
- if ($stateNode->statuses) {
- foreach ($stateNode->statuses->children() as $statusNode) {
- if (!$status) {
- $status = $statusNode->getName();
- }
- $attributes = $statusNode->attributes();
- // empty($attributes['default']) is for backwards compatibility
- if (isset($attributes['default']) && (empty($attributes['default']) || $attributes['default'] == '1')) {
- $status = $statusNode->getName();
- }
- }
- }
+ $status = Mage::getModel('sales/order_status')
+ ->loadDefaultByState($state);
+ $status = $status->getStatus();
}
return $status;
}
@@ -79,18 +77,32 @@ public function getStateDefaultStatus($state)
/**
* Retrieve status label
*
- * @param string $status
+ * @param string $code
+ * @return string
+ */
+ public function getStatusLabel($code)
+ {
+ $status = Mage::getModel('sales/order_status')
+ ->load($code);
+ return $status->getStoreLabel();
+ }
+
+ /**
+ * State label getter
+ *
+ * @param string $state
* @return string
*/
- public function getStatusLabel($status)
+ public function getStateLabel($state)
{
- if ($statusNode = $this->_getStatus($status)) {
- $status = (string) $statusNode->label;
- return Mage::helper('sales')->__($status);
+ if ($stateNode = $this->_getState($state)) {
+ $state = (string) $stateNode->label;
+ return Mage::helper('sales')->__($state);
}
- return $status;
+ return $state;
}
+
/**
* Retrieve all statuses
*
@@ -98,14 +110,27 @@ public function getStatusLabel($status)
*/
public function getStatuses()
{
- $statuses = array();
- foreach ($this->getNode('statuses')->children() as $status) {
- $label = (string) $status->label;
- $statuses[$status->getName()] = Mage::helper('sales')->__($label);
- }
+ $statuses = Mage::getResourceModel('sales/order_status_collection')
+ ->toOptionHash();
return $statuses;
}
+ /**
+ * Order states getter
+ *
+ * @return array
+ */
+ public function getStates()
+ {
+ $states = array();
+ foreach ($this->getNode('states')->children() as $state) {
+ $label = (string) $state->label;
+ $states[$state->getName()] = Mage::helper('sales')->__($label);
+ }
+ return $states;
+ }
+
+
/**
* Retrieve statuses available for state
* Get all possible statuses, or for specified state, or specified states array
@@ -117,23 +142,30 @@ public function getStatuses()
*/
public function getStateStatuses($state, $addLabels = true)
{
+ $key = $state . $addLabels;
+ if (isset($this->_stateStatuses[$key])) {
+ return $this->_stateStatuses[$key];
+ }
$statuses = array();
if (empty($state) || !is_array($state)) {
$state = array($state);
}
foreach ($state as $_state) {
if ($stateNode = $this->_getState($_state)) {
- foreach ($stateNode->statuses->children() as $statusNode) {
- $status = $statusNode->getName();
+ $collection = Mage::getResourceModel('sales/order_status_collection')
+ ->addStateFilter($_state)
+ ->orderByLabel();
+ foreach ($collection as $status) {
+ $code = $status->getStatus();
if ($addLabels) {
- $statuses[$status] = $this->getStatusLabel($status);
- }
- else {
- $statuses[] = $status;
+ $statuses[$code] = $status->getStoreLabel();
+ } else {
+ $statuses[] = $code;
}
}
}
}
+ $this->_stateStatuses[$key] = $statuses;
return $statuses;
}
diff --git a/app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php b/app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php
index 4e91365868..20ffd60c46 100644
--- a/app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php
+++ b/app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php
@@ -89,14 +89,18 @@ public function collect(Mage_Sales_Model_Order_Creditmemo $creditmemo)
}
if ($invoice = $creditmemo->getInvoice()) {
- $totalTax += $invoice->getShippingTaxAmount();
- $baseTotalTax += $invoice->getBaseShippingTaxAmount();
- $totalHiddenTax += $invoice->getShippingHiddenTaxAmount();
- $baseTotalHiddenTax += $invoice->getBaseShippingHiddenTaxAmount();
- $shippingTaxAmount = $invoice->getShippingTaxAmount();
- $baseShippingTaxAmount = $invoice->getBaseShippingTaxAmount();
- $shippingHiddenTaxAmount = $invoice->getShippingHiddenTaxAmount();
- $baseShippingHiddenTaxAmount = $invoice->getBaseShippingHiddenTaxAmount();
+ //recalculate tax amounts in case if refund shipping value was changed
+ if ($order->getBaseShippingAmount() && $creditmemo->getBaseShippingAmount()) {
+ $taxFactor = $creditmemo->getBaseShippingAmount()/$order->getBaseShippingAmount();
+ $shippingTaxAmount = $invoice->getShippingTaxAmount()*$taxFactor;
+ $baseShippingTaxAmount = $invoice->getBaseShippingTaxAmount()*$taxFactor;
+ $totalHiddenTax += $invoice->getShippingHiddenTaxAmount()*$taxFactor;
+ $baseTotalHiddenTax += $invoice->getBaseShippingHiddenTaxAmount()*$taxFactor;
+ $shippingHiddenTaxAmount = $invoice->getShippingHiddenTaxAmount()*$taxFactor;
+ $baseShippingHiddenTaxAmount = $invoice->getBaseShippingHiddenTaxAmount()*$taxFactor;
+ $totalTax += $shippingTaxAmount;
+ $baseTotalTax += $baseShippingTaxAmount;
+ }
} else {
$orderShippingAmount = $order->getShippingAmount();
$baseOrderShippingAmount = $order->getBaseShippingAmount();
diff --git a/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php b/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php
index 671fcb417f..a060d8c404 100644
--- a/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php
+++ b/app/code/core/Mage/Sales/Model/Order/Invoice/Api/V2.php
@@ -42,7 +42,7 @@ class Mage_Sales_Model_Order_Invoice_Api_V2 extends Mage_Sales_Model_Order_Invoi
public function items($filters = null)
{
//TODO: add full name logic
- $collection = Mage::getResourceModel('sales/order_invoice_collection')
+ $collection = Mage::getModel('sales/order_invoice')->getCollection()
->addAttributeToSelect('order_id')
->addAttributeToSelect('increment_id')
->addAttributeToSelect('created_at')
@@ -57,26 +57,36 @@ public function items($filters = null)
$preparedFilters = array();
if (isset($filters->filter)) {
foreach ($filters->filter as $_filter) {
- $preparedFilters[$_filter->key] = $_filter->value;
+ $preparedFilters[][$_filter->key] = $_filter->value;
}
}
if (isset($filters->complex_filter)) {
foreach ($filters->complex_filter as $_filter) {
$_value = $_filter->value;
- $preparedFilters[$_filter->key] = array(
- $_value->key => $_value->value
- );
+ if(is_object($_value)) {
+ $preparedFilters[][$_filter->key] = array(
+ $_value->key => $_value->value
+ );
+ } elseif(is_array($_value)) {
+ $preparedFilters[][$_filter->key] = array(
+ $_value['key'] => $_value['value']
+ );
+ } else {
+ $preparedFilters[][$_filter->key] = $_value;
+ }
}
}
if (!empty($preparedFilters)) {
try {
- foreach ($preparedFilters as $field => $value) {
- if (isset($this->_attributesMap['invoice'][$field])) {
- $field = $this->_attributesMap['invoice'][$field];
- }
+ foreach ($preparedFilters as $preparedFilter) {
+ foreach ($preparedFilter as $field => $value) {
+ if (isset($this->_attributesMap['order'][$field])) {
+ $field = $this->_attributesMap['order'][$field];
+ }
- $collection->addFieldToFilter($field, $value);
+ $collection->addFieldToFilter($field, $value);
+ }
}
} catch (Mage_Core_Exception $e) {
$this->_fault('filters_invalid', $e->getMessage());
diff --git a/app/code/core/Mage/Sales/Model/Order/Payment.php b/app/code/core/Mage/Sales/Model/Order/Payment.php
index 42ac4e3e7c..d2a26176e6 100644
--- a/app/code/core/Mage/Sales/Model/Order/Payment.php
+++ b/app/code/core/Mage/Sales/Model/Order/Payment.php
@@ -277,7 +277,7 @@ public function capture($invoice)
$message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amountToCapture));
$state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
if ($this->getIsFraudDetected()) {
- $status = 'fraud';
+ $status = Mage_Sales_Model_Order::STATUS_FRAUD;
}
$invoice->setIsPaid(false);
} else { // normal online capture: invoice is marked as "paid"
@@ -330,6 +330,7 @@ public function registerCaptureNotification($amount)
$order->addRelatedObject($invoice);
$this->setCreatedInvoice($invoice);
} else {
+ $this->setIsFraudDetected(true);
$this->_updateTotals(array('base_amount_paid_online' => $amount));
}
}
@@ -339,11 +340,17 @@ public function registerCaptureNotification($amount)
$message = Mage::helper('sales')->__('Capturing amount of %s is pending approval on gateway.', $this->_formatPrice($amount));
$state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
if ($this->getIsFraudDetected()) {
- $status = 'fraud';
+ $message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount));
+ $status = Mage_Sales_Model_Order::STATUS_FRAUD;
}
} else {
$message = Mage::helper('sales')->__('Registered notification about captured amount of %s.', $this->_formatPrice($amount));
$state = Mage_Sales_Model_Order::STATE_PROCESSING;
+ if ($this->getIsFraudDetected()) {
+ $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
+ $message = Mage::helper('sales')->__('Order is suspended as its capture amount %s is suspected to be fraudulent.', $this->_formatPrice($amount));
+ $status = Mage_Sales_Model_Order::STATUS_FRAUD;
+ }
// register capture for an existing invoice
if ($invoice && Mage_Sales_Model_Order_Invoice::STATE_OPEN == $invoice->getState()) {
$invoice->pay();
@@ -803,22 +810,21 @@ protected function _authorize($isOnline, $amount)
$state = Mage_Sales_Model_Order::STATE_PROCESSING;
$status = true;
if ($isOnline) {
-
// invoke authorization on gateway
$this->getMethodInstance()->setStore($order->getStoreId())->authorize($this, $amount);
+ } else {
+ $message = Mage::helper('sales')->__('Registered notification about authorized amount of %s.', $this->_formatPrice($amount));
+ }
- // similar logic of "payment review" order as in capturing
- if ($this->getIsTransactionPending()) {
- $message = Mage::helper('sales')->__('Authorizing amount of %s is pending approval on gateway.', $this->_formatPrice($amount));
- $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
- if ($this->getIsFraudDetected()) {
- $status = 'fraud';
- }
- } else {
- $message = Mage::helper('sales')->__('Authorized amount of %s.', $this->_formatPrice($amount));
+ // similar logic of "payment review" order as in capturing
+ if ($this->getIsTransactionPending()) {
+ $message = Mage::helper('sales')->__('Authorizing amount of %s is pending approval on gateway.', $this->_formatPrice($amount));
+ $state = Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW;
+ if ($this->getIsFraudDetected()) {
+ $status = Mage_Sales_Model_Order::STATUS_FRAUD;
}
} else {
- $message = Mage::helper('sales')->__('Registered notification about authorized amount of %s.', $this->_formatPrice($amount));
+ $message = Mage::helper('sales')->__('Authorized amount of %s.', $this->_formatPrice($amount));
}
// update transactions, order state and add comments
@@ -926,6 +932,11 @@ protected function _void($isOnline, $amount = null, $gatewayCallback = 'void')
*/
protected function _addTransaction($type, $salesDocument = null, $failsafe = false)
{
+ if ($this->getSkipTransactionCreation()) {
+ $this->unsTransactionId();
+ return null;
+ }
+
// look for set transaction ids
$transactionId = $this->getTransactionId();
if (null !== $transactionId) {
@@ -985,11 +996,20 @@ protected function _addTransaction($type, $salesDocument = null, $failsafe = fal
* @param string $type
* @param Mage_Sales_Model_Abstract $salesDocument
* @param bool $failsafe
+ * @param string $message
* @return null|Mage_Sales_Model_Order_Payment_Transaction
*/
- public function addTransaction($type, $salesDocument = null, $failsafe = false)
+ public function addTransaction($type, $salesDocument = null, $failsafe = false, $message = false)
{
- return $this->_addTransaction($type, $salesDocument, $failsafe);
+ $transaction = $this->_addTransaction($type, $salesDocument, $failsafe);
+
+ if ($message) {
+ $order = $this->getOrder();
+ $message = $this->_appendTransactionToMessage($transaction, $message);
+ $order->addStatusHistoryComment($message);
+ }
+
+ return $transaction;
}
/**
@@ -1275,6 +1295,17 @@ public function setTransactionAdditionalInfo($key, $value)
$this->_transactionAdditionalInfo[$key] = $value;
}
+ /**
+ * Reset transaction additional info property
+ *
+ * @return Mage_Sales_Model_Order_Payment
+ */
+ public function resetTransactionAdditionalInfo()
+ {
+ $this->_transactionAdditionalInfo = array();
+ return $this;
+ }
+
/**
* Return invoice model for transaction
*
diff --git a/app/code/core/Mage/Sales/Model/Order/Pdf/Total/Default.php b/app/code/core/Mage/Sales/Model/Order/Pdf/Total/Default.php
index abe2abc34f..b4db890861 100644
--- a/app/code/core/Mage/Sales/Model/Order/Pdf/Total/Default.php
+++ b/app/code/core/Mage/Sales/Model/Order/Pdf/Total/Default.php
@@ -53,6 +53,47 @@ public function getTotalsForDisplay()
return array($total);
}
+ /**
+ * Get array of arrays with tax information for display in PDF
+ * array(
+ * $index => array(
+ * 'amount' => $amount,
+ * 'label' => $label,
+ * 'font_size'=> $font_size
+ * )
+ * )
+ * @return array
+ */
+ public function getFullTaxInfo()
+ {
+ $rates = Mage::getResourceModel('sales/order_tax_collection')->loadByOrder($this->getOrder())->toArray();
+ $fullInfo = Mage::getSingleton('tax/calculation')->reproduceProcess($rates['items']);
+ $fontSize = $this->getFontSize() ? $this->getFontSize() : 7;
+ $tax_info = array();
+
+ if ($fullInfo) {
+ foreach ($fullInfo as $info) {
+ if (isset($info['hidden']) && $info['hidden']) {
+ continue;
+ }
+
+ $_amount = $info['amount'];
+
+ foreach ($info['rates'] as $rate) {
+ $percent = $rate['percent'] ? ' (' . $rate['percent']. '%)' : '';
+
+ $tax_info[] = array(
+ 'amount' => $this->getAmountPrefix().$this->getOrder()->formatPriceTxt($_amount),
+ 'label' => Mage::helper('tax')->__($rate['title']) . $percent . ':',
+ 'font_size' => $fontSize
+ );
+ }
+ }
+ }
+
+ return $tax_info;
+ }
+
/**
* Check if we can display total information in PDF
*
diff --git a/app/code/core/Mage/Sales/Model/Order/Status.php b/app/code/core/Mage/Sales/Model/Order/Status.php
index 640abd1b98..d48cb94de0 100644
--- a/app/code/core/Mage/Sales/Model/Order/Status.php
+++ b/app/code/core/Mage/Sales/Model/Order/Status.php
@@ -34,20 +34,86 @@ protected function _construct()
}
/**
- * Retrieve order status label
+ * Assign order status to particular state
*
- * @return string
+ * @param string $state
+ * @param boolean $isDefault make the status as default one for state
+ * @return Mage_Sales_Model_Order_Status
+ */
+ public function assignState($state, $isDefault=false)
+ {
+ $this->_getResource()->beginTransaction();
+ try {
+ $this->_getResource()->assignState($this->getStatus(), $state, $isDefault);
+ $this->_getResource()->commit();
+ } catch (Exception $e) {
+ $this->_getResource()->rollBack();
+ throw $e;
+ }
+ return $this;
+ }
+
+ /**
+ * Unassigns order status from particular state
+ *
+ * @param string $state
+ * @return Mage_Sales_Model_Order_Status
*/
- public function getFrontendLabel()
+ public function unassignState($state)
{
- $label = '';
- if ($storeId = Mage::app()->getStore()->getId()) {
- $label = Mage::app()->getStore()->getConfig('sales/order_statuses/status_' . $this->getId());
+ $this->_getResource()->beginTransaction();
+ try {
+ $this->_getResource()->unassignState($this->getStatus(), $state);
+ $this->_getResource()->commit();
+ } catch (Exception $e) {
+ $this->_getResource()->rollBack();
+ throw $e;
}
- if (! $label) {
- $label = $this->getData('frontend_label');
+ return $this;
+ }
+
+ /**
+ * Getter for status labels per store
+ *
+ * @return array
+ */
+ public function getStoreLabels()
+ {
+ if ($this->hasData('store_labels')) {
+ return $this->_getData('store_labels');
}
- return $label;
+ $labels = $this->_getResource()->getStoreLabels($this);
+ $this->setData('store_labels', $labels);
+ return $labels;
}
+ /**
+ * Get status label by store
+ *
+ * @param mixed $store
+ * @return string
+ */
+ public function getStoreLabel($store=null)
+ {
+ $store = Mage::app()->getStore($store);
+ $label = false;
+ if (!$store->isAdmin()) {
+ $labels = $this->getStoreLabels();
+ if (isset($labels[$store->getId()])) {
+ return $labels[$store->getId()];
+ }
+ }
+ return Mage::helper('sales')->__($this->getLabel());
+ }
+
+ /**
+ * Load default status per state
+ *
+ * @param string $state
+ */
+ public function loadDefaultByState($state)
+ {
+ $this->load($state, 'default_state');
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/Sales/Model/Payment/Method/Billing/AgreementAbstract.php b/app/code/core/Mage/Sales/Model/Payment/Method/Billing/AgreementAbstract.php
index b1109e5a87..fc24e2cf93 100644
--- a/app/code/core/Mage/Sales/Model/Payment/Method/Billing/AgreementAbstract.php
+++ b/app/code/core/Mage/Sales/Model/Payment/Method/Billing/AgreementAbstract.php
@@ -61,10 +61,12 @@ public function isAvailable($quote = null)
$availableBA = Mage::getModel('sales/billing_agreement')->getAvailableCustomerBillingAgreements(
$quote->getCustomer()->getId()
);
- $this->_canUseCheckout = count($availableBA) > 0;
+ $isAvailableBA = count($availableBA) > 0;
+ $this->_canUseCheckout = $this->_canUseInternal = $isAvailableBA;
}
$this->_isAvailable = parent::isAvailable($quote) && $this->_isAvailable($quote);
$this->_canUseCheckout = ($this->_isAvailable && $this->_canUseCheckout);
+ $this->_canUseInternal = ($this->_isAvailable && $this->_canUseInternal);
}
return $this->_isAvailable;
}
diff --git a/app/code/core/Mage/Sales/Model/Quote.php b/app/code/core/Mage/Sales/Model/Quote.php
index bb1a5c52cc..034c644229 100644
--- a/app/code/core/Mage/Sales/Model/Quote.php
+++ b/app/code/core/Mage/Sales/Model/Quote.php
@@ -623,6 +623,23 @@ public function hasItemsWithDecimalQty()
return false;
}
+ /**
+ * Checking product exist in Quote
+ *
+ * @param int $productId
+ * @return bool
+ */
+ public function hasProductId($productId)
+ {
+ foreach ($this->getAllItems() as $item) {
+ if ($item->getProductId() == $productId) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/**
* Retrieve item model object by item identifier
*
@@ -642,7 +659,8 @@ public function getItemById($itemId)
*/
public function removeItem($itemId)
{
- if ($item = $this->getItemById($itemId)) {
+ $item = $this->getItemById($itemId);
+ if ($item) {
$item->setQuote($this);
/**
* If we remove item from quote - we can't use multishipping mode
@@ -688,16 +706,16 @@ public function addItem(Mage_Sales_Model_Quote_Item $item)
}
/**
- * Add product to quote
+ * Advanced func to add product to quote - processing mode can be specified there.
+ * Returns error message if product type instance can't prepare product.
*
- * return error message if product type instance can't prepare product
- *
- * @param mixed $product
- * @return Mage_Sales_Model_Quote_Item || string
+ * @param mixed $product
+ * @param null|float|Varien_Object $request
+ * @param null|string $processMode
+ * @return Mage_Sales_Model_Quote_Item|string
*/
- public function addProduct(Mage_Catalog_Model_Product $product, $request=null)
+ public function addProductAdvanced(Mage_Catalog_Model_Product $product, $request = null, $processMode = null)
{
-
if ($request === null) {
$request = 1;
}
@@ -709,12 +727,11 @@ public function addProduct(Mage_Catalog_Model_Product $product, $request=null)
}
$cartCandidates = $product->getTypeInstance(true)
- ->prepareForCart($request, $product);
+ ->prepareForCartAdvanced($request, $product, $processMode);
/**
* Error message
*/
-
if (is_string($cartCandidates)) {
return $cartCandidates;
}
@@ -726,9 +743,6 @@ public function addProduct(Mage_Catalog_Model_Product $product, $request=null)
$cartCandidates = array($cartCandidates);
}
-
-
-
$parentItem = null;
$errors = array();
$items = array();
@@ -742,7 +756,7 @@ public function addProduct(Mage_Catalog_Model_Product $product, $request=null)
if (!$parentItem) {
$parentItem = $item;
}
- if ($parentItem && $candidate->getParentProductId()) {
+ if ($parentItem && $candidate->getParentProductId() && !$item->getId()) {
$item->setParentItem($parentItem);
}
@@ -765,6 +779,21 @@ public function addProduct(Mage_Catalog_Model_Product $product, $request=null)
return $item;
}
+
+ /**
+ * Add product to quote
+ *
+ * return error message if product type instance can't prepare product
+ *
+ * @param mixed $product
+ * @param null|float|Varien_Object $request
+ * @return Mage_Sales_Model_Quote_Item|string
+ */
+ public function addProduct(Mage_Catalog_Model_Product $product, $request = null)
+ {
+ return $this->addProductAdvanced($product, $request, Mage_Catalog_Model_Product_Type_Abstract::PROCESS_MODE_FULL);
+ }
+
/**
* Adding catalog product object data to quote
*
@@ -801,10 +830,66 @@ protected function _addCatalogProduct(Mage_Catalog_Model_Product $product, $qty
return $item;
}
+ /**
+ * Updates quote item with new configuration
+ *
+ * @param int $itemId
+ * @param Varien_Object $buyRequest
+ * @return Mage_Sales_Model_Quote_Item
+ */
+ public function updateItem($itemId, $buyRequest)
+ {
+ $item = $this->getItemById($itemId);
+ if (!$item) {
+ Mage::throwException(Mage::helper('sales')->__('Wrong quote item id to update configuration.'));
+ }
+ $productId = $item->getProduct()->getId();
+
+ //We need to create new clear product instance with same $productId
+ //to set new option values from $buyRequest
+ $product = Mage::getModel('catalog/product')
+ ->setStoreId($this->getStore()->getId())
+ ->load($productId);
+
+ $resultItem = $this->addProduct($product, $buyRequest);
+
+ if (is_string($resultItem)) {
+ Mage::throwException($resultItem);
+ }
+
+ if ($resultItem->getParentItem()) {
+ $resultItem = $resultItem->getParentItem();
+ }
+
+ if ($resultItem->getId() != $itemId) {
+ /*
+ * Product configuration didn't stick to original quote item
+ * It either has same configuration as some other quote item's product or completely new configuration
+ */
+ $this->removeItem($itemId);
+
+ $items = $this->getAllItems();
+ foreach ($items as $item) {
+ if (($item->getProductId() == $productId) && ($item->getId() != $resultItem->getId())) {
+ if ($resultItem->compare($item)) {
+ // Product configuration is same as in other quote item
+ $resultItem->setQty($resultItem->getQty() + $item->getQty());
+ $this->removeItem($item->getId());
+ break;
+ }
+ }
+ }
+ } else {
+ $resultItem->setQty($buyRequest->getQty());
+ }
+
+ return $resultItem;
+ }
+
/**
* Retrieve quote item by product id
*
- * @param int $productId
+ * @param Mage_Catalog_Model_Product $product
* @return Mage_Sales_Model_Quote_Item || false
*/
public function getItemByProduct($product)
diff --git a/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php b/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php
index e8eed9739b..6fd92aae57 100644
--- a/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php
+++ b/app/code/core/Mage/Sales/Model/Quote/Address/Total/Shipping.php
@@ -166,7 +166,7 @@ public function collect(Mage_Sales_Model_Quote_Address $address)
$this->_setAmount($amountPrice);
$this->_setBaseAmount($rate->getPrice());
$shippingDescription = $rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle();
- $address->setShippingDescription(trim($shippingDescription, '-'));
+ $address->setShippingDescription(trim($shippingDescription, ' -'));
break;
}
}
diff --git a/app/code/core/Mage/Sales/Model/Quote/Item.php b/app/code/core/Mage/Sales/Model/Quote/Item.php
index 205faafc67..edcfa1156d 100644
--- a/app/code/core/Mage/Sales/Model/Quote/Item.php
+++ b/app/code/core/Mage/Sales/Model/Quote/Item.php
@@ -78,6 +78,12 @@ class Mage_Sales_Model_Quote_Item extends Mage_Sales_Model_Quote_Item_Abstract
*/
protected $_notRepresentOptions = array('info_buyRequest');
+ /**
+ * Flag stating that options were successfully saved
+ *
+ */
+ protected $_flagOptionsSaved = null;
+
/**
* Initialize resource model
*
@@ -288,29 +294,6 @@ public function setProduct($product)
return $this;
}
- /**
- * Retrieve product model object associated with item
- *
- * @return Mage_Catalog_Model_Product
- */
- public function getProduct()
- {
- $product = $this->_getData('product');
- if (($product === null) && $this->getProductId()) {
- $product = Mage::getModel('catalog/product')
- ->setStoreId($this->getQuote()->getStoreId())
- ->load($this->getProductId());
- $this->setProduct($product);
- }
-
- /**
- * Reset product final price because it related to custom options
- */
- $product->setFinalPrice(null);
- $product->setCustomOptions($this->_optionsByCode);
- return $product;
- }
-
/**
* Check product representation in item
*
@@ -320,7 +303,7 @@ public function getProduct()
public function representProduct($product)
{
$itemProduct = $this->getProduct();
- if ($itemProduct->getId() != $product->getId()) {
+ if (!$product || $itemProduct->getId() != $product->getId()) {
return false;
}
@@ -597,12 +580,7 @@ protected function _hasModelChanged()
return false;
}
- $result = $this->_getResource()->hasDataChanged($this);
- if ($result === false) {
- $this->_saveItemOptions();
- }
-
- return $result;
+ return $this->_getResource()->hasDataChanged($this);
}
/**
@@ -622,9 +600,27 @@ protected function _saveItemOptions()
}
}
+ $this->_flagOptionsSaved = true; // Report to watchers that options were saved
+
return $this;
}
+ /**
+ * Save model plus its options
+ * Ensures saving options in case when resource model was not changed
+ */
+ public function save()
+ {
+ $hasDataChanges = $this->hasDataChanges();
+ $this->_flagOptionsSaved = false;
+
+ parent::save();
+
+ if ($hasDataChanges && !$this->_flagOptionsSaved) {
+ $this->_saveItemOptions();
+ }
+ }
+
/**
* Save item options after item saved
*
@@ -653,4 +649,22 @@ public function __clone()
}
return $this;
}
+
+ /**
+ * Returns formatted buy request - object, holding request received from
+ * product view page with keys and options for configured product
+ *
+ * @return Varien_Object
+ */
+ public function getBuyRequest()
+ {
+ $option = $this->getOptionByCode('info_buyRequest');
+ $buyRequest = new Varien_Object(unserialize($option->getValue()));
+
+ // Owerwrite standard buy request qty, because item qty could have changed since adding to quote
+ $buyRequest->setOriginalQty($buyRequest);
+ $buyRequest->setQty($this->getQty());
+
+ return $buyRequest;
+ }
}
diff --git a/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php b/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php
index 89da5b4e43..5cebc4001a 100644
--- a/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php
+++ b/app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php
@@ -39,6 +39,7 @@
* @author Magento Core Team
*/
abstract class Mage_Sales_Model_Quote_Item_Abstract extends Mage_Core_Model_Abstract
+ implements Mage_Catalog_Model_Product_Configuration_Item_Interface
{
protected $_parentItem = null;
protected $_children = array();
@@ -51,6 +52,43 @@ abstract class Mage_Sales_Model_Quote_Item_Abstract extends Mage_Core_Model_Abst
*/
abstract function getQuote();
+ /**
+ * Retrieve product model object associated with item
+ *
+ * @return Mage_Catalog_Model_Product
+ */
+ public function getProduct()
+ {
+ $product = $this->_getData('product');
+ if (($product === null) && $this->getProductId()) {
+ $product = Mage::getModel('catalog/product')
+ ->setStoreId($this->getQuote()->getStoreId())
+ ->load($this->getProductId());
+ $this->setProduct($product);
+ }
+
+ /**
+ * Reset product final price because it related to custom options
+ */
+ $product->setFinalPrice(null);
+ if (is_array($this->_optionsByCode)) {
+ $product->setCustomOptions($this->_optionsByCode);
+ }
+ return $product;
+ }
+
+ /**
+ * Returns special download params (if needed) for custom option with type = 'file'
+ * Needed to implement Mage_Catalog_Model_Product_Configuration_Item_Interface.
+ * Return null, as quote item needs no additional configuration.
+ *
+ * @return null|Varien_Object
+ */
+ public function getFileDownloadParams()
+ {
+ return null;
+ }
+
/**
* Specify parent item id before saving data
*
@@ -121,11 +159,14 @@ public function addChild($child)
* @return Mage_Sales_Model_Quote_Item_Abstract
*/
public function setMessage($messages) {
+ $messagesExists = $this->getMessage(false);
if (!is_array($messages)) {
$messages = array($messages);
}
foreach ($messages as $message) {
- $this->addMessage($message);
+ if (!in_array($message, $messagesExists)) {
+ $this->addMessage($message);
+ }
}
return $this;
}
@@ -195,7 +236,7 @@ public function checkData()
$this->setMessage($e->getMessage());
$this->getQuote()->setHasError(true);
$this->getQuote()->addMessage(
- Mage::helper('sales')->__('Some of the products below do not have all the required options. Please remove them and add again with all the required options.')
+ Mage::helper('sales')->__('Some of the products below do not have all the required options. Please edit them and configure all the required options.')
);
} catch (Exception $e) {
$this->setHasError(true);
diff --git a/app/code/core/Mage/Sales/Model/Quote/Item/Option.php b/app/code/core/Mage/Sales/Model/Quote/Item/Option.php
index 6a0c7521ab..71113cde4b 100644
--- a/app/code/core/Mage/Sales/Model/Quote/Item/Option.php
+++ b/app/code/core/Mage/Sales/Model/Quote/Item/Option.php
@@ -32,6 +32,7 @@
* @author Magento Core Team
*/
class Mage_Sales_Model_Quote_Item_Option extends Mage_Core_Model_Abstract
+ implements Mage_Catalog_Model_Product_Configuration_Item_Option_Interface
{
protected $_item;
protected $_product;
@@ -104,6 +105,16 @@ public function getProduct()
return $this->_product;
}
+ /**
+ * Get option value
+ *
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->_getData('value');
+ }
+
/**
* Initialize item identifier before save data
*
diff --git a/app/code/core/Mage/Sales/Model/Service/Order.php b/app/code/core/Mage/Sales/Model/Service/Order.php
index 264157e43b..61dd04bed1 100644
--- a/app/code/core/Mage/Sales/Model/Service/Order.php
+++ b/app/code/core/Mage/Sales/Model/Service/Order.php
@@ -128,7 +128,7 @@ public function prepareShipment($qtys = array())
}
$item = $this->_convertor->itemToShipmentItem($orderItem);
- if ($orderItem->isDummy()) {
+ if ($orderItem->isDummy(true)) {
$qty = 1;
} else {
if (isset($qtys[$orderItem->getId()])) {
@@ -229,8 +229,16 @@ public function prepareInvoiceCreditmemo($invoice, $data = array())
$this->_initCreditmemoData($creditmemo, $data);
if (!isset($data['shipping_amount'])) {
$order = $invoice->getOrder();
- $baseAllowedAmount = $order->getBaseShippingAmount()-$order->getBaseShippingRefunded();
- $creditmemo->setBaseShippingAmount(min($baseAllowedAmount, $invoice->getBaseShippingAmount()));
+ $isShippingInclTax = Mage::getSingleton('tax/config')->displaySalesShippingInclTax($order->getStoreId());
+ if ($isShippingInclTax) {
+ $baseAllowedAmount = $order->getBaseShippingInclTax()
+ - $order->getBaseShippingRefunded()
+ - $order->getBaseShippingTaxRefunded();
+ } else {
+ $baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded();
+ $baseAllowedAmount = min($baseAllowedAmount, $invoice->getBaseShippingAmount());
+ }
+ $creditmemo->setBaseShippingAmount($baseAllowedAmount);
}
$creditmemo->collectTotals();
diff --git a/app/code/core/Mage/Sales/Model/Service/Quote.php b/app/code/core/Mage/Sales/Model/Service/Quote.php
index 94fd6a6274..225be103a7 100644
--- a/app/code/core/Mage/Sales/Model/Service/Quote.php
+++ b/app/code/core/Mage/Sales/Model/Service/Quote.php
@@ -168,6 +168,8 @@ public function submitOrder()
$order->addItem($orderItem);
}
+ $order->setQuote($quote);
+
$transaction->addObject($order);
$transaction->addCommitCallback(array($order, 'place'));
$transaction->addCommitCallback(array($order, 'save'));
diff --git a/app/code/core/Mage/Sales/controllers/DownloadController.php b/app/code/core/Mage/Sales/controllers/DownloadController.php
index 1c023fb28a..19bd184fb9 100644
--- a/app/code/core/Mage/Sales/controllers/DownloadController.php
+++ b/app/code/core/Mage/Sales/controllers/DownloadController.php
@@ -49,33 +49,56 @@ protected function _downloadFileAction($info)
}
$filePath = Mage::getBaseDir() . $info['order_path'];
- if (!is_file($filePath) || !is_readable($filePath)) {
- // try get file from quote
+ if ((!is_file($filePath) || !is_readable($filePath)) && !$this->_processDatabaseFile($filePath)) {
+ //try get file from quote
$filePath = Mage::getBaseDir() . $info['quote_path'];
- if (!is_file($filePath) || !is_readable($filePath)) {
+ if ((!is_file($filePath) || !is_readable($filePath)) && !$this->_processDatabaseFile($filePath)) {
throw new Exception();
}
}
+ $this->_prepareDownloadResponse($info['title'], array(
+ 'value' => $filePath,
+ 'type' => 'filename'
+ ));
+ } catch (Exception $e) {
+ $this->_forward('noRoute');
+ }
+ }
- $this->getResponse()
- ->setHttpResponseCode(200)
- ->setHeader('Pragma', 'public', true)
- ->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true)
- ->setHeader('Content-type', $info['type'], true)
- ->setHeader('Content-Length', $info['size'])
- ->setHeader('Content-Disposition', 'inline' . '; filename='.$info['title']);
-
- $this->getResponse()
- ->clearBody();
- $this->getResponse()
- ->sendHeaders();
+ /**
+ * Check file in database storage if needed and place it on file system
+ *
+ * @param string $filePath
+ * @return bool
+ */
+ protected function _processDatabaseFile($filePath)
+ {
+ if (!Mage::helper('core/file_storage_database')->checkDbUsage()) {
+ return false;
+ }
- readfile($filePath);
+ $relativePath = Mage::helper('core/file_storage_database')->getMediaRelativePath($filePath);
+ $file = Mage::getModel('core/file_storage_database')->loadByFilename($relativePath);
- } catch (Exception $e) {
- $this->_forward('noRoute');
+ if (!$file->getId()) {
+ return false;
}
+
+ $directory = dirname($filePath);
+ @mkdir($directory, 0777, true);
+
+ $io = new Varien_Io_File();
+ $io->cd($directory);
+
+ $io->streamOpen($filePath);
+ $io->streamLock(true);
+ $io->streamWrite($file->getContent());
+ $io->streamUnlock();
+ $io->streamClose();
+
+ return true;
}
+
/**
* Profile custom options download action
*/
diff --git a/app/code/core/Mage/Sales/etc/adminhtml.xml b/app/code/core/Mage/Sales/etc/adminhtml.xml
index a2127ef37e..18ccf8d906 100644
--- a/app/code/core/Mage/Sales/etc/adminhtml.xml
+++ b/app/code/core/Mage/Sales/etc/adminhtml.xml
@@ -69,6 +69,15 @@
+
+
+
+ Order Statuses
+ adminhtml/sales_order_status
+ 105
+
+
+
@@ -85,6 +94,7 @@
Create
View
+ Send Order Email
Reorder
Edit
Cancel
@@ -153,6 +163,10 @@
+
+ Order Statuses
+ 15
+
diff --git a/app/code/core/Mage/Sales/etc/config.xml b/app/code/core/Mage/Sales/etc/config.xml
index 421d51eee2..e045e03fc8 100644
--- a/app/code/core/Mage/Sales/etc/config.xml
+++ b/app/code/core/Mage/Sales/etc/config.xml
@@ -28,7 +28,7 @@
- 1.4.0.21
+ 1.4.0.23
@@ -378,6 +378,9 @@
sales_flat_order_status_history
+
+
+
@@ -630,6 +633,10 @@
+
Pending
Pending Payment
diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-1.4.0.21-1.4.0.22.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-1.4.0.21-1.4.0.22.php
new file mode 100644
index 0000000000..7c16325469
--- /dev/null
+++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-1.4.0.21-1.4.0.22.php
@@ -0,0 +1,37 @@
+getTable($table);
+ $installer->getConnection()->dropKey($tableName, 'IDX_INCREMENT_ID');
+ $installer->getConnection()->addKey($tableName, 'UNQ_INCREMENT_ID', 'increment_id', 'unique');
+}
diff --git a/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-1.4.0.22-1.4.0.23.php b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-1.4.0.22-1.4.0.23.php
new file mode 100644
index 0000000000..24a90f0242
--- /dev/null
+++ b/app/code/core/Mage/Sales/sql/sales_setup/mysql4-upgrade-1.4.0.22-1.4.0.23.php
@@ -0,0 +1,93 @@
+getTable('sales/order_status');
+$statusStateTable = $installer->getTable('sales/order_status_state');
+$statusLabelTable = $installer->getTable('sales/order_status_label');
+
+$installer->run("
+CREATE TABLE `{$statusTable}` (
+ `status` varchar(32) NOT NULL,
+ `label` varchar(128) NOT NULL,
+ PRIMARY KEY (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+");
+
+$statuses = Mage::getConfig()->getNode('global/sales/order/statuses')->asArray();
+$data = array();
+foreach ($statuses as $code => $info) {
+ $data[] = array(
+ 'status' => $code,
+ 'label' => $info['label']
+ );
+}
+$installer->getConnection()->insertArray($statusTable, array('status', 'label'), $data);
+
+$installer->run("
+CREATE TABLE `{$statusStateTable}` (
+ `status` varchar(32) NOT NULL,
+ `state` varchar(32) NOT NULL,
+ `is_default` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`status`,`state`),
+ CONSTRAINT `FK_SALES_ORDER_STATUS_STATE_STATUS` FOREIGN KEY (`status`)
+ REFERENCES `{$statusTable}` (`status`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+");
+$states = Mage::getConfig()->getNode('global/sales/order/states')->asArray();
+$data = array();
+foreach ($states as $code => $info) {
+ if (isset($info['statuses'])) {
+ foreach ($info['statuses'] as $status => $statusInfo) {
+ $data[] = array(
+ 'status' => $status,
+ 'state' => $code,
+ 'is_default'=> is_array($statusInfo) && isset($statusInfo['@']['default']) ? 1 : 0
+ );
+ }
+ }
+}
+$installer->getConnection()->insertArray(
+ $statusStateTable,
+ array('status', 'state', 'is_default'),
+ $data
+);
+
+$installer->run("
+CREATE TABLE `{$statusLabelTable}` (
+ `status` varchar(32) NOT NULL,
+ `store_id` smallint(5) unsigned NOT NULL,
+ `label` varchar(128) NOT NULL,
+ PRIMARY KEY (`status`,`store_id`),
+ KEY `FK_SALES_ORDER_STATUS_LABEL_STORE` (`store_id`),
+ CONSTRAINT `FK_SALES_ORDER_STATUS_LABEL_STATUS` FOREIGN KEY (`status`)
+ REFERENCES `{$statusTable}` (`status`) ON DELETE CASCADE ON UPDATE CASCADE,
+ CONSTRAINT `FK_SALES_ORDER_STATUS_LABEL_STORE` FOREIGN KEY (`store_id`)
+ REFERENCES `{$installer->getTable('core/store')}` (`store_id`)ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+");
diff --git a/app/code/core/Mage/SalesRule/Model/Quote/Discount.php b/app/code/core/Mage/SalesRule/Model/Quote/Discount.php
index 63b24d5ba1..8e4c705f13 100644
--- a/app/code/core/Mage/SalesRule/Model/Quote/Discount.php
+++ b/app/code/core/Mage/SalesRule/Model/Quote/Discount.php
@@ -51,6 +51,7 @@ public function collect(Mage_Sales_Model_Quote_Address $address)
parent::collect($address);
$quote = $address->getQuote();
$store = Mage::app()->getStore($quote->getStoreId());
+ $this->_calculator->reset($address);
$items = $this->_getAddressItems($address);
if (!count($items)) {
diff --git a/app/code/core/Mage/SalesRule/Model/Validator.php b/app/code/core/Mage/SalesRule/Model/Validator.php
index f3283be909..095805d2cc 100644
--- a/app/code/core/Mage/SalesRule/Model/Validator.php
+++ b/app/code/core/Mage/SalesRule/Model/Validator.php
@@ -50,16 +50,32 @@ class Mage_SalesRule_Model_Validator extends Mage_Core_Model_Abstract
* Defines if method Mage_SalesRule_Model_Validator::process() was already called
* Used for clearing applied rule ids in Quote and in Address
*
+ * @deprecated since 1.4.2.0
* @var bool
*/
protected $_isFirstTimeProcessRun = false;
+ /**
+ * Defines if method Mage_SalesRule_Model_Validator::reset() wasn't called
+ * Used for clearing applied rule ids in Quote and in Address
+ *
+ * @var bool
+ */
+ protected $_isFirstTimeResetRun = true;
+
/**
* Information about item totals for rules.
* @var array
*/
protected $_rulesItemTotals = array();
+ /**
+ * Store information about addresses which cart fixed rule applied for
+ *
+ * @var array
+ */
+ protected $_cartFixedRuleUsedForAddress = array();
+
/**
* Init validator
* Init process load collection of rules for specific website,
@@ -221,6 +237,23 @@ public function processFreeShipping(Mage_Sales_Model_Quote_Item_Abstract $item)
return $this;
}
+ /**
+ * Reset quote and address applied rules
+ *
+ * @param Mage_Sales_Model_Quote_Address $address
+ * @return Mage_SalesRule_Model_Validator
+ */
+ public function reset(Mage_Sales_Model_Quote_Address $address)
+ {
+ if ($this->_isFirstTimeResetRun) {
+ $address->setAppliedRuleIds('');
+ $address->getQuote()->setAppliedRuleIds('');
+ $this->_isFirstTimeResetRun = false;
+ }
+
+ return $this;
+ }
+
/**
* Quote item discount calculation process
*
@@ -235,13 +268,6 @@ public function process(Mage_Sales_Model_Quote_Item_Abstract $item)
$quote = $item->getQuote();
$address = $this->_getAddress($item);
- //Clearing applied rule ids for quote and address
- if ($this->_isFirstTimeProcessRun !== true){
- $this->_isFirstTimeProcessRun = true;
- $quote->setAppliedRuleIds('');
- $address->setAppliedRuleIds('');
- }
-
$itemPrice = $this->_getItemPrice($item);
$baseItemPrice = $this->_getItemBasePrice($item);
@@ -302,29 +328,42 @@ public function process(Mage_Sales_Model_Quote_Item_Abstract $item)
if (empty($this->_rulesItemTotals[$rule->getId()])) {
Mage::throwException(Mage::helper('salesrule')->__('Item totals are not set for rule.'));
}
+
+ /**
+ * prevent applying whole cart discount for every shipping order, but only for first order
+ */
+ if ($quote->getIsMultiShipping()) {
+ $usedForAddressId = $this->getCartFixedRuleUsedForAddress($rule->getId());
+ if ($usedForAddressId && $usedForAddressId != $address->getId()) {
+ break;
+ } else {
+ $this->setCartFixedRuleUsedForAddress($rule->getId(), $address->getId());
+ }
+ }
$cartRules = $address->getCartFixedRules();
if (!isset($cartRules[$rule->getId()])) {
$cartRules[$rule->getId()] = $rule->getDiscountAmount();
}
if ($cartRules[$rule->getId()] > 0) {
- if (1 >= $this->_rulesItemTotals[$rule->getId()]['items_count']) {
+ if ($this->_rulesItemTotals[$rule->getId()]['items_count'] <= 1) {
$quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]);
- $discountAmount = min($itemPrice * $qty, $quoteAmount);
$baseDiscountAmount = min($baseItemPrice * $qty, $cartRules[$rule->getId()]);
} else {
$discountRate = $baseItemPrice * $qty / $this->_rulesItemTotals[$rule->getId()]['base_items_price'];
$maximumItemDiscount = $rule->getDiscountAmount() * $discountRate;
$quoteAmount = $quote->getStore()->convertPrice($maximumItemDiscount);
- $discountAmount = min($itemPrice * $qty, $quoteAmount);
$baseDiscountAmount = min($baseItemPrice * $qty, $maximumItemDiscount);
$this->_rulesItemTotals[$rule->getId()]['items_count']--;
}
+
+ $discountAmount = min($itemPrice * $qty, $quoteAmount);
$cartRules[$rule->getId()] -= $baseDiscountAmount;
}
$address->setCartFixedRules($cartRules);
+
break;
case Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION:
@@ -397,13 +436,16 @@ public function process(Mage_Sales_Model_Quote_Item_Abstract $item)
$this->_maintainAddressCouponCode($address, $rule);
$this->_addDiscountDescription($address, $rule);
+
if ($rule->getStopRulesProcessing()) {
break;
}
}
+
$item->setAppliedRuleIds(join(',',$appliedRuleIds));
$address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds));
$quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds));
+
return $this;
}
@@ -452,7 +494,6 @@ public function processShippingAmount(Mage_Sales_Model_Quote_Address $address)
$discountAmount = $quoteAmount;
$baseDiscountAmount = $rule->getDiscountAmount();
break;
-
case Mage_SalesRule_Model_Rule::CART_FIXED_ACTION:
$cartRules = $address->getCartFixedRules();
if (!isset($cartRules[$rule->getId()])) {
@@ -460,10 +501,17 @@ public function processShippingAmount(Mage_Sales_Model_Quote_Address $address)
}
if ($cartRules[$rule->getId()] > 0) {
$quoteAmount = $quote->getStore()->convertPrice($cartRules[$rule->getId()]);
- $discountAmount = min($shippingAmount-$address->getShippingDiscountAmount(), $quoteAmount);
- $baseDiscountAmount = min($baseShippingAmount-$address->getBaseShippingDiscountAmount(), $cartRules[$rule->getId()]);
+ $discountAmount = min(
+ $shippingAmount-$address->getShippingDiscountAmount(),
+ $quoteAmount
+ );
+ $baseDiscountAmount = min(
+ $baseShippingAmount-$address->getBaseShippingDiscountAmount(),
+ $cartRules[$rule->getId()]
+ );
$cartRules[$rule->getId()] -= $baseDiscountAmount;
}
+
$address->setCartFixedRules($cartRules);
break;
}
@@ -480,12 +528,22 @@ public function processShippingAmount(Mage_Sales_Model_Quote_Address $address)
break;
}
}
+
$address->setAppliedRuleIds($this->mergeIds($address->getAppliedRuleIds(), $appliedRuleIds));
$quote->setAppliedRuleIds($this->mergeIds($quote->getAppliedRuleIds(), $appliedRuleIds));
+
return $this;
}
- public function mergeIds($a1, $a2, $asString=true)
+ /**
+ * Merge two sets of ids
+ *
+ * @param array|string $a1
+ * @param array|string $a2
+ * @param bool $asString
+ * @return array
+ */
+ public function mergeIds($a1, $a2, $asString = true)
{
if (!is_array($a1)) {
$a1 = empty($a1) ? array() : explode(',', $a1);
@@ -500,6 +558,32 @@ public function mergeIds($a1, $a2, $asString=true)
return $a;
}
+ /**
+ * Set information about usage cart fixed rule by quote address
+ *
+ * @param int $ruleId
+ * @param int $itemId
+ * @return void
+ */
+ public function setCartFixedRuleUsedForAddress($ruleId, $itemId)
+ {
+ $this->_cartFixedRuleUsedForAddress[$ruleId] = $itemId;
+ }
+
+ /**
+ * Retrieve information about usage cart fixed rule by quote address
+ *
+ * @param int $ruleId
+ * @return int|null
+ */
+ public function getCartFixedRuleUsedForAddress($ruleId)
+ {
+ if (isset($this->_cartFixedRuleUsedForAddress[$ruleId])) {
+ return $this->_cartFixedRuleUsedForAddress[$ruleId];
+ }
+ return null;
+ }
+
/**
* Calculate quote totals for each rule and save results
*
@@ -524,6 +608,10 @@ public function initTotals($items, Mage_Sales_Model_Quote_Address $address)
$validItemsCount = 0;
foreach ($items as $item) {
+ // For complex product handle only its child items
+ if ($item->getHasChildren()) {
+ continue;
+ }
if (!$rule->getActions()->validate($item)) {
continue;
}
diff --git a/app/code/core/Mage/Sendfriend/controllers/ProductController.php b/app/code/core/Mage/Sendfriend/controllers/ProductController.php
index 4a71dbdd7a..4aefb9de22 100644
--- a/app/code/core/Mage/Sendfriend/controllers/ProductController.php
+++ b/app/code/core/Mage/Sendfriend/controllers/ProductController.php
@@ -119,7 +119,7 @@ public function sendAction()
return;
}
- if ($model->getMaxSendsToFriend()) {
+ if ($model->getMaxSendsToFriend() && $model->isExceedLimit()) {
Mage::getSingleton('catalog/session')->addNotice(
$this->__('The messages cannot be sent more than %d times in an hour', $model->getMaxSendsToFriend())
);
diff --git a/app/code/core/Mage/Shipping/Model/Carrier/Freeshipping.php b/app/code/core/Mage/Shipping/Model/Carrier/Freeshipping.php
index 52e08b9670..ac806704e1 100644
--- a/app/code/core/Mage/Shipping/Model/Carrier/Freeshipping.php
+++ b/app/code/core/Mage/Shipping/Model/Carrier/Freeshipping.php
@@ -53,8 +53,7 @@ public function collectRates(Mage_Shipping_Model_Rate_Request $request)
}
$result = Mage::getModel('shipping/rate_result');
-// $packageValue = $request->getBaseCurrency()->convert($request->getPackageValueWithDiscount(), $request->getPackageCurrency());
- $packageValue = $request->getPackageValueWithDiscount();
+ $packageValue = $request->getPackageValue();
$this->_updateFreeMethodQuote($request);
diff --git a/app/code/core/Mage/Tax/Model/Calculation/Rate.php b/app/code/core/Mage/Tax/Model/Calculation/Rate.php
index 5d321468b5..33157c6a00 100644
--- a/app/code/core/Mage/Tax/Model/Calculation/Rate.php
+++ b/app/code/core/Mage/Tax/Model/Calculation/Rate.php
@@ -91,6 +91,20 @@ protected function _afterSave()
return parent::_afterSave();
}
+ /**
+ * Processing object before delete data
+ *
+ * @return Mage_Core_Model_Abstract
+ * @throws Mage_Core_Exception
+ */
+ protected function _beforeDelete()
+ {
+ if ($this->_isInRule()) {
+ Mage::throwException(Mage::helper('tax')->__('Tax rate cannot be removed. It exists in tax rule'));
+ }
+ return parent::_beforeDelete();
+ }
+
/**
* After rate delete
* redeclared for dispatch tax_settings_change_after event
@@ -159,4 +173,15 @@ public function loadByCode($code)
return $this;
}
+
+ /**
+ * Check if rate exists in tax rule
+ *
+ * @return array
+ */
+ protected function _isInRule()
+ {
+ return $this->getResource()->isInRule($this->getId());
+ }
+
}
diff --git a/app/code/core/Mage/Tax/Model/Mysql4/Calculation.php b/app/code/core/Mage/Tax/Model/Mysql4/Calculation.php
index c04931e2bb..9c671045ae 100644
--- a/app/code/core/Mage/Tax/Model/Mysql4/Calculation.php
+++ b/app/code/core/Mage/Tax/Model/Mysql4/Calculation.php
@@ -173,7 +173,7 @@ protected function _createSearchPostCodeTemplates($postcode)
$strlen = $len;
}
- $strArr = array($postcode);
+ $strArr = array($postcode, $postcode . '*');
if ($strlen > 1) {
for ($i = 1; $i < $strlen; $i++) {
$strArr[] = sprintf('%s*', substr($postcode, 0, - $i));
@@ -247,12 +247,16 @@ protected function _getRates($request)
$selectClone = clone $select;
$select
- ->where("rate.zip_is_range IS NULL")
- ->where("rate.tax_postcode in ('*', '', ?)", $this->_createSearchPostCodeTemplates($postcode));
-
+ ->where("rate.zip_is_range IS NULL");
$selectClone
- ->where("rate.zip_is_range IS NOT NULL")
- ->where("? BETWEEN rate.zip_from AND rate.zip_to", $postcode);
+ ->where("rate.zip_is_range IS NOT NULL");
+
+ if ($request->getPostcode() != '*') {
+ $select
+ ->where("rate.tax_postcode in ('*', '', ?)", $this->_createSearchPostCodeTemplates($postcode));
+ $selectClone
+ ->where("? BETWEEN rate.zip_from AND rate.zip_to", $postcode);
+ }
/**
* @see ZF-7592 issue http://framework.zend.com/issues/browse/ZF-7592
diff --git a/app/code/core/Mage/Tax/Model/Mysql4/Calculation/Rate.php b/app/code/core/Mage/Tax/Model/Mysql4/Calculation/Rate.php
index 8e8f9810ba..4ab1057f40 100644
--- a/app/code/core/Mage/Tax/Model/Mysql4/Calculation/Rate.php
+++ b/app/code/core/Mage/Tax/Model/Mysql4/Calculation/Rate.php
@@ -56,4 +56,20 @@ public function deleteAllRates()
{
$this->_getWriteAdapter()->delete($this->getMainTable());
}
+
+
+ /**
+ * Check if this rate exists in rule
+ *
+ * @param int $rateId
+ * @return array
+ */
+ public function isInRule($rateId)
+ {
+ $adapter = $this->_getReadAdapter();
+ $select = $adapter->select()
+ ->from($this->getTable('tax/tax_calculation'), array('tax_calculation_rate_id'))
+ ->where('tax_calculation_rate_id = ?', $rateId);
+ return $adapter->fetchCol($select);
+ }
}
diff --git a/app/code/core/Mage/Tax/Model/Mysql4/Report/Collection.php b/app/code/core/Mage/Tax/Model/Mysql4/Report/Collection.php
index c9509d3740..8bad157710 100644
--- a/app/code/core/Mage/Tax/Model/Mysql4/Report/Collection.php
+++ b/app/code/core/Mage/Tax/Model/Mysql4/Report/Collection.php
@@ -89,10 +89,7 @@ protected function _initSelect()
{
$this->getSelect()->from($this->getResource()->getMainTable() , $this->_getSelectedColumns());
if (!$this->isTotals() && !$this->isSubTotals()) {
- $this->getSelect()->group(array(
- $this->_periodFormat,
- 'code'
- ));
+ $this->getSelect()->group(array($this->_periodFormat, 'code', 'percent'));
}
if ($this->isSubTotals()) {
diff --git a/app/code/core/Mage/Tax/Model/Mysql4/Report/Tax.php b/app/code/core/Mage/Tax/Model/Mysql4/Report/Tax.php
index 6ac7f87c0c..04a94a6d84 100644
--- a/app/code/core/Mage/Tax/Model/Mysql4/Report/Tax.php
+++ b/app/code/core/Mage/Tax/Model/Mysql4/Report/Tax.php
@@ -80,12 +80,7 @@ public function aggregate($from = null, $to = null)
$select->where($this->_makeConditionFromDateRangeSelect($subSelect, 'e.created_at'));
}
- $select->group(array(
- 'period',
- 'store_id',
- 'code',
- 'order_status'
- ));
+ $select->group(array('period', 'store_id', 'code', 'tax.percent', 'order_status'));
$writeAdapter->query($select->insertFromSelect($this->getMainTable(), array_keys($columns)));
@@ -109,11 +104,7 @@ public function aggregate($from = null, $to = null)
$select->where($this->_makeConditionFromDateRangeSelect($subSelect, 'period'));
}
- $select->group(array(
- 'period',
- 'code',
- 'order_status'
- ));
+ $select->group(array('period', 'code', 'percent', 'order_status'));
$writeAdapter->query($select->insertFromSelect($this->getMainTable(), array_keys($columns)));
diff --git a/app/code/core/Mage/Tax/Model/Mysql4/Report/Updatedat/Collection.php b/app/code/core/Mage/Tax/Model/Mysql4/Report/Updatedat/Collection.php
index 64a65d8403..f02bae9322 100644
--- a/app/code/core/Mage/Tax/Model/Mysql4/Report/Updatedat/Collection.php
+++ b/app/code/core/Mage/Tax/Model/Mysql4/Report/Updatedat/Collection.php
@@ -165,10 +165,7 @@ protected function _initSelect()
}
if (!$this->isTotals() && !$this->isSubTotals()) {
- $select->group(array(
- $this->_periodFormat,
- 'code'
- ));
+ $select->group(array($this->_periodFormat, 'code', 'percent'));
}
if ($this->isSubTotals()) {
diff --git a/app/code/core/Mage/Tax/Model/Sales/Pdf/Grandtotal.php b/app/code/core/Mage/Tax/Model/Sales/Pdf/Grandtotal.php
index 9b73d167c9..86edf598c9 100644
--- a/app/code/core/Mage/Tax/Model/Sales/Pdf/Grandtotal.php
+++ b/app/code/core/Mage/Tax/Model/Sales/Pdf/Grandtotal.php
@@ -50,22 +50,25 @@ public function getTotalsForDisplay()
$tax = $this->getOrder()->formatPriceTxt($this->getSource()->getTaxAmount());
$fontSize = $this->getFontSize() ? $this->getFontSize() : 7;
- $totals = array(
- array(
- 'amount' => $this->getAmountPrefix().$amountExclTax,
- 'label' => Mage::helper('tax')->__('Grand Total (Excl. Tax)') . ':',
- 'font_size' => $fontSize
- ),
- array(
- 'amount' => $this->getAmountPrefix().$tax,
- 'label' => Mage::helper('tax')->__('Tax') . ':',
- 'font_size' => $fontSize
- ),
- array(
- 'amount' => $this->getAmountPrefix().$amount,
- 'label' => Mage::helper('tax')->__('Grand Total (Incl. Tax)') . ':',
- 'font_size' => $fontSize
- ),
+ $totals = array(array(
+ 'amount' => $this->getAmountPrefix().$amountExclTax,
+ 'label' => Mage::helper('tax')->__('Grand Total (Excl. Tax)') . ':',
+ 'font_size' => $fontSize
+ ));
+
+ if ($config->displaySalesFullSummary($store)) {
+ $totals = array_merge($totals, $this->getFullTaxInfo());
+ }
+
+ $totals[] = array(
+ 'amount' => $this->getAmountPrefix().$tax,
+ 'label' => Mage::helper('tax')->__('Tax') . ':',
+ 'font_size' => $fontSize
+ );
+ $totals[] = array(
+ 'amount' => $this->getAmountPrefix().$amount,
+ 'label' => Mage::helper('tax')->__('Grand Total (Incl. Tax)') . ':',
+ 'font_size' => $fontSize
);
return $totals;
}
diff --git a/app/code/core/Mage/Tax/Model/Sales/Pdf/Tax.php b/app/code/core/Mage/Tax/Model/Sales/Pdf/Tax.php
index 91fe56ff00..7c216d8ef8 100644
--- a/app/code/core/Mage/Tax/Model/Sales/Pdf/Tax.php
+++ b/app/code/core/Mage/Tax/Model/Sales/Pdf/Tax.php
@@ -44,6 +44,18 @@ public function getTotalsForDisplay()
if ($config->displaySalesTaxWithGrandTotal($store)) {
return array();
}
- return parent::getTotalsForDisplay();
+
+ $fontSize = $this->getFontSize() ? $this->getFontSize() : 7;
+ $totals = array();
+
+ if ($config->displaySalesFullSummary($store)) {
+ $totals = $this->getFullTaxInfo();
+ }
+
+ $totals = array_merge($totals, parent::getTotalsForDisplay());
+
+ return $totals;
}
+
+
}
diff --git a/app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php b/app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php
index 40ea620b97..a3451d52a3 100644
--- a/app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php
+++ b/app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php
@@ -128,7 +128,7 @@ public function collect(Mage_Sales_Model_Quote_Address $address)
}
foreach ($items as $item) {
- if ($item->getParentItemId()) {
+ if ($item->getParentItem()) {
continue;
}
if ($item->getHasChildren() && $item->isChildrenCalculated()) {
@@ -577,12 +577,12 @@ protected function _recalculateParent(Mage_Sales_Model_Quote_Item_Abstract $item
$rowTotalInclTax = 0;
$baseRowTotalInclTax= 0;
foreach ($item->getChildren() as $child) {
- $price += $child->getOriginalPrice() * $child->getQty();
- $basePrice += $child->getBaseOriginalPrice() * $child->getQty();
+ $price += $child->getPrice() * $child->getQty();
+ $basePrice += $child->getBasePrice() * $child->getQty();
$rowTotal += $child->getRowTotal();
$baseRowTotal += $child->getBaseRowTotal();
- $priceInclTax += $child->getPriceInclTax();
- $basePriceInclTax += $child->getBasePriceInclTax();
+ $priceInclTax += $child->getPriceInclTax() * $child->getQty();
+ $basePriceInclTax += $child->getBasePriceInclTax() * $child->getQty();
$rowTotalInclTax += $child->getRowTotalInclTax();
$baseRowTotalInclTax+= $child->getBaseRowTotalInclTax();
}
diff --git a/app/code/core/Mage/Tax/etc/config.xml b/app/code/core/Mage/Tax/etc/config.xml
index 04f489fa8a..483687d669 100644
--- a/app/code/core/Mage/Tax/etc/config.xml
+++ b/app/code/core/Mage/Tax/etc/config.xml
@@ -28,7 +28,7 @@
- 1.4.0.0
+ 1.4.0.1
diff --git a/app/code/core/Mage/Tax/sql/tax_setup/mysql4-upgrade-1.4.0.0-1.4.0.1.php b/app/code/core/Mage/Tax/sql/tax_setup/mysql4-upgrade-1.4.0.0-1.4.0.1.php
new file mode 100644
index 0000000000..2f78820bd8
--- /dev/null
+++ b/app/code/core/Mage/Tax/sql/tax_setup/mysql4-upgrade-1.4.0.0-1.4.0.1.php
@@ -0,0 +1,39 @@
+getTable('tax/tax_order_aggregated_created');
+$installer->getConnection()->truncate($table);
+$installer->getConnection()->addKey($table, 'UNQ_PERIOD_STORE_CODE_ORDER_STATUS',
+ array('period', 'store_id', 'code', 'percent', 'order_status'), 'unique'
+);
diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php
index 44a249cb8e..c8cec58129 100644
--- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php
+++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php
@@ -599,7 +599,7 @@ public function getCurrencyCode ()
'CLP' => 'CHP', // Chilean Pesos
'TWD' => 'NTD', // New Taiwan Dollars
);
- $currencyCode = Mage::app()->getBaseCurrencyCode();
+ $currencyCode = Mage::app()->getStore()->getBaseCurrencyCode();
return isset($codes[$currencyCode]) ? $codes[$currencyCode] : $currencyCode;
}
diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php
index da8111a10f..d5712ca099 100644
--- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php
+++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php
@@ -47,6 +47,13 @@ class Mage_Usa_Model_Shipping_Carrier_Ups
protected $_defaultCgiGatewayUrl = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi';
+ /**
+ * Base currency rate
+ *
+ * @var double
+ */
+ protected $_baseCurrencyRate;
+
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
if (!$this->getConfigFlag('active')) {
@@ -681,6 +688,23 @@ protected function _getXmlQuotes()
return $this->_parseXmlResponse($xmlResponse);
}
+ /**
+ * Get base currency rate
+ *
+ * @param string $code
+ * @return double
+ */
+ protected function _getBaseCurrencyRate($code)
+ {
+ if (!$this->_baseCurrencyRate) {
+ $this->_baseCurrencyRate = Mage::getModel('directory/currency')
+ ->load($code)
+ ->getAnyRate($this->_request->getBaseCurrency()->getCode());
+ }
+
+ return $this->_baseCurrencyRate;
+ }
+
protected function _parseXmlResponse($xmlResponse)
{
$costArr = array();
@@ -690,7 +714,7 @@ protected function _parseXmlResponse($xmlResponse)
$xml->loadString($xmlResponse);
$arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/ResponseStatusCode/text()");
$success = (int)$arr[0];
- if($success===1){
+ if ($success===1) {
$arr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment");
$allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
@@ -700,6 +724,8 @@ protected function _parseXmlResponse($xmlResponse)
&& $this->getConfigData('shipper_number')
&& !empty($negotiatedArr);
+ $allowedCurrencies = Mage::getModel('directory/currency')->getConfigAllowCurrencies();
+
foreach ($arr as $shipElement){
$code = (string)$shipElement->Service->Code;
#$shipment = $this->getShipmentByCode($code);
@@ -711,8 +737,29 @@ protected function _parseXmlResponse($xmlResponse)
$cost = $shipElement->TotalCharges->MonetaryValue;
}
- $costArr[$code] = $cost;
- $priceArr[$code] = $this->getMethodPrice(floatval($cost),$code);
+ //convert price with Origin country currency code to base currency code
+ $successConversion = true;
+ $responseCurrencyCode = (string) $shipElement->TotalCharges->CurrencyCode;
+ if ($responseCurrencyCode) {
+ if (in_array($responseCurrencyCode, $allowedCurrencies)) {
+ $cost *= $this->_getBaseCurrencyRate($responseCurrencyCode);
+ } else {
+ $errorTitle = Mage::helper('directory')
+ ->__('Can\'t convert rate from "%s-%s".',
+ $responseCurrencyCode,
+ $this->_request->getPackageCurrency()->getCode());
+ $error = Mage::getModel('shipping/rate_result_error');
+ $error->setCarrier('ups');
+ $error->setCarrierTitle($this->getConfigData('title'));
+ $error->setErrorMessage($errorTitle);
+ $successConversion = false;
+ }
+ }
+
+ if ($successConversion) {
+ $costArr[$code] = $cost;
+ $priceArr[$code] = $this->getMethodPrice(floatval($cost),$code);
+ }
}
}
} else {
@@ -721,7 +768,7 @@ protected function _parseXmlResponse($xmlResponse)
$error = Mage::getModel('shipping/rate_result_error');
$error->setCarrier('ups');
$error->setCarrierTitle($this->getConfigData('title'));
- //$error->setErrorMessage($errorTitle);
+ Mage::log($errorTitle);
$error->setErrorMessage($this->getConfigData('specificerrmsg'));
}
}
@@ -735,7 +782,7 @@ protected function _parseXmlResponse($xmlResponse)
if(!isset($errorTitle)){
$errorTitle = Mage::helper('usa')->__('Cannot retrieve shipping rates');
}
- //$error->setErrorMessage($errorTitle);
+ Mage::log($errorTitle);
$error->setErrorMessage($this->getConfigData('specificerrmsg'));
$result->append($error);
} else {
diff --git a/app/code/core/Mage/Weee/Model/Total/Quote/Weee.php b/app/code/core/Mage/Weee/Model/Total/Quote/Weee.php
index 45e20a2e36..d450cdd37b 100644
--- a/app/code/core/Mage/Weee/Model/Total/Quote/Weee.php
+++ b/app/code/core/Mage/Weee/Model/Total/Quote/Weee.php
@@ -35,6 +35,13 @@ class Mage_Weee_Model_Total_Quote_Weee extends Mage_Tax_Model_Sales_Total_Quote_
protected $_helper;
protected $_store;
+ /**
+ * Tax configuration object
+ *
+ * @var Mage_Tax_Model_Config
+ */
+ protected $_config;
+
/**
* Flag which notify what tax amount can be affected by fixed porduct tax
*
@@ -49,6 +56,7 @@ public function __construct()
{
$this->setCode('weee');
$this->_helper = Mage::helper('weee');
+ $this->_config = Mage::getSingleton('tax/config');
}
/**
@@ -215,11 +223,13 @@ protected function _processDiscountSettings($item, $value, $baseValue)
protected function _processTaxSettings($item, $value, $baseValue, $rowValue, $baseRowValue)
{
if ($this->_helper->isTaxable($this->_store) && $rowValue) {
- $item->setExtraTaxableAmount($value)
- ->setBaseExtraTaxableAmount($baseValue)
- ->setExtraRowTaxableAmount($rowValue)
- ->setBaseExtraRowTaxableAmount($baseRowValue)
- ->unsRowTotalInclTax()
+ if ($this->_config->priceIncludesTax($this->_store)) {
+ $item->setExtraTaxableAmount($value)
+ ->setBaseExtraTaxableAmount($baseValue)
+ ->setExtraRowTaxableAmount($rowValue)
+ ->setBaseExtraRowTaxableAmount($baseRowValue);
+ }
+ $item->unsRowTotalInclTax()
->unsBaseRowTotalInclTax()
->unsPriceInclTax()
->unsBasePriceInclTax();
diff --git a/app/code/core/Mage/Wishlist/Block/Abstract.php b/app/code/core/Mage/Wishlist/Block/Abstract.php
index a7aa5955f1..ffc6a3bf32 100644
--- a/app/code/core/Mage/Wishlist/Block/Abstract.php
+++ b/app/code/core/Mage/Wishlist/Block/Abstract.php
@@ -37,7 +37,7 @@ abstract class Mage_Wishlist_Block_Abstract extends Mage_Catalog_Block_Product_A
/**
* Wishlist Product Items Collection
*
- * @var Mage_Wishlist_Model_Mysql4_Product_Collection
+ * @var Mage_Wishlist_Model_Mysql4_Item_Collection
*/
protected $_collection;
@@ -95,7 +95,7 @@ protected function _getWishlist()
/**
* Prepare additional conditions to collection
*
- * @param Mage_Wishlist_Model_Mysql4_Product_Collection $collection
+ * @param Mage_Wishlist_Model_Mysql4_Item_Collection $collection
* @return Mage_Wishlist_Block_Customer_Wishlist
*/
protected function _prepareCollection($collection)
@@ -106,20 +106,14 @@ protected function _prepareCollection($collection)
/**
* Retrieve Wishlist Product Items collection
*
- * @return Mage_Wishlist_Model_Mysql4_Product_Collection
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
*/
public function getWishlistItems()
{
if (is_null($this->_collection)) {
- $attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
$this->_collection = $this->_getWishlist()
- ->getProductCollection()
- ->addAttributeToSelect($attributes)
- ->addStoreFilter()
- ->addUrlRewrite();
-
- Mage::getSingleton('catalog/product_visibility')
- ->addVisibleInSiteFilterToCollection($this->_collection);
+ ->getItemCollection()
+ ->addStoreFilter();
$this->_prepareCollection($this->_collection);
}
@@ -130,8 +124,8 @@ public function getWishlistItems()
/**
* Back compatibility retrieve wishlist product items
*
- * @deprecated
- * @return Mage_Wishlist_Model_Mysql4_Product_Collection
+ * @deprecated after 1.4.2.0
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
*/
public function getWishlist()
{
@@ -141,7 +135,7 @@ public function getWishlist()
/**
* Retrieve URL for Removing item from wishlist
*
- * @param Mage_Catalog_Model_Product $item
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
* @return string
*/
public function getItemRemoveUrl($product)
@@ -152,12 +146,12 @@ public function getItemRemoveUrl($product)
/**
* Retrieve Add Item to shopping cart URL
*
- * @param Mage_Catalog_Model_Product $product
+ * @param string|Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
* @return string
*/
- public function getItemAddToCartUrl($product)
+ public function getItemAddToCartUrl($item)
{
- return $this->_getHelper()->getAddToCartUrl($product);
+ return $this->_getHelper()->getAddToCartUrl($item);
}
/**
@@ -171,6 +165,26 @@ public function getAddToWishlistUrl($product)
return $this->_getHelper()->getAddUrl($product);
}
+ /**
+ * Returns item configure url in wishlist
+ *
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $product
+ *
+ * @return string
+ */
+ public function getItemConfigureUrl($product)
+ {
+ if ($product instanceof Mage_Catalog_Model_Product) {
+ $id = $product->getWishlistItemId();
+ } else {
+ $id = $product->getId();
+ }
+ $params = array('id' => $id);
+
+ return $this->getUrl('wishlist/index/configure/', $params);
+ }
+
+
/**
* Retrieve Escaped Description for Wishlist Item
*
@@ -179,8 +193,8 @@ public function getAddToWishlistUrl($product)
*/
public function getEscapedDescription($item)
{
- if ($item->getWishlistItemDescription()) {
- return $this->htmlEscape($item->getWishlistItemDescription());
+ if ($item->getDescription()) {
+ return $this->htmlEscape($item->getDescription());
}
return ' ';
}
@@ -193,7 +207,7 @@ public function getEscapedDescription($item)
*/
public function hasDescription($item)
{
- return trim($item->getWishlistItemDescription()) != '';
+ return trim($item->getDescription()) != '';
}
/**
@@ -215,7 +229,7 @@ public function getFormatedDate($date)
public function isSaleable()
{
foreach ($this->getWishlistItems() as $item) {
- if ($item->isSaleable()) {
+ if ($item->getProduct()->isSaleable()) {
return true;
}
}
@@ -233,6 +247,21 @@ public function getWishlistItemsCount()
return $this->getWishlistItems()->count();
}
+ /**
+ * Retrieve Qty from item
+ *
+ * @param Mage_Wishlist_Model_Item|Mage_Catalog_Model_Product $item
+ * @return float
+ */
+ public function getQty($item)
+ {
+ $qty = $item->getQty() * 1;
+ if (!$qty) {
+ $qty = 1;
+ }
+ return $qty;
+ }
+
/**
* Check is the wishlist has items
*
diff --git a/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php b/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php
index f73647e712..e590db7a41 100644
--- a/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php
+++ b/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php
@@ -37,13 +37,15 @@ class Mage_Wishlist_Block_Customer_Sidebar extends Mage_Wishlist_Block_Abstract
/**
* Add sidebar conditions to collection
*
- * @param Mage_Wishlist_Model_Mysql4_Product_Collection $collection
+ * @param Mage_Wishlist_Model_Mysql4_Item_Collection $collection
* @return Mage_Wishlist_Block_Customer_Wishlist
*/
protected function _prepareCollection($collection)
{
- $collection->setPage(1, 3);
- $collection->addAttributeToSort('added_at', 'desc');
+ $collection->setCurPage(1)
+ ->setPageSize(3)
+ ->setInStockFilter(true)
+ ->addWishListSortOrder('added_at', 'desc');
return $this;
}
@@ -76,7 +78,7 @@ public function getCanDisplayWishlist()
* Retrieve URL for removing item from wishlist
*
* @deprecated back compatibility alias for getItemRemoveUrl
- * @param Mage_Wishlist_Model_Item $item
+ * @param Mage_Wishlist_Model_Item $item
* @return string
*/
public function getRemoveItemUrl($item)
@@ -88,7 +90,7 @@ public function getRemoveItemUrl($item)
* Retrieve URL for adding product to shopping cart and remove item from wishlist
*
* @deprecated
- * @param Mage_Catalog_Model_Product $product
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $product
* @return string
*/
public function getAddToCartItemUrl($product)
diff --git a/app/code/core/Mage/Wishlist/Block/Customer/Wishlist.php b/app/code/core/Mage/Wishlist/Block/Customer/Wishlist.php
index 01fc7d8984..ff92a26675 100644
--- a/app/code/core/Mage/Wishlist/Block/Customer/Wishlist.php
+++ b/app/code/core/Mage/Wishlist/Block/Customer/Wishlist.php
@@ -34,6 +34,32 @@
*/
class Mage_Wishlist_Block_Customer_Wishlist extends Mage_Wishlist_Block_Abstract
{
+ /*
+ * List of product type configuration to render options list
+ */
+ protected $_optionsCfg = array();
+
+ /*
+ * Constructor of block - adds default renderer for product configuration
+ */
+ public function _construct()
+ {
+ parent::_construct();
+ $this->addOptionsRenderCfg('default', 'catalog/product_configuration', 'wishlist/options_list.phtml');
+ }
+
+ /**
+ * Add wishlist conditions to collection
+ *
+ * @param Mage_Wishlist_Model_Mysql4_Item_Collection $collection
+ * @return Mage_Wishlist_Block_Customer_Wishlist
+ */
+ protected function _prepareCollection($collection)
+ {
+ $collection->setInStockFilter(true)->setOrder('added_at', 'ASC');
+ return $this;
+ }
+
/**
* Preparing global layout
*
@@ -60,4 +86,119 @@ public function getBackUrl()
}
return $this->getUrl('customer/account/');
}
+
+ /**
+ * Sets all options render configurations
+ *
+ * @param null|array $optionCfg
+ * @return Mage_Wishlist_Block_Customer_Wishlist
+ */
+ public function setOptionsRenderCfgs($optionCfg)
+ {
+ $this->_optionsCfg = $optionCfg;
+ return $this;
+ }
+
+ /**
+ * Returns all options render configurations
+ *
+ * @return array
+ */
+ public function getOptionsRenderCfgs()
+ {
+ return $this->_optionsCfg;
+ }
+
+ /*
+ * Adds config for rendering product type options
+ * If template is null - later default will be used
+ *
+ * @param string $productType
+ * @param string $helperName
+ * @param null|string $template
+ * @return Mage_Wishlist_Block_Customer_Wishlist
+ */
+ public function addOptionsRenderCfg($productType, $helperName, $template = null)
+ {
+ $this->_optionsCfg[$productType] = array('helper' => $helperName, 'template' => $template);
+ return $this;
+ }
+
+ /**
+ * Returns html for showing item options
+ *
+ * @param string $productType
+ * @return array|null
+ */
+ public function getOptionsRenderCfg($productType)
+ {
+ if (isset($this->_optionsCfg[$productType])) {
+ return $this->_optionsCfg[$productType];
+ } elseif (isset($this->_optionsCfg['default'])) {
+ return $this->_optionsCfg['default'];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns html for showing item options
+ *
+ * @param Mage_Wishlist_Model_Item $item
+ * @return string
+ */
+ public function getDetailsHtml(Mage_Wishlist_Model_Item $item)
+ {
+ $cfg = $this->getOptionsRenderCfg($item->getProduct()->getTypeId());
+ if (!$cfg) {
+ return '';
+ }
+
+ $helper = Mage::helper($cfg['helper']);
+ if (!($helper instanceof Mage_Catalog_Helper_Product_Configuration_Interface)) {
+ Mage::throwException($this->__("Helper for wishlist options rendering doesn't implement required interface."));
+ }
+
+ $block = $this->getChild('item_options');
+ if (!$block) {
+ return '';
+ }
+
+ if ($cfg['template']) {
+ $template = $cfg['template'];
+ } else {
+ $cfgDefault = $this->getOptionsRenderCfg('default');
+ if (!$cfgDefault) {
+ return '';
+ }
+ $template = $cfgDefault['template'];
+ }
+
+ return $block->setTemplate($template)
+ ->setOptionList($helper->getOptions($item))
+ ->toHtml();
+ }
+
+ /**
+ * Returns default description to show in textarea field
+ *
+ * @param Mage_Wishlist_Model_Item $item
+ * @return string
+ */
+ public function getCommentValue(Mage_Wishlist_Model_Item $item)
+ {
+ return $this->hasDescription($item) ? $this->getEscapedDescription($item) : Mage::helper('wishlist')->defaultCommentString();
+ }
+
+ /**
+ * Returns qty to show visually to user
+ *
+ * @param Mage_Wishlist_Model_Item $item
+ * @return float
+ */
+ public function getAddToCartQty(Mage_Wishlist_Model_Item $item)
+ {
+ $qty = $this->getQty($item);
+ return $qty ? $qty : 1;
+ }
}
diff --git a/app/code/core/Mage/Wishlist/Block/Customer/Wishlist/Item/Options.php b/app/code/core/Mage/Wishlist/Block/Customer/Wishlist/Item/Options.php
new file mode 100644
index 0000000000..6770c96015
--- /dev/null
+++ b/app/code/core/Mage/Wishlist/Block/Customer/Wishlist/Item/Options.php
@@ -0,0 +1,36 @@
+
+ */
+class Mage_Wishlist_Block_Customer_Wishlist_Item_Options extends Mage_Wishlist_Block_Abstract
+{
+}
diff --git a/app/code/core/Mage/Wishlist/Block/Item/Configure.php b/app/code/core/Mage/Wishlist/Block/Item/Configure.php
new file mode 100644
index 0000000000..2f1032b381
--- /dev/null
+++ b/app/code/core/Mage/Wishlist/Block/Item/Configure.php
@@ -0,0 +1,56 @@
+_localFilter) {
+ $this->_localFilter = new Zend_Filter_LocalizedToNormalized(array('locale' => Mage::app()->getLocale()->getLocaleCode()));
+ }
+ $qty = $this->_localFilter->filter($qty);
+ if ($qty < 0) {
+ $qty = null;
+ }
+ return $qty;
+ }
+
/**
* Retrieve current wishlist instance
*
@@ -58,14 +82,26 @@ public function allcartAction()
$addedItems = array();
$notSalable = array();
$hasOptions = array();
- $isGrouped = array();
$cart = Mage::getSingleton('checkout/cart');
- $collection = $wishlist->getItemCollection();
+ $collection = $wishlist->getItemCollection()
+ ->setVisibilityFilter();
+ $qtys = $this->getRequest()->getParam('qty');
foreach ($collection as $item) {
/** @var Mage_Wishlist_Model_Item */
try {
+ $item->unsProduct();
+
+ // Set qty
+ if (isset($qtys[$item->getId()])) {
+ $qty = $this->_processLocalizedQty($qtys[$item->getId()]);
+ if ($qty) {
+ $item->setQty($qty);
+ }
+ }
+
+ // Add to cart
if ($item->addToCart($cart, $isOwner)) {
$addedItems[] = $item->getProduct();
}
@@ -75,10 +111,8 @@ public function allcartAction()
$notSalable[] = $item;
} else if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_HAS_REQUIRED_OPTIONS) {
$hasOptions[] = $item;
- } else if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_IS_GROUPED_PRODUCT) {
- $isGrouped[] = $item;
} else {
- $messages[] = $e->getMessage();
+ $messages[] = $this->__('%s for "%s".', trim($e->getMessage(), '.'), $item->getProduct()->getName());
}
} catch (Exception $e) {
Mage::logException($e);
@@ -107,14 +141,6 @@ public function allcartAction()
$messages[] = Mage::helper('wishlist')->__('Unable to add the following product(s) to shopping cart: %s.', join(', ', $products));
}
- if ($isGrouped) {
- $products = array();
- foreach ($isGrouped as $item) {
- $products[] = '"' . $item->getProduct()->getName() . '"';
- }
- $messages[] = Mage::helper('wishlist')->__('Product(s) %s are grouped. Each of them can be added to cart separately only.', join(', ', $products));
- }
-
if ($hasOptions) {
$products = array();
foreach ($hasOptions as $item) {
@@ -131,12 +157,6 @@ public function allcartAction()
$item->delete();
}
$redirectUrl = $item->getProductUrl();
- } elseif ($isMessageSole && count($isGrouped) == 1) {
- $item = $isGrouped[0];
- if ($isOwner) {
- $item->delete();
- }
- $redirectUrl = $item->getProductUrl();
} else {
$wishlistSession = Mage::getSingleton('wishlist/session');
foreach ($messages as $message) {
diff --git a/app/code/core/Mage/Wishlist/Helper/Data.php b/app/code/core/Mage/Wishlist/Helper/Data.php
index 757e411c32..778d7da9fa 100644
--- a/app/code/core/Mage/Wishlist/Helper/Data.php
+++ b/app/code/core/Mage/Wishlist/Helper/Data.php
@@ -48,6 +48,13 @@ class Mage_Wishlist_Helper_Data extends Mage_Core_Helper_Abstract
*/
protected $_productCollection = null;
+ /**
+ * Wishlist Items Collection
+ *
+ * @var Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ protected $_wishlistItemCollection = null;
+
/**
* Retrieve customer login status
*
@@ -111,6 +118,9 @@ public function getItemCount()
*
* alias for getProductCollection
*
+ * @deprecated after 1.4.2.0
+ * @see Mage_Wishlist_Model_Wishlist::getItemCollection()
+ *
* @return Mage_Wishlist_Model_Mysql4_Product_Collection
*/
public function getItemCollection()
@@ -118,9 +128,28 @@ public function getItemCollection()
return $this->getProductCollection();
}
+
+ /**
+ * Retrieve wishlist items collection
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function getWishlistItemCollection()
+ {
+ if (is_null($this->_wishlistItemCollection)) {
+ $this->_wishlistItemCollection = $this->getWishlist()
+ ->getItemCollection();
+ }
+ return $this->_wishlistItemCollection;
+ }
+
+
/**
* Retrieve wishlist product items collection
*
+ * @deprecated after 1.4.2.0
+ * @see Mage_Wishlist_Model_Wishlist::getItemCollection()
+ *
* @return Mage_Wishlist_Model_Mysql4_Product_Collection
*/
public function getProductCollection()
@@ -144,12 +173,18 @@ public function getProductCollection()
protected function _getUrlStore($item)
{
$storeId = null;
- if ($item instanceof Mage_Catalog_Model_Product) {
- if ($item->isVisibleInSiteVisibility()) {
- $storeId = $item->getStoreId();
+ $product = null;
+ if ($item instanceof Mage_Wishlist_Model_Item) {
+ $product = $item->getProduct();
+ } elseif ($item instanceof Mage_Catalog_Model_Product) {
+ $product = $item;
+ }
+ if ($product) {
+ if ($product->isVisibleInSiteVisibility()) {
+ $storeId = $product->getStoreId();
}
- else if ($item->hasUrlDataObject()) {
- $storeId = $item->getUrlDataObject()->getStoreId();
+ else if ($product->hasUrlDataObject()) {
+ $storeId = $product->getUrlDataObject()->getStoreId();
}
}
return Mage::app()->getStore($storeId);
@@ -168,6 +203,19 @@ public function getRemoveUrl($item)
));
}
+ /**
+ * Retrieve URL for removing item from wishlist
+ *
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
+ * @return string
+ */
+ public function getConfigureUrl($item)
+ {
+ return $this->_getUrl('wishlist/index/configure', array(
+ 'item' => $item->getWishlistItemId()
+ ));
+ }
+
/**
* Retrieve url for adding product to wishlist
*
@@ -179,6 +227,30 @@ public function getAddUrl($item)
return $this->getAddUrlWithParams($item);
}
+ /**
+ * Retrieve url for updating product in wishlist
+ *
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $product
+ * @return string|boolean
+ */
+ public function getUpdateUrl($item)
+ {
+ $itemId = null;
+ if ($item instanceof Mage_Catalog_Model_Product) {
+ $itemId = $item->getWishlistItemId();
+ }
+ if ($item instanceof Mage_Wishlist_Model_Item) {
+ $itemId = $item->getId();
+ }
+
+ if ($itemId) {
+ $params['id'] = $itemId;
+ return $this->_getUrlStore($item)->getUrl('wishlist/index/updateItemOptions', $params);
+ }
+
+ return false;
+ }
+
/**
* Retrieve url for adding product to wishlist with params
*
@@ -207,22 +279,23 @@ public function getAddUrlWithParams($item, array $params = array())
/**
* Retrieve URL for adding item to shoping cart
*
- * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
+ * @param string|Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
* @return string
*/
public function getAddToCartUrl($item)
{
- $urlParamName = Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED;
$continueUrl = Mage::helper('core')->urlEncode(Mage::getUrl('*/*/*', array(
'_current' => true,
'_use_rewrite' => true,
'_store_to_url' => true,
)));
- return $this->_getUrlStore($item)->getUrl('wishlist/index/cart', array(
- 'item' => $item->getWishlistItemId(),
- $urlParamName => $continueUrl
- ));
+ $urlParamName = Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED;
+ $params = array(
+ 'item' => is_string($item) ? $item : $item->getWishlistItemId(),
+ $urlParamName => $continueUrl
+ );
+ return $this->_getUrlStore($item)->getUrl('wishlist/index/cart', $params);
}
/**
@@ -327,7 +400,9 @@ public function calculate()
$count = 0;
}
else {
- $count = $this->getProductCollection()
+ $count = $this->getWishlistItemCollection()
+ /* Price data is added to consider item stock status using price index */
+// ->addPriceData()
->getSize();
}
Mage::getSingleton('customer/session')->setWishlistItemCount($count);
diff --git a/app/code/core/Mage/Wishlist/Model/Item.php b/app/code/core/Mage/Wishlist/Model/Item.php
index 7c7631c4d3..6fb7206da4 100644
--- a/app/code/core/Mage/Wishlist/Model/Item.php
+++ b/app/code/core/Mage/Wishlist/Model/Item.php
@@ -33,10 +33,17 @@
* @author Magento Core Team
*/
class Mage_Wishlist_Model_Item extends Mage_Core_Model_Abstract
+ implements Mage_Catalog_Model_Product_Configuration_Item_Interface
{
const EXCEPTION_CODE_NOT_SALABLE = 901;
const EXCEPTION_CODE_HAS_REQUIRED_OPTIONS = 902;
- const EXCEPTION_CODE_IS_GROUPED_PRODUCT = 903;
+ const EXCEPTION_CODE_IS_GROUPED_PRODUCT = 903; // deprecated after 1.4.2.0, because we can store product configuration and add grouped products
+
+ /**
+ * Custom path to download attached file
+ * @var string
+ */
+ protected $_customOptionDownloadUrl = 'wishlist/index/downloadCustomOption';
/**
* Prefix of model events names
@@ -54,6 +61,33 @@ class Mage_Wishlist_Model_Item extends Mage_Core_Model_Abstract
*/
protected $_eventObject = 'item';
+ /**
+ * Item options array
+ *
+ * @var array
+ */
+ protected $_options = array();
+
+ /**
+ * Item options by code cache
+ *
+ * @var array
+ */
+ protected $_optionsByCode = array();
+
+ /**
+ * Not Represent options
+ *
+ * @var array
+ */
+ protected $_notRepresentOptions = array('info_buyRequest');
+
+ /**
+ * Flag stating that options were successfully saved
+ *
+ */
+ protected $_flagOptionsSaved = null;
+
/**
* Initialize resource model
*
@@ -73,6 +107,108 @@ protected function _getResource()
return parent::_getResource();
}
+ /**
+ * Check if two options array are identical
+ *
+ * @param array $options1
+ * @param array $options2
+ * @return bool
+ */
+ protected function _compareOptions($options1, $options2)
+ {
+ $skipOptions = array('id', 'qty', 'return_url');
+ foreach ($options1 as $code => $value) {
+ if (in_array($code, $skipOptions)) {
+ continue;
+ }
+ if (!isset($options2[$code]) || $options2[$code] != $value) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Register option code
+ *
+ * @param Mage_Wishlist_Model_Item_Option $option
+ * @return Mage_Wishlist_Model_Item
+ */
+ protected function _addOptionCode($option)
+ {
+ if (!isset($this->_optionsByCode[$option->getCode()])) {
+ $this->_optionsByCode[$option->getCode()] = $option;
+ }
+ else {
+ Mage::throwException(Mage::helper('sales')->__('An item option with code %s already exists.', $option->getCode()));
+ }
+ return $this;
+ }
+
+ /**
+ * Checks that item model has data changes.
+ * Call save item options if model isn't need to save in DB
+ *
+ * @return boolean
+ */
+ protected function _hasModelChanged()
+ {
+ if (!$this->hasDataChanges()) {
+ return false;
+ }
+
+ return $this->_getResource()->hasDataChanged($this);
+ }
+
+ /**
+ * Save item options
+ *
+ * @return Mage_Wishlist_Model_Item
+ */
+ protected function _saveItemOptions()
+ {
+ foreach ($this->_options as $index => $option) {
+ if ($option->isDeleted()) {
+ $option->delete();
+ unset($this->_options[$index]);
+ unset($this->_optionsByCode[$option->getCode()]);
+ } else {
+ $option->save();
+ }
+ }
+
+ $this->_flagOptionsSaved = true; // Report to watchers that options were saved
+
+ return $this;
+ }
+
+ /**
+ * Save model plus its options
+ * Ensures saving options in case when resource model was not changed
+ */
+ public function save()
+ {
+ $hasDataChanges = $this->hasDataChanges();
+ $this->_flagOptionsSaved = false;
+
+ parent::save();
+
+ if ($hasDataChanges && !$this->_flagOptionsSaved) {
+ $this->_saveItemOptions();
+ }
+ }
+
+ /**
+ * Save item options after item saved
+ *
+ * @return Mage_Wishlist_Model_Item
+ */
+ protected function _afterSave()
+ {
+ $this->_saveItemOptions();
+ return parent::_afterSave();
+ }
+
/**
* Validate wish list item data
*
@@ -166,10 +302,17 @@ public function getProduct()
}
$product = Mage::getModel('catalog/product')
+ ->setStoreId($this->getStoreId())
->load($this->getProductId());
$this->setData('product', $product);
}
+
+ /**
+ * Reset product final price because it related to custom options
+ */
+ $product->setFinalPrice(null);
+ $product->setCustomOptions($this->_optionsByCode);
return $product;
}
@@ -188,11 +331,6 @@ public function addToCart(Mage_Checkout_Model_Cart $cart, $delete = false)
{
$product = $this->getProduct();
- if (Mage_Catalog_Model_Product_Type::TYPE_GROUPED == $product->getTypeId()) {
- throw new Mage_Core_Exception(null, self::EXCEPTION_CODE_IS_GROUPED_PRODUCT);
- }
-
- $product->setQty(1);
$storeId = $this->getStoreId();
if ($product->getStatus() != Mage_Catalog_Model_Product_Status::STATUS_ENABLED) {
@@ -219,11 +357,9 @@ public function addToCart(Mage_Checkout_Model_Cart $cart, $delete = false)
throw new Mage_Core_Exception(null, self::EXCEPTION_CODE_NOT_SALABLE);
}
- if ($product->getTypeInstance(true)->hasRequiredOptions($product)) {
- throw new Mage_Core_Exception(null, self::EXCEPTION_CODE_HAS_REQUIRED_OPTIONS);
- }
+ $buyRequest = $this->getBuyRequest();
- $cart->addProduct($product);
+ $cart->addProduct($product, $buyRequest);
if (!$product->isVisibleInSiteVisibility()) {
$cart->getQuote()->getItemByProduct($product)->setStoreId($storeId);
}
@@ -253,4 +389,261 @@ public function getProductUrl()
return $product->getUrlModel()->getUrl($product, array('_query' => $query));
}
+
+ /**
+ * Returns formatted buy request - object, holding request received from
+ * product view page with keys and options for configured product
+ *
+ * @return Varien_Object
+ */
+ public function getBuyRequest()
+ {
+ $option = $this->getOptionByCode('info_buyRequest');
+ if ($option) {
+ $buyRequest = new Varien_Object(unserialize($option->getValue()));
+ } else {
+ $buyRequest = new Varien_Object();
+ }
+
+ $buyRequest->setQty($this->getQty()*1);
+ return $buyRequest;
+ }
+
+ /**
+ * Set buy request - object, holding request received from
+ * product view page with keys and options for configured product
+ * @param Varien_Object $buyRequest
+ * @return Mage_Wishlist_Model_Item
+ */
+ public function setBuyRequest($buyRequest)
+ {
+ $buyRequest->setId($this->getId());
+
+ $_buyRequest = serialize($buyRequest->getData());
+ $this->setData('buy_request', $_buyRequest);
+ return $this;
+ }
+
+ /**
+ * Check product representation in item
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param Varien_Object $buyRequest
+ * @return bool
+ */
+ public function isRepresent($product, $buyRequest)
+ {
+ if ($this->getProductId() != $product->getId()) {
+ return false;
+ }
+
+ $selfOptions = $this->getBuyRequest()->getData();
+
+ if (empty($buyRequest) && !empty($selfOptions)) {
+ return false;
+ }
+ if (empty($selfOptions) && !empty($buyRequest)) {
+ if (!$product->isComposite()){
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ $requestArray = $buyRequest->getData();
+
+ if(!$this->_compareOptions($requestArray, $selfOptions)){
+ return false;
+ }
+ if(!$this->_compareOptions($selfOptions, $requestArray)){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check product representation in item
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return bool
+ */
+ public function representProduct($product)
+ {
+ $itemProduct = $this->getProduct();
+ if ($itemProduct->getId() != $product->getId()) {
+ return false;
+ }
+
+ $itemOptions = $this->getOptionsByCode();
+ $productOptions = $product->getCustomOptions();
+
+ if(!$this->compareOptions($itemOptions, $productOptions)){
+ return false;
+ }
+ if(!$this->compareOptions($productOptions, $itemOptions)){
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check if two options array are identical
+ * First options array is prerogative
+ * Second options array checked against first one
+ *
+ * @param array $options1
+ * @param array $options2
+ * @return bool
+ */
+ public function compareOptions($options1, $options2)
+ {
+ foreach ($options1 as $option) {
+ $code = $option->getCode();
+ if (in_array($code, $this->_notRepresentOptions )) {
+ continue;
+ }
+ if ( !isset($options2[$code])
+ || ($options2[$code]->getValue() === null)
+ || $options2[$code]->getValue() != $option->getValue()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Initialize item options
+ *
+ * @param array $options
+ * @return Mage_Wishlist_Model_Item
+ */
+ public function setOptions($options)
+ {
+ foreach ($options as $option) {
+ $this->addOption($option);
+ }
+ return $this;
+ }
+
+ /**
+ * Get all item options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Get all item options as array with codes in array key
+ *
+ * @return array
+ */
+ public function getOptionsByCode()
+ {
+ return $this->_optionsByCode;
+ }
+
+ /**
+ * Add option to item
+ *
+ * @param Mage_Wishlist_Model_Item_Option $option
+ * @return Mage_Wishlist_Model_Item
+ */
+ public function addOption($option)
+ {
+ if (is_array($option)) {
+ $option = Mage::getModel('wishlist/item_option')->setData($option)
+ ->setItem($this);
+ } else if ($option instanceof Mage_Wishlist_Model_Item_Option) {
+ $option->setItem($this);
+ } else if ($option instanceof Varien_Object) {
+ $option = Mage::getModel('wishlist/item_option')->setData($option->getData())
+ ->setProduct($option->getProduct())
+ ->setItem($this);
+ } else {
+ Mage::throwException(Mage::helper('sales')->__('Invalid item option format.'));
+ }
+
+ $exOption = $this->getOptionByCode($option->getCode());
+ if ($exOption) {
+ $exOption->addData($option->getData());
+ } else {
+ $this->_addOptionCode($option);
+ $this->_options[] = $option;
+ }
+ return $this;
+ }
+
+ /**
+ *Remove option from item options
+ *
+ * @param string $code
+ * @return Mage_Wishlist_Model_Item
+ */
+ public function removeOption($code)
+ {
+ $option = $this->getOptionByCode($code);
+ if ($option) {
+ $option->isDeleted(true);
+ }
+ return $this;
+ }
+
+ /**
+ * Get item option by code
+ *
+ * @param string $code
+ * @return Mage_Wishlist_Model_Item_Option || null
+ */
+ public function getOptionByCode($code)
+ {
+ if (isset($this->_optionsByCode[$code]) && !$this->_optionsByCode[$code]->isDeleted()) {
+ return $this->_optionsByCode[$code];
+ }
+ return null;
+ }
+
+ /**
+ * Returns whether Qty field is valid for this item
+ *
+ * @return bool
+ */
+ public function canHaveQty()
+ {
+ $product = $this->getProduct();
+ return $product->getTypeId() != Mage_Catalog_Model_Product_Type_Grouped::TYPE_CODE;
+ }
+
+ /**
+ * Get current custom option download url
+ */
+ public function getCustomDownloadUrl()
+ {
+ return $this->_customOptionDownloadUrl;
+ }
+
+ /**
+ * Sets custom option download url
+ */
+ public function setCustomDownloadUrl($url)
+ {
+ $this->_customOptionDownloadUrl = $url;
+ }
+
+ /**
+ * Returns special download params (if needed) for custom option with type = 'file'.
+ * Needed to implement Mage_Catalog_Model_Product_Configuration_Item_Interface.
+ *
+ * We have to customize only controller url, so return it.
+ *
+ * @return null|Varien_Object
+ */
+ public function getFileDownloadParams()
+ {
+ $params = new Varien_Object();
+ $params->setUrl($this->_customOptionDownloadUrl);
+ return $params;
+ }
}
diff --git a/app/code/core/Mage/Wishlist/Model/Item/Option.php b/app/code/core/Mage/Wishlist/Model/Item/Option.php
new file mode 100644
index 0000000000..bcf210cd63
--- /dev/null
+++ b/app/code/core/Mage/Wishlist/Model/Item/Option.php
@@ -0,0 +1,142 @@
+
+ */
+class Mage_Wishlist_Model_Item_Option extends Mage_Core_Model_Abstract
+ implements Mage_Catalog_Model_Product_Configuration_Item_Option_Interface
+{
+ protected $_item;
+ protected $_product;
+
+ /**
+ * Initialize resource model
+ */
+ protected function _construct()
+ {
+ $this->_init('wishlist/item_option');
+ }
+
+ /**
+ * Checks that item option model has data changes
+ *
+ * @return boolean
+ */
+ protected function _hasModelChanged()
+ {
+ if (!$this->hasDataChanges()) {
+ return false;
+ }
+
+ return $this->_getResource()->hasDataChanged($this);
+ }
+
+ /**
+ * Set quote item
+ *
+ * @param Mage_Wishlist_Model_Item $item
+ * @return Mage_Wishlist_Model_Item_Option
+ */
+ public function setItem($item)
+ {
+ $this->setWishlistItemId($item->getId());
+ $this->_item = $item;
+ return $this;
+ }
+
+ /**
+ * Get option item
+ *
+ * @return Mage_Wishlist_Model_Item
+ */
+ public function getItem()
+ {
+ return $this->_item;
+ }
+
+ /**
+ * Set option product
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return Mage_Wishlist_Model_Item_Option
+ */
+ public function setProduct($product)
+ {
+ $this->setProductId($product->getId());
+ $this->_product = $product;
+ return $this;
+ }
+
+ /**
+ * Get option product
+ *
+ * @return Mage_Catalog_Model_Product
+ */
+ public function getProduct()
+ {
+ return $this->_product;
+ }
+
+ /**
+ * Get option value
+ *
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->_getData('value');
+ }
+
+ /**
+ * Initialize item identifier before save data
+ *
+ * @return Mage_Wishlist_Model_Item_Option
+ */
+ protected function _beforeSave()
+ {
+ if ($this->getItem()) {
+ $this->setWishlistItemId($this->getItem()->getId());
+ }
+ return parent::_beforeSave();
+ }
+
+ /**
+ * Clone option object
+ *
+ * @return Mage_Wishlist_Model_Item_Option
+ */
+ public function __clone()
+ {
+ $this->setId(null);
+ $this->_item = null;
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Collection.php b/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Collection.php
index c81f0573d4..271b7aa853 100644
--- a/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Collection.php
+++ b/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Collection.php
@@ -34,6 +34,48 @@
*/
class Mage_Wishlist_Model_Mysql4_Item_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
{
+ /**
+ * Product Visibility Filter to product collection flag
+ *
+ * @var bool
+ */
+ protected $_productVisible = false;
+
+ /**
+ * Product Salable Filter to product collection flag
+ *
+ * @var bool
+ */
+ protected $_productSalable = false;
+
+ /**
+ * If product out of stock, its item will be removed after load
+ *
+ * @var bool
+ */
+ protected $_productInStock = false;
+
+ /**
+ * Product Ids array
+ *
+ * @var array
+ */
+ protected $_productIds = array();
+
+ /**
+ * Store Ids array
+ *
+ * @var array
+ */
+ protected $_storeIds = array();
+
+ /**
+ * Add days in whishlist filter of product collection
+ *
+ * @var boolean
+ */
+ protected $_addDaysInWishlist = false;
+
/**
* Initialize resource model for collection
*
@@ -43,6 +85,108 @@ public function _construct()
$this->_init('wishlist/item');
}
+ /**
+ * After load processing
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ protected function _afterLoad()
+ {
+ parent::_afterLoad();
+
+ /**
+ * Assign products
+ */
+ $this->_assignOptions();
+ $this->_assignProducts();
+ $this->resetItemsDataChanged();
+
+
+ $this->getPageSize();
+
+ return $this;
+ }
+
+ /**
+ * Add options to items
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ protected function _assignOptions()
+ {
+ $itemIds = array_keys($this->_items);
+ $optionCollection = Mage::getModel('wishlist/item_option')->getCollection()
+ ->addItemFilter($itemIds);
+ foreach ($this as $item) {
+ $item->setOptions($optionCollection->getOptionsByItem($item));
+ }
+ $productIds = $optionCollection->getProductIds();
+ $this->_productIds = array_merge($this->_productIds, $productIds);
+
+ return $this;
+ }
+
+ /**
+ * Add products to items and item options
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ protected function _assignProducts()
+ {
+ Varien_Profiler::start('WISHLIST:'.__METHOD__);
+ $productIds = array();
+ foreach ($this as $item) {
+ $productIds[$item->getProductId()]=1;
+ }
+ $this->_productIds = array_merge($this->_productIds, array_keys($productIds));
+ $attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
+
+ $productCollection = Mage::getModel('catalog/product')->getCollection()
+ ->addIdFilter($this->_productIds)
+ ->addAttributeToSelect($attributes)
+ ->addOptionsToResult()
+ ->addPriceData()
+ ->addUrlRewrite();
+
+ if ($this->_productVisible) {
+ Mage::getSingleton('catalog/product_visibility')->addVisibleInSiteFilterToCollection($productCollection);
+ }
+ if ($this->_productSalable) {
+ $productCollection = Mage::helper('adminhtml/sales')->applySalableProductTypesFilter($productCollection);
+ }
+
+ foreach ($this->_storeIds as $id) {
+ $productCollection->addStoreFilter($id);
+ }
+
+ Mage::dispatchEvent('wishlist_item_collection_products_after_load', array(
+ 'product_collection' => $productCollection
+ ));
+
+ foreach ($this as $item) {
+ $product = $productCollection->getItemById($item->getProductId());
+ if ($product) {
+ if ($this->_productInStock &&
+ !$product->isSalable() &&
+ !Mage::helper('cataloginventory')->isShowOutOfStock()) {
+ $this->removeItemByKey($item->getId());
+ } else {
+ $product->setCustomOptions(array());
+ $item->setProduct($product);
+ $item->setProductName($product->getName());
+ $item->setName($product->getName());
+ $item->setPrice($product->getPrice());
+ }
+ } else {
+ $item->isDeleted(true);
+ }
+ }
+
+ Varien_Profiler::stop('WISHLIST:'.__METHOD__);
+
+ return $this;
+ }
+
/**
* Add filter by wishlist object
*
@@ -62,21 +206,103 @@ public function addWishlistFilter(Mage_Wishlist_Model_Wishlist $wishlist)
* @param int|array $store
* @return Mage_Wishlist_Model_Mysql4_Item_Collection
*/
- public function addStoreFilter($store)
+ public function addStoreFilter($store = null)
{
- $this->addFieldToFilter('store_id', array('in' => $store));
+ if (!is_array($store)) {
+ $store = array($store);
+ }
+ $this->_storeIds = $store;
return $this;
}
/**
- * This method will be not supported anymore
+ * Add items store data to collection
*
- * @deprecated since 1.4.0.0
* @return Mage_Wishlist_Model_Mysql4_Item_Collection
*/
public function addStoreData()
{
+ $storeTable = Mage::getSingleton('core/resource')->getTableName('core/store');
+ $this->getSelect()->join(array('store'=>$storeTable), 'main_table.store_id=store.store_id', array(
+ 'store_name'=>'name',
+ 'item_store_id' => 'store_id'
+ ));
+ return $this;
+ }
+
+ /**
+ * Add wishlist sort order
+ *
+ * @param string $attribute
+ * @param string $dir
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function addWishListSortOrder($attribute = 'added_at', $dir = 'desc')
+ {
+ $this->setOrder($attribute, $dir);
+ return $this;
+ }
+
+ /**
+ * Reset sort order
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function resetSortOrder()
+ {
+ $this->getSelect()->reset(Zend_Db_Select::ORDER);
+ return $this;
+ }
+
+ /**
+ * Set product Visibility Filter to product collection flag
+ *
+ * @param bool $flag
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function setVisibilityFilter($flag = true)
+ {
+ $this->_productVisible = (bool)$flag;
+ return $this;
+ }
+
+ /**
+ * Set Salable Filter.
+ * This filter apply Salable Product Types Filter to product collection.
+ *
+ * @param bool $flag
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function setSalableFilter($flag = true)
+ {
+ $this->_productSalable = (bool)$flag;
+ return $this;
+ }
+
+ /**
+ * Set In Stock Filter.
+ * This filter remove items with no salable product.
+ *
+ * @param bool $flag
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function setInStockFilter($flag = true)
+ {
+ $this->_productInStock = (bool)$flag;
+ return $this;
+ }
+
+ /**
+ * Set add days in whishlist
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Collection
+ */
+ public function addDaysInWishlist($flag = null)
+ {
+ $this->getSelect()->columns(array('days_in_wishlist' =>
+ "(TO_DAYS('" . (substr(Mage::getSingleton('core/date')->date(), 0, -2) . '00') . "') ".
+ "- TO_DAYS(DATE_ADD(added_at, INTERVAL " .(int) Mage::getSingleton('core/date')->getGmtOffset() . " SECOND)))"));
return $this;
}
}
diff --git a/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Option.php b/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Option.php
new file mode 100644
index 0000000000..47fec2571f
--- /dev/null
+++ b/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Option.php
@@ -0,0 +1,40 @@
+
+ */
+class Mage_Wishlist_Model_Mysql4_Item_Option extends Mage_Core_Model_Mysql4_Abstract
+{
+ protected function _construct()
+ {
+ $this->_init('wishlist/item_option', 'option_id');
+ }
+}
diff --git a/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Option/Collection.php b/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Option/Collection.php
new file mode 100644
index 0000000000..b69da1838e
--- /dev/null
+++ b/app/code/core/Mage/Wishlist/Model/Mysql4/Item/Option/Collection.php
@@ -0,0 +1,175 @@
+
+ */
+class Mage_Wishlist_Model_Mysql4_Item_Option_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
+{
+ /**
+ * Array of option ids grouped by item id
+ *
+ * @var array
+ */
+ protected $_optionsByItem = array();
+
+ /**
+ * Array of option ids grouped by product id
+ *
+ * @var array
+ */
+ protected $_optionsByProduct = array();
+
+ /**
+ * Define resource model for collection
+ *
+ * @return void
+ */
+ protected function _construct()
+ {
+ $this->_init('wishlist/item_option');
+ }
+
+ /**
+ * Fill array of options by item and product
+ *
+ * @return Mage_Wishlist_Model_Mysql4_Item_Option_Collection
+ */
+ protected function _afterLoad()
+ {
+ parent::_afterLoad();
+
+ foreach ($this as $option) {
+ $optionId = $option->getId();
+ $itemId = $option->getWishlistItemId();
+ $productId = $option->getProductId();
+ if (isset($this->_optionsByItem[$itemId])) {
+ $this->_optionsByItem[$itemId][] = $optionId;
+ } else {
+ $this->_optionsByItem[$itemId] = array($optionId);
+ }
+ if (isset($this->_optionsByProduct[$productId])) {
+ $this->_optionsByProduct[$productId][] = $optionId;
+ } else {
+ $this->_optionsByProduct[$productId] = array($optionId);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Apply quote item(s) filter to collection
+ *
+ * @param int | array $item
+ * @return Mage_Wishlist_Model_Mysql4_Item_Option_Collection
+ */
+ public function addItemFilter($item)
+ {
+ if (empty($item)) {
+ $this->_totalRecords = 0;
+ $this->_setIsLoaded(true);
+ //$this->addFieldToFilter('item_id', '');
+ } else if (is_array($item)) {
+ $this->addFieldToFilter('wishlist_item_id', array('in'=>$item));
+ } else if ($item instanceof Mage_Wishlist_Model_Item) {
+ $this->addFieldToFilter('wishlist_item_id', $item->getId());
+ } else {
+ $this->addFieldToFilter('wishlist_item_id', $item);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get array of all product ids
+ *
+ * @return array
+ */
+ public function getProductIds()
+ {
+ $this->load();
+
+ return array_keys($this->_optionsByProduct);
+ }
+
+ /**
+ * Get all option for item
+ *
+ * @param mixed $item
+ * @return array
+ */
+ public function getOptionsByItem($item)
+ {
+ if ($item instanceof Mage_Wishlist_Model_Item) {
+ $itemId = $item->getId();
+ } else {
+ $itemId = $item;
+ }
+
+ $this->load();
+
+ $options = array();
+ if (isset($this->_optionsByItem[$itemId])) {
+ foreach ($this->_optionsByItem[$itemId] as $optionId) {
+ $options[] = $this->_items[$optionId];
+ }
+ }
+
+ return $options;
+ }
+
+ /**
+ * Get all option for item
+ *
+ * @param mixed $item
+ * @return array
+ */
+ public function getOptionsByProduct($product)
+ {
+ if ($product instanceof Mage_Catalog_Model_Product) {
+ $productId = $product->getId();
+ } else {
+ $productId = $product;
+ }
+
+ $this->load();
+
+ $options = array();
+ if (isset($this->_optionsByProduct[$productId])) {
+ foreach ($this->_optionsByProduct[$productId] as $optionId) {
+ $options[] = $this->_items[$optionId];
+ }
+ }
+
+ return $options;
+ }
+}
diff --git a/app/code/core/Mage/Wishlist/Model/Mysql4/Product/Collection.php b/app/code/core/Mage/Wishlist/Model/Mysql4/Product/Collection.php
index fb6dee0572..93a537342b 100644
--- a/app/code/core/Mage/Wishlist/Model/Mysql4/Product/Collection.php
+++ b/app/code/core/Mage/Wishlist/Model/Mysql4/Product/Collection.php
@@ -27,7 +27,10 @@
/**
* Wishlist Product collection
+ * Deprecated because after Magento 1.4.2.0 it's impossible
+ * to use product collection in wishlist
*
+ * @deprecated after 1.4.2.0
* @category Mage
* @package Mage_Wishlist
* @author Magento Core Team
@@ -35,7 +38,6 @@
class Mage_Wishlist_Model_Mysql4_Product_Collection
extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
{
-
/**
* Add days in whishlist filter of product collection
*
@@ -43,6 +45,8 @@ class Mage_Wishlist_Model_Mysql4_Product_Collection
*/
protected $_addDaysInWishlist = false;
+
+
/**
* Get add days in whishlist filter of product collection flag
*
@@ -159,4 +163,15 @@ protected function _getAttributeFieldName($attributeCode)
}
return parent::_getAttributeFieldName($attributeCode);
}
+
+ /**
+ * Prevent loading collection because since Magento 1.4.2.0 it's impossible
+ * to use product collection in wishlist
+ *
+ * @return bool
+ */
+ public function load($printQuery = false, $logQuery = false)
+ {
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/Wishlist/Model/Mysql4/Wishlist.php b/app/code/core/Mage/Wishlist/Model/Mysql4/Wishlist.php
index e5686e8c4d..94365f0677 100644
--- a/app/code/core/Mage/Wishlist/Model/Mysql4/Wishlist.php
+++ b/app/code/core/Mage/Wishlist/Model/Mysql4/Wishlist.php
@@ -58,12 +58,9 @@ public function setCustomerIdFieldName($fieldName)
public function fetchItemsCount(Mage_Wishlist_Model_Wishlist $wishlist)
{
if (is_null($this->_itemsCount)) {
- $collection = $wishlist->getProductCollection()
- //->addAttributeToFilter('store_id', array('in'=>$wishlist->getSharedStoreIds()))
- ->addStoreFilter();
-
- Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
- Mage::getSingleton('catalog/product_visibility')->addVisibleInSiteFilterToCollection($collection);
+ $collection = $wishlist->getItemCollection()
+ ->addStoreFilter()
+ ->setVisibilityFilter();
$this->_itemsCount = $collection->getSize();
}
diff --git a/app/code/core/Mage/Wishlist/Model/Observer.php b/app/code/core/Mage/Wishlist/Model/Observer.php
index 198c3cf343..9062f875b0 100644
--- a/app/code/core/Mage/Wishlist/Model/Observer.php
+++ b/app/code/core/Mage/Wishlist/Model/Observer.php
@@ -69,6 +69,9 @@ public function processCartUpdateBefore($observer)
if (!empty($itemInfo['wishlist'])) {
if ($item = $cart->getQuote()->getItemById($itemId)) {
$productId = $item->getProductId();
+
+ $wishlist->addNewItem($productId, $item->getBuyRequest());
+
$productIds[] = $productId;
$cart->getQuote()->removeItem($itemId);
}
@@ -76,9 +79,6 @@ public function processCartUpdateBefore($observer)
}
if (!empty($productIds)) {
- foreach ($productIds as $productId) {
- $wishlist->addNewItem($productId);
- }
$wishlist->save();
Mage::helper('wishlist')->calculate();
}
diff --git a/app/code/core/Mage/Wishlist/Model/Wishlist.php b/app/code/core/Mage/Wishlist/Model/Wishlist.php
index fc53222d4a..b2e512aebe 100644
--- a/app/code/core/Mage/Wishlist/Model/Wishlist.php
+++ b/app/code/core/Mage/Wishlist/Model/Wishlist.php
@@ -126,6 +126,58 @@ protected function _beforeSave()
return $this;
}
+ /**
+ * Save related items
+ *
+ * @return Mage_Sales_Model_Quote
+ */
+ protected function _afterSave()
+ {
+ parent::_afterSave();
+
+ if (null !== $this->_itemCollection) {
+ $this->getItemCollection()->save();
+ }
+ return $this;
+ }
+
+ /**
+ * Adding catalog product object data to wishlist
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return Mage_Wishlist_Model_Item
+ */
+ protected function _addCatalogProduct(Mage_Catalog_Model_Product $product, $qty = 1)
+ {
+ $item = null;
+ foreach ($this->getItemCollection() as $_item) {
+ if ($_item->representProduct($product)) {
+ $item = $_item;
+ break;
+ }
+ }
+
+ if ($item === null) {
+ $storeId = $product->hasWishlistStoreId() ? $product->getWishlistStoreId() : $this->getStore()->getId();
+ $item = Mage::getModel('wishlist/item');
+ $item->setProductId($product->getId())
+ ->setWishlistId($this->getId())
+ ->setAddedAt(now())
+ ->setStoreId($storeId)
+ ->setOptions($product->getCustomOptions())
+ ->setProduct($product)
+ ->setQty($qty)
+ ->save();
+ } else {
+ $item->setQty($item->getQty() + $qty)
+ ->save();
+ }
+
+ $this->addItem($item);
+
+ return $item;
+ }
+
/**
* Retrieve wishlist item collection
*
@@ -141,43 +193,132 @@ public function getItemCollection()
return $this->_itemCollection;
}
+ /**
+ * Retrieve wishlist item collection
+ *
+ * @param int $itemId
+ * @return Mage_Wishlist_Model_Item
+ */
+ public function getItem($itemId)
+ {
+ if (!$itemId) {
+ return false;
+ }
+ return $this->getItemCollection()->getItemById($itemId);
+ }
+
/**
* Retrieve Product collection
*
+ * @deprecated after 1.4.2.0
+ * @see Mage_Wishlist_Model_Wishlist::getItemCollection()
+ *
* @return Mage_Wishlist_Model_Mysql4_Product_Collection
*/
public function getProductCollection()
{
$collection = $this->getData('product_collection');
if (is_null($collection)) {
- $collection = Mage::getResourceModel('wishlist/product_collection')
- ->setStoreId($this->getStore()->getId())
- ->addWishlistFilter($this)
- ->addWishListSortOrder();
+ $collection = Mage::getResourceModel('wishlist/product_collection');
$this->setData('product_collection', $collection);
}
return $collection;
}
/**
- * Add new item to wishlist
+ * Adding item to wishlist
+ *
+ * @param Mage_Wishlist_Model_Item $item
+ * @return Mage_Wishlist_Model_Wishlist
+ */
+ public function addItem(Mage_Wishlist_Model_Item $item)
+ {
+ $item->setWishlist($this);
+ if (!$item->getId()) {
+ $this->getItemCollection()->addItem($item);
+ Mage::dispatchEvent('wishlist_add_item', array('item' => $item));
+ }
+ return $this;
+ }
+
+ /**
+ * Add new product to wishlist
*
- * @param int $productId
+ * @param int|Mage_Catalog_Model_Product $product
+ * @param mixed $buyRequest
* @return Mage_Wishlist_Model_Item
*/
- public function addNewItem($productId)
+ public function addNewItem($product, $buyRequest = null)
{
- $item = Mage::getModel('wishlist/item');
- $item->loadByProductWishlist($this->getId(), $productId, $this->getSharedStoreIds());
+ /*
+ * Always load product, to ensure:
+ * a) we have new instance and do not interfere with other products in wishlist
+ * b) product has full set of attributes
+ */
+ if ($product instanceof Mage_Catalog_Model_Product) {
+ $productId = $product->getId();
+ // Maybe force some store by wishlist internal properties
+ $storeId = $product->hasWishlistStoreId() ? $product->getWishlistStoreId() : $product->getStoreId();
+ } else {
+ $productId = (int) $product;
+ if ($buyRequest->getStoreId()) {
+ $storeId = $buyRequest->getStoreId();
+ } else {
+ $storeId = Mage::app()->getStore()->getId();
+ }
+ }
- if (!$item->getId()) {
- $item->setProductId($productId)
- ->setWishlistId($this->getId())
- ->setAddedAt(now())
- ->setStoreId($this->getStore()->getId())
- ->save();
+ /* @var $product Mage_Catalog_Model_Product */
+ $product = Mage::getModel('catalog/product')
+ ->setStoreId($storeId)
+ ->load($productId);
+
+ if ($buyRequest instanceof Varien_Object) {
+ $_buyRequest = $buyRequest;
+ } elseif (is_string($buyRequest)) {
+ $_buyRequest = new Varien_Object(unserialize($buyRequest));
+ } elseif (is_array($buyRequest)) {
+ $_buyRequest = new Varien_Object($buyRequest);
+ } else {
+ $_buyRequest = new Varien_Object();
+ }
+
+ $cartCandidates = $product->getTypeInstance(true)
+ ->processConfiguration($_buyRequest, $product);
+
+ /**
+ * Error message
+ */
+ if (is_string($cartCandidates)) {
+ return $cartCandidates;
+ }
+
+ /**
+ * If prepare process return one object
+ */
+ if (!is_array($cartCandidates)) {
+ $cartCandidates = array($cartCandidates);
}
+ $errors = array();
+ $items = array();
+
+ foreach ($cartCandidates as $candidate) {
+ if ($candidate->getParentProductId()) {
+ continue;
+ }
+ $candidate->setWishlistStoreId($storeId);
+ $item = $this->_addCatalogProduct($candidate, $candidate->getQty());
+ $items[] = $item;
+
+ // Collect errors instead of throwing first one
+ if ($item->getHasError()) {
+ $errors[] = $item->getMessage();
+ }
+ }
+
+ Mage::dispatchEvent('wishlist_product_add_after', array('items' => $items));
+
return $item;
}
@@ -292,8 +433,8 @@ public function getItemsCount()
*/
public function isSalable()
{
- foreach ($this->getProductCollection() as $product) {
- if ($product->getIsSalable()) {
+ foreach ($this->getItemCollection() as $item) {
+ if ($item->getProduct()->getIsSalable()) {
return true;
}
}
@@ -310,4 +451,53 @@ public function isOwner($customerId)
{
return $customerId == $this->getCustomerId();
}
+
+
+ /**
+ * Update wishlist Item and set data from request
+ *
+ * @param int $itemId
+ * @param Varien_Object $buyRequest
+ * @return Mage_Wishlist_Model_Wishlist
+ */
+ public function updateItem($itemId, $buyRequest) {
+ $item = $this->getItem((int)$itemId);
+ if (!$item) {
+ Mage::throwException(Mage::helper('wishlist')->__('Cannot specify wishlist item.'));
+ }
+
+ $product = $item->getProduct();
+ $productId = $product->getId();
+ if ($productId) {
+ $product->setWishlistStoreId($item->getStoreId());
+ $resultItem = $this->addNewItem($product, $buyRequest);
+ /**
+ * Error message
+ */
+ if (is_string($resultItem)) {
+ Mage::throwException(Mage::helper('checkout')->__($resultItem));
+ }
+
+ if ($resultItem->getId() != $itemId) {
+ $item->isDeleted(true);
+ $this->setDataChanges(true);
+
+ $items = $this->getItemCollection();
+ $eqItems = array();
+ foreach ($items as $_item) {
+ if ($_item->getProductId() == $productId && $_item->getId() != $resultItem->getId()) {
+ if ($resultItem->compareOptions($resultItem->getOptions(), $_item->getOptions())) {
+ $resultItem->setQty($resultItem->getQty() + $_item->getQty());
+ $_item->isDeleted(true);
+ }
+ }
+ }
+ } else {
+ $resultItem->setQty($buyRequest->getQty()*1);
+ }
+ } else {
+ Mage::throwException(Mage::helper('checkout')->__('The product does not exist.'));
+ }
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/Wishlist/controllers/IndexController.php b/app/code/core/Mage/Wishlist/controllers/IndexController.php
index 0ff88f6ade..9216ce94a6 100644
--- a/app/code/core/Mage/Wishlist/controllers/IndexController.php
+++ b/app/code/core/Mage/Wishlist/controllers/IndexController.php
@@ -87,6 +87,7 @@ public function indexAction()
$this->_getWishlist();
$this->loadLayout();
+
$session = Mage::getSingleton('customer/session');
$block = $this->getLayout()->getBlock('customer.wishlist');
$referer = $session->getAddActionReferer(true);
@@ -131,15 +132,27 @@ public function addAction()
}
try {
- $wishlist->addNewItem($product->getId());
+ $buyRequest = new Varien_Object($this->getRequest()->getParams());
+
+ $result = $wishlist->addNewItem($product, $buyRequest);
+ if (is_string($result)) {
+ Mage::throwException($result);
+ }
$wishlist->save();
- Mage::dispatchEvent('wishlist_add_product', array('wishlist'=>$wishlist, 'product'=>$product));
+ Mage::dispatchEvent(
+ 'wishlist_add_product',
+ array(
+ 'wishlist' => $wishlist,
+ 'product' => $product,
+ 'item' => $result
+ )
+ );
- if ($referer = $session->getBeforeWishlistUrl()) {
+ $referer = $session->getBeforeWishlistUrl();
+ if ($referer) {
$session->setBeforeWishlistUrl(null);
- }
- else {
+ } else {
$referer = $this->_getRefererUrl();
}
@@ -157,11 +170,104 @@ public function addAction()
$session->addError($this->__('An error occurred while adding item to wishlist: %s', $e->getMessage()));
}
catch (Exception $e) {
+ mage::log($e->getMessage());
$session->addError($this->__('An error occurred while adding item to wishlist.'));
}
+
$this->_redirect('*');
}
+ /**
+ * Action to reconfigure wishlist item
+ */
+ public function configureAction()
+ {
+ $id = (int) $this->getRequest()->getParam('id');
+ $wishlist = $this->_getWishlist();
+ /* @var $item Mage_Wishlist_Model_Item */
+ $item = $wishlist->getItem($id);
+
+ try {
+ if (!$item) {
+ throw new Exception($this->__('Cannot load wishlist item'));
+ }
+
+ Mage::register('wishlist_item', $item);
+
+ $params = new Varien_Object();
+ $params->setCategoryId(false);
+ $params->setConfigureMode(true);
+
+ $buyRequest = $item->getBuyRequest();
+ if (!$buyRequest->getQty() && $item->getQty()) {
+ $buyRequest->setQty($item->getQty());
+ }
+ if ($buyRequest->getQty() && !$item->getQty()) {
+ $item->setQty($buyRequest->getQty());
+ }
+ $params->setBuyRequest($buyRequest);
+
+ Mage::helper('catalog/product_view')->prepareAndRender($item->getProductId(), $this, $params);
+ } catch (Mage_Core_Exception $e) {
+ Mage::getSingleton('customer/session')->addError($e->getMessage());
+ $this->_redirect('*');
+ return;
+ } catch (Exception $e) {
+ Mage::getSingleton('customer/session')->addError($this->__('Cannot configure product'));
+ Mage::logException($e);
+ $this->_redirect('*');
+ return;
+ }
+ }
+
+ /**
+ * Action to accept new configuration for a wishlist item
+ */
+ public function updateItemOptionsAction()
+ {
+ $session = Mage::getSingleton('customer/session');
+ $wishlist = $this->_getWishlist();
+ if (!$wishlist) {
+ $this->_redirect('*/');
+ return;
+ }
+
+ $productId = (int) $this->getRequest()->getParam('product');
+ if (!$productId) {
+ $this->_redirect('*/');
+ return;
+ }
+
+ $product = Mage::getModel('catalog/product')->load($productId);
+ if (!$product->getId() || !$product->isVisibleInCatalog()) {
+ $session->addError($this->__('Cannot specify product.'));
+ $this->_redirect('*/');
+ return;
+ }
+
+ try {
+ $id = (int) $this->getRequest()->getParam('id');
+ $buyRequest = new Varien_Object($this->getRequest()->getParams());
+
+ /* @var $item Mage_Wishlist_Model_Item */
+ $item = $wishlist->updateItem($id, $buyRequest)
+ ->save();
+
+ Mage::dispatchEvent('wishlist_update_item', array('wishlist' => $wishlist, 'product' => $product, 'item' => $item));
+
+ Mage::helper('wishlist')->calculate();
+
+ $message = $this->__('%1$s has been updated in your wishlist.', $product->getName());
+ $session->addSuccess($message);
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e) {
+ $session->addError($this->__('An error occurred while updating wishlist.'));
+ Mage::logException($e);
+ }
+ $this->_redirect('*/*');
+ }
+
/**
* Update wishlist item comments
*/
@@ -177,12 +283,43 @@ public function updateAction()
foreach ($post['description'] as $itemId => $description) {
$item = Mage::getModel('wishlist/item')->load($itemId);
+ if ($item->getWishlistId() != $wishlist->getId()) {
+ continue;
+ }
+
+ // Extract new values
$description = (string) $description;
- if(!strlen($description) || $item->getWishlistId()!=$wishlist->getId()) {
+ if (!strlen($description)) {
+ $description = $item->getDescription();
+ }
+
+ $qty = null;
+ if (isset($post['qty'][$itemId])) {
+ $qty = $this->_processLocalizedQty($post['qty'][$itemId]);
+ }
+ if (is_null($qty)) {
+ $qty = $item->getQty();
+ if (!$qty) {
+ $qty = 1;
+ }
+ } elseif (0 == $qty) {
+ try {
+ $item->delete();
+ } catch (Exception $e) {
+ Mage::logException($e);
+ Mage::getSingleton('customer/session')->addError(
+ $this->__('Can\'t delete item from wishlist')
+ );
+ }
+ }
+
+ // Check that we need to save
+ if (($item->getDescription() == $description) && ($item->getQty() == $qty)) {
continue;
}
try {
$item->setDescription($description)
+ ->setQty($qty)
->save();
$updatedItems++;
}
@@ -256,14 +393,24 @@ public function cartAction()
return $this->_redirect('*/*');
}
- $itemId = (int)$this->getRequest()->getParam('item');
+ $itemId = (int) $this->getRequest()->getParam('item');
+
/* @var $item Mage_Wishlist_Model_Item */
- $item = Mage::getModel('wishlist/item')->load($itemId);
+ $item = Mage::getModel('wishlist/item')->load($itemId);
if (!$item->getId() || $item->getWishlistId() != $wishlist->getId()) {
return $this->_redirect('*/*');
}
+ // Set qty
+ $qtys = $this->getRequest()->getParam('qty');
+ if (isset($qtys[$itemId])) {
+ $qty = $this->_processLocalizedQty($qtys[$itemId]);
+ if ($qty) {
+ $item->setQty($qty);
+ }
+ }
+
/* @var $session Mage_Wishlist_Model_Session */
$session = Mage::getSingleton('wishlist/session');
$cart = Mage::getSingleton('checkout/cart');
@@ -271,8 +418,12 @@ public function cartAction()
$redirectUrl = Mage::getUrl('*/*');
try {
+ $options = Mage::getModel('wishlist/item_option')->getCollection()
+ ->addItemFilter(array($itemId));
+ $item->setOptions($options->getOptionsByItem($itemId));
+
$item->addToCart($cart, true);
- $cart->save()-> getQuote()->collectTotals();
+ $cart->save()->getQuote()->collectTotals();
$wishlist->save();
Mage::helper('wishlist')->calculate();
@@ -286,13 +437,11 @@ public function cartAction()
if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_NOT_SALABLE) {
$session->addError(Mage::helper('wishlist')->__('This product(s) is currently out of stock'));
} else if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_HAS_REQUIRED_OPTIONS) {
- $redirectUrl = $item->getProductUrl();
- $item->delete();
- } else if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_IS_GROUPED_PRODUCT) {
- $redirectUrl = $item->getProductUrl();
- $item->delete();
+ Mage::getSingleton('catalog/session')->addNotice($e->getMessage());
+ $redirectUrl = Mage::getUrl('*/*/configure/', array('id' => $item->getId()));
} else {
- $session->addError($e->getMessage());
+ Mage::getSingleton('catalog/session')->addNotice($e->getMessage());
+ $redirectUrl = Mage::getUrl('*/*/configure/', array('id' => $item->getId()));
}
} catch (Exception $e) {
$session->addException($e, Mage::helper('wishlist')->__('Cannot add item to shopping cart'));
@@ -394,4 +543,33 @@ public function sendAction()
$this->_redirect('*/*/share');
}
}
+
+ /**
+ * Custom options download action
+ *
+ * @return void
+ */
+ public function downloadCustomOptionAction()
+ {
+ try {
+ $optionId = $this->getRequest()->getParam('id');
+ $option = Mage::getModel('wishlist/item_option')->load($optionId);
+ $hasError = false;
+
+ if ($option->getId()) {
+ $info = unserialize($option->getValue());
+ $filePath = Mage::getBaseDir() . $info['quote_path'];
+ $secretKey = $this->getRequest()->getParam('key');
+
+ if ($secretKey == $info['secret_key']) {
+ $this->_prepareDownloadResponse($info['title'], array(
+ 'value' => $filePath,
+ 'type' => 'filename'
+ ));
+ }
+ }
+ } catch(Exception $e) {
+ }
+ $this->_forward('noRoute');
+ }
}
diff --git a/app/code/core/Mage/Wishlist/etc/config.xml b/app/code/core/Mage/Wishlist/etc/config.xml
index 119fde80f2..192f7a1669 100644
--- a/app/code/core/Mage/Wishlist/etc/config.xml
+++ b/app/code/core/Mage/Wishlist/etc/config.xml
@@ -28,7 +28,7 @@
- 0.7.8
+ 0.7.9
@@ -51,6 +51,10 @@
-
+ -
+
+
+
diff --git a/app/code/core/Mage/Wishlist/sql/wishlist_setup/mysql4-upgrade-0.7.8-0.7.9.php b/app/code/core/Mage/Wishlist/sql/wishlist_setup/mysql4-upgrade-0.7.8-0.7.9.php
new file mode 100644
index 0000000000..003838869f
--- /dev/null
+++ b/app/code/core/Mage/Wishlist/sql/wishlist_setup/mysql4-upgrade-0.7.8-0.7.9.php
@@ -0,0 +1,51 @@
+startSetup();
+$installer->getConnection()->addColumn($this->getTable('wishlist/item'), 'qty', 'DECIMAL( 12, 4 ) NOT NULL');
+
+$installer->run("
+CREATE TABLE `{$this->getTable('wishlist/item_option')}` (
+ `option_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `wishlist_item_id` int(10) unsigned NOT NULL,
+ `product_id` int(10) unsigned NOT NULL,
+ `code` varchar(255) NOT NULL,
+ `value` text NOT NULL,
+ PRIMARY KEY (`option_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Additional options for wishlist item';
+");
+
+$installer->getConnection()->addConstraint(
+ 'FK_WISHLIST_ITEM_OPTION_ITEM_ID',
+ $this->getTable('wishlist/item_option'),
+ 'wishlist_item_id',
+ $this->getTable('wishlist/item'),
+ 'wishlist_item_id'
+);
+
+$installer->endSetup();
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/History.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/History.php
new file mode 100644
index 0000000000..65e9244054
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/History.php
@@ -0,0 +1,50 @@
+
+ */
+
+
+class Mage_XmlConnect_Block_Adminhtml_History extends Mage_Adminhtml_Block_Widget_Grid_Container
+{
+ /**
+ * Class constructor
+ */
+ public function __construct()
+ {
+ $this->_blockGroup = 'xmlconnect';
+ $this->_controller = 'adminhtml_history';
+ $this->_headerText = Mage::helper('xmlconnect')->__('App Submission History');
+
+ parent::__construct();
+ $this->removeButton('add');
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/History/Grid.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/History/Grid.php
new file mode 100644
index 0000000000..b7c8b5d46d
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/History/Grid.php
@@ -0,0 +1,107 @@
+
+ */
+class Mage_XmlConnect_Block_Adminhtml_History_Grid extends Mage_Adminhtml_Block_Widget_Grid
+{
+
+ /**
+ * Constructor
+ *
+ * Setting grid_id, sort order and sort direction
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setId('app_history_grid');
+ $this->setDefaultSort('created_at');
+ $this->setDefaultDir('ASC');
+ }
+
+ /**
+ * Setting collection to show
+ *
+ * @return Mage_Adminhtml_Block_Widget_Grid
+ */
+ protected function _prepareCollection()
+ {
+ $collection = Mage::getModel('xmlconnect/history')->getCollection();
+ $this->setCollection($collection);
+ return parent::_prepareCollection();
+ }
+
+ /**
+ * Configuration of grid
+ *
+ * @return Mage_Adminhtml_Block_Widget_Grid
+ */
+ protected function _prepareColumns()
+ {
+ $this->addColumn('title', array(
+ 'header' => Mage::helper('xmlconnect')->__('App Title'),
+ 'align' => 'left',
+ 'index' => 'title',
+ 'type' => 'text',
+ ));
+
+ $this->addColumn('code', array(
+ 'header' => Mage::helper('xmlconnect')->__('App Code'),
+ 'align' => 'left',
+ 'index' => 'code',
+ ));
+
+ $this->addColumn('created_at', array(
+ 'header' => Mage::helper('xmlconnect')->__('Date Submitted'),
+ 'align' => 'left',
+ 'index' => 'created_at',
+ 'type' => 'datetime'
+ ));
+
+ $this->addColumn('activation_key', array(
+ 'header' => Mage::helper('xmlconnect')->__('Activation Key'),
+ 'align' => 'left',
+ 'index' => 'activation_key',
+ ));
+ return parent::_prepareColumns();
+ }
+
+ /**
+ * Remove row click url
+ *
+ * @param Mage_Catalog_Model_Product|Varien_Object $row
+ * @return string
+ */
+ public function getRowUrl($row)
+ {
+ return '';
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile.php
new file mode 100644
index 0000000000..0434fd2a15
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile.php
@@ -0,0 +1,44 @@
+_controller = 'adminhtml_mobile';
+ $this->_blockGroup = 'xmlconnect';
+ $this->_headerText = Mage::helper('xmlconnect')->__('Manage Apps');
+ $this->_addButtonLabel = Mage::helper('xmlconnect')->__('Add App');
+
+ parent::__construct();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit.php
new file mode 100644
index 0000000000..ce2041d0ca
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit.php
@@ -0,0 +1,97 @@
+_objectId = 'application_id';
+ $this->_controller = 'adminhtml_mobile';
+ $this->_blockGroup = 'xmlconnect';
+ parent::__construct();
+ $model = Mage::registry('current_app');
+
+ $this->_updateButton('save', 'label', Mage::helper('xmlconnect')->__('Save'));
+ $this->_updateButton('save', 'onclick', 'if (editForm.submit()) {disableElements(\'save\')}');
+
+ $this->_addButton('save_and_continue', array(
+ 'label' => Mage::helper('xmlconnect')->__('Save and Continue Edit'),
+ 'onclick' => 'saveAndContinueEdit()',
+ 'class' => 'save',
+ ), -5);
+
+ if (Mage::registry('current_app')->getId()) {
+ $this->_addButton('submit_application_button', array(
+ 'label' => Mage::helper('xmlconnect')->__('Save and Submit App'),
+ 'onclick' => 'saveAndSubmitApp()',
+ 'class' => 'save'
+ ), -10);
+ }
+
+ $this->_formScripts[] = 'function saveAndContinueEdit() {'
+ .'if (editForm.submit($(\'edit_form\').action + \'back/edit/\')) {disableElements(\'save\')};}';
+ if ($model->getId()) {
+ $this->_formScripts[] = 'function saveAndSubmitApp() {'
+ .'if (editForm.submit($(\'edit_form\').action+\'submitapp/' . $model->getId() . '\')) {'
+ .'disableElements(\'save\')};}';
+ }
+
+ if (Mage::registry('current_app')->getIsSubmitted()) {
+ $this->removeButton('delete');
+ }
+ $this->removeButton('reset');
+ }
+
+ /**
+ * Adding JS scripts to block
+ *
+ * @return Mage_Adminhtml_Block_Widget_Form_Container
+ */
+ protected function _prepareLayout()
+ {
+ $this->getLayout()->getBlock('head')->addJs('jscolor/jscolor.js');
+ $this->getLayout()->getBlock('head')->addJs('scriptaculous/scriptaculous.js');
+ return parent::_prepareLayout();
+ }
+
+ /**
+ * Get form header title
+ *
+ * @return string
+ */
+ public function getHeaderText()
+ {
+ $app = Mage::registry('current_app');
+ if ($app && $app->getId()) {
+ return Mage::helper('xmlconnect')->__('Edit App "%s"', $this->htmlEscape($app->getName()));
+ } else {
+ return Mage::helper('xmlconnect')->__('New App');
+ }
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php
new file mode 100644
index 0000000000..4af1501076
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php
@@ -0,0 +1,42 @@
+ 'edit_form', 'action' => $this->getUrl('*/mobile/save'), 'method' => 'post', 'enctype' => 'multipart/form-data'));
+ $form->setUseContainer(true);
+ $this->setForm($form);
+ return parent::_prepareForm();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php
new file mode 100644
index 0000000000..5813c679e3
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php
@@ -0,0 +1,41 @@
+setId('mobile_app_submit');
+ $this->setDestElementId('content');
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php
new file mode 100644
index 0000000000..7d8e63dad9
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php
@@ -0,0 +1,138 @@
+setShowGlobalIcon(true);
+ }
+
+ /**
+ * Add page input to fieldset
+ *
+ * @param Varien_Data_Form_Element_Fieldset $fieldset
+ * @param string $fieldPrefix
+ */
+ protected function _addPage($fieldset, $fieldPrefix)
+ {
+ $el = $fieldset->addField($fieldPrefix, 'page', array(
+ 'name' => $fieldPrefix,
+ ));
+ $el->initFields(array(
+ 'name' => $fieldPrefix,
+ 'values' => $this->_pages,
+ ));
+ }
+
+ /**
+ * Prepare form before rendering HTML
+ * Setting Form Fieldsets and fields
+ *
+ * @return Mage_Adminhtml_Block_Widget_Form
+ */
+ protected function _prepareForm()
+ {
+ $model = Mage::registry('current_app');
+ $conf = $model->getConf();
+ $form = new Varien_Data_Form();
+ $this->setForm($form);
+
+ $pages = Mage::getResourceModel('xmlconnect/cms_page_collection')->toOptionIdArray();
+ $dummy = array(array( 'value' => '', 'label' => '' ));
+ $this->_pages = array_merge($dummy, $pages);
+
+ $fieldset = $form->addFieldset('cms_pages', array('legend' => Mage::helper('xmlconnect')->__('Pages')));
+ $this->_addElementTypes($fieldset);
+
+ $fieldset->addField('page_row_add', 'addrow', array(
+ 'onclick' => 'insertNewTableRow(this)',
+ 'options' => $this->_pages,
+ 'class' => ' scalable save ',
+ 'label' => Mage::helper('xmlconnect')->__('Label'),
+ 'before_element_html' => Mage::helper('xmlconnect')->__('Get Content from CMS Page').'',
+ ));
+
+ if (isset($conf['native']['pages'])) {
+ foreach ($conf['native']['pages'] as $key=>$dummy) {
+ $this->_addPage($fieldset, 'conf[native][pages]['.$key.']');
+ }
+ }
+
+ $data = $model->getFormData();
+ $data['page_row_add'] = Mage::helper('xmlconnect')->__('Add Page');
+ $form->setValues($data);
+ return parent::_prepareForm();
+ }
+
+ /**
+ * Prepare label for tab
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('Content');
+ }
+
+ /**
+ * Prepare title for tab
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('Content');
+ }
+
+ /**
+ * Returns status flag about this tab can be showen or not
+ *
+ * @return true
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Returns status flag about this tab hidden or not
+ *
+ * @return false
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php
new file mode 100644
index 0000000000..4d43ea3b5a
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php
@@ -0,0 +1,79 @@
+setShowGlobalIcon(true);
+ $this->setTemplate('xmlconnect/edit/tab/design.phtml');
+ }
+
+ /**
+ * Tab label getter
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('Design');
+ }
+
+ /**
+ * Tab title getter
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('Design');
+ }
+
+ /**
+ * Check if tab can be shown
+ *
+ * @return bool
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Check if tab hidden
+ *
+ * @return bool
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php
new file mode 100644
index 0000000000..25f9874f74
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php
@@ -0,0 +1,48 @@
+getLayout()->createBlock($block);
+ } else {
+ $block = $this->getLayout()->getBlock($block);
+ }
+
+ $this->addItem($itemId, array(
+ 'title' => $block->getTitle(),
+ 'content' => $block->toHtml(),
+ 'open' => $block->getIsOpen(),
+ ));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php
new file mode 100644
index 0000000000..4af6291d69
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php
@@ -0,0 +1,96 @@
+__('Images');
+ }
+
+ /**
+ * Getter for accordion item is open flag
+ *
+ * @return bool
+ */
+ public function getIsOpen()
+ {
+ return true;
+ }
+
+ /**
+ * Prepare form
+ *
+ * @return Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
+ */
+ protected function _prepareForm()
+ {
+ $form = new Varien_Data_Form();
+
+ $fieldset = $form->addFieldset('field_logo', array());
+ $this->_addElementTypes($fieldset);
+ $this->addImage($fieldset,
+ 'conf[native][navigationBar][icon]',
+ Mage::helper('xmlconnect')->__('Logo in Header'),
+ Mage::helper('xmlconnect')->__('Recommended size 35px x 35px.'),
+ $this->_getDesignPreviewImageUrl(Mage::helper('xmlconnect/image')->getInterfaceImagesPaths('conf/native/navigationBar/icon')),
+ true
+ );
+ $this->addImage($fieldset,
+ 'conf[native][body][bannerImage]',
+ Mage::helper('xmlconnect')->__('Banner on Home Screen'),
+ Mage::helper('xmlconnect')->__('Recommended size 320px x 230px. Note: Image size affects the performance of your app. Keep your image size below 50 KB for optimal performance.'),
+ $this->_getDesignPreviewImageUrl(Mage::helper('xmlconnect/image')->getInterfaceImagesPaths('conf/native/body/bannerImage')),
+ true
+ );
+ $this->addImage($fieldset,
+ 'conf[native][body][backgroundImage]',
+ Mage::helper('xmlconnect')->__('App Background'),
+ Mage::helper('xmlconnect')->__('Recommended size 320px x 367px. Note: Image size affects the performance of your app. Keep your image size below 75 KB for optimal performance.'),
+ $this->_getDesignPreviewImageUrl(Mage::helper('xmlconnect/image')->getInterfaceImagesPaths('conf/native/body/backgroundImage')),
+ true
+ );
+
+ $form->setValues($this->getApplication()->getFormData());
+ $this->setForm($form);
+ return parent::_prepareForm();
+ }
+
+ /**
+ * Retrieve url for images in the skin folder
+ *
+ * @param string $name - path to file name relative to the skin dir
+ * @return string
+ */
+ protected function _getDesignPreviewImageUrl($name)
+ {
+ return Mage::helper('xmlconnect/image')->getSkinImagesUrl('design_default/' . $name);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php
new file mode 100644
index 0000000000..19dc140666
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php
@@ -0,0 +1,65 @@
+__('Tabs');
+ }
+
+ /**
+ * Getter for accordion item is open flag
+ *
+ * @return bool
+ */
+ public function getIsOpen()
+ {
+ return true;
+ }
+
+ /**
+ * Prepare form
+ *
+ * @return Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
+ */
+ protected function _prepareForm()
+ {
+ $form = new Varien_Data_Form();
+
+ $fieldset = $form->addFieldset('field_tabs', array());
+ $this->_addElementTypes($fieldset);
+ $fieldset->addField('conf[extra][tabs]', 'tabs', array('name' => 'conf[extra][tabs]'));
+
+ $form->setValues($this->getApplication()->getFormData());
+ $this->setForm($form);
+ return parent::_prepareForm();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Themes.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Themes.php
new file mode 100644
index 0000000000..3e307e1106
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Themes.php
@@ -0,0 +1,68 @@
+__('Color Themes');
+ }
+
+ /**
+ * Getter for accordion item is open flag
+ *
+ * @return bool
+ */
+ public function getIsOpen()
+ {
+ return true;
+ }
+
+ /**
+ * Add theme field
+ *
+ * @return Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
+ */
+ protected function _prepareForm()
+ {
+ $form = new Varien_Data_Form();
+
+ $fieldset = $form->addFieldset('field_colors', array());
+ $this->_addElementTypes($fieldset);
+ $fieldset->addField('theme', 'theme', array(
+ 'name' => 'theme',
+ 'themes' => Mage::helper('xmlconnect/theme')->getAllThemes(),
+ ));
+ $form->setValues($this->getApplication()->getFormData());
+ $this->setForm($form);
+
+ return parent::_prepareForm();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php
new file mode 100644
index 0000000000..88b768a51c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php
@@ -0,0 +1,47 @@
+setTemplate('xmlconnect/edit/tab/design/preview.phtml');
+ }
+
+ /**
+ * Retieve preview action url
+ *
+ * @param string $page
+ * @return string
+ */
+ public function getPreviewActionUrl($page = 'home')
+ {
+ return $this->getUrl('*/*/preview' . $page, array('application_id' => Mage::registry('current_app')->getId()));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Theme.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Theme.php
new file mode 100644
index 0000000000..646e712ec0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Theme.php
@@ -0,0 +1,33 @@
+setTemplate('xmlconnect/theme.phtml');
+ }
+}
\ No newline at end of file
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php
new file mode 100644
index 0000000000..9724ca5279
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php
@@ -0,0 +1,148 @@
+setTemplate('xmlconnect/form/element/themes.phtml');
+
+ $data = $model->getFormData();
+ $this->setColorFieldset (array (
+ array ( 'id' => 'field_colors', 'label' => Mage::helper('xmlconnect')->__('Colors'), 'fields' => array (
+ $this->_addColorBox('conf[native][navigationBar][tintColor]', Mage::helper('xmlconnect')->__('Header Background Color'), $data),
+ $this->_addColorBox('conf[native][body][primaryColor]', Mage::helper('xmlconnect')->__('Primary Color'), $data),
+ $this->_addColorBox('conf[native][body][secondaryColor]', Mage::helper('xmlconnect')->__('Secondary Color'), $data),
+ $this->_addColorBox('conf[native][categoryItem][backgroundColor]', Mage::helper('xmlconnect')->__('Category Item Background Color'), $data),
+ $this->_addColorBox('conf[native][categoryItem][tintColor]', Mage::helper('xmlconnect')->__('Category Button Color'), $data),
+ )),
+ array ( 'id' => 'field_fonts', 'label' => Mage::helper('xmlconnect')->__('Fonts'), 'fields' => array (
+ $this->_addColorBox('conf[extra][fontColors][header]', Mage::helper('xmlconnect')->__('Header Font Color'), $data),
+ $this->_addColorBox('conf[extra][fontColors][primary]', Mage::helper('xmlconnect')->__('Primary Font Color'), $data),
+ $this->_addColorBox('conf[extra][fontColors][secondary]', Mage::helper('xmlconnect')->__('Secondary Font Color'), $data),
+ $this->_addColorBox('conf[extra][fontColors][price]', Mage::helper('xmlconnect')->__('Price Font Color'), $data),
+ )),
+ array ( 'id' => 'field_advanced', 'label' => Mage::helper('xmlconnect')->__('Advanced Settings'), 'fields' => array (
+ $this->_addColorBox('conf[native][body][backgroundColor]', Mage::helper('xmlconnect')->__('Background Color'), $data),
+ $this->_addColorBox('conf[native][body][scrollBackgroundColor]', Mage::helper('xmlconnect')->__('Scroll Background Color'), $data),
+ $this->_addColorBox('conf[native][itemActions][relatedProductBackgroundColor]', Mage::helper('xmlconnect')->__('Related Product Background Color'), $data),
+ )),
+ ));
+ }
+
+ /**
+ * Themes array getter
+ *
+ * @return array
+ */
+ public function getAllThemes()
+ {
+ $result = array();
+ foreach ($this->getThemes() as $theme) {
+ $result[$theme->getName()] = $theme->getFormData();
+ }
+ return $result;
+ }
+
+ /**
+ * Create color field params
+ *
+ * @param id $id
+ * @param string $label
+ * @param array $data
+ * @return array
+ */
+ protected function _addColorBox($id, $label, $data)
+ {
+ return array(
+ 'id' => $id,
+ 'name' => $id,
+ 'label' => $label,
+ 'value' => isset($data[$id]) ? $data[$id] : ''
+ );
+ }
+
+ /**
+ * Getter, check if it's needed to load default theme config
+ *
+ * @return bool
+ */
+ public function getDefaultThemeLoaded()
+ {
+ return $this->getApplication()->getDefaultThemeLoaded();
+ }
+
+ /**
+ * Check if adding new Application
+ *
+ * @return bool
+ */
+ public function isNewApplication()
+ {
+ return $this->getApplication()->getId() ? false : true;
+ }
+
+ /**
+ * Save theme action url getter
+ *
+ * @return string
+ */
+ public function getSaveThemeActionUrl()
+ {
+ return $this->getUrl('*/*/saveTheme');
+ }
+
+ /**
+ * Reset theme action url getter
+ *
+ * @return string
+ */
+ public function getResetThemeActionUrl()
+ {
+ return $this->getUrl('*/*/resetTheme');
+ }
+
+ /**
+ * Getter for current loaded application model
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ public function getApplication()
+ {
+ $model = Mage::registry('current_app');
+ if (!($model instanceof Mage_XmlConnect_Model_Application)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('App model not loaded.'));
+ }
+
+ return $model;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php
new file mode 100644
index 0000000000..3a7e3f83ae
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php
@@ -0,0 +1,147 @@
+setHtmlIdPrefix('app_');
+ $fieldset = $form->addFieldset('base_fieldset', array('legend' => Mage::helper('xmlconnect')->__('App Information')));
+
+ if ($model->getId()) {
+ $fieldset->addField('application_id', 'hidden', array(
+ 'name' => 'application_id',
+ ));
+ }
+
+ $fieldset->addField('name', 'text', array(
+ 'name' => 'name',
+ 'label' => Mage::helper('xmlconnect')->__('App Name'),
+ 'title' => Mage::helper('xmlconnect')->__('App Name'),
+ 'required' => true,
+ ));
+
+ if ($model->getId()) {
+ $field = $fieldset->addField('code', 'label', array(
+ 'label' => Mage::helper('xmlconnect')->__('App Code'),
+ 'title' => Mage::helper('xmlconnect')->__('App Code'),
+ ));
+ }
+
+ /**
+ * Check is single store mode
+ */
+ if (!Mage::app()->isSingleStoreMode()) {
+ $storeElement = $fieldset->addField('store_id', 'select', array(
+ 'name' => 'store_id',
+ 'label' => Mage::helper('xmlconnect')->__('Store View'),
+ 'title' => Mage::helper('xmlconnect')->__('Store View'),
+ 'required' => true,
+ 'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(true, false),
+ ));
+ } else {
+ $storeElement = $fieldset->addField('store_id', 'hidden', array(
+ 'name' => 'store_id',
+ 'value' => Mage::app()->getStore(true)->getId()
+ ));
+ $model->setStoreId(Mage::app()->getStore(true)->getId());
+ }
+
+ if ($model->getId()) {
+ $storeElement->setDisabled(true);
+ }
+
+ $fieldset->addField('type', 'select', array(
+ 'name' => 'type',
+ 'label' => Mage::helper('xmlconnect')->__('Device Type'),
+ 'title' => Mage::helper('xmlconnect')->__('Device Type'),
+ 'disabled' => $model->getId() ? true : false,
+ 'values' => Mage::helper('xmlconnect')->getDeviceTypeOptions(),
+ ));
+
+ $yesNoValues = Mage::getModel('adminhtml/system_config_source_yesno')->toOptionArray();
+
+ $fieldset->addField('browsing_mode', 'select', array(
+ 'label' => Mage::helper('xmlconnect')->__('Catalog Only App?'),
+ 'name' => 'browsing_mode',
+ 'note' => Mage::helper('xmlconnect')->__('A Catalog Only App will not support functions such as add to cart, add to wishlist, or login.'),
+ 'values' => $yesNoValues
+ ));
+
+ $form->setValues($model->getFormData());
+ $this->setForm($form);
+ return parent::_prepareForm();
+ }
+
+ /**
+ * Tab label getter
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('General');
+ }
+
+ /**
+ * Tab title getter
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('General');
+ }
+
+ /**
+ * Check if tab can be shown
+ *
+ * @return bool
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Check if tab hidden
+ *
+ * @return bool
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php
new file mode 100644
index 0000000000..6068cfb4a0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php
@@ -0,0 +1,153 @@
+setShowGlobalIcon(true);
+ }
+
+ /**
+ * Prepare form before rendering HTML
+ * Setting Form Fieldsets and fields
+ *
+ * @return Mage_Adminhtml_Block_Widget_Form
+ */
+ protected function _prepareForm()
+ {
+
+ $form = new Varien_Data_Form();
+
+ $this->setForm($form);
+
+ $data = $this->getApplication()->getFormData();
+ $yesNoValues = Mage::getModel('adminhtml/system_config_source_yesno')->toOptionArray();
+
+ $fieldset = $form->addFieldset('onepage_checkout', array('legend' => Mage::helper('xmlconnect')->__('Standard Checkout')));
+
+ $fieldset->addField('conf/native/defaultCheckout/isActive', 'select', array(
+ 'label' => Mage::helper('xmlconnect')->__('Enable Standard Checkout'),
+ 'name' => 'conf[native][defaultCheckout][isActive]',
+ 'values' => $yesNoValues,
+ 'note' => Mage::helper('xmlconnect')->__('Standard Checkout uses the checkout methods provided by Magento. Only inline payment methods are supported. (e.g PayPal Direct, Authorize.Net, etc.)'),
+ 'value' => (isset($data['conf[native][defaultCheckout][isActive]']) ? $data['conf[native][defaultCheckout][isActive]'] : '1')
+ ));
+
+
+ /**
+ * PayPal MEP management
+ */
+ $isExpressCheckoutAvaliable = Mage::getModel('xmlconnect/payment_method_paypal_mep')->isAvailable();
+
+ $paypalActive = 0;
+ if (isset($data['conf[native][paypal][isActive]'])) {
+ $paypalActive = (int)($data['conf[native][paypal][isActive]'] && $isExpressCheckoutAvaliable);
+ }
+ $fieldsetPaypal = $form->addFieldset('paypal_mep_checkout', array('legend' => Mage::helper('xmlconnect')->__('PayPal Mobile Embedded Payment (MEP)')));
+
+ $activateMepMethodNote = Mage::helper('xmlconnect')->__('To activate PayPal MEP payment method activate Express checkout first. ');
+ $paypalConfigurationUrl = $this->escapeHtml($this->getUrl('adminhtml/system_config/edit', array('section' => 'paypal')));
+ $businessAccountNote = Mage::helper('xmlconnect')->__('MEP is PayPal`s native checkout experience for the iPhone. You can choose to use MEP alongside standard checkout, or use it as your only checkout method for Magento mobile. PayPal MEP requires a PayPal business account ', $paypalConfigurationUrl);
+
+ $paypalActiveField = $fieldsetPaypal->addField('conf/native/paypal/isActive', 'select', array(
+ 'label' => Mage::helper('xmlconnect')->__('Activate PayPal Checkout'),
+ 'name' => 'conf[native][paypal][isActive]',
+ 'note' => (!$isExpressCheckoutAvaliable ? $activateMepMethodNote : $businessAccountNote),
+ 'values' => $yesNoValues,
+ 'value' => $paypalActive,
+ 'disabled' => !$isExpressCheckoutAvaliable
+ ));
+
+ $merchantlabelField = $fieldsetPaypal->addField('conf/special/merchantLabel', 'text', array(
+ 'name' => 'conf[special][merchantLabel]',
+ 'label' => Mage::helper('xmlconnect')->__('Merchant Label'),
+ 'title' => Mage::helper('xmlconnect')->__('Merchant Label'),
+ 'required' => true,
+ 'value' => (isset($data['conf[special][merchantLabel]']) ? $data['conf[special][merchantLabel]'] : '')
+ ));
+
+ // field dependencies
+ $this->setChild('form_after', $this->getLayout()->createBlock('adminhtml/widget_form_element_dependence')
+ ->addFieldMap($merchantlabelField->getHtmlId(), $merchantlabelField->getName())
+ ->addFieldMap($paypalActiveField->getHtmlId(), $paypalActiveField->getName())
+ ->addFieldDependence(
+ $merchantlabelField->getName(),
+ $paypalActiveField->getName(),
+ 1)
+ );
+
+ return parent::_prepareForm();
+ }
+
+ /**
+ * Tab label getter
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('Payment Methods');
+ }
+
+ /**
+ * Tab title getter
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('Payment Methods');
+ }
+
+ /**
+ * Check if tab can be shown
+ *
+ * @return bool
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Check if tab hidden
+ *
+ * @return bool
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php
new file mode 100644
index 0000000000..1980e1a9da
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php
@@ -0,0 +1,162 @@
+
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Submission_History extends Mage_Adminhtml_Block_Widget_Grid
+ implements Mage_Adminhtml_Block_Widget_Tab_Interface
+{
+
+ /**
+ * Set order by column and order direction
+ * Set grid ID
+ * Set use AJAX for grid
+ *
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setId('history_grid');
+ $this->setDefaultSort('created_at');
+ $this->setDefaultDir('ASC');
+ $this->setUseAjax(true);
+ $this->setSaveParametersInSession(true);
+ $this->setVarNameFilter('history_filter');
+ }
+
+ /**
+ * Tab label getter
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('Submission History');
+ }
+
+ /**
+ * Tab title getter
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('Submission History');
+ }
+
+ /**
+ * Check if tab can be shown
+ *
+ * @return bool
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Check if tab hidden
+ *
+ * @return bool
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+
+ /**
+ * Initialize history colelction
+ * Set aaplication filter
+ *
+ * @return Mage_Adminhtml_Block_Widget_Grid
+ */
+ protected function _prepareCollection()
+ {
+ $collection = Mage::getResourceModel('xmlconnect/history_collection')
+ ->addApplicationFilter($this->_getApplication()->getId());
+ $this->setCollection($collection);
+ return parent::_prepareCollection();
+ }
+
+ /**
+ * Configuration of grid
+ *
+ * @return Mage_Adminhtml_Block_Widget_Grid
+ */
+ protected function _prepareColumns()
+ {
+ $this->addColumn('activation_key', array(
+ 'header' => Mage::helper('xmlconnect')->__('Activation Key'),
+ 'align' => 'left',
+ 'index' => 'activation_key',
+ 'type' => 'text'
+ ));
+
+ $this->addColumn('created_at', array(
+ 'header' => Mage::helper('xmlconnect')->__('Date Submitted'),
+ 'align' => 'left',
+ 'index' => 'created_at',
+ 'type' => 'datetime'
+ ));
+
+ return parent::_prepareColumns();
+ }
+
+ /**
+ * Ajax grid URL getter
+ * @return string
+ */
+ public function getGridUrl()
+ {
+ return $this->getUrl('*/*/submissionHistoryGrid', array('_current'=>true));
+ }
+
+ /**
+ * Get current application model
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ protected function _getApplication()
+ {
+ return Mage::registry('current_app');
+ }
+
+ /**
+ * Remove row click url
+ *
+ * @param Mage_Catalog_Model_Product|Varien_Object $row
+ * @return string
+ */
+ public function getRowUrl($row)
+ {
+ return '';
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php
new file mode 100644
index 0000000000..1acec8fcc1
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php
@@ -0,0 +1,41 @@
+setId('mobile_app_tabs');
+ $this->setDestElementId('edit_form');
+ $this->setTitle(Mage::helper('xmlconnect')->__('Manage Mobile App'));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php
new file mode 100644
index 0000000000..d8a9d1d7c1
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php
@@ -0,0 +1,84 @@
+getBeforeElementHtml() . 'serialize($this->getHtmlAttributes())
+ . ' >'.$this->getEscapedValue().' '.$this->getAfterElementHtml();
+ return $html;
+ }
+
+ /**
+ * Getter for "before_element_html"
+ *
+ * @return string
+ */
+ public function getBeforeElementHtml()
+ {
+ return $this->getData('before_element_html');
+ }
+
+ /**
+ * Return label html code
+ *
+ * @param string $idSuffix
+ * @return string
+ */
+ public function getLabelHtml($idSuffix = '')
+ {
+ if (!is_null($this->getLabel())) {
+ $html = ''.$this->getLabel()
+ . ( $this->getRequired() ? ' * ' : '' ).' ';
+ } else {
+ $html = '';
+ }
+ return $html;
+ }
+
+ /**
+ * Overriding toHtml parent method
+ * Adding addrow Block to element renderer
+ *
+ * @return string
+ */
+ public function toHtml()
+ {
+ $blockClassName = Mage::getConfig()->getBlockClassName('adminhtml/template');
+ $jsBlock = new $blockClassName;
+ $jsBlock->setTemplate('xmlconnect/form/element/addrow.phtml');
+ $jsBlock->setOptions($this->getOptions());
+ return parent::toHtml() . $jsBlock->toHtml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php
new file mode 100644
index 0000000000..41ad94b739
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php
@@ -0,0 +1,39 @@
+addClass('color {required:false,hash:true}');
+ return parent::getHtml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Font.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Font.php
new file mode 100644
index 0000000000..63324848c0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Font.php
@@ -0,0 +1,94 @@
+setType('font');
+ }
+
+ /**
+ * Setting stored data to Font element
+ *
+ * @param array $conf
+ */
+ public function initFields($conf)
+ {
+ $name = $conf['name'];
+
+ $this->addElement(new Varien_Data_Form_Element_Select(array(
+ 'name' => $name . '[name]',
+ 'values' => $conf['fontNames'],
+ 'style' => 'width: 206px; margin: 0',
+ )));
+
+ $this->addElement(new Varien_Data_Form_Element_Select(array(
+ 'name' => $name . '[size]',
+ 'values' => $conf['fontSizes'],
+ 'style' => 'width: 70px; margin: 0',
+ )));
+
+ $this->addElement(new Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Color(array(
+ 'name' => $name . '[color]',
+ 'style' => 'width: 60px; margin: 0'
+ )));
+ }
+
+ /**
+ * Add form element
+ *
+ * @param Varien_Data_Form_Element_Abstract $element
+ * @param boolean|'^'|string $after
+ * @return Varien_Data_Form
+ */
+ public function addElement(Varien_Data_Form_Element_Abstract $element, $after=false)
+ {
+ $element->setId($element->getData('name'));
+ $element->setNoSpan(TRUE);
+ parent::addElement($element, $after);
+ }
+
+ /**
+ * Get Rendered Element Html
+ *
+ * @return string
+ */
+ public function getElementHtml()
+ {
+ $el = array();
+ foreach ($this->getElements() as $element) {
+ $el[] .= $element->toHtml();
+ }
+ return $el[0] . $el[1] . ' ' . $el[2];
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Image.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Image.php
new file mode 100644
index 0000000000..77cdff62ad
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Image.php
@@ -0,0 +1,88 @@
+getValue()) {
+ if (strpos($this->getValue(), '://') === FALSE ) {
+ $url = Mage::getBaseUrl('media') . 'xmlconnect/' . Mage::helper('xmlconnect/image')->getFileDefaultSizeSuffixAsUrl($this->getValue());
+ } else {
+ $url = $this->getValue();
+ }
+ } else {
+ $url = $this->getDefaultValue();
+ }
+ return $url;
+ }
+
+ /**
+ * Get "clear" filename from element
+ *
+ * @return string
+ */
+ public function getUploadName()
+ {
+ /**
+ * Ugly hack to avoid $_FILES[..]['name'][..][..]
+ */
+ $name = $this->getName();
+ $name = strtr($name, array('[' => '/', ']' => ''));
+ return $name;
+ }
+
+ /**
+ * Compose output html for element
+ *
+ * @return string
+ */
+ public function getElementHtml()
+ {
+ $html = '';
+
+ $url = $this->_getUrl();
+ $html .= '
';
+
+ $html .= '
';
+
+ $this->setClass('input-file');
+ $html .= '
serialize($this->getHtmlAttributes()).'/>'."\n";
+ $html.= $this->getAfterElementHtml();
+
+ $html.= '
';
+
+ return $html;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Page.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Page.php
new file mode 100644
index 0000000000..d333b4ce22
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Page.php
@@ -0,0 +1,98 @@
+setType('page');
+ }
+
+ /**
+ * Setting stored data to page element
+ *
+ * @param array $conf
+ */
+ public function initFields($conf)
+ {
+ $this->addElement(new Varien_Data_Form_Element_Text(array(
+ 'name' => $conf['name'] . '[label]',
+ 'class' => 'label onclick_text',
+ )));
+
+ $this->addElement(new Varien_Data_Form_Element_Select(array(
+ 'name' => $conf['name'] . '[id]',
+ 'values' => $conf['values'],
+ )));
+ }
+
+ /**
+ * Add form element
+ *
+ * @param Varien_Data_Form_Element_Abstract $element
+ * @param boolean|'^'|string $after
+ * @return Varien_Data_Form
+ */
+ public function addElement(Varien_Data_Form_Element_Abstract $element, $after=false)
+ {
+ $element->setId($element->getData('name'));
+ parent::addElement($element, $after);
+ }
+
+ /**
+ * Getter for Label field
+ * fetching first element as label
+ *
+ * @param string $idSuffix
+ * @return string
+ */
+ public function getLabelHtml($idSuffix = '')
+ {
+ list($label, $element) = $this->getElements();
+ return $label->toHtml();
+ }
+
+ /**
+ * Enter description here...
+ * gettter for second part of rendered field ("selectbox" and "delete button")
+ * fetching second element as
+ *
+ * @return string
+ */
+ public function getElementHtml()
+ {
+ list($label, $element) = $this->getElements();
+ return $element->toHtml() . ' ' .
+ ''
+ . Mage::helper('xmlconnect')->__('Delete') . ' ';
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Tabs.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Tabs.php
new file mode 100644
index 0000000000..edeaae8d18
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Tabs.php
@@ -0,0 +1,44 @@
+getBlockClassName('adminhtml/template');
+ $block = new $blockClassName;
+ $block->setTemplate('xmlconnect/form/element/app_tabs.phtml');
+ $tabs = Mage::getModel('xmlconnect/tabs', $this->getValue());
+ $block->setTabs($tabs);
+ $block->setName($this->getName());
+ return $block->toHtml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Theme.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Theme.php
new file mode 100644
index 0000000000..35d5bbeee0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Theme.php
@@ -0,0 +1,43 @@
+getBlockClassName('xmlconnect/adminhtml_mobile_edit_tab_design_themes');
+ $block = new $blockClassName;
+ $block->setThemes($this->getThemes());
+ $block->setName($this->getName());
+ $block->setValue($this->getValue());
+ return $block->toHtml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid.php
new file mode 100644
index 0000000000..2b6a26c24a
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid.php
@@ -0,0 +1,115 @@
+setId('mobile_apps_grid');
+ $this->setDefaultSort('application_id');
+ $this->setDefaultDir('ASC');
+ }
+
+ /**
+ * Initialize grid data collection
+ *
+ * @return Mage_Adminhtml_Block_Widget_Grid
+ */
+ protected function _prepareCollection()
+ {
+ $collection = Mage::getModel('xmlconnect/application')->getCollection();
+ $this->setCollection($collection);
+ return parent::_prepareCollection();
+ }
+
+ /**
+ * Declare grid columns
+ *
+ * @return Mage_Adminhtml_Block_Widget_Grid
+ */
+ protected function _prepareColumns()
+ {
+ $this->addColumn('name', array(
+ 'header' => Mage::helper('xmlconnect')->__('App Name'),
+ 'align' => 'left',
+ 'index' => 'name',
+ ));
+
+ $this->addColumn('code', array(
+ 'header' => Mage::helper('xmlconnect')->__('Code'),
+ 'align' => 'left',
+ 'index' => 'code',
+ 'width' => '200',
+ ));
+
+ if (!Mage::app()->isSingleStoreMode()) {
+ $this->addColumn('store_id', array(
+ 'header' => Mage::helper('xmlconnect')->__('Store View'),
+ 'index' => 'store_id',
+ 'type' => 'store',
+ 'store_view' => true,
+ 'sortable' => false,
+ 'width' => '250',
+ ));
+ }
+
+ $this->addColumn('type', array(
+ 'header' => Mage::helper('xmlconnect')->__('Device'),
+ 'type' => 'text',
+ 'index' => 'type',
+ 'align' => 'center',
+ 'filter' => 'adminhtml/widget_grid_column_filter_select',
+ 'options' => Mage::helper('xmlconnect')->getSupportedDevices(),
+ 'renderer' => 'xmlconnect/adminhtml_mobile_grid_renderer_type',
+ ));
+
+ $this->addColumn('status', array(
+ 'header' => Mage::helper('xmlconnect')->__('Status'),
+ 'index' => 'status',
+ 'renderer' => 'xmlconnect/adminhtml_mobile_grid_renderer_bool',
+ 'align' => 'center',
+ 'filter' => 'adminhtml/widget_grid_column_filter_select',
+ 'options' => Mage::helper('xmlconnect')->getStatusOptions(),
+
+ ));
+
+ return parent::_prepareColumns();
+ }
+
+ /**
+ * Row click url
+ *
+ * @param Mage_Catalog_Model_Product|Varien_Object $row
+ * @return string
+ */
+ public function getRowUrl($row)
+ {
+ return $this->getUrl('*/*/edit', array('application_id' => $row->getId()));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid/Renderer/Bool.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid/Renderer/Bool.php
new file mode 100644
index 0000000000..3d55817be3
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid/Renderer/Bool.php
@@ -0,0 +1,56 @@
+
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Grid_Renderer_Bool extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
+{
+ /**
+ * Render application status image
+ *
+ * @param Varien_Object $row
+ * @return string
+ */
+ public function render(Varien_Object $row)
+ {
+ $result = '';
+ $status = (int) $row->getData($this->getColumn()->getIndex());
+ $options = Mage::helper('xmlconnect')->getStatusOptions();
+ if ($status == Mage_XmlConnect_Model_Application::APP_STATUS_SUCCESS) {
+ $result = ' ' . (isset($options[$status]) ? $options[$status] : '');
+ } else if ($status == Mage_XmlConnect_Model_Application::APP_STATUS_INACTIVE) {
+ $result = ' ' . (isset($options[$status]) ? $options[$status] : '');
+ }
+ return $result;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid/Renderer/Type.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid/Renderer/Type.php
new file mode 100644
index 0000000000..4b15440113
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Grid/Renderer/Type.php
@@ -0,0 +1,52 @@
+
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Grid_Renderer_Type extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
+{
+ /**
+ * Renders grid column
+ *
+ * @param Varien_Object $row
+ * @return string
+ */
+ public function render(Varien_Object $row)
+ {
+ $type = $row->getData($this->getColumn()->getIndex());
+ $devices = Mage::helper('xmlconnect')->getSupportedDevices();
+ if (isset($devices[$type])) {
+ return $devices[$type];
+ } else {
+ return $type;
+ }
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Preview/Content.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Preview/Content.php
new file mode 100644
index 0000000000..4966b47f5e
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Preview/Content.php
@@ -0,0 +1,96 @@
+getEnabledTabs() as $tab) {
+ $conf['tabBar'][$tab->action]['label'] = $tab->label;
+ $conf['tabBar'][$tab->action]['image'] =
+ Mage::helper('xmlconnect/image')->getSkinImagesUrl('mobile_preview/' . $tab->image);
+ }
+ }
+ $this->setData('conf', $conf);
+ }
+
+ /**
+ * Get preview images url
+ *
+ * @param string $name - file name
+ * @return string
+ */
+ public function getPreviewImagesUrl($name = '')
+ {
+ return Mage::helper('xmlconnect/image')->getSkinImagesUrl('mobile_preview/' . $name);
+ }
+
+
+ /**
+ * Retrieve url for images in the skin folder
+ *
+ * @param string $name - path to file name relative to the skin dir
+ * @return string
+ */
+ public function getDesignPreviewImageUrl($name)
+ {
+ return Mage::helper('xmlconnect/image')->getSkinImagesUrl('design_default/' . $name);
+ }
+
+ /**
+ * Expose function getInterfaceImagesPaths from xmlconnect/images
+ * Converts Data path(conf/submision/zzzz) to config path (conf/native/submission/zzzzz)
+ *
+ * @param string $path
+ * @return array
+ */
+ public function getInterfaceImagesPaths($path)
+ {
+ $path = preg_replace('/^conf\/(.*)$/', 'conf/native/${1}', $path);
+ return Mage::helper('xmlconnect/image')->getInterfaceImagesPaths($path);
+ }
+
+ /**
+ * Get xmlconnect css url
+ *
+ * @param string $name - file name
+ * @return string
+ */
+ public function getPreviewCssUrl($name = '')
+ {
+ return Mage::getDesign()->getSkinUrl('xmlconnect/' . $name);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Preview/Tabitems.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Preview/Tabitems.php
new file mode 100644
index 0000000000..489e96487c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Preview/Tabitems.php
@@ -0,0 +1,60 @@
+setTemplate('xmlconnect/edit/tab/design/preview/tab_items.phtml');
+ }
+
+ /**
+ * Collect tab items array
+ *
+ * @return array
+ */
+ public function getTabItems()
+ {
+ $items = array();
+ $model = Mage::registry('current_app');
+ $tabs = $model->getEnabledTabsArray();
+
+ $tabLimit = (int) Mage::getStoreConfig('xmlconnect/devices/'.strtolower($model->getType()).'/tab_limit');
+ $showedTabs = 0;
+ foreach ($tabs as $tab) {
+ if (++$showedTabs > $tabLimit) {
+ break;
+ }
+ $items[] = array(
+ 'label' => Mage::helper('xmlconnect')->getTabLabel($tab->action),
+ 'image' => $tab->image);
+ }
+ return $items;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission.php
new file mode 100644
index 0000000000..4d5f37a4d4
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission.php
@@ -0,0 +1,79 @@
+_objectId = 'application_id';
+ $this->_controller = 'adminhtml_mobile';
+ $this->_blockGroup = 'xmlconnect';
+ $this->_mode = 'submission';
+ parent::__construct();
+
+ $this->removeButton('delete');
+ $this->removeButton('save');
+ $this->removeButton('reset');
+
+ $app = Mage::registry('current_app');
+ if ($app && $app->getIsResubmitAction()) {
+ $label = Mage::helper('xmlconnect')->__('Resubmit App');
+ } else {
+ $label = Mage::helper('xmlconnect')->__('Submit App');
+ }
+
+ $this->_addButton('submission_post', array(
+ 'class' => 'save',
+ 'label' => $label,
+ 'onclick' => "submitApplication()",
+ ));
+
+ $this->_updateButton('back', 'label', Mage::helper('xmlconnect')->__('Back to App Edit'));
+ $this->_updateButton('back', 'onclick', 'setLocation(\''. $this->getUrl('*/*/edit',
+ array('application_id' => Mage::registry('current_app')->getId())) . '\')');
+
+ }
+
+ /**
+ * Get form header title
+ *
+ * @return string
+ */
+ public function getHeaderText()
+ {
+ $app = Mage::registry('current_app');
+ if ($app && $app->getId()) {
+ return Mage::helper('xmlconnect')->__('Submit App "%s"', $this->htmlEscape($app->getName()));
+ }
+ return '';
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Form.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Form.php
new file mode 100644
index 0000000000..df1653f0a8
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Form.php
@@ -0,0 +1,40 @@
+ 'edit_form', 'action' => $this->getUrl('*/mobile/submission'), 'method' => 'post', 'enctype' => 'multipart/form-data'));
+ $form->setUseContainer(true);
+ $this->setForm($form);
+ return parent::_prepareForm();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Container.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Container.php
new file mode 100644
index 0000000000..a53484c75d
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Container.php
@@ -0,0 +1,89 @@
+setShowGlobalIcon(true);
+ $this->setTemplate('xmlconnect/submission/container.phtml');
+ }
+
+ /**
+ * Prepare label for tab
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('Submission');
+ }
+
+ /**
+ * Prepare title for tab
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('Submission');
+ }
+
+ /**
+ * Returns status flag about this tab can be showen or not
+ *
+ * @return true
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Returns status flag about this tab hidden or not
+ *
+ * @return true
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+
+ /**
+ * Retrive submission action url
+ *
+ * @return string
+ */
+ public function getActionUrl()
+ {
+ return $this->getUrl('*/*/submissionPost', array('key' => Mage::registry('current_app')->getId()));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Container/Submission.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Container/Submission.php
new file mode 100644
index 0000000000..45e7e4aac0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Container/Submission.php
@@ -0,0 +1,274 @@
+setShowGlobalIcon(true);
+ }
+
+ /**
+ * Adding preview for images if application was submitted(so we have saved images)
+ *
+ * @return Mage_Core_Block_Abstract
+ */
+ protected function _prepareLayout()
+ {
+ $block = $this->getLayout()->createBlock('adminhtml/template')
+ ->setTemplate('xmlconnect/submission/app_icons_preview.phtml')
+ ->setImages($this->getApplication()->getImages());
+ $this->setChild('images', $block);
+ parent::_prepareLayout();
+ }
+
+ /**
+ * Add image uploader to fieldset
+ *
+ * @param Varien_Data_Form_Element_Fieldset $fieldset
+ * @param string $fieldName
+ * @param string $title
+ * @param string $note
+ * @param string $default
+ * @param boolean $required
+ */
+ public function addImage($fieldset, $fieldName, $title, $note = '', $default = '', $required = false)
+ {
+ $fieldset->addField($fieldName, 'image', array(
+ 'name' => $fieldName,
+ 'label' => $title,
+ 'note' => !empty($note) ? $note : null,
+ 'required' => $required,
+ ));
+ }
+
+ /**
+ * Prepare form before rendering HTML
+ *
+ * @return Mage_Adminhtml_Block_Widget_Form
+ */
+ protected function _prepareForm()
+ {
+ $form = new Varien_Data_Form();
+ $this->setForm($form);
+
+ $form->setAction($this->getUrl('*/mobile/submission'));
+ $isResubmit = $this->getApplication()->getIsResubmitAction();
+ $formData = $this->getApplication()->getFormData();
+
+ $url = Mage::getStoreConfig('xmlconnect/mobile_application/activation_key_url');
+ $afterElementHtml = Mage::helper('xmlconnect')->__('In order to submit your app, you need to first purchase a %s from MagentoCommerce', $url, Mage::helper('xmlconnect')->__('Activation Key'));
+ $fieldset = $form->addFieldset('submit_keys', array('legend' => Mage::helper('xmlconnect')->__('Key')));
+ $field = $fieldset->addField('conf[submit_text][key]', 'text', array(
+ 'name' => 'conf[submit_text][key]',
+ 'label' => Mage::helper('xmlconnect')->__('Activation Key'),
+ 'value' => isset($formData['conf[submit_text][key]']) ? $formData['conf[submit_text][key]'] : null,
+ 'after_element_html' => $afterElementHtml,
+ ));
+ if (!$isResubmit) {
+ $field->setRequired(true);
+ } else {
+ $field->setDisabled('disabled');
+ $fieldset->addField('conf[submit_text][key]_hidden', 'hidden', array(
+ 'name' => 'conf[submit_text][key]',
+ 'value' => isset($formData['conf[submit_text][key]']) ? $formData['conf[submit_text][key]'] : null,
+ ));
+ }
+
+ if ($isResubmit) {
+ $url = Mage::getStoreConfig('xmlconnect/mobile_application/resubmission_key_url');
+ $afterElementHtml = Mage::helper('xmlconnect')->__('In order to resubmit your app, you need to first purchase a %s from MagentoCommerce', $url, Mage::helper('xmlconnect')->__('Resubmission Key'));
+
+ $fieldset->addField('conf[submit_text][resubmission_activation_key]', 'text', array(
+ 'name' => 'conf[submit_text][resubmission_activation_key]',
+ 'label' => Mage::helper('xmlconnect')->__('Resubmission Key'),
+ 'value' => isset($formData['conf[submit_text][resubmission_activation_key]']) ? $formData['conf[submit_text][resubmission_activation_key]'] : null,
+ 'required' => true,
+ 'after_element_html' => $afterElementHtml,
+ ));
+ }
+
+ $fieldset = $form->addFieldset('submit_general', array('legend' => Mage::helper('xmlconnect')->__('Submission Fields')));
+
+ $fieldset->addField('submission_action', 'hidden', array(
+ 'name' => 'submission_action',
+ 'value' => '1',
+ ));
+ $fieldset->addField('conf/submit_text/title', 'text', array(
+ 'name' => 'conf[submit_text][title]',
+ 'label' => Mage::helper('xmlconnect')->__('Title'),
+ 'maxlength' => '200',
+ 'value' => isset($formData['conf[submit_text][title]']) ? $formData['conf[submit_text][title]'] : null,
+ 'note' => Mage::helper('xmlconnect')->__('Name that appears beneath your app when users install it to their device. We recommend choosing a name that is 10-12 characters and that your customers will recognize.'),
+ 'required' => true,
+ ));
+
+ $field = $fieldset->addField('conf/submit_text/description', 'textarea', array(
+ 'name' => 'conf[submit_text][description]',
+ 'label' => Mage::helper('xmlconnect')->__('Description'),
+ 'maxlength' => '500',
+ 'value' => isset($formData['conf[submit_text][description]']) ? $formData['conf[submit_text][description]'] : null,
+ 'note' => Mage::helper('xmlconnect')->__('Description that appears in the iTunes App Store. 4000 chars maximum. '),
+ 'required' => true,
+ ));
+ $field->setRows(15);
+
+ $fieldset->addField('conf/submit_text/contact_email', 'text', array(
+ 'name' => 'conf[submit_text][email]',
+ 'label' => Mage::helper('xmlconnect')->__('Contact Email'),
+ 'class' => 'email',
+ 'maxlength' => '40',
+ 'value' => isset($formData['conf[submit_text][email]']) ? $formData['conf[submit_text][email]'] : null,
+ 'note' => Mage::helper('xmlconnect')->__('Administrative contact for this app and for app submission issues.'),
+ 'required' => true,
+ ));
+
+ $fieldset->addField('conf/submit_text/price_free_label', 'label', array(
+ 'name' => 'conf[submit_text][price_free_label]',
+ 'label' => Mage::helper('xmlconnect')->__('Price'),
+ 'value' => Mage::helper('xmlconnect')->__('Free'),
+ 'maxlength' => '40',
+ 'checked' => 'checked',
+ 'note' => Mage::helper('xmlconnect')->__('Only free apps are allowed in this version.'),
+ ));
+
+ $fieldset->addField('conf/submit_text/price_free', 'hidden', array(
+ 'name' => 'conf[submit_text][price_free]',
+ 'value' => '1',
+ ));
+
+ $selected = isset($formData['conf[submit_text][country]']) ? explode(',', $formData['conf[submit_text][country]']) : null;
+ $fieldset->addField('conf/submit_text/country', 'multiselect', array(
+ 'name' => 'conf[submit_text][country][]',
+ 'label' => Mage::helper('xmlconnect')->__('Country'),
+ 'values' => Mage::helper('xmlconnect')->getCountryOptionsArray(),
+ 'value' => $selected,
+ 'note' => Mage::helper('xmlconnect')->__('Make this app available in the following territories'),
+ 'required' => true,
+ ));
+
+ $fieldset->addField('conf/submit_text/copyright', 'text', array(
+ 'name' => 'conf[submit_text][copyright]',
+ 'label' => Mage::helper('xmlconnect')->__('Copyright'),
+ 'maxlength' => '200',
+ 'value' => isset($formData['conf[submit_text][copyright]']) ? $formData['conf[submit_text][copyright]'] : null,
+ 'note' => Mage::helper('xmlconnect')->__('Appears in the info section of your app (example: Copyright 2010 – Your Company, Inc.)'),
+ 'required' => true,
+ ));
+
+ $fieldset->addField('conf/submit_text/keywords', 'text', array(
+ 'name' => 'conf[submit_text][keywords]',
+ 'label' => Mage::helper('xmlconnect')->__('Keywords'),
+ 'maxlength' => '100',
+ 'value' => isset($formData['conf[submit_text][keywords]']) ? $formData['conf[submit_text][keywords]'] : null,
+ 'note' => Mage::helper('xmlconnect')->__('One or more keywords that describe your app. Keywords are matched to users` searches in the App Store and help return accurate search results. Separate multiple keywords with commas. 100 chars is maximum.'),
+ ));
+
+ $fieldset = $form->addFieldset('submit_icons', array('legend' => Mage::helper('xmlconnect')->__('Icons')));
+ $this->addImage($fieldset, 'conf/submit/icon', Mage::helper('xmlconnect')->__('Large iTunes Icon'),
+ Mage::helper('xmlconnect')->__('Large icon that appears in the iTunes App Store. You do not need to apply a gradient or soft edges (this is done automatically by Apple). Required size: 512px x 512px.'), '', true);
+ $this->addImage($fieldset, 'conf/submit/loader_image', Mage::helper('xmlconnect')->__('Loader Splash Screen'),
+ Mage::helper('xmlconnect')->__('Image that appears on first screen while your app is loading. Required size: 320px x 460px.'), '', true);
+
+ $this->addImage($fieldset, 'conf/submit/logo', Mage::helper('xmlconnect')->__('Custom App Icon'),
+ Mage::helper('xmlconnect')->__('Icon that will appear on the user’s phone after they download your app. You do not need to apply a gradient or soft edges (this is done automatically by Apple). Recommended size: 57px x 57px at 72 dpi.'), '', true);
+ $this->addImage($fieldset, 'conf/submit/big_logo', Mage::helper('xmlconnect')->__('Copyright Page Logo'),
+ Mage::helper('xmlconnect')->__('Store logo that is displayed on copyright page of app. Preferred size: 100px x 100px.'), '', true);
+
+ return parent::_prepareForm();
+ }
+
+ /**
+ * Prepare label for tab
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return Mage::helper('xmlconnect')->__('Submission');
+ }
+
+ /**
+ * Prepare title for tab
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return Mage::helper('xmlconnect')->__('Submission');
+ }
+
+ /**
+ * Returns status flag about this tab can be showen or not
+ *
+ * @return true
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Returns status flag about this tab hidden or not
+ *
+ * @return false
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+
+ /**
+ * Configure image element type
+ *
+ * @return array
+ */
+ protected function _getAdditionalElementTypes()
+ {
+ return array(
+ 'image' => Mage::getConfig()->getBlockClassName('xmlconnect/adminhtml_mobile_helper_image'),
+ );
+ }
+
+ /**
+ * Prepare html output
+ * Adding preview for images if application was submitted(so we have saved images)
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return parent::_toHtml() . $this->getChildHtml('images');
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Submission.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Submission.php
new file mode 100644
index 0000000000..5f627fdce7
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tab/Submission.php
@@ -0,0 +1,285 @@
+setShowGlobalIcon(true);
+
+ }
+
+ protected function _prepareLayout()
+ {
+ $application = Mage::registry('current_app');
+
+ $actionUrl = $this->getUrl('*/*/submissionPost', array('key' => $application->getId()));
+ $this->setChild('submission_scripts',
+ $this->getLayout()->createBlock('adminhtml/template')
+ ->setActionUrl($actionUrl)
+ ->setTemplate('xmlconnect/submission_scripts.phtml'));
+ if ($application->getIsResubmitAction()) {
+ $block = $this->getLayout()->createBlock('adminhtml/template')
+ ->setTemplate('xmlconnect/resubmit.phtml')
+ ->setActionUrl($actionUrl)
+ ->setActivationKey($application->getActivationKey())
+ ->setResubmissionName('conf[submit_text][resubmission_activation_key]');
+ $this->setChild('resubmit', $block);
+
+ $block = $this->getLayout()->createBlock('adminhtml/template')
+ ->setTemplate('xmlconnect/images.phtml')
+ ->setImages($application->getImages());
+ $this->setChild('images', $block);
+ }
+ parent::_prepareLayout();
+ }
+
+
+ /**
+ * Add image uploader to fieldset
+ *
+ * @param Varien_Data_Form_Element_Fieldset $fieldset
+ * @param string $fieldName
+ * @param string $title
+ */
+ protected function addImage($fieldset, $fieldName, $title, $note = '')
+ {
+ $fieldset->addField($fieldName, 'image', array(
+ 'name' => $fieldName,
+ 'label' => $title,
+ 'note' => !empty($note) ? $note : null,
+ ));
+ }
+
+ protected function _prepareForm()
+ {
+ $form = new Varien_Data_Form();
+ $this->setForm($form);
+
+ $form->setAction($this->getUrl('*/mobile/submission'));
+ $application = Mage::registry('current_app');
+ $isResubmit = $application->getIsResubmitAction();
+ $formData = $application->getFormData();
+
+ $fieldset = $form->addFieldset('submit0', array('legend' => $this->__('Submission Fields')));
+
+ $fieldset->addField('conf/submit_text/title', 'text', array(
+ 'name' => 'conf[submit_text][title]',
+ 'label' => $this->__('Title'),
+ 'maxlength' => '200',
+ 'value' => isset($formData['conf[submit_text][title]']) ? $formData['conf[submit_text][title]'] : null,
+ 'note' => $this->__('This is the name that will appear beneath your app when users install it to their device. . We recommend choosing a name that is 10-12 characters in length, and that your customers will recognize.'),
+ 'required' => true,
+ ));
+
+ $field = $fieldset->addField('conf/submit_text/description', 'textarea', array(
+ 'name' => 'conf[submit_text][description]',
+ 'label' => $this->__('Description'),
+ 'maxlength' => '500',
+ 'value' => isset($formData['conf[submit_text][description]']) ? $formData['conf[submit_text][description]'] : null,
+ 'note' => $this->__('This is the description that will appear in the iTunes marketplace. '),
+ 'required' => true,
+ ));
+ $field->setRows(15);
+
+ $fieldset->addField('conf/submit_text/username/', 'text', array(
+ 'name' => 'conf[submit_text][username]',
+ 'label' => $this->__('Username'),
+ 'maxlength' => '40',
+ 'value' => isset($formData['conf[submit_text][username]']) ? $formData['conf[submit_text][username]'] : null,
+ 'note' => $this->__('Paypal Merchant Account Username.'),
+ 'required' => true,
+ ));
+
+ $fieldset->addField('conf/submit_text/email', 'text', array(
+ 'name' => 'conf[submit_text][email]',
+ 'label' => $this->__('Email'),
+ 'class' => 'email',
+ 'maxlength' => '40',
+ 'value' => isset($formData['conf[submit_text][email]']) ? $formData['conf[submit_text][email]'] : null,
+ 'note' => $this->__('Paypal Merchant Account Email.'),
+ 'required' => true,
+ ));
+
+ $fieldset->addField('conf/submit_text/price_free', 'radio', array(
+ 'name' => 'conf[submit_text][price_free]',
+ 'label' => $this->__('Price'),
+ 'value' => '1',
+ 'maxlength' => '40',
+ 'after_element_html' => $this->__('Free'),
+ 'onclick' => "$('conf/submit_text/price').setValue('')",
+ ));
+
+ $fieldset->addField('conf/submit_text/price', 'text', array(
+ 'name' => 'conf[submit_text][price]',
+ 'label' => $this->__(' '),
+ 'maxlength' => '40',
+ 'value' => isset($formData['conf[submit_text][price]']) ? $formData['conf[submit_text][price]'] : null,
+ 'note' => $this->__('You can set any price you want for your app, or you can give it away for free. Most apps range from $0.99 - $4.99'),
+ 'onchange' => "$('conf/submit_text/price_free').checked = false",
+
+ ));
+
+ $selected = isset($formData['conf[submit_text][country]']) ? json_decode($formData['conf[submit_text][country]']) : null;
+ $fieldset->addField('conf/submit_text/country', 'multiselect', array(
+ 'name' => 'conf[submit_text][country][]',
+ 'label' => $this->__('Country'),
+ 'values' => Mage::helper('xmlconnect')->getCountryOptionsArray(),
+ 'value' => $selected,
+ 'note' => $this->__('Make this app available in the following territories'),
+ ));
+
+ $fieldset->addField('conf/submit_text/country_additional', 'text', array(
+ 'name' => 'conf[submit_text][country_additional]',
+ 'label' => $this->__('Additional Countries'),
+ 'maxlength' => '200',
+ 'value' => isset($formData['conf[submit_text][country_additional]']) ? $formData['conf[submit_text][country_additional]'] : null,
+ 'note' => $this->__('You can set any additional countries added by Apple Store.'),
+
+ ));
+
+ $fieldset->addField('conf/submit_text/copyright', 'textarea', array(
+ 'name' => 'conf[submit_text][copyright]',
+ 'label' => $this->__('Copyright'),
+ 'maxlength' => '200',
+ 'value' => isset($formData['conf[submit_text][copyright]']) ? $formData['conf[submit_text][copyright]'] : null,
+ 'note' => $this->__('This will appear in the info section of your App (example: Copyright 2010 – Your Company, Inc.)'),
+ 'size' => '30',
+ 'required' => true,
+ ));
+
+ $fieldset->addField('conf/submit_text/push_notification', 'checkbox', array(
+ 'name' => 'conf[submit_text][push_notification]',
+ 'label' => $this->__('Push Notification'),
+ 'checked' => isset($formData['conf[submit_text][push_notification]']),
+ 'value' => '1',
+ ));
+
+ $fieldset = $form->addFieldset('submit1', array('legend' => $this->__('Icons')));
+ $this->addImage($fieldset, 'conf/submit/icon', 'Application Icon',
+ $this->__('Apply will automatically resize this image for display in the App Store and on users’ devices. A gloss (i.e. gradient) will also be applied, so you do not need to apply a gradient. Image must be at least 512x512'));
+ $this->addImage($fieldset, 'conf/submit/loader_image', 'Loader Splash Screen',
+ $this->__('Users will see this image as the first screen while your application is loading. It is a 320x460 image.'));
+
+ $this->addImage($fieldset, 'conf/submit/logo', $this->__('Custom application icon'),
+ $this->__('This icon will be used for users’ devices in case if different than AppSore icon needed. '));
+ $this->addImage($fieldset, 'conf/submit/big_logo', $this->__('Copyright page logo'),
+ $this->__('Store logo that will be displayed on copyright page of application '));
+
+ $fieldset = $form->addFieldset('submit2', array('legend' => $this->__('Key')));
+ $fieldset->addField('conf[submit_text][key]', 'text', array(
+ 'name' => 'conf[submit_text][key]',
+ 'label' => $this->__('Activation Key'),
+ 'value' => isset($formData['conf[submit_text][key]']) ? $formData['conf[submit_text][key]'] : null,
+ 'disabled' => $isResubmit,
+ 'after_element_html' => ''
+ . $this->__('Get Activation Key'). ' ',
+ ));
+
+ if (!$isResubmit) {
+ $fieldset->addField('submit_application', 'button', array(
+ 'name' => 'submit_application',
+ 'label'=>$this->__('Submit'),
+ 'value' => $this->__('Submit Application'),
+ 'onclick' => 'submitApplication()',
+ ));
+ } else {
+ $fieldset->addField('submit_application', 'button', array(
+ 'name' => 'submit_application',
+ 'label'=> $this->__('Resubmit'),
+ 'value' => $this->__('Resubmit Application'),
+ 'onclick' => 'resubmitAction(); return false;',
+ ));
+ }
+
+ return parent::_prepareForm();
+ }
+
+ /**
+ * Prepare label for tab
+ *
+ * @return string
+ */
+ public function getTabLabel()
+ {
+ return $this->__('Submission');
+ }
+
+ /**
+ * Prepare title for tab
+ *
+ * @return string
+ */
+ public function getTabTitle()
+ {
+ return $this->__('Submission');
+ }
+
+ /**
+ * Returns status flag about this tab can be showen or not
+ *
+ * @return true
+ */
+ public function canShowTab()
+ {
+ return true;
+ }
+
+ /**
+ * Returns status flag about this tab hidden or not
+ *
+ * @return false
+ */
+ public function isHidden()
+ {
+ return false;
+ }
+
+ /**
+ * Configure image element type
+ *
+ */
+ protected function _getAdditionalElementTypes()
+ {
+ return array(
+ 'image' => Mage::getConfig()->getBlockClassName('xmlconnect/adminhtml_mobile_helper_image'),
+ );
+ }
+
+ protected function _toHtml()
+ {
+ return parent::_toHtml()
+ . $this->getChildHtml('submission_scripts')
+ . (!Mage::registry('current_app')->getIsResubmitAction() ? '' :
+ ($this->getChildHtml('mobile_edit_tab_submission_history')
+ . $this->getChildHtml('resubmit')
+ . $this->getChildHtml('images')));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tabs.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tabs.php
new file mode 100644
index 0000000000..d3961b8545
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Submission/Tabs.php
@@ -0,0 +1,40 @@
+setId('mobile_app_tabs');
+ $this->setDestElementId('edit_form');
+ $this->setTitle(Mage::helper('xmlconnect')->__('Manage Mobile App'));
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Widget/Form.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Widget/Form.php
new file mode 100644
index 0000000000..a6103b351a
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Adminhtml/Mobile/Widget/Form.php
@@ -0,0 +1,117 @@
+addField($fieldName, 'color', array(
+ 'name' => $fieldName,
+ 'label' => $title,
+ ));
+ }
+
+ /**
+ * Add image uploader to fieldset
+ *
+ * @param Varien_Data_Form_Element_Fieldset $fieldset
+ * @param string $fieldName
+ * @param string $title
+ * @param string|null $note
+ * @param string $default
+ * @param boolean $required
+ */
+ public function addImage($fieldset, $fieldName, $title, $note = null, $default = '', $required = false)
+ {
+ $fieldset->addField($fieldName, 'image', array(
+ 'name' => $fieldName,
+ 'label' => $title,
+ 'note' => $note,
+ 'default_value' => $default,
+ 'required' => $required,
+ ));
+ }
+
+ /**
+ * Add font selector to fieldset
+ *
+ * @param Varien_Data_Form_Element_Fieldset $fieldset
+ * @param string $fieldPrefix
+ * @param string $title
+ */
+ public function addFont($fieldset, $fieldPrefix, $title)
+ {
+ $el = $fieldset->addField($fieldPrefix, 'font', array(
+ 'name' => $fieldPrefix,
+ 'label' => $title,
+ ));
+ $el->initFields(array(
+ 'name' => $fieldPrefix,
+ 'fontNames' => Mage::helper('xmlconnect/iphone')->getFontList(),
+ 'fontSizes' => Mage::helper('xmlconnect/iphone')->getFontSizes(),
+ ));
+ }
+
+ /**
+ * Configure image element type
+ *
+ * @return array
+ */
+ protected function _getAdditionalElementTypes()
+ {
+ $config = Mage::getConfig();
+ return array(
+ 'image' => $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_image'),
+ 'font' => $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_font'),
+ 'color' => $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_color'),
+ 'tabs' => $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_tabs'),
+ 'theme' => $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_theme'),
+ 'page' => $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_page'),
+ 'addrow'=> $config->getBlockClassName('xmlconnect/adminhtml_mobile_form_element_addrow'),
+ );
+ }
+
+ /**
+ * Getter for current loaded application model
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ public function getApplication()
+ {
+ $model = Mage::registry('current_app');
+ if (!($model instanceof Mage_XmlConnect_Model_Application)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('App model not loaded.'));
+ }
+
+ return $model;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart.php
new file mode 100644
index 0000000000..5b08d67d99
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart.php
@@ -0,0 +1,225 @@
+
+ */
+class Mage_XmlConnect_Block_Cart extends Mage_Checkout_Block_Cart_Abstract
+{
+ /**
+ * Render shopping cart xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $cartMessages = $this->getMessages();
+ $quote = $this->getQuote();
+ $xmlObject = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $xmlObject->addAttribute('is_virtual', (int)$this->helper('checkout/cart')->getIsVirtualQuote());
+ $xmlObject->addAttribute('summary_qty', (int)$this->helper('checkout/cart')->getSummaryCount());
+ if (strlen($quote->getCouponCode())) {
+ $xmlObject->addAttribute('has_coupon_code', 1);
+ }
+ $products = $xmlObject->addChild('products');
+
+ /* @var $item Mage_Sales_Model_Quote_Item */
+ foreach ($this->getItems() as $item) {
+ $type = $item->getProductType();
+ $renderer = $this->getItemRenderer($type)->setItem($item);
+
+ /**
+ * General information
+ */
+ $itemXml = $products->addChild('item');
+ $itemXml->addChild('entity_id', $item->getProduct()->getId());
+ $itemXml->addChild('entity_type', $type);
+ $itemXml->addChild('item_id', $item->getId());
+ $itemXml->addChild('name', $xmlObject->xmlentities(strip_tags($renderer->getProductName())));
+ $itemXml->addChild('code', 'cart[' . $item->getId() . '][qty]');
+ $itemXml->addChild('qty', $renderer->getQty());
+ $icon = $renderer->getProductThumbnail()->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('product_small'));
+
+ $iconXml = $itemXml->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+
+ /**
+ * Price
+ */
+ $exclPrice = $inclPrice = 0.00;
+ if ($this->helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $exclPrice = $item->getCalculationPrice() + $item->getWeeeTaxAppliedAmount() + $item->getWeeeTaxDisposition();
+ } else {
+ $exclPrice = $item->getCalculationPrice();
+ }
+ }
+
+ if ($this->helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ $_incl = $this->helper('checkout')->getPriceInclTax($item);
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $inclPrice = $_incl + $item->getWeeeTaxAppliedAmount();
+ } else {
+ $inclPrice = $_incl - $item->getWeeeTaxDisposition();
+ }
+ }
+
+ $exclPrice = Mage::helper('xmlconnect')->formatPriceForXml($exclPrice);
+ $formatedExclPrice = $quote->getStore()->formatPrice($exclPrice, false);
+
+ $inclPrice = Mage::helper('xmlconnect')->formatPriceForXml($inclPrice);
+ $formatedInclPrice = $quote->getStore()->formatPrice($inclPrice, false);
+
+ $priceXmlObj = $itemXml->addChild('price');
+ $formatedPriceXmlObj = $itemXml->addChild('formated_price');
+
+ if ($this->helper('tax')->displayCartBothPrices()) {
+ $priceXmlObj->addAttribute('excluding_tax', $exclPrice);
+ $priceXmlObj->addAttribute('including_tax', $inclPrice);
+
+ $formatedPriceXmlObj->addAttribute('excluding_tax', $formatedExclPrice);
+ $formatedPriceXmlObj->addAttribute('including_tax', $formatedInclPrice);
+ } else {
+ if ($this->helper('tax')->displayCartPriceExclTax()) {
+ $priceXmlObj->addAttribute('regular', $exclPrice);
+ $formatedPriceXmlObj->addAttribute('regular', $formatedExclPrice);
+ }
+ if ($this->helper('tax')->displayCartPriceInclTax()) {
+ $priceXmlObj->addAttribute('regular', $inclPrice);
+ $formatedPriceXmlObj->addAttribute('regular', $formatedInclPrice);
+ }
+ }
+
+
+ /**
+ * Subtotal
+ */
+ $exclPrice = $inclPrice = 0.00;
+ if ($this->helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $exclPrice = $item->getRowTotal() + $item->getWeeeTaxAppliedRowAmount() + $item->getWeeeTaxRowDisposition();
+ } else {
+ $exclPrice = $item->getRowTotal();
+ }
+ }
+ if ($this->helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ $_incl = $this->helper('checkout')->getSubtotalInclTax($item);
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $inclPrice = $_incl + $item->getWeeeTaxAppliedRowAmount();
+ } else {
+ $inclPrice = $_incl - $item->getWeeeTaxRowDisposition();
+ }
+ }
+
+ $exclPrice = Mage::helper('xmlconnect')->formatPriceForXml($exclPrice);
+ $formatedExclPrice = $quote->getStore()->formatPrice($exclPrice, false);
+
+ $inclPrice = Mage::helper('xmlconnect')->formatPriceForXml($inclPrice);
+ $formatedInclPrice = $quote->getStore()->formatPrice($inclPrice, false);
+
+ $subtotalPriceXmlObj = $itemXml->addChild('subtotal');
+ $subtotalFormatedPriceXmlObj = $itemXml->addChild('formated_subtotal');
+
+ if ($this->helper('tax')->displayCartBothPrices()) {
+ $subtotalPriceXmlObj->addAttribute('excluding_tax', $exclPrice);
+ $subtotalPriceXmlObj->addAttribute('including_tax', $inclPrice);
+
+ $subtotalFormatedPriceXmlObj->addAttribute('excluding_tax', $formatedExclPrice);
+ $subtotalFormatedPriceXmlObj->addAttribute('including_tax', $formatedInclPrice);
+ } else {
+ if ($this->helper('tax')->displayCartPriceExclTax()) {
+ $subtotalPriceXmlObj->addAttribute('regular', $exclPrice);
+ $subtotalFormatedPriceXmlObj->addAttribute('regular', $formatedExclPrice);
+ }
+ if ($this->helper('tax')->displayCartPriceInclTax()) {
+ $subtotalPriceXmlObj->addAttribute('regular', $inclPrice);
+ $subtotalFormatedPriceXmlObj->addAttribute('regular', $formatedInclPrice);
+ }
+ }
+
+ /**
+ * Options list
+ */
+ if ($_options = $renderer->getOptionList()) {
+ $itemOptionsXml = $itemXml->addChild('options');
+ foreach ($_options as $_option) {
+ $_formatedOptionValue = $renderer->getFormatedOptionValue($_option);
+ $optionXml = $itemOptionsXml->addChild('option');
+ $optionXml->addAttribute('label', $xmlObject->xmlentities(strip_tags($_option['label'])));
+ $optionXml->addAttribute('text', $xmlObject->xmlentities(strip_tags($_formatedOptionValue['value'])));
+// if (isset($_formatedOptionValue['full_view'])) {
+// $label = strip_tags($_option['label']);
+// $value = strip_tags($_formatedOptionValue['full_view']);
+// }
+ }
+ }
+
+ /**
+ * Item messages
+ */
+ if ($messages = $renderer->getMessages()) {
+ $itemMessagesXml = $itemXml->addChild('messages');
+ foreach ($messages as $message) {
+ $messageXml = $itemMessagesXml->addChild('option');
+ $messageXml->addChild('type', $message['type']);
+ $messageXml->addChild('text', $xmlObject->xmlentities(strip_tags($message['text'])));
+ }
+ }
+ }
+
+ /**
+ * Cart messages
+ */
+ if ($cartMessages) {
+ $messagesXml = $xmlObject->addChild('messages');
+ foreach ($cartMessages as $status => $messages) {
+ foreach ($messages as $message) {
+ $messageXml = $messagesXml->addChild('message');
+ $messageXml->addChild('status', $status);
+ $messageXml->addChild('text', strip_tags($message));
+ }
+ }
+ }
+
+ /**
+ * Cross Sell Products
+ */
+ $crossSellXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($this->getChildHtml('crosssell'));
+ $xmlObject->appendChild($crossSellXmlObj);
+
+ return $xmlObject->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Crosssell.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Crosssell.php
new file mode 100644
index 0000000000..29bf967e48
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Crosssell.php
@@ -0,0 +1,84 @@
+
+ */
+class Mage_XmlConnect_Block_Cart_Crosssell extends Mage_Checkout_Block_Cart_Crosssell
+{
+ /**
+ * Render cross sell items xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $crossSellXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ if (!$this->getItemCount()) {
+ return $crossSellXmlObj->asNiceXml();
+ }
+
+ foreach ($this->getItems() as $_item) {
+ $itemXmlObj = $crossSellXmlObj->addChild('item');
+ $itemXmlObj->addChild('name', $crossSellXmlObj->xmlentities(strip_tags($_item->getName())));
+ $icon = $this->helper('catalog/image')->init($_item, 'thumbnail')
+ ->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('product_small'));
+
+ $iconXml = $itemXmlObj->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+
+ $itemXmlObj->addChild('entity_id', $_item->getId());
+ $itemXmlObj->addChild('entity_type', $_item->getTypeId());
+ $itemXmlObj->addChild('has_options', (int)$_item->getHasOptions());
+
+ if ($this->getChild('product_price')) {
+ $this->getChild('product_price')->setProduct($_item)
+ ->setProductXmlObj($itemXmlObj)
+ ->collectProductPrices();
+ }
+
+ if (!$_item->getRatingSummary()) {
+ Mage::getModel('review/review')
+ ->getEntitySummary($_item, Mage::app()->getStore()->getId());
+ }
+
+ $itemXmlObj->addChild('rating_summary', round((int)$_item->getRatingSummary()->getRatingSummary() / 10));
+ $itemXmlObj->addChild('reviews_count', $_item->getRatingSummary()->getReviewsCount());
+ }
+
+ return $crossSellXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Info.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Info.php
new file mode 100644
index 0000000000..133dbef863
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Info.php
@@ -0,0 +1,61 @@
+
+ */
+class Mage_XmlConnect_Block_Cart_Info extends Mage_XmlConnect_Block_Cart
+{
+ /**
+ * Render cart summary xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $quote = $this->getQuote();
+ $xmlObject = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $xmlObject->addChild('is_virtual', (int)$this->helper('checkout/cart')->getIsVirtualQuote());
+ $xmlObject->addChild('summary_qty', (int)$this->helper('checkout/cart')->getSummaryCount());
+ $xmlObject->addChild('virtual_qty', (int)$quote->getItemVirtualQty());
+ if (strlen($quote->getCouponCode())) {
+ $xmlObject->addChild('has_coupon_code', 1);
+ }
+
+ $totalsXml = $this->getChildHtml('totals');
+ if ($totalsXml) {
+ $totalsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($totalsXml);
+ $xmlObject->appendChild($totalsXmlObj);
+ }
+
+ return $xmlObject->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Paypal/Mep/Totals.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Paypal/Mep/Totals.php
new file mode 100644
index 0000000000..59dc468cab
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Paypal/Mep/Totals.php
@@ -0,0 +1,51 @@
+
+ */
+class Mage_XmlConnect_Block_Cart_Paypal_Mep_Totals extends Mage_Checkout_Block_Cart_Totals
+{
+ /**
+ * Render cart totals xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $paypalCart = Mage::getModel('paypal/cart', array($this->getQuote()));
+ $totalsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ foreach ($paypalCart->getTotals(true) as $code => $amount) {
+ $currencyAmount = $this->helper('core')->currency($amount, false, false);
+ $totalsXmlObj->addChild($code, Mage::helper('xmlconnect')->formatPriceForXml($currencyAmount));
+ }
+ return $totalsXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Totals.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Totals.php
new file mode 100644
index 0000000000..9fd03bafa3
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cart/Totals.php
@@ -0,0 +1,123 @@
+
+ */
+class Mage_XmlConnect_Block_Cart_Totals extends Mage_Checkout_Block_Cart_Totals
+{
+ /**
+ * Render cart totals xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $totalsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $taxConfig = Mage::getSingleton('tax/config');
+ $displayInclTax = $displayBoth = false;
+
+ foreach ($this->getQuote()->getTotals() as $total) {
+ $code = $total->getCode();
+ if ($code == 'giftcardaccount') {
+ continue;
+ }
+ $title = '';
+ $value = null;
+ $renderer = $this->_getTotalRenderer($code)->setTotal($total);
+ switch ($code) {
+ case 'subtotal':
+ if ($renderer->displayBoth()) {
+ $title = $this->helper('xmlconnect')->__('Subtotal (Excl. Tax)');
+ $this->_addTotalDataToXmlObj($totalsXmlObj, $code . '_excl_tax', $title, $total->getValueExclTax());
+
+ $code = $code . '_incl_tax';
+ $title = $this->helper('xmlconnect')->__('Subtotal (Incl. Tax)');
+ $value = $total->getValueInclTax();
+ }
+ break;
+ case 'shipping':
+ if ($renderer->displayBoth()) {
+ $title = $renderer->getExcludeTaxLabel();
+ $this->_addTotalDataToXmlObj($totalsXmlObj, $code . '_excl_tax', $title, $renderer->getShippingExcludeTax());
+
+ $code = $code . '_incl_tax';
+ $title = $renderer->getIncludeTaxLabel();
+ $value = $renderer->getShippingIncludeTax();
+ } else if ($renderer->displayIncludeTax()) {
+ $value = $renderer->getShippingIncludeTax();
+ } else {
+ $value = $renderer->getShippingExcludeTax();
+ }
+ break;
+ case 'grand_total':
+ $grandTotalExlTax = $renderer->getTotalExclTax();
+ $displayBoth = $renderer->includeTax() && $grandTotalExlTax >= 0;
+ if ($displayBoth) {
+ $title = $this->helper('xmlconnect')->__('Grand Total (Excl. Tax)');
+ $this->_addTotalDataToXmlObj($totalsXmlObj, $code . '_excl_tax', $title, $grandTotalExlTax);
+
+ $code = $code . '_incl_tax';
+ $title = $this->helper('xmlconnect')->__('Grand Total (Incl. Tax)');
+ }
+ break;
+ default:
+ break;
+ }
+ if ($title == '') {
+ $title = $total->getTitle();
+ }
+ if (is_null($value)) {
+ $value = $total->getValue();
+ }
+ $this->_addTotalDataToXmlObj($totalsXmlObj, $code, $title, $value);
+ }
+
+ return $totalsXmlObj->asNiceXml();
+ }
+
+ /**
+ * Add total data to totals xml object
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $totalsXmlObj
+ * @param string $code
+ * @param string $title
+ * @param float $value
+ */
+ protected function _addTotalDataToXmlObj($totalsXmlObj, $code, $title, $value)
+ {
+ $value = Mage::helper('xmlconnect')->formatPriceForXml($value);
+ $totalXmlObj = $totalsXmlObj->addChild($code);
+ $totalXmlObj->addChild('title', $totalsXmlObj->xmlentities(strip_tags($title)));
+ $formatedValue = $this->getQuote()->getStore()->formatPrice($value, false);
+ $totalXmlObj->addChild('value', $value);
+ $totalXmlObj->addChild('formated_value', $formatedValue);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog.php
new file mode 100644
index 0000000000..72c3920046
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog.php
@@ -0,0 +1,65 @@
+');
+ $sortOptions = Mage::getModel('catalog/category')->getAvailableSortByOptions();
+ $sortOptions = array_slice($sortOptions, 0, self::PRODUCT_SORT_FIELDS_NUMBER);
+ foreach ($sortOptions as $code => $name) {
+ $item = $ordersXmlObject->addChild('item');
+ $item->addChild('code', $code);
+ $item->addChild('name', $ordersXmlObject->xmlentities(strip_tags($name)));
+ }
+
+ return $ordersXmlObject;
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Category.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Category.php
new file mode 100644
index 0000000000..af9e9010d6
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Category.php
@@ -0,0 +1,112 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Category extends Mage_XmlConnect_Block_Catalog
+{
+ /**
+ * Render block HTML
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $categoryXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $categoryId = $this->getRequest()->getParam('id', null);
+ if ($categoryId === null) {
+ $categoryId = Mage::app()->getStore()->getRootCategoryId();
+ }
+ $categoryModel = Mage::getModel('catalog/category')->load($categoryId);
+ if ($categoryModel->getId()) {
+ $hasMoreProductItems = 0;
+ $productsXmlObj = $productListBlock = null;
+ /**
+ * Return products list if there are no child categories
+ */
+ if (!$categoryModel->hasChildren()) {
+ $productListBlock = $this->getChild('product_list');
+ if ($productListBlock) {
+ $layer = Mage::getSingleton('catalog/layer');
+ $productsXmlObj = $productListBlock->setCategory($categoryModel)
+ ->setLayer($layer)
+ ->getProductsXmlObject();
+ $hasMoreProductItems = (int)$productListBlock->getHasProductItems();
+ }
+ }
+
+ $infoBlock = $this->getChild('category_info');
+ if ($infoBlock) {
+ $categoryInfoXmlObj = $infoBlock->setCategory($categoryModel)
+ ->getCategoryInfoXmlObject();
+ $categoryInfoXmlObj->addChild('has_more_items', $hasMoreProductItems);
+ $categoryXmlObj->appendChild($categoryInfoXmlObj);
+ }
+
+ if ($productListBlock && $productsXmlObj) {
+ $categoryXmlObj->appendChild($productsXmlObj);
+ }
+
+ }
+
+ $categoryCollection = Mage::getResourceModel('xmlconnect/category_collection');
+ $categoryCollection->setStoreId(Mage::app()->getStore()->getId())
+ ->setOrder('position', 'ASC')
+ ->addParentIdFilter($categoryId);
+
+ if (sizeof($categoryCollection)) {
+ $itemsXmlObj = $categoryXmlObj->addChild('items');
+ }
+
+ foreach ($categoryCollection->getItems() as $item) {
+ $itemXmlObj = $itemsXmlObj->addChild('item');
+ $itemXmlObj->addChild('label', $categoryXmlObj->xmlentities(strip_tags($item->getName())));
+ $itemXmlObj->addChild('entity_id', $item->getEntityId());
+ $itemXmlObj->addChild('content_type', $item->hasChildren() ? 'categories' : 'products');
+ if (!is_null($categoryId)) {
+ $itemXmlObj->addChild('parent_id', $item->getParentId());
+ }
+ $icon = Mage::helper('xmlconnect/catalog_category_image')->initialize($item, 'thumbnail')
+ ->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('category'));
+
+ $iconXml = $itemXmlObj->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+ }
+
+ return $categoryXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Category/Info.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Category/Info.php
new file mode 100644
index 0000000000..50395a53a0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Category/Info.php
@@ -0,0 +1,78 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Category_Info extends Mage_XmlConnect_Block_Catalog
+{
+
+ /**
+ * Produce category info xml object
+ *
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function getCategoryInfoXmlObject()
+ {
+ $infoXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $category = $this->getCategory();
+ if ($category && is_object($category) && $category->getId()) {
+ $title = $infoXmlObj->xmlentities(strip_tags($category->getParentCategory()->getName()));
+ if ($category->getParentCategory()->getLevel() == 1) {
+ /**
+ * @var string $title
+ *
+ * Copied data from "getDefaultApplicationDesignTabs()" method in "Mage_XmlConnect_Helper_Data"
+ */
+ $title = Mage::helper('xmlconnect')->__('Shop');
+ }
+
+ $infoXmlObj->addChild('parent_title', $title);
+ $pId = $category->getParentId();
+ if ($category->getLevel() == 1) {
+ $pId = 0;
+ }
+ $infoXmlObj->addChild('parent_id', $pId);
+ }
+
+ return $infoXmlObj;
+ }
+
+ /**
+ * Render category info xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return $this->getCategoryInfoXmlObject()->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Filters.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Filters.php
new file mode 100644
index 0000000000..90a6e172ee
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Filters.php
@@ -0,0 +1,71 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Filters extends Mage_XmlConnect_Block_Catalog
+{
+
+ /**
+ * Render filters list xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $categoryId = $this->getRequest()->getParam('category_id', null);
+ $categoryXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $filtersCollection = Mage::getResourceModel('xmlconnect/filter_collection')->setCategoryId($categoryId);
+
+ $filtersXmlObj = $categoryXmlObj->addChild('filters');
+ foreach ($filtersCollection->getItems() as $item) {
+ if (!sizeof($item->getValues())) {
+ continue;
+ }
+ $itemXmlObj = $filtersXmlObj->addChild('item');
+ $itemXmlObj->addChild('name', $categoryXmlObj->xmlentities(strip_tags($item->getName())));
+ $itemXmlObj->addChild('code', $categoryXmlObj->xmlentities($item->getCode()));
+
+ $valuesXmlObj = $itemXmlObj->addChild('values');
+ foreach ($item->getValues() as $value) {
+ $valueXmlObj = $valuesXmlObj->addChild('value');
+ $valueXmlObj->addChild('id', $categoryXmlObj->xmlentities($value->getValueString()));
+ $valueXmlObj->addChild('label', $categoryXmlObj->xmlentities(strip_tags($value->getLabel())));
+ $valueXmlObj->addChild('count', (int)$value->getProductsCount());
+ }
+ }
+ $categoryXmlObj->appendChild($this->getProductSortFeildsXmlObject());
+
+ return $categoryXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product.php
new file mode 100644
index 0000000000..77a8eb9d9d
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product.php
@@ -0,0 +1,159 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product extends Mage_XmlConnect_Block_Catalog
+{
+
+ /**
+ * Retrieve product attributes as xml object
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param string $itemNodeName
+ *
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function productToXmlObject(Mage_Catalog_Model_Product $product, $itemNodeName = 'item')
+ {
+ $item = new Mage_XmlConnect_Model_Simplexml_Element('<' . $itemNodeName . '>' . $itemNodeName . '>');
+ if ($product && $product->getId()) {
+ $item->addChild('entity_id', $product->getId());
+ $item->addChild('name', $item->xmlentities(strip_tags($product->getName())));
+ $item->addChild('entity_type', $product->getTypeId());
+ $item->addChild('short_description', $item->xmlentities(strip_tags($product->getShortDescription())));
+ $item->addChild('description', Mage::helper('xmlconnect')->htmlize($item->xmlentities($product->getDescription())));
+
+ if ($itemNodeName == 'item') {
+ $imageToResize = Mage::helper('xmlconnect/image')->getImageSizeForContent('product_small');
+ $propertyToResizeName = 'small_image';
+ } else {
+ $imageToResize = Mage::helper('xmlconnect/image')->getImageSizeForContent('product_big');
+ $propertyToResizeName = 'image';
+ }
+
+
+ $icon = clone Mage::helper('catalog/image')->init($product, $propertyToResizeName)
+ ->resize($imageToResize);
+
+ $iconXml = $item->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+
+ $item->addChild('in_stock', (int)$product->isSalable());
+ $item->addChild('is_salable', (int)$product->isSalable());
+ /**
+ * By default all products has gallery (because of collection not load gallery attribute)
+ */
+ $hasGallery = 1;
+ if ($product->getMediaGalleryImages()) {
+ $hasGallery = sizeof($product->getMediaGalleryImages()) > 0 ? 1 : 0;
+ }
+ $item->addChild('has_gallery', $hasGallery);
+ /**
+ * If product type is grouped than it has options as its grouped items
+ */
+ if ($product->getTypeId() == Mage_Catalog_Model_Product_Type_Grouped::TYPE_CODE) {
+ $product->setHasOptions(true);
+ }
+ $item->addChild('has_options', (int)$product->getHasOptions());
+
+ if ($minSaleQty = $this->_getMinimalQty($product)) {
+ $item->addChild('min_sale_qty', (int) $minSaleQty);
+ }
+
+ if (!$product->getRatingSummary()) {
+ Mage::getModel('review/review')
+ ->getEntitySummary($product, Mage::app()->getStore()->getId());
+ }
+
+ $item->addChild('rating_summary', round((int)$product->getRatingSummary()->getRatingSummary() / 10));
+ $item->addChild('reviews_count', $product->getRatingSummary()->getReviewsCount());
+
+ if ($this->getChild('product_price')) {
+ $this->getChild('product_price')->setProduct($product)
+ ->setProductXmlObj($item)
+ ->collectProductPrices();
+ }
+
+ if ($this->getChild('additional_info')) {
+ $this->getChild('additional_info')->addAdditionalData($product, $item);
+ }
+ }
+
+ return $item;
+ }
+
+ /**
+ * Get MinSaleQty for product
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return int|null
+ */
+ protected function _getMinimalQty($product)
+ {
+ if ($stockItem = $product->getStockItem()) {
+ return ($stockItem->getMinSaleQty() && $stockItem->getMinSaleQty() > 0 ? $stockItem->getMinSaleQty() * 1 : null);
+ }
+ return null;
+ }
+ /**
+ * Render product info xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $product = Mage::getModel('catalog/product')
+ ->setStoreId(Mage::app()->getStore()->getId())
+ ->load($this->getRequest()->getParam('id', 0));
+
+ if (!$product) {
+ throw new Mage_Core_Exception(Mage::helper('xmlconnect')->__('Selected product is unavailable.'));
+ } else {
+ $this->setProduct($product);
+ $productXmlObj = $this->productToXmlObject($product, 'product');
+
+ $relatedProductsBlock = $this->getChild('related_products');
+ if ($relatedProductsBlock) {
+ $relatedXmlObj = $relatedProductsBlock->getRelatedProductsXmlObj();
+ $productXmlObj->appendChild($relatedXmlObj);
+ }
+ }
+ return $productXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Attributes.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Attributes.php
new file mode 100644
index 0000000000..ec1d5c17a2
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Attributes.php
@@ -0,0 +1,61 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Attributes extends Mage_Catalog_Block_Product_View_Attributes
+{
+
+ /**
+ * Add additional information (attributes) to current product xml object
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param Mage_XmlConnect_Model_Simplexml_Element $productXmlObject
+ *
+ */
+ public function addAdditionalData(Mage_Catalog_Model_Product $product, Mage_XmlConnect_Model_Simplexml_Element $productXmlObject)
+ {
+ if ($product && $productXmlObject && $product->getId()) {
+ $this->_product = $product;
+ $additionalData = $this->getAdditionalData();
+ if (!empty($additionalData)) {
+ $attributesXmlObj = $productXmlObject->addChild('additional_attributes');
+ foreach ($additionalData as $data) {
+ $_attrXmlObject = $attributesXmlObj->addChild('item');
+ $_attrXmlObject->addChild('label', $this->htmlEscape(Mage::helper('xmlconnect')->__($data['label'])));
+ $_attrXmlObject->addChild('value', Mage::helper('catalog/output')->productAttribute($product, $data['value'], $data['code']));
+ }
+ }
+ }
+
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Gallery.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Gallery.php
new file mode 100644
index 0000000000..09d083baae
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Gallery.php
@@ -0,0 +1,91 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Gallery extends Mage_XmlConnect_Block_Catalog
+{
+
+ /**
+ * Generate images gallery xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $productId = $this->getRequest()->getParam('id', null);
+ $product = Mage::getModel('catalog/product')
+ ->setStoreId(Mage::app()->getStore()->getId())
+ ->load($productId);
+ $collection = $product->getMediaGalleryImages();
+
+ $imagesNode = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $helper = $this->helper('catalog/image');
+
+ foreach ($collection as $item) {
+ $imageNode = $imagesNode->addChild('image');
+
+ /**
+ * Big image
+ */
+ $bigImage = $helper->init($product, 'image', $item->getFile())
+ ->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('product_gallery_big'));
+
+ $fileNode = $imageNode->addChild('file');
+ $fileNode->addAttribute('type', 'big');
+ $fileNode->addAttribute('url', $bigImage);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $bigImage);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $fileNode->addAttribute('id', ($id = $item->getId()) ? (int) $id : 0);
+ $fileNode->addAttribute('modification_time', filemtime($file));
+
+ /**
+ * Small image
+ */
+ $smallImage = $helper->init($product, 'thumbnail', $item->getFile())
+ ->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('product_gallery_small'));
+
+ $fileNode = $imageNode->addChild('file');
+ $fileNode->addAttribute('type', 'small');
+ $fileNode->addAttribute('url', $smallImage);
+
+ $path = str_replace($baseUrl, '', $smallImage);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $fileNode->addAttribute('modification_time', filemtime($file));
+ }
+ return $imagesNode->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/List.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/List.php
new file mode 100644
index 0000000000..14071ebbfb
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/List.php
@@ -0,0 +1,204 @@
+
+ */
+class Mage_XmlConnect_Block_Catalog_Product_List extends Mage_XmlConnect_Block_Catalog_Product
+{
+
+ /**
+ * Store product collection
+ *
+ * @var Mage_Eav_Model_Entity_Collection_Abstract
+ */
+ protected $_productCollection = null;
+
+ /**
+ * Store collected layered navigation filters whike applying them
+ *
+ * @var array
+ */
+ protected $_collectedFilters = array();
+
+ /**
+ * Produce products list xml object
+ *
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function getProductsXmlObject()
+ {
+ $productsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $collection = $this->_getProductCollection();
+
+ if (!$collection) {
+ return $productsXmlObj;
+ }
+ foreach ($collection->getItems() as $product) {
+ $productXmlObj = $this->productToXmlObject($product);
+ if ($productXmlObj) {
+ $productsXmlObj->appendChild($productXmlObj);
+ }
+ }
+
+ return $productsXmlObj;
+ }
+
+ /**
+ * Getter for collected layered navigation filters
+ *
+ * @return array
+ */
+ public function getCollectedFilters()
+ {
+ return $this->_collectedFilters;
+ }
+
+ /**
+ * Retrieve product collection with all prepared data and limitations
+ *
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
+ */
+ protected function _getProductCollection()
+ {
+ if (is_null($this->_productCollection)) {
+ $filters = array();
+ $request = $this->getRequest();
+ $requestParams = $request->getParams();
+ $layer = $this->getLayer();
+ if (!$layer) {
+ return null;
+ }
+ $category = $this->getCategory();
+ if ($category && is_object($category) && $category->getId()) {
+ $layer->setCurrentCategory($category);
+ }
+
+ if (!$this->getNeedBlockApplyingFilters()) {
+ $attributes = $layer->getFilterableAttributes();
+ /**
+ * Apply filters
+ */
+ foreach ($attributes as $attributeItem) {
+ $attributeCode = $attributeItem->getAttributeCode();
+ $filterModel = $this->helper('xmlconnect')->getFilterByKey($attributeCode);
+
+ $filterModel->setLayer($layer)
+ ->setAttributeModel($attributeItem);
+
+ $filterParam = parent::REQUEST_FILTER_PARAM_REFIX . $attributeCode;
+ /**
+ * Set new request var
+ */
+ if (isset($requestParams[$filterParam])) {
+ $filterModel->setRequestVar($filterParam);
+ }
+ $filterModel->apply($request, null);
+ $filters[] = $filterModel;
+ }
+
+ /**
+ * Separately apply and save category filter
+ */
+ $categoryFilter = $this->helper('xmlconnect')->getFilterByKey('category');
+ $filterParam = parent::REQUEST_FILTER_PARAM_REFIX . $categoryFilter->getRequestVar();
+ $categoryFilter->setLayer($layer)
+ ->setRequestVar($filterParam)
+ ->apply($this->getRequest(), null);
+ $filters[] = $categoryFilter;
+
+ $this->_collectedFilters = $filters;
+ }
+
+ /**
+ * Products
+ */
+ $layer = $this->getLayer();
+ $collection = $layer->getProductCollection();
+
+ /**
+ * Add rating and review summary, image attribute, apply sort params
+ */
+ $this->_prepareCollection($collection);
+
+ /**
+ * Apply offset and count
+ */
+ $offset = (int)$request->getParam('offset', 0);
+ $count = (int)$request->getParam('count', 0);
+ $count = $count <= 0 ? 1 : $count;
+ if ($offset + $count < $collection->getSize()) {
+ $this->setHasProductItems(1);
+ }
+ $collection->getSelect()->limit($count, $offset);
+
+ $collection->setFlag('require_stock_items', true);
+
+ $this->_productCollection = $collection;
+ }
+ return $this->_productCollection;
+ }
+
+ /**
+ * Add image attribute and apply sort fields to product collection
+ *
+ * @param Mage_Eav_Model_Entity_Collection_Abstract $collection
+ * @return Mage_XmlConnect_Block_Catalog_Product_List
+ */
+ protected function _prepareCollection($collection)
+ {
+ /**
+ * Apply sort params
+ */
+ $reguest = $this->getRequest();
+ foreach ($reguest->getParams() as $key => $value) {
+ if (0 === strpos($key, parent::REQUEST_SORT_ORDER_PARAM_REFIX)) {
+ $key = str_replace(parent::REQUEST_SORT_ORDER_PARAM_REFIX, '', $key);
+ if ($value != 'desc') {
+ $value = 'asc';
+ }
+ $collection->addAttributeToSort($key, $value);
+ }
+ }
+ $collection->addAttributeToSelect(array('image', 'name', 'description'));
+
+ return $this;
+ }
+
+ /**
+ * Render products list xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return $this->getProductsXmlObject()->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options.php
new file mode 100644
index 0000000000..18c2edf39d
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options.php
@@ -0,0 +1,198 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Options extends Mage_XmlConnect_Block_Catalog
+{
+
+ const OPTION_TYPE_SELECT = 'select';
+ const OPTION_TYPE_CHECKBOX = 'checkbox';
+ const OPTION_TYPE_TEXT = 'text';
+
+ /**
+ * Store supported product options xml renderers based on product types
+ *
+ * @var array
+ */
+ protected $_renderers = array();
+
+ /**
+ * Add new product options renderer
+ *
+ * @param string $type
+ * @param string $renderer
+ * @return Mage_XmlConnect_Block_Product_Options
+ */
+ public function addRenderer($type, $renderer)
+ {
+ if (!isset($this->_renderers[$type])) {
+ $this->_renderers[$type] = $renderer;
+ }
+ return $this;
+ }
+
+ /**
+ * Create produc custom options Mage_XmlConnect_Model_Simplexml_Element object
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function getProductCustomOptionsXmlObject(Mage_Catalog_Model_Product $product)
+ {
+ $xmlModel = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $optionsNode = $xmlModel->addChild('options');
+
+ if (!$product->getId()) {
+ return $xmlModel;
+ }
+ $xmlModel->addAttribute('id', $product->getId());
+ if (!$product->isSaleable() || !sizeof($product->getOptions())) {
+ return $xmlModel;
+ }
+
+
+ foreach ($product->getOptions() as $option) {
+ $optionNode = $optionsNode->addChild('option');
+ $type = $this->_getOptionTypeForXmlByRealType($option->getType());
+ $code = 'options[' . $option->getId() . ']';
+ if ($type == self::OPTION_TYPE_CHECKBOX) {
+ $code .= '[]';
+ }
+ $optionNode->addAttribute('code', $code);
+ $optionNode->addAttribute('type', $type);
+ $optionNode->addAttribute('label', $xmlModel->xmlentities(strip_tags($option->getTitle())));
+ if ($option->getIsRequire()) {
+ $optionNode->addAttribute('is_required', 1);
+ }
+
+ /**
+ * Process option price
+ */
+ $price = Mage::helper('xmlconnect')->formatPriceForXml($option->getPrice());
+ if ($price > 0.00) {
+ $optionNode->addAttribute('price', $price);
+ $formatedPrice = Mage::app()->getStore($product->getStoreId())->formatPrice($price, false);
+ $optionNode->addAttribute('formated_price', $formatedPrice);
+ }
+ if ($type == self::OPTION_TYPE_CHECKBOX ||
+ $type == self::OPTION_TYPE_SELECT) {
+ foreach ($option->getValues() as $value) {
+ $valueNode = $optionNode->addChild('value');
+ $valueNode->addAttribute('code', $value->getId());
+ $valueNode->addAttribute('label', $xmlModel->xmlentities(strip_tags($value->getTitle())));
+
+ $price = Mage::helper('xmlconnect')->formatPriceForXml($value->getPrice());
+ if ($price > 0.00) {
+ $valueNode->addAttribute('price', $price);
+ $formatedPrice = $this->_formatPriceString($price, $product);
+ $valueNode->addAttribute('formated_price', $formatedPrice);
+ }
+ }
+ }
+ }
+ return $xmlModel;
+ }
+
+ /**
+ * Format price with currency code and taxes
+ *
+ * @param string|int|float $price
+ * @param Mage_Catalog_Model_Product $product
+ * @return string
+ */
+ protected function _formatPriceString($price, $product)
+ {
+ $priceTax = Mage::helper('tax')->getPrice($product, $price);
+ $priceIncTax = Mage::helper('tax')->getPrice($product, $price, true);
+
+ if (Mage::helper('tax')->displayBothPrices() && $priceTax != $priceIncTax) {
+ $formated = Mage::helper('core')->currency($priceTax, true, false);
+ $formated .= ' (+'.Mage::helper('core')->currency($priceIncTax, true, false) . ' ' . Mage::helper('tax')->__('Incl. Tax').')';
+ } else {
+ $formated = $this->helper('core')->currency($priceTax, true, false);
+ }
+
+ return $formated;
+ }
+
+ /**
+ * Retrieve option type name by specified option real type name
+ *
+ * @param string $realType
+ * @return string
+ */
+ protected function _getOptionTypeForXmlByRealType($realType)
+ {
+ switch ($realType) {
+ case Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN:
+ case Mage_Catalog_Model_Product_Option::OPTION_TYPE_RADIO:
+ $type = self::OPTION_TYPE_SELECT;
+ break;
+ case Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE:
+ case Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX:
+ $type = self::OPTION_TYPE_CHECKBOX;
+ break;
+ case Mage_Catalog_Model_Product_Option::OPTION_TYPE_FIELD:
+ case Mage_Catalog_Model_Product_Option::OPTION_TYPE_AREA:
+ default:
+ $type = self::OPTION_TYPE_TEXT;
+ break;
+ }
+ return $type;
+ }
+
+ /**
+ * Generate product options xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $productId = $this->getRequest()->getParam('id', null);
+ $product = Mage::getModel('catalog/product')->setStoreId(Mage::app()->getStore()->getId());
+ if ($productId) {
+ $product->load($productId);
+ }
+
+ if ($product->getId()) {
+ $type = $product->getTypeId();
+ if (isset($this->_renderers[$type])) {
+ $renderer = $this->getLayout()->createBlock($this->_renderers[$type]);
+ if ($renderer) {
+ return $renderer->getProductOptionsXml($product);
+ }
+ }
+ }
+ return ' ';
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Bundle.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Bundle.php
new file mode 100644
index 0000000000..8f40ecdc50
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Bundle.php
@@ -0,0 +1,122 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Options_Bundle extends Mage_XmlConnect_Block_Catalog_Product_Options
+{
+ /**
+ * Generate bundle product options xml
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return string
+ */
+ public function getProductOptionsXml(Mage_Catalog_Model_Product $product)
+ {
+
+ $xmlModel = $this->getProductCustomOptionsXmlObject($product);
+ $optionsXmlObj = $xmlModel->options;
+ $options = array();
+
+ if (!$product->isSaleable()) {
+ return $xmlModel->asNiceXml();
+ }
+
+ /**
+ * Bundle options
+ */
+ $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
+ $optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product);
+ $selectionCollection = $product->getTypeInstance(true)->getSelectionsCollection(
+ $product->getTypeInstance(true)->getOptionsIds($product),
+ $product
+ );
+ $bundleOptions = $optionCollection->appendSelections($selectionCollection, false, false);
+ if (!sizeof($bundleOptions)) {
+ return $xmlModel->asNiceXml();
+ }
+
+ foreach ($bundleOptions as $_option) {
+ $selections = $_option->getSelections();
+ if (empty($selections)) {
+ continue;
+ }
+
+ $optionNode = $optionsXmlObj->addChild('option');
+
+ $type = parent::OPTION_TYPE_SELECT;
+ if ($_option->isMultiSelection()) {
+ $type = parent::OPTION_TYPE_CHECKBOX;
+ }
+ $code = 'bundle_option[' . $_option->getId() . ']';
+ if ($type == parent::OPTION_TYPE_CHECKBOX) {
+ $code .= '[]';
+ }
+ $optionNode->addAttribute('code', $code);
+ $optionNode->addAttribute('type', $type);
+ $optionNode->addAttribute('label', $optionsXmlObj->xmlentities(strip_tags($_option->getTitle())));
+ if ($_option->getRequired()) {
+ $optionNode->addAttribute('is_required', 1);
+ }
+
+// $_default = $_option->getDefaultSelection();
+
+ foreach ($selections as $_selection) {
+ if (!$_selection->isSaleable()) {
+ continue;
+ }
+ $_qty = !($_selection->getSelectionQty() * 1) ? '1' : $_selection->getSelectionQty() * 1;
+
+ $valueNode = $optionNode->addChild('value');
+ $valueNode->addAttribute('code', $_selection->getSelectionId());
+ $valueNode->addAttribute('label', $optionsXmlObj->xmlentities(strip_tags($_selection->getName())));
+ if (!$_option->isMultiSelection()) {
+ if ($_selection->getSelectionCanChangeQty()) {
+ $valueNode->addAttribute('is_qty_editable', 1);
+ }
+ }
+ $valueNode->addAttribute('qty', $_qty);
+
+ $price = $product->getPriceModel()->getSelectionPreFinalPrice($product, $_selection);
+ $price = Mage::helper('xmlconnect')->formatPriceForXml($price);
+ if ($price > 0.00) {
+ $valueNode->addAttribute('price', $price);
+ $valueNode->addAttribute('formated_price', $this->_formatPriceString($price, $product));
+ }
+
+// $_selection->getIsDefault();
+ }
+ }
+
+ return $xmlModel->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Configurable.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Configurable.php
new file mode 100644
index 0000000000..012dd6102b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Configurable.php
@@ -0,0 +1,219 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Options_Configurable extends Mage_XmlConnect_Block_Catalog_Product_Options
+{
+ /**
+ * Generate bundle product options xml
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return string
+ */
+ public function getProductOptionsXml(Mage_Catalog_Model_Product $product)
+ {
+ $xmlModel = $this->getProductCustomOptionsXmlObject($product);
+ $optionsXmlObj = $xmlModel->options;
+ $options = array();
+
+ if (!$product->isSaleable()) {
+ return $xmlModel->asNiceXml();
+ }
+
+ /**
+ * Configurable attributes
+ */
+ $_attributes = $product->getTypeInstance(true)->getConfigurableAttributes($product);
+ if (!sizeof($_attributes)) {
+ return $xmlModel->asNiceXml();
+ }
+
+ $_allowProducts = array();
+ $_allProducts = $product->getTypeInstance(true)->getUsedProducts(null, $product);
+ foreach ($_allProducts as $_product) {
+ if ($_product->isSaleable()) {
+ $_allowProducts[] = $_product;
+ }
+ }
+
+ /**
+ * Allowed products options
+ */
+ foreach ($_allowProducts as $_item) {
+ $_productId = $_item->getId();
+
+ foreach ($_attributes as $attribute) {
+ $productAttribute = $attribute->getProductAttribute();
+ $attributeValue = $_item->getData($productAttribute->getAttributeCode());
+ if (!isset($options[$productAttribute->getId()])) {
+ $options[$productAttribute->getId()] = array();
+ }
+
+ if (!isset($options[$productAttribute->getId()][$attributeValue])) {
+ $options[$productAttribute->getId()][$attributeValue] = array();
+ }
+ $options[$productAttribute->getId()][$attributeValue][] = $_productId;
+ }
+ }
+
+ foreach ($_attributes as $attribute) {
+ $productAttribute = $attribute->getProductAttribute();
+ $attributeId = $productAttribute->getId();
+ $info = array(
+ 'id' => $productAttribute->getId(),
+ 'label' => $attribute->getLabel(),
+ 'options' => array()
+ );
+
+ $prices = $attribute->getPrices();
+ if (is_array($prices)) {
+ foreach ($prices as $value) {
+ if (!isset($options[$attributeId][$value['value_index']])) {
+ continue;
+ }
+ $price = Mage::helper('xmlconnect')->formatPriceForXml($this->_preparePrice($product, $value['pricing_value'], $value['is_percent']));
+ $info['options'][] = array(
+ 'id' => $value['value_index'],
+ 'label' => $value['label'],
+ 'price' => $price,
+ 'formated_price' => $this->_formatPriceString($price, $product),
+ 'products' => isset($options[$attributeId][$value['value_index']]) ? $options[$attributeId][$value['value_index']] : array(),
+ );
+ }
+ }
+
+ if (sizeof($info['options']) > 0) {
+ $attributes[$attributeId] = $info;
+ }
+ }
+
+ $isFirst = true;
+
+ $_attributes = $attributes;
+ reset($_attributes);
+ foreach ($attributes as $id => $attribute) {
+ $optionNode = $optionsXmlObj->addChild('option');
+ $optionNode->addAttribute('code', 'super_attribute[' . $id . ']');
+ $optionNode->addAttribute('type', 'select');
+ $optionNode->addAttribute('label', strip_tags($attribute['label']));
+ $optionNode->addAttribute('is_required', 1);
+ if ($isFirst) {
+ foreach ($attribute['options'] as $option) {
+ $valueNode = $optionNode->addChild('value');
+ $valueNode->addAttribute('code', $option['id']);
+ $valueNode->addAttribute('label', $optionsXmlObj->xmlentities(strip_tags($option['label'])));
+ if ($option['price'] > 0.00) {
+ $valueNode->addAttribute('price', $option['price']);
+ $valueNode->addAttribute('formated_price', $option['formated_price']);
+ }
+ if (sizeof($_attributes) > 1) {
+ $this->_prepareRecursivelyRelatedValues($valueNode, $_attributes, $option['products'], 1);
+ }
+ }
+ $isFirst = false;
+ }
+ }
+
+ return $xmlModel->asNiceXml();
+ }
+
+ /**
+ * Add recursively relations on each option
+ *
+ * @param &Mage_XmlConnect_Model_Simplexml_Element &$valueNode value node object
+ * @param array $attributes all products attributes (options)
+ * @param array $productIds prodcuts to search in next levels attributes
+ * @param int $cycle
+ */
+ protected function _prepareRecursivelyRelatedValues(&$valueNode, $attributes, $productIds, $cycle = 1)
+ {
+ $relatedNode = null;
+
+ for ($i = 0; $i < $cycle; $i++) {
+ next($attributes);
+ }
+ $attribute = current($attributes);
+ $attrId = key($attributes);
+ foreach ($attribute['options'] as $option) {
+ /**
+ * Search products in option
+ */
+ $intersect = array_intersect($productIds, $option['products']);
+
+ if (empty($intersect)) {
+ continue;
+ }
+
+ if ($relatedNode === null) {
+ $relatedNode = $valueNode->addChild('relation');
+ $relatedNode->addAttribute('to', 'super_attribute[' . $attrId . ']');
+ }
+
+ $_valueNode = $relatedNode->addChild('value');
+ $_valueNode->addAttribute('code', $option['id']);
+ $_valueNode->addAttribute('label', $_valueNode->xmlentities(strip_tags($option['label'])));
+ if ($option['price'] > 0.00) {
+ $_valueNode->addAttribute('price', $option['price']);
+ $_valueNode->addAttribute('formated_price', $option['formated_price']);
+ }
+
+ /**
+ * Recursive relation adding
+ */
+ $_attrClone = $attributes;
+ if (next($_attrClone) != false) {
+ reset($_attrClone);
+ $this->_prepareRecursivelyRelatedValues($_valueNode, $_attrClone, $intersect, $cycle + 1);
+ }
+ }
+ }
+
+ /**
+ * Prepare price accordingly to percentage and store rates and round its
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param float|int|string $price
+ * @param unknown_type $isPercent
+ * @return float
+ */
+ protected function _preparePrice($product, $price, $isPercent = false)
+ {
+ if ($isPercent && !empty($price)) {
+ $price = $product->getFinalPrice() * $price / 100;
+ }
+
+ $price = Mage::app()->getStore()->convertPrice($price);
+ $price = Mage::app()->getStore()->roundPrice($price);
+ return $price;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Grouped.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Grouped.php
new file mode 100644
index 0000000000..fed7957b6d
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Grouped.php
@@ -0,0 +1,92 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Options_Grouped extends Mage_XmlConnect_Block_Catalog_Product_Options
+{
+ /**
+ * Generate bundle product options xml
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return string
+ */
+ public function getProductOptionsXml(Mage_Catalog_Model_Product $product)
+ {
+ $xmlModel = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $optionsNode = $xmlModel->addChild('options');
+
+ if (!$product->getId()) {
+ return $xmlModel->asNiceXml();
+ }
+ $xmlModel->addAttribute('id', $product->getId());
+ if (!$product->isSaleable()) {
+ return $xmlModel->asNiceXml();
+ }
+ /**
+ * Grouped (associated) products
+ */
+ $_associatedProducts = $product->getTypeInstance(true)->getAssociatedProducts($product);
+ if (!sizeof($_associatedProducts)) {
+ return $xmlModel->asNiceXml();
+ }
+ foreach ($_associatedProducts as $_item) {
+ if (!$_item->isSaleable()) {
+ continue;
+ }
+ $optionNode = $optionsNode->addChild('option');
+
+ $optionNode->addAttribute('code', 'super_group[' . $_item->getId() . ']');
+ $optionNode->addAttribute('type', 'product');
+ $optionNode->addAttribute('label', $xmlModel->xmlentities(strip_tags($_item->getName())));
+ $optionNode->addAttribute('is_qty_editable', 1);
+ $optionNode->addAttribute('qty', $_item->getQty()*1);
+
+
+ /**
+ * Process product price
+ */
+ if ($_item->getPrice() != $_item->getFinalPrice()) {
+ $productPrice = $_item->getFinalPrice();
+ } else {
+ $productPrice = $_item->getPrice();
+ }
+ $productPrice = Mage::helper('xmlconnect')->formatPriceForXml($productPrice);
+ if ($productPrice > 0.00) {
+ $optionNode->addAttribute('price', $productPrice);
+ $optionNode->addAttribute('formated_price', $this->_formatPriceString($productPrice, $product));
+ }
+ }
+
+ return $xmlModel->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Simple.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Simple.php
new file mode 100644
index 0000000000..abda11053c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Simple.php
@@ -0,0 +1,47 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Options_Simple extends Mage_XmlConnect_Block_Catalog_Product_Options
+{
+ /**
+ * Generate simple product options xml
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return string
+ */
+ public function getProductOptionsXml(Mage_Catalog_Model_Product $product)
+ {
+ return $this->getProductCustomOptionsXmlObject($product)->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Virtual.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Virtual.php
new file mode 100644
index 0000000000..208ad60a71
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Options/Virtual.php
@@ -0,0 +1,47 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Options_Virtual extends Mage_XmlConnect_Block_Catalog_Product_Options
+{
+ /**
+ * Generate virtual product options xml
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return string
+ */
+ public function getProductOptionsXml(Mage_Catalog_Model_Product $product)
+ {
+ return $this->getProductCustomOptionsXmlObject($product)->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price.php
new file mode 100644
index 0000000000..551c3ea3fd
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price.php
@@ -0,0 +1,100 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Price extends Mage_XmlConnect_Block_Catalog
+{
+
+ /**
+ * Default product price renderer block factory name
+ *
+ * @var string
+ */
+ protected $_defaultPriceRenderer = 'xmlconnect/catalog_product_price_default';
+
+ /**
+ * Store supported product price xml renderers based on product types
+ *
+ * @var array
+ */
+ protected $_renderers = array();
+
+ /**
+ * Store already initialized renderers instances
+ *
+ * @var array
+ */
+ protected $_renderersInstances = array();
+
+ /**
+ * Add new product price renderer
+ *
+ * @param string $type
+ * @param string $renderer
+ * @return Mage_XmlConnect_Block_Product_Options
+ */
+ public function addRenderer($type, $renderer)
+ {
+ if (!isset($this->_renderers[$type])) {
+ $this->_renderers[$type] = $renderer;
+ }
+ return $this;
+ }
+
+ /**
+ * Collect product prices to current xml object
+ */
+ public function collectProductPrices()
+ {
+ $product = $this->getProduct();
+ $xmlObject = $this->getProductXmlObj();
+
+ if ($product && $product->getId()) {
+ $type = $product->getTypeId();
+ if (isset($this->_renderers[$type])) {
+ $blockName = $this->_renderers[$type];
+ } else {
+ $blockName = $this->_defaultPriceRenderer;
+ }
+
+ $renderer = $this->getLayout()->getBlock($blockName);
+ if (!$renderer) {
+ $renderer = $this->getLayout()->createBlock($blockName);
+ }
+
+ if ($renderer) {
+ $renderer->collectProductPrices($product, $xmlObject);
+ }
+ }
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price/Bundle.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price/Bundle.php
new file mode 100644
index 0000000000..e2c32d67bb
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price/Bundle.php
@@ -0,0 +1,308 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Price_Bundle extends Mage_Bundle_Block_Catalog_Product_Price
+{
+ /**
+ * Collect product prices to specified item xml object
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param Mage_XmlConnect_Model_Simplexml_Element $item
+ */
+ public function collectProductPrices(Mage_Catalog_Model_Product $product, Mage_XmlConnect_Model_Simplexml_Element $item)
+ {
+ $this->setProduct($product)
+ ->setDisplayMinimalPrice(true)
+ ->setUseLinkForAsLowAs(false);
+
+ $priceXmlObj = $item->addChild('price');
+
+ $_coreHelper = $this->helper('core');
+ $_weeeHelper = $this->helper('weee');
+ $_taxHelper = $this->helper('tax');
+ /* @var $_coreHelper Mage_Core_Helper_Data */
+ /* @var $_weeeHelper Mage_Weee_Helper_Data */
+ /* @var $_taxHelper Mage_Tax_Helper_Data */
+
+ $_tierPrices = $this->_getTierPrices($product);
+
+ if (count($_tierPrices) > 0) {
+ $tierPricesTextArray = array();
+ foreach ($_tierPrices as $_price) {
+ $tierPricesTextArray[] = Mage::helper('catalog')->__('Buy %1$s with %2$s discount each', $_price['price_qty'], ' '.($_price['price']*1).'%');
+ }
+ $item->addChild('price_tier', implode("\n", $tierPricesTextArray));
+ }
+
+
+ list($_minimalPrice, $_maximalPrice) = $product->getPriceModel()->getPrices($product);
+ $_id = $product->getId();
+
+ $_weeeTaxAmount = 0;
+
+ $_minimalPriceTax = $_taxHelper->getPrice($product, $_minimalPrice);
+ $_minimalPriceInclTax = $_taxHelper->getPrice($product, $_minimalPrice, true);
+
+ if ($product->getPriceType() == 1) {
+ $_weeeTaxAmount = $_weeeHelper->getAmount($product);
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, array(0, 1, 4))) {
+ $_minimalPriceTax += $_weeeTaxAmount;
+ $_minimalPriceInclTax += $_weeeTaxAmount;
+ }
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 2)) {
+ $_minimalPriceInclTax += $_weeeTaxAmount;
+ }
+
+ if ($_weeeHelper->typeOfDisplay($product, array(1,2,4))) {
+ $_weeeTaxAttributes = $_weeeHelper->getProductWeeeAttributesForDisplay($product);
+ }
+ }
+
+ if ($product->getPriceView()) {
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('as_low_as_excluding_tax', $_coreHelper->currency($_minimalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ $priceXmlObj->addAttribute('as_low_as_including_tax', $_coreHelper->currency($_minimalPriceInclTax, true, false));
+ } else {
+ $priceXmlObj->addAttribute('as_low_as', $_coreHelper->currency($_minimalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ if ($_weeeHelper->typeOfDisplay($product, 2) && $_weeeTaxAmount) {
+ $priceXmlObj->addAttribute('as_low_as_including_tax', $_coreHelper->currency($_minimalPriceInclTax, true, false));
+ }
+ }
+ /**
+ * if ($product->getPriceView()) {
+ */
+ } else {
+ if ($_minimalPrice <> $_maximalPrice) {
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('from_excluding_tax', $_coreHelper->currency($_minimalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('from_weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ $priceXmlObj->addAttribute('from_including_tax', $_coreHelper->currency($_minimalPriceInclTax, true, false));
+ } else {
+ $priceXmlObj->addAttribute('from', $_coreHelper->currency($_minimalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('from_weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ if ($_weeeHelper->typeOfDisplay($product, 2) && $_weeeTaxAmount) {
+ $priceXmlObj->addAttribute('from_including_tax', $_coreHelper->currency($_minimalPriceInclTax, true, false));
+ }
+ }
+
+ $_maximalPriceTax = Mage::helper('tax')->getPrice($product, $_maximalPrice);
+ $_maximalPriceInclTax = Mage::helper('tax')->getPrice($product, $_maximalPrice, true);
+
+ if ($product->getPriceType() == 1) {
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, array(0, 1, 4))) {
+ $_maximalPriceTax += $_weeeTaxAmount;
+ $_maximalPriceInclTax += $_weeeTaxAmount;
+ }
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 2)) {
+ $_maximalPriceInclTax += $_weeeTaxAmount;
+ }
+ }
+
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('to_excluding_tax', $_coreHelper->currency($_maximalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('to_weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ $priceXmlObj->addAttribute('to_including_tax', $_coreHelper->currency($_maximalPriceInclTax, true, false));
+ } else {
+ $priceXmlObj->addAttribute('to', $_coreHelper->currency($_maximalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('to_weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ if ($_weeeHelper->typeOfDisplay($product, 2) && $_weeeTaxAmount) {
+ $priceXmlObj->addAttribute('to_including_tax', $_coreHelper->currency($_maximalPriceInclTax, true, false));
+ }
+ }
+ /**
+ * if ($_minimalPrice <> $_maximalPrice) {
+ */
+ } else {
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('excluding_tax', $_coreHelper->currency($_minimalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_minimalPriceInclTax, true, false));
+ } else {
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_minimalPriceTax, true, false));
+ if ($_weeeTaxAmount && $product->getPriceType() == 1 && $_weeeHelper->typeOfDisplay($product, array(2, 1, 4))) {
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ if ($_weeeHelper->typeOfDisplay($product, array(2, 4))) {
+ $amount = $_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount();
+ } else {
+ $amount = $_weeeTaxAttribute->getAmount();
+ }
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($amount, true, false));
+ }
+ }
+ if ($_weeeHelper->typeOfDisplay($product, 2) && $_weeeTaxAmount) {
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_minimalPriceInclTax, true, false));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get tier prices (formatted)
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return array
+ */
+ protected function _getTierPrices($product)
+ {
+ if (is_null($product)) {
+ return array();
+ }
+ $prices = $product->getFormatedTierPrice();
+
+ $res = array();
+ if (is_array($prices)) {
+ foreach ($prices as $price) {
+ $price['price_qty'] = $price['price_qty']*1;
+ $price['savePercent'] = ceil(100 - $price['price'] );
+ $price['formated_price'] = Mage::app()->getStore()->formatPrice(
+ Mage::app()->getStore()->convertPrice(
+ Mage::helper('tax')->getPrice($product, $price['website_price'])),
+ false);
+ $price['formated_price_incl_tax'] = Mage::app()->getStore()->formatPrice(
+ Mage::app()->getStore()->convertPrice(
+ Mage::helper('tax')->getPrice($product, $price['website_price'], true)),
+ false);
+ $res[] = $price;
+ }
+ }
+
+ return $res;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price/Default.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price/Default.php
new file mode 100644
index 0000000000..54a500fe44
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Price/Default.php
@@ -0,0 +1,495 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Price_Default extends Mage_Catalog_Block_Product_Price
+{
+ /**
+ * Collect product prices to specified item xml object
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param Mage_XmlConnect_Model_Simplexml_Element $item
+ */
+ public function collectProductPrices(Mage_Catalog_Model_Product $product, Mage_XmlConnect_Model_Simplexml_Element $item)
+ {
+ $this->setProduct($product)
+ ->setDisplayMinimalPrice(true)
+ ->setUseLinkForAsLowAs(false);
+
+ $priceXmlObj = $item->addChild('price');
+ $_tierPrices = $this->_getTierPrices($product);
+ if (count($_tierPrices) > 0) {
+ $tierPricesTextArray = array();
+ $tierPricesTextArray = $this->_getTierPricesTextArray($_tierPrices, $product);
+ $item->addChild('price_tier', implode("\n", $tierPricesTextArray));
+ }
+
+ $_coreHelper = $this->helper('core');
+ $_weeeHelper = $this->helper('weee');
+ $_taxHelper = $this->helper('tax');
+
+ /* @var $_coreHelper Mage_Core_Helper_Data */
+ /* @var $_weeeHelper Mage_Weee_Helper_Data */
+ /* @var $_taxHelper Mage_Tax_Helper_Data */
+
+ $_id = $product->getId();
+ $_weeeSeparator = '';
+ $_simplePricesTax = ($_taxHelper->displayPriceIncludingTax() || $_taxHelper->displayBothPrices());
+ $_minimalPriceValue = $product->getMinimalPrice();
+ $_minimalPrice = $_taxHelper->getPrice($product, $_minimalPriceValue, $_simplePricesTax);
+
+ if (!$product->isGrouped()) {
+ $_weeeTaxAmount = $_weeeHelper->getAmountForDisplay($product);
+ if ($_weeeHelper->typeOfDisplay($product, array(1,2,4))) {
+ $_weeeTaxAmount = $_weeeHelper->getAmount($product);
+ $_weeeTaxAttributes = $_weeeHelper->getProductWeeeAttributesForDisplay($product);
+ }
+
+ $_price = $_taxHelper->getPrice($product, $product->getPrice());
+ $_regularPrice = $_taxHelper->getPrice($product, $product->getPrice(), $_simplePricesTax);
+ $_finalPrice = $_taxHelper->getPrice($product, $product->getFinalPrice());
+ $_finalPriceInclTax = $_taxHelper->getPrice($product, $product->getFinalPrice(), true);
+ $_weeeDisplayType = $_weeeHelper->getPriceDisplayType();
+ if ($_finalPrice == $_price) {
+ if ($_taxHelper->displayBothPrices()) {
+ /**
+ * Including
+ */
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 0)) {
+ $priceXmlObj->addAttribute('excluding_tax', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 1)) {
+ /**
+ * Including + Weee
+ */
+ $priceXmlObj->addAttribute('excluding_tax', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount(), true, false));
+ }
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 4)) {
+ /**
+ * Including + Weee
+ */
+ $priceXmlObj->addAttribute('excluding_tax', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount(), true, false));
+ }
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 2)) {
+ /**
+ * Excluding + Weee + Final
+ */
+ $priceXmlObj->addAttribute('excluding_tax', $_coreHelper->currency($_price, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount(), true, false));
+ }
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ } else {
+ $priceXmlObj->addAttribute('excluding_tax', $_coreHelper->currency($_price, true, false));
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_finalPriceInclTax, true, false));
+ }
+ /**
+ * if ($_taxHelper->displayBothPrices()) {
+ */
+ } else {
+ /**
+ * Including
+ */
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 0)) {
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 1)) {
+ /**
+ * Including + Weee
+ */
+
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount(), true, false));
+ }
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 4)) {
+ /**
+ * Including + Weee
+ */
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount(), true, false));
+ }
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 2)) {
+ /**
+ * Excluding + Weee + Final
+ */
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_price, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount(), true, false));
+ }
+ $priceXmlObj->addAttribute('including_tax', $_coreHelper->currency($_price + $_weeeTaxAmount, true, false));
+ } else {
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_price, true, false));
+ }
+ }
+ /**
+ * if ($_finalPrice == $_price) {
+ */
+ } else {
+ $_originalWeeeTaxAmount = $_weeeHelper->getOriginalAmount($product);
+ /**
+ * Including
+ */
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 0)) {
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_regularPrice + $_originalWeeeTaxAmount, true, false));
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('special_excluding_tax', $_coreHelper->currency($_finalPrice + $_weeeTaxAmount, true, false));
+ $priceXmlObj->addAttribute('special_including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ } else {
+ $priceXmlObj->addAttribute('special', $_coreHelper->currency($_finalPrice + $_weeeTaxAmount, true, false));
+ }
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 1)) {
+ /**
+ * Including + Weee
+ */
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_regularPrice + $_originalWeeeTaxAmount, true, false));
+ $priceXmlObj->addAttribute('special_excluding_tax', $_coreHelper->currency($_finalPrice + $_weeeTaxAmount, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount(), true, false));
+ }
+ $priceXmlObj->addAttribute('special_including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 4)) {
+ /**
+ * Including + Weee
+ */
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_regularPrice + $_originalWeeeTaxAmount, true, false));
+ $priceXmlObj->addAttribute('special_excluding_tax', $_coreHelper->currency($_finalPrice + $_weeeTaxAmount, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ $_weeeSeparator = ' + ';
+ $weeeXmlObj->addAttribute('separator', $_weeeSeparator);
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount() + $_weeeTaxAttribute->getTaxAmount(), true, false));
+ }
+ $priceXmlObj->addAttribute('special_including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ } elseif ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, 2)) {
+ /**
+ * Excluding + Weee + Final
+ */
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_regularPrice, true, false));
+ $priceXmlObj->addAttribute('special_excluding_tax', $_coreHelper->currency($_finalPrice, true, false));
+ $weeeXmlObj = $priceXmlObj->addChild('weee');
+ foreach ($_weeeTaxAttributes as $_weeeTaxAttribute) {
+ $weeeItemXmlObj = $weeeXmlObj->addChild('item');
+ $weeeItemXmlObj->addAttribute('name', $weeeItemXmlObj->xmlentities(strip_tags($_weeeTaxAttribute->getName())));
+ $weeeItemXmlObj->addAttribute('amount', $_coreHelper->currency($_weeeTaxAttribute->getAmount(), true, false));
+ }
+ $priceXmlObj->addAttribute('special_including_tax', $_coreHelper->currency($_finalPriceInclTax + $_weeeTaxAmount, true, false));
+ } else {
+ /**
+ * Excluding
+ */
+ $priceXmlObj->addAttribute('regular', $_coreHelper->currency($_regularPrice, true, false));
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('special_excluding_tax', $_coreHelper->currency($_finalPrice, true, false));
+ $priceXmlObj->addAttribute('special_including_tax', $_coreHelper->currency($_finalPriceInclTax, true, false));
+ } else {
+ $priceXmlObj->addAttribute('special', $_coreHelper->currency($_finalPrice, true, false));
+ }
+ }
+ }
+
+ if ($this->getDisplayMinimalPrice() && $_minimalPriceValue && $_minimalPriceValue < $product->getFinalPrice()) {
+ $_minimalPriceDisplayValue = $_minimalPrice;
+ if ($_weeeTaxAmount && $_weeeHelper->typeOfDisplay($product, array(0, 1, 4))) {
+ $_minimalPriceDisplayValue = $_minimalPrice + $_weeeTaxAmount;
+ }
+
+ if (!$this->getUseLinkForAsLowAs()) {
+ $priceXmlObj->addAttribute('as_low_as', $_coreHelper->currency($_minimalPriceDisplayValue, true, false));
+ }
+ }
+ /**
+ * if (!$product->isGrouped()) {
+ */
+ } else {
+ $_exclTax = $_taxHelper->getPrice($product, $_minimalPriceValue, $includingTax = null);
+ $_inclTax = $_taxHelper->getPrice($product, $_minimalPriceValue, $includingTax = true);
+
+ if ($this->getDisplayMinimalPrice() && $_minimalPriceValue) {
+ if ($_taxHelper->displayBothPrices()) {
+ $priceXmlObj->addAttribute('starting_at_excluding_tax', $_coreHelper->currency($_exclTax, true, false));
+ $priceXmlObj->addAttribute('starting_at_including_tax', $_coreHelper->currency($_inclTax, true, false));
+ } else {
+ $_showPrice = $_inclTax;
+ if (!$_taxHelper->displayPriceIncludingTax()) {
+ $_showPrice = $_exclTax;
+ }
+ $priceXmlObj->addAttribute('starting_at', $_coreHelper->currency($_showPrice, true, false));
+ }
+ }
+ }
+ }
+
+ /**
+ * Get tier prices (formatted)
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return array
+ */
+ protected function _getTierPrices(Mage_Catalog_Model_Product $product)
+ {
+ if (is_null($product)) {
+ return array();
+ }
+ $prices = $product->getFormatedTierPrice();
+
+ $res = array();
+ if (is_array($prices)) {
+ foreach ($prices as $price) {
+ $price['price_qty'] = $price['price_qty']*1;
+ if ($product->getPrice() != $product->getFinalPrice()) {
+ if ($price['price']<$product->getFinalPrice()) {
+ $price['savePercent'] = ceil(100 - (( 100/$product->getFinalPrice() ) * $price['price'] ));
+ $price['formated_price'] = Mage::app()->getStore()->formatPrice(Mage::app()->getStore()->convertPrice(Mage::helper('tax')->getPrice($product, $price['website_price'])), false);
+ $price['formated_price_incl_tax'] = Mage::app()->getStore()->formatPrice(Mage::app()->getStore()->convertPrice(Mage::helper('tax')->getPrice($product, $price['website_price'], true)), false);
+ $res[] = $price;
+ }
+ } else {
+ if ($price['price']<$product->getPrice()) {
+ $price['savePercent'] = ceil(100 - (( 100/$product->getPrice() ) * $price['price'] ));
+ $price['formated_price'] = Mage::app()->getStore()->formatPrice(Mage::app()->getStore()->convertPrice(Mage::helper('tax')->getPrice($product, $price['website_price'])), false);
+ $price['formated_price_incl_tax'] = Mage::app()->getStore()->formatPrice(Mage::app()->getStore()->convertPrice(Mage::helper('tax')->getPrice($product, $price['website_price'], true)), false);
+ $res[] = $price;
+ }
+ }
+ }
+ }
+
+ return $res;
+ }
+
+ /**
+ * Get tier prices (formatted) as array of strings
+ *
+ * @param array $_tierPrices
+ * @param Mage_Catalog_Model_Product $_product
+ *
+ * @return array
+ */
+ protected function _getTierPricesTextArray($_tierPrices, $_product)
+ {
+
+ $pricesArray = array();
+ if (Mage::helper('weee')->typeOfDisplay($_product, array(1, 2, 4))) {
+ $_weeeTaxAttributes = Mage::helper('weee')->getProductWeeeAttributesForDisplay($_product);
+ }
+
+ if ($_product->isGrouped()) {
+ $_tierPrices = $this->getTierPrices($_product);
+ }
+ Mage::helper('weee')->processTierPrices($_product, $_tierPrices);
+
+ foreach ($_tierPrices as $_price) {
+ $s = '';
+ if ($this->helper('tax')->displayBothPrices()) {
+ if (Mage::helper('weee')->typeOfDisplay($_product, 0)) {
+ $s .= $this->__('Buy %1$s for %2$s (%3$s incl. tax) each', $_price['price_qty'], $_price['formated_price_incl_weee_only'], $_price['formated_price_incl_weee']);
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 1)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_weee_only']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ $s .= $this->__('%1$s incl tax.', $_price['formated_price_incl_weee']);
+ $separator = ' + ';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $separator;
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount());
+ }
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 4)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_weee_only']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ $s .= $this->__('%1$s incl tax.', $_price['formated_price_incl_weee']);
+ $separator = ' + ';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $separator;
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount() + $_attribute->getTaxAmount());
+ }
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 2)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount());
+ }
+ $s .= $this->__('Total incl. Tax: %1$s', $_price['formated_price_incl_weee']);
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else {
+ $s .= $this->__('Buy %1$s for %2$s (%3$s incl. tax) each', $_price['price_qty'], $_price['formated_price'], $_price['formated_price_incl_tax']);
+ }
+ } else {
+ if ($this->helper('tax')->displayPriceIncludingTax()) {
+ if (Mage::helper('weee')->typeOfDisplay($_product, 0)) {
+ $s .= $this->__('Buy %1$s for %2$s each', $_price['price_qty'], $_price['formated_price_incl_weee']);
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 1)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_weee']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ $separator = '';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $separator;
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount());
+ $separator = ' + ';
+ }
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 4)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_weee']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ $separator = '';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $separator;
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount() + $_attribute->getTaxAmount());
+ $separator = ' + ';
+ }
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 2)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_tax']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount());
+ }
+ $s .= $this->__('Total incl. Tax: %1$s', $_price['formated_price_incl_weee']);
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else {
+ $s .= $this->__('Buy %1$s for %2$s each', $_price['price_qty'], $_price['formated_price_incl_tax']);
+ }
+ } else {
+ if (Mage::helper('weee')->typeOfDisplay($_product, 0)) {
+ $s .= $this->__('Buy %1$s for %2$s each', $_price['price_qty'], $_price['formated_price_incl_weee_only']);
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 1)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_weee_only']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ $separator = '';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $separator;
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount());
+ $separator = ' + ';
+ }
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 4)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price_incl_weee_only']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ $separator = '';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $separator;
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount() + $_attribute->getTaxAmount());
+ $separator = ' + ';
+ }
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else if (Mage::helper('weee')->typeOfDisplay($_product, 2)) {
+ $s .= $this->__('Buy %1$s for %2$s', $_price['price_qty'], $_price['formated_price']);
+ if ($_weeeTaxAttributes) {
+ $s .= '(';
+ foreach ($_weeeTaxAttributes as $_attribute) {
+ $s .= $_attribute->getName() . ': ' . Mage::helper('core')->currency($_attribute->getAmount());
+ }
+ $s .= $this->__('Total incl. Tax: %1$s', $_price['formated_price_incl_weee_only']);
+ $s .= ')';
+ }
+ $s .= $this->__('each');
+ } else {
+ $s .= $this->__('Buy %1$s for %2$s each', $_price['price_qty'], $_price['formated_price']);
+ }
+ }
+ }
+ if (!$_product->isGrouped()) {
+ if (($_product->getPrice() == $_product->getFinalPrice() && $_product->getPrice() > $_price['price'])
+ || ($_product->getPrice() != $_product->getFinalPrice() && $_product->getFinalPrice() > $_price['price'])) {
+ $s .= ' ' . $this->__('and') . ' ' . $this->__('save') . ' ' . $_price['savePercent'] . '%';
+ }
+ }
+ $pricesArray[] = $s;
+ }
+ return $pricesArray;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Related.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Related.php
new file mode 100644
index 0000000000..cf75ce4f60
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Related.php
@@ -0,0 +1,97 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Related extends Mage_XmlConnect_Block_Catalog_Product_List
+{
+
+ /**
+ * Retrieve related products xml object based on current product
+ *
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ * @see $this->getProduct()
+ */
+ public function getRelatedProductsXmlObj()
+ {
+ $relatedXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ if ($this->getParentBlock()->getProduct()->getId() > 0) {
+ $collection = $this->_getProductCollection();
+ if (!$collection) {
+ return $relatedXmlObj;
+ }
+ foreach ($collection->getItems() as $product) {
+ $productXmlObj = $this->productToXmlObject($product);
+ if ($productXmlObj) {
+ if ($this->getParentBlock()->getChild('product_price')) {
+ $this->getParentBlock()->getChild('product_price')->setProduct($product)
+ ->setProductXmlObj($productXmlObj)
+ ->collectProductPrices();
+ }
+ $relatedXmlObj->appendChild($productXmlObj);
+ }
+ }
+ }
+
+ return $relatedXmlObj;
+ }
+
+ /**
+ * Generate related products xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return $this->getRelatedProductsXmlObj()->asNiceXml();
+ }
+
+ /**
+ * Retrieve product collection with all prepared data
+ *
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
+ */
+ protected function _getProductCollection()
+ {
+ if (is_null($this->_productCollection)) {
+ $collection = $this->getParentBlock()->getProduct()->getRelatedProductCollection();
+ Mage::getSingleton('catalog/layer')->prepareProductCollection($collection);
+ /**
+ * Add rating and review summary, image attribute, apply sort params
+ */
+ $this->_prepareCollection($collection);
+
+ $this->_productCollection = $collection;
+ }
+ return $this->_productCollection;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Review.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Review.php
new file mode 100644
index 0000000000..c26d593ee1
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Review.php
@@ -0,0 +1,89 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Review extends Mage_XmlConnect_Block_Catalog
+{
+ /**
+ * Limit to product review text length
+ */
+ const REVIEW_DETAIL_TRUNCATE_LEN = 200;
+
+ /**
+ * Retrieve review data as xml object
+ *
+ * @param Mage_Review_Model_Review $review
+ * @param string $itemNodeName
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function reviewToXmlObject(Mage_Review_Model_Review $review, $itemNodeName = 'item')
+ {
+ $rating = 0;
+ $item = new Mage_XmlConnect_Model_Simplexml_Element('<' . $itemNodeName . '>' . $itemNodeName . '>');
+ if ($review->getId()) {
+ $item->addChild('review_id', $review->getId());
+ $item->addChild('created_at', $review->getCreatedAt());
+ $item->addChild('title', $item->xmlentities(strip_tags($review->getTitle())));
+ $item->addChild('nickname', $item->xmlentities(strip_tags($review->getNickname())));
+ $detail = $item->xmlentities($review->getDetail());
+ if ($itemNodeName == 'item') {
+ $remainder = '';
+ $detail = Mage::helper('core/string')
+ ->truncate($detail, self::REVIEW_DETAIL_TRUNCATE_LEN, '', $remainder, false);
+ }
+ $item->addChild('detail', $detail);
+
+ $summary = Mage::getModel('rating/rating')->getReviewSummary($review->getId());
+ if ($summary->getCount() > 0) {
+ $rating = round($summary->getSum() / $summary->getCount() / 10);
+ }
+ if ($rating) {
+ $item->addChild('rating_votes', $rating);
+ }
+
+ }
+ return $item;
+ }
+
+ /**
+ * Render review xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $review = Mage::getModel('review/review')->load((int)$this->getRequest()->getParam('id', 0));
+ return $this->reviewToXmlObject($review, 'review')->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Review/List.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Review/List.php
new file mode 100644
index 0000000000..324fa83076
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Product/Review/List.php
@@ -0,0 +1,113 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Product_Review_List extends Mage_XmlConnect_Block_Catalog_Product_Review
+{
+ /**
+ * Store reviews collection
+ *
+ * @var Mage_Review_Model_Mysql4_Review_Collection
+ */
+ protected $_reviewCollection = null;
+
+ /**
+ * Produce reviews list xml object
+ *
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function getReviewsXmlObject()
+ {
+ $reviewsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $collection = $this->_getReviewCollection();
+
+ if (!$collection) {
+ return $reviewsXmlObj;
+ }
+ foreach ($collection->getItems() as $review) {
+ $reviewXmlObj = $this->reviewToXmlObject($review);
+ if ($reviewXmlObj) {
+ $reviewsXmlObj->appendChild($reviewXmlObj);
+ }
+ }
+
+ return $reviewsXmlObj;
+ }
+
+ /**
+ * Retrieve reviews collection with all prepared data and limitations
+ *
+ * @return Mage_Eav_Model_Entity_Collection_Abstract
+ */
+ protected function _getReviewCollection()
+ {
+ if (is_null($this->_reviewCollection)) {
+ $product = $this->getProduct();
+ $request = $this->getRequest();
+ if (!$product) {
+ return null;
+ }
+ $collection = Mage::getResourceModel('review/review_collection')
+ ->addEntityFilter('product', $product->getId())
+ ->addStoreFilter(Mage::app()->getStore()->getId())
+ ->addStatusFilter('approved');
+
+ /**
+ * Apply offset and count
+ */
+ $offset = (int)$request->getParam('offset', 0);
+ $count = (int)$request->getParam('count', 0);
+ $count = $count <= 0 ? 1 : $count;
+ $collection->getSelect()->limit($count, $offset);
+
+ $this->_reviewCollection = $collection;
+ }
+ return $this->_reviewCollection;
+ }
+
+ /**
+ * Render reviews list xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $product = Mage::getModel('catalog/product')->load((int)$this->getRequest()->getParam('id', 0));
+ if ($product->getId()) {
+ $this->setProduct($product);
+ }
+
+ return $this->getReviewsXmlObject()->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Search.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Search.php
new file mode 100644
index 0000000000..89a7601c03
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Search.php
@@ -0,0 +1,144 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Search extends Mage_XmlConnect_Block_Catalog
+{
+ /**
+ * Search results xml renderer
+ * XML also contains filters that can be apply (accorfingly already applyed filters and search query)
+ * and sort fields
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $searchXmlObject = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $filtersXmlObject = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ $helper = Mage::helper('catalogsearch');
+ if (method_exists($helper, 'getEngine')) {
+ $engine = Mage::helper('catalogsearch')->getEngine();
+ $isLayeredNavigationAllowed = ($engine instanceof Varien_Object) ? $engine->isLeyeredNavigationAllowed() : true;
+ } else {
+ $isLayeredNavigationAllowed = true;
+ }
+
+ $request = $this->getRequest();
+ $requestParams = $request->getParams();
+ $hasMoreProductItems = 0;
+
+ /**
+ * Products
+ */
+ $productListBlock = $this->getChild('product_list');
+ if ($productListBlock) {
+ $layer = Mage::getSingleton('catalogsearch/layer');
+ $productsXmlObj = $productListBlock->setLayer($layer)
+ ->setNeedBlockApplyingFilters(!$isLayeredNavigationAllowed)
+ ->getProductsXmlObject();
+ $searchXmlObject->appendChild($productsXmlObj);
+ $hasMoreProductItems = (int)$productListBlock->getHasProductItems();
+ }
+
+ $searchXmlObject->addAttribute('has_more_items', $hasMoreProductItems);
+
+ /**
+ * Filters
+ */
+ $showFiltersAndOrders = true;
+ $reguest = $this->getRequest();
+ foreach ($reguest->getParams() as $key => $value) {
+ if (0 === strpos($key, parent::REQUEST_SORT_ORDER_PARAM_REFIX) ||
+ 0 === strpos($key, parent::REQUEST_FILTER_PARAM_REFIX)) {
+ $showFiltersAndOrders = false;
+ break;
+ }
+ }
+ if ($isLayeredNavigationAllowed && $productListBlock && $showFiltersAndOrders) {
+ $filters = $productListBlock->getCollectedFilters();
+ /**
+ * Render filters xml
+ */
+ foreach ($filters as $filter) {
+ if (!$this->_isFilterItemsHasValues($filter)) {
+ continue;
+ }
+ $item = $filtersXmlObject->addChild('item');
+ $item->addChild('name', $searchXmlObject->xmlentities($filter->getName()));
+ $item->addChild('code', $filter->getRequestVar());
+ $values = $item->addChild('values');
+
+ foreach ($filter->getItems() as $valueItem) {
+ $count = (int)$valueItem->getCount();
+ if (!$count) {
+ continue;
+ }
+ $value = $values->addChild('value');
+ $value->addChild('id', $valueItem->getValueString());
+ $value->addChild('label', $searchXmlObject->xmlentities(strip_tags($valueItem->getLabel())));
+ $value->addChild('count', $count);
+ }
+ }
+ $searchXmlObject->appendChild($filtersXmlObject);
+ }
+
+ /**
+ * Sort fields
+ */
+ if ($showFiltersAndOrders) {
+ $searchXmlObject->appendChild($this->getProductSortFeildsXmlObject());
+ }
+
+ return $searchXmlObject->asNiceXml();
+ }
+
+ /**
+ * Check if items of specified filter have values
+ *
+ * @param object $filter filter model
+ * @return bool
+ */
+ protected function _isFilterItemsHasValues($filter)
+ {
+ if (!$filter->getItemsCount()) {
+ return false;
+ }
+ foreach ($filter->getItems() as $valueItem) {
+ if ((int)$valueItem->getCount()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Search/Suggest.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Search/Suggest.php
new file mode 100644
index 0000000000..ad1d5f8689
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Catalog/Search/Suggest.php
@@ -0,0 +1,73 @@
+
+ */
+
+class Mage_XmlConnect_Block_Catalog_Search_Suggest extends Mage_CatalogSearch_Block_Autocomplete
+{
+ const SUGGEST_ITEM_SEPARATOR = '::sep::';
+
+ /**
+ * Search suggestions xml renderer
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $suggestXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ if (!$this->getRequest()->getParam('q', false)) {
+ return $suggestXmlObj->asNiceXml();
+ }
+
+ $suggestData = $this->getSuggestData();
+ if (!($count = count($suggestData))) {
+ return $suggestXmlObj->asNiceXml();
+ }
+
+ $items = '';
+ foreach ($suggestData as $index => $item) {
+ $items .= $suggestXmlObj->xmlentities(strip_tags($item['title']))
+ . self::SUGGEST_ITEM_SEPARATOR
+ . (int)$item['num_of_results']
+ . self::SUGGEST_ITEM_SEPARATOR;
+// $itemXmlObj = $suggestXmlObj->addChild('item');
+// $itemXmlObj->addChild('title', $suggestXmlObj->xmlentities(strip_tags($item['title'])));
+// $itemXmlObj->addChild('count', (int)$item['num_of_results']);
+ }
+
+ $suggestXmlObj = new Mage_XmlConnect_Model_Simplexml_Element('' . $items . ' ');
+
+ return $suggestXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Billing.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Billing.php
new file mode 100644
index 0000000000..cb27eaf8b2
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Billing.php
@@ -0,0 +1,63 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Address_Billing extends Mage_Checkout_Block_Onepage_Billing
+{
+ /**
+ * Render billing addresses xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $billingXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ $addressId = $this->getAddress()->getId();
+ $address = $this->getCustomer()->getPrimaryBillingAddress();
+ if ($address) {
+ $addressId = $address->getId();
+ }
+
+ foreach ($this->getCustomer()->getAddresses() as $address) {
+ $item = $billingXmlObj->addChild('item');
+ if ($addressId == $address->getId()) {
+ $item->addAttribute('selected', 1);
+ }
+ $this->getChild('address_list')->prepareAddressData($address, $item);
+ $item->addChild('address_line', $billingXmlObj->xmlentities($address->format('oneline')));
+ }
+
+ return $billingXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Form.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Form.php
new file mode 100644
index 0000000000..9ce3451bfd
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Form.php
@@ -0,0 +1,185 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Address_Form extends Mage_Core_Block_Template
+{
+ /**
+ * Render customer address form xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+
+ $address = $this->getAddress();
+ $xmlModel = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
+ $addressType = $this->getType() == 'shipping' || $this->getType() == 'billing' ? $this->getType() : 'billing';
+ $isAllowedGuestCheckout= Mage::getSingleton('checkout/session')->getQuote()->isAllowedGuestCheckout();
+ if ($addressType == 'shipping') {
+ $addressId = $customer->getDefaultShipping();
+ $address = $customer->getAddressById($addressId);
+ } else {
+ $addressId = $customer->getDefaultBilling();
+ $address = $customer->getAddressById($addressId);
+ }
+
+ if ($addressId && $address && $address->getId()) {
+
+ $firstname = $xmlModel->xmlentities(strip_tags($address->getFirstname()));
+ $lastname = $xmlModel->xmlentities(strip_tags($address->getLastname()));
+ $company = $xmlModel->xmlentities(strip_tags($address->getCompany()));
+ if ($isAllowedGuestCheckout) {
+ $email = $xmlModel->xmlentities(strip_tags($address->getEmail()));
+ }
+ $street1 = $xmlModel->xmlentities(strip_tags($address->getStreet(1)));
+ $street2 = $xmlModel->xmlentities(strip_tags($address->getStreet(2)));
+ $city = $xmlModel->xmlentities(strip_tags($address->getCity()));
+ $regionId = $xmlModel->xmlentities($address->getRegionId());
+ $region = Mage::getModel('directory/region')->load($regionId)->getName();
+ if (!$region) {
+ $region = $address->getRegion();
+ }
+ $region = $xmlModel->xmlentities(strip_tags($region));
+ $postcode = $xmlModel->xmlentities(strip_tags($address->getPostcode()));
+ $countryId = $xmlModel->xmlentities($address->getCountryId());
+ $telephone = $xmlModel->xmlentities(strip_tags($address->getTelephone()));
+ $fax = $xmlModel->xmlentities(strip_tags($address->getFax()));
+ } else {
+ $firstname = $lastname = $company = $email = $street1 = $street2 = '';
+ $city = $region = $postcode = $telephone = $fax = '';
+ $countryId = $regionId = null;
+ }
+
+ $countries = $this->_getCountryOptions();
+
+ $regions = array();
+ $countryOptionsXml = '';
+ if (is_array($countries)) {
+ foreach ($countries as $key => $data) {
+ if ($data['value']) {
+ $regions = $this->_getRegionOptions($data['value']);
+ }
+ $countryOptionsXml .= '
+ -
+
' . $xmlModel->xmlentities((string)$data['label']) . '
+ ' . $xmlModel->xmlentities($data['value']) . ' ';
+ if (is_array($regions) && !empty($regions)) {
+ $countryOptionsXml .= '';
+ foreach ($regions as $_key => $_data) {
+ $countryOptionsXml .= '';
+ $countryOptionsXml .=
+ '' . $xmlModel->xmlentities((string)$_data['label']) . '
+ ' . $xmlModel->xmlentities($_data['value']) . ' ';
+ $countryOptionsXml .= ' ';
+ }
+ $countryOptionsXml .= ' ';
+ }
+ $countryOptionsXml .= ' ';
+ }
+ }
+ $countryOptionsXml .= ' ';
+
+ $xml = <<
+
+
+
+EOT;
+ if ($isAllowedGuestCheckout) {
+ $xml .= <<
+EOT;
+ }
+ $xml .= <<
+
+
+
+ $countryOptionsXml
+
+
+
+
+
+
+
+
+EOT;
+ return $xml;
+ }
+
+ /**
+ * Retrieve regions by country
+ *
+ * @param string $countryId
+ * @return array
+ */
+ protected function _getRegionOptions($countryId)
+ {
+ $cacheKey = 'DIRECTORY_REGION_SELECT_STORE'.Mage::app()->getStore()->getId().$countryId;
+ if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
+ $options = unserialize($cache);
+ } else {
+ $collection = Mage::getModel('directory/region')->getResourceCollection()
+ ->addCountryFilter($countryId)
+ ->load();
+ $options = $collection->toOptionArray();
+ if (Mage::app()->useCache('config')) {
+ Mage::app()->saveCache(serialize($options), $cacheKey, array('config'));
+ }
+ }
+ return $options;
+ }
+
+ /**
+ * Retrieve countries
+ *
+ * @return array
+ */
+ protected function _getCountryOptions()
+ {
+ $cacheKey = 'DIRECTORY_COUNTRY_SELECT_STORE_'.Mage::app()->getStore()->getCode();
+ if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
+ $options = unserialize($cache);
+ } else {
+ $collection = Mage::getModel('directory/country')->getResourceCollection()
+ ->loadByStore();
+ $options = $collection->toOptionArray();
+ if (Mage::app()->useCache('config')) {
+ Mage::app()->saveCache(serialize($options), $cacheKey, array('config'));
+ }
+ }
+ return $options;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Shipping.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Shipping.php
new file mode 100644
index 0000000000..caa6e4ad3b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Address/Shipping.php
@@ -0,0 +1,63 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Address_Shipping extends Mage_Checkout_Block_Onepage_Shipping
+{
+ /**
+ * Render billing shipping xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $shippingXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ $addressId = $this->getAddress()->getId();
+ $address = $this->getCustomer()->getPrimaryShippingAddress();
+ if ($address) {
+ $addressId = $address->getId();
+ }
+
+ foreach ($this->getCustomer()->getAddresses() as $address) {
+ $item = $shippingXmlObj->addChild('item');
+ if ($addressId == $address->getId()) {
+ $item->addAttribute('selected', 1);
+ }
+ $this->getChild('address_list')->prepareAddressData($address, $item);
+ $item->addChild('address_line', $shippingXmlObj->xmlentities($address->format('oneline')));
+ }
+
+ return $shippingXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Agreements.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Agreements.php
new file mode 100644
index 0000000000..7cb361f96c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Agreements.php
@@ -0,0 +1,62 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Agreements extends Mage_Checkout_Block_Agreements
+{
+ /**
+ * Render agreements xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $agreementsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ if ($this->getAgreements()) {
+ foreach ($this->getAgreements() as $agreement) {
+ $itemXmlObj = $agreementsXmlObj->addChild('item');
+ $content = $agreementsXmlObj->xmlentities($agreement->getContent());
+ if (!$agreement->getIsHtml()) {
+ $content = nl2br(strip_tags($content));
+ }
+ $itemXmlObj->addChild('label', $agreementsXmlObj->xmlentities(strip_tags($agreement->getCheckboxText())));
+ $itemXmlObj->addChild('content', $content);
+ $itemXmlObj->addChild('code', 'agreement[' . $agreement->getId() . ']');
+ $itemXmlObj->addChild('agreement_id', $agreement->getId());
+ }
+ }
+
+ return $agreementsXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Order/Review.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Order/Review.php
new file mode 100644
index 0000000000..d1fcf74dbb
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Order/Review.php
@@ -0,0 +1,76 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Order_Review extends Mage_Checkout_Block_Onepage_Review
+{
+ /**
+ * Render order review xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $orderXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ /**
+ * Order items
+ */
+ $products = $this->getChildHtml('order_products');
+ if ($products) {
+ $productsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($products);
+ $orderXmlObj->appendChild($productsXmlObj);
+ }
+
+ /**
+ * Totals
+ */
+ $totalsXml = $this->getChildHtml('totals');
+ if ($totalsXml) {
+ $totalsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($totalsXml);
+ $orderXmlObj->appendChild($totalsXmlObj);
+ }
+
+ /**
+ * Agreements
+ */
+ $agreements = $this->getChildHtml('agreements');
+ if ($agreements) {
+ $agreementsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($agreements);
+ $orderXmlObj->appendChild($agreementsXmlObj);
+ }
+
+ return $orderXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Order/Review/Info.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Order/Review/Info.php
new file mode 100644
index 0000000000..f34a2ca85c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Order/Review/Info.php
@@ -0,0 +1,186 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Order_Review_Info extends Mage_Checkout_Block_Onepage_Review_Info
+{
+ /**
+ * Render order review items
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $itemsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $quote = Mage::getSingleton('checkout/session')->getQuote();
+
+ /* @var $item Mage_Sales_Model_Quote_Item */
+ foreach ($this->getItems() as $item) {
+ $type = $this->_getItemType($item);
+ $renderer = $this->getItemRenderer($type)->setItem($item);
+
+ /**
+ * General information
+ */
+ $itemXml = $itemsXmlObj->addChild('item');
+ $itemXml->addChild('entity_id', $item->getProduct()->getId());
+ $itemXml->addChild('entity_type', $type);
+ $itemXml->addChild('item_id', $item->getId());
+ $itemXml->addChild('name', $itemsXmlObj->xmlentities(strip_tags($renderer->getProductName())));
+ $itemXml->addChild('qty', $renderer->getQty());
+ $icon = $renderer->getProductThumbnail()->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('product_small'));
+
+ $iconXml = $itemXml->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+
+ /**
+ * Price
+ */
+ $exclPrice = $inclPrice = 0.00;
+ if ($this->helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $exclPrice = $item->getCalculationPrice() + $item->getWeeeTaxAppliedAmount() + $item->getWeeeTaxDisposition();
+ } else {
+ $exclPrice = $item->getCalculationPrice();
+ }
+ }
+
+ if ($this->helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ $_incl = $this->helper('checkout')->getPriceInclTax($item);
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $inclPrice = $_incl + $item->getWeeeTaxAppliedAmount();
+ } else {
+ $inclPrice = $_incl - $item->getWeeeTaxDisposition();
+ }
+ }
+
+ $exclPrice = Mage::helper('xmlconnect')->formatPriceForXml($exclPrice);
+ $formatedExclPrice = $quote->getStore()->formatPrice($exclPrice, false);
+
+ $inclPrice = Mage::helper('xmlconnect')->formatPriceForXml($inclPrice);
+ $formatedInclPrice = $quote->getStore()->formatPrice($inclPrice, false);
+
+ $priceXmlObj = $itemXml->addChild('price');
+ $formatedPriceXmlObj = $itemXml->addChild('formated_price');
+
+ if ($this->helper('tax')->displayCartBothPrices()) {
+ $priceXmlObj->addAttribute('excluding_tax', $exclPrice);
+ $priceXmlObj->addAttribute('including_tax', $inclPrice);
+
+ $formatedPriceXmlObj->addAttribute('excluding_tax', $formatedExclPrice);
+ $formatedPriceXmlObj->addAttribute('including_tax', $formatedInclPrice);
+ } else {
+ if ($this->helper('tax')->displayCartPriceExclTax()) {
+ $priceXmlObj->addAttribute('regular', $exclPrice);
+ $formatedPriceXmlObj->addAttribute('regular', $formatedExclPrice);
+ }
+ if ($this->helper('tax')->displayCartPriceInclTax()) {
+ $priceXmlObj->addAttribute('regular', $inclPrice);
+ $formatedPriceXmlObj->addAttribute('regular', $formatedInclPrice);
+ }
+ }
+
+
+ /**
+ * Subtotal
+ */
+ $exclPrice = $inclPrice = 0.00;
+ if ($this->helper('tax')->displayCartPriceExclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $exclPrice = $item->getRowTotal() + $item->getWeeeTaxAppliedRowAmount() + $item->getWeeeTaxRowDisposition();
+ } else {
+ $exclPrice = $item->getRowTotal();
+ }
+ }
+ if ($this->helper('tax')->displayCartPriceInclTax() || $this->helper('tax')->displayCartBothPrices()) {
+ $_incl = $this->helper('checkout')->getSubtotalInclTax($item);
+ if (Mage::helper('weee')->typeOfDisplay($item, array(0, 1, 4), 'sales') && $item->getWeeeTaxAppliedAmount()) {
+ $inclPrice = $_incl + $item->getWeeeTaxAppliedRowAmount();
+ } else {
+ $inclPrice = $_incl - $item->getWeeeTaxRowDisposition();
+ }
+ }
+
+ $exclPrice = Mage::helper('xmlconnect')->formatPriceForXml($exclPrice);
+ $formatedExclPrice = $quote->getStore()->formatPrice($exclPrice, false);
+
+ $inclPrice = Mage::helper('xmlconnect')->formatPriceForXml($inclPrice);
+ $formatedInclPrice = $quote->getStore()->formatPrice($inclPrice, false);
+
+ $subtotalPriceXmlObj = $itemXml->addChild('subtotal');
+ $subtotalFormatedPriceXmlObj = $itemXml->addChild('formated_subtotal');
+
+ if ($this->helper('tax')->displayCartBothPrices()) {
+ $subtotalPriceXmlObj->addAttribute('excluding_tax', $exclPrice);
+ $subtotalPriceXmlObj->addAttribute('including_tax', $inclPrice);
+
+ $subtotalFormatedPriceXmlObj->addAttribute('excluding_tax', $formatedExclPrice);
+ $subtotalFormatedPriceXmlObj->addAttribute('including_tax', $formatedInclPrice);
+ } else {
+ if ($this->helper('tax')->displayCartPriceExclTax()) {
+ $subtotalPriceXmlObj->addAttribute('regular', $exclPrice);
+ $subtotalFormatedPriceXmlObj->addAttribute('regular', $formatedExclPrice);
+ }
+ if ($this->helper('tax')->displayCartPriceInclTax()) {
+ $subtotalPriceXmlObj->addAttribute('regular', $inclPrice);
+ $subtotalFormatedPriceXmlObj->addAttribute('regular', $formatedInclPrice);
+ }
+ }
+
+ /**
+ * Options list
+ */
+ if ($_options = $renderer->getOptionList()) {
+ $itemOptionsXml = $itemXml->addChild('options');
+ foreach ($_options as $_option) {
+ $_formatedOptionValue = $renderer->getFormatedOptionValue($_option);
+ $optionXml = $itemOptionsXml->addChild('option');
+ $optionXml->addAttribute('label', $itemsXmlObj->xmlentities(strip_tags($_option['label'])));
+ $optionXml->addAttribute('text', $itemsXmlObj->xmlentities(strip_tags($_formatedOptionValue['value'])));
+// if (isset($_formatedOptionValue['full_view'])) {
+// $label = strip_tags($_option['label']);
+// $value = strip_tags($_formatedOptionValue['full_view']);
+// }
+ }
+ }
+ }
+
+ return $itemsXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Authorizenet.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Authorizenet.php
new file mode 100644
index 0000000000..34a940e55f
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Authorizenet.php
@@ -0,0 +1,124 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_Authorizenet extends Mage_Payment_Block_Form_Ccsave
+{
+ /**
+ * Prevent any rendering
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return '';
+ }
+
+ /**
+ * Retrieve payment method model
+ *
+ * @return Mage_Payment_Model_Method_Abstract
+ */
+ public function getMethod()
+ {
+ $method = $this->getData('method');
+ if (!$method) {
+ $method = Mage::getModel('paygate/authorizenet');
+ $this->setData('method', $method);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Add Authorize.net payment method form to payment XML object
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function addPaymentFormToXmlObj(Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj)
+ {
+ $helper = Mage::helper('xmlconnect');
+ $method = $this->getMethod();
+ if (!$method) {
+ return $paymentItemXmlObj;
+ }
+ $formXmlObj = $paymentItemXmlObj->addChild('form');
+ $formXmlObj->addAttribute('name', 'payment_form_' . $method->getCode());
+ $formXmlObj->addAttribute('method', 'post');
+
+ $ccTypes = $helper->getArrayAsXmlItemValues($this->getCcAvailableTypes(), $this->getInfoData('cc_type'));
+
+ $ccMonths = $helper->getArrayAsXmlItemValues($this->getCcMonths(), $this->getInfoData('cc_exp_month'));
+
+ $ccYears = $helper->getArrayAsXmlItemValues($this->getCcYears(), $this->getInfoData('cc_exp_year'));
+
+ $verification = '';
+ if ($this->hasVerification()) {
+ $verification =
+ '
+
+
+
+ ';
+ }
+
+ $xml = <<
+
+
+ $ccTypes
+
+
+
+
+
+
+
+
+
+ $ccMonths
+
+
+
+
+ $ccYears
+
+
+ $verification
+
+EOT;
+ $fieldsetXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($xml);
+ $formXmlObj->appendChild($fieldsetXmlObj);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Ccsave.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Ccsave.php
new file mode 100644
index 0000000000..6d724a6e10
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Ccsave.php
@@ -0,0 +1,136 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_Ccsave extends Mage_Payment_Block_Form_Ccsave
+{
+ /**
+ * Prevent any rendering
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return '';
+ }
+
+ /**
+ * Retrieve payment method model
+ *
+ * @return Mage_Payment_Model_Method_Abstract
+ */
+ public function getMethod()
+ {
+ $method = $this->getData('method');
+ if (!$method) {
+ $method = Mage::getModel('payment/method_ccsave');
+ $this->setData('method', $method);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Add cc save payment method form to payment XML object
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function addPaymentFormToXmlObj(Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj)
+ {
+ $helper = Mage::helper('xmlconnect');
+ $method = $this->getMethod();
+ if (!$method) {
+ return $paymentItemXmlObj;
+ }
+ $formXmlObj = $paymentItemXmlObj->addChild('form');
+ $formXmlObj->addAttribute('name', 'payment_form_' . $method->getCode());
+ $formXmlObj->addAttribute('method', 'post');
+
+ $owner = $this->getInfoData('cc_owner');
+
+ $ccTypes = $helper->getArrayAsXmlItemValues($this->getCcAvailableTypes(), $this->getInfoData('cc_type'));
+
+ $_ccMonthArray = $this->getCcMonths();
+ $ccMonths = $helper->getArrayAsXmlItemValues($_ccMonthArray, $this->getInfoData('cc_exp_month'));
+
+ $ccYears = $helper->getArrayAsXmlItemValues($this->getCcYears(), $this->getInfoData('cc_exp_year'));
+
+ $verification = '';
+ if ($this->hasVerification()) {
+ $verification =
+ '
+
+
+
+ ';
+ }
+
+ $solo = '';
+ if ($this->hasSsCardType()) {
+ $ssCcMonths = $helper->getArrayAsXmlItemValues($_ccMonthArray, $this->getInfoData('cc_ss_start_month'));
+ $ssCcYears = $helper->getArrayAsXmlItemValues($this->getSsStartYears(), $this->getInfoData('cc_ss_start_year'));
+ $solo = $helper->getSoloXml($ssCcMonths, $ssCcYears);
+ }
+
+ $xml = <<
+
+
+
+ $ccTypes
+
+ $solo
+
+
+
+
+
+
+
+
+ $ccMonths
+
+
+
+
+ $ccYears
+
+
+ $verification
+
+EOT;
+ $fieldsetXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($xml);
+ $formXmlObj->appendChild($fieldsetXmlObj);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Checkmo.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Checkmo.php
new file mode 100644
index 0000000000..afafe52751
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Checkmo.php
@@ -0,0 +1,73 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_Checkmo extends Mage_Payment_Block_Form_Checkmo
+{
+ /**
+ * Prevent any rendering
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return '';
+ }
+
+ /**
+ * Retrieve payment method model
+ *
+ * @return Mage_Payment_Model_Method_Abstract
+ */
+ public function getMethod()
+ {
+ $method = $this->getData('method');
+ if (!$method) {
+ $method = Mage::getModel('payment/method_checkmo');
+ $this->setData('method', $method);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Add cc save payment method form to payment XML object
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function addPaymentFormToXmlObj(Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj)
+ {
+ return $paymentItemXmlObj;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/List.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/List.php
new file mode 100644
index 0000000000..fa8ee71d30
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/List.php
@@ -0,0 +1,198 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_List extends Mage_Payment_Block_Form_Container
+{
+
+ /**
+ * Prevent parent set childs
+ *
+ * @return Mage_XmlConnect_Block_Checkout_Payment_Method_List
+ */
+ protected function _prepareLayout()
+ {
+ return $this;
+ }
+
+ /**
+ * Retrieve quote model object
+ *
+ * @return Mage_Sales_Model_Quote
+ */
+ public function getQuote()
+ {
+ return Mage::getSingleton('checkout/session')->getQuote();
+ }
+
+ /**
+ * Render payment methods xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $methodsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ $methodBlocks = $this->getChild();
+ $methodArray = array (
+ 'payment_ccsave' => 'Mage_Payment_Model_Method_Cc',
+ 'payment_checkmo' => 'Mage_Payment_Model_Method_Checkmo',
+ 'payment_purchaseorder' => 'Mage_Payment_Model_Method_Purchaseorder');
+ $usedMethods = $sortedAvailableMethodCodes = $usedCodes = array();
+ $allAvailableMethods = Mage::helper('payment')->getStoreMethods(Mage::app()->getStore(), $this->getQuote());
+
+ foreach ($allAvailableMethods as $method) {
+ $sortedAvailableMethodCodes[] = $method->getCode();
+ }
+
+ /**
+ * Collect directly supported by xmlconnect methods
+ */
+ foreach ($methodBlocks as $block) {
+ if (!$block) {
+ continue;
+ }
+
+ $method = $block->getMethod();
+ if (!$this->_canUseMethod($method) || in_array($method->getCode(), $usedCodes)) {
+ continue;
+ }
+ $this->_assignMethod($method);
+ $usedCodes[] = $method->getCode();
+ $usedMethods[$method->getCode()] = array('renderer' => $block, 'method' => $method);
+ }
+
+ /**
+ * Collect all "Credit Card" / "CheckMo" / "Purchaseorder" method compatible methods
+ */
+ foreach ($methodArray as $methodName => $methodModelClassName) {
+ $methodRenderer = $this->getChild($methodName);
+ if (!is_null($methodRenderer)) {
+ foreach ($sortedAvailableMethodCodes as $methodCode) {
+ /**
+ * Skip used methods
+ */
+ if (in_array($methodCode, $usedCodes)) {
+ continue;
+ }
+ try {
+ $method = Mage::helper('payment')->getMethodInstance($methodCode);
+ if (!is_subclass_of($method, $methodModelClassName)) {
+ continue;
+ }
+ if (!$this->_canUseMethod($method)) {
+ continue;
+ }
+
+ $this->_assignMethod($method);
+ $usedCodes[] = $method->getCode();
+ $usedMethods[$method->getCode()] = array('renderer' => $methodRenderer, 'method' => $method);
+ } catch (Exception $e) {
+ Mage::logException($e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Generate methods XML according to sort order
+ */
+ foreach ($sortedAvailableMethodCodes as $code) {
+ if (!in_array($code, $usedCodes)) {
+ continue;
+ }
+
+ $method = $usedMethods[$code]['method'];
+ $renderer = $usedMethods[$code]['renderer'];
+ /**
+ * Render all Credit Card method compatible methods
+ */
+ if ($renderer instanceOf Mage_XmlConnect_Block_Checkout_Payment_Method_Ccsave) {
+ $renderer->setData('method', $method);
+ }
+
+ $methodItemXmlObj = $methodsXmlObj->addChild('method');
+ $methodItemXmlObj->addAttribute('post_name', 'payment[method]');
+ $methodItemXmlObj->addAttribute('code', $method->getCode());
+ $methodItemXmlObj->addAttribute('label', $methodsXmlObj->xmlentities(strip_tags($method->getTitle())));
+ if ($this->getQuote()->getPayment()->getMethod() == $method->getCode()) {
+ $methodItemXmlObj->addAttribute('selected', 1);
+ }
+ $renderer->addPaymentFormToXmlObj($methodItemXmlObj);
+ }
+
+
+ return $methodsXmlObj->asNiceXml();
+ }
+
+ /**
+ * Check and prepare payment method model
+ *
+ * @param mixed $method
+ * @return bool
+ */
+ protected function _canUseMethod($method)
+ {
+ if (!$method || !$method->canUseCheckout() || !$method->canUseForMultishipping() || !$method->isAvailable($this->getQuote())) {
+ return false;
+ }
+ return parent::_canUseMethod($method);
+ }
+
+ /**
+ * Deprecated function adding Payment method to the xml
+ *
+ * @deprecated after 1.4.2.0
+ * @param Mage_Core_Block_Template $block
+ * @param Mage_XmlConnect_Model_Simplexml_Element $methodsXmlObj
+ * @param array $usedCodes
+ * @return bool
+ */
+ protected function _addToXml($block, $methodsXmlObj, $usedCodes)
+ {
+ return false;
+ }
+
+ /**
+ * Deprecated function check method status
+ *
+ * @deprecated after 1.4.2.0
+ * @param Mage_Payment_Model_Method_Abstract $method
+ * @return bool
+ */
+ public function isAvailable($method)
+ {
+ return $method->isAvailable($this->getQuote());
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Paypal/Direct.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Paypal/Direct.php
new file mode 100644
index 0000000000..e1ba260749
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Paypal/Direct.php
@@ -0,0 +1,62 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_Paypal_Direct extends Mage_XmlConnect_Block_Checkout_Payment_Method_Paypal_Payflow
+{
+ /**
+ * Prevent any rendering
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return '';
+ }
+
+ /**
+ * Retrieve payment method model
+ *
+ * @return Mage_Payment_Model_Method_Abstract
+ */
+ public function getMethod()
+ {
+ $method = $this->getData('method');
+ if (!$method) {
+ $method = Mage::getModel('paypal/direct');
+ $this->setData('method', $method);
+ }
+
+ return $method;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Paypal/Payflow.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Paypal/Payflow.php
new file mode 100644
index 0000000000..2c1f1ffa11
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Paypal/Payflow.php
@@ -0,0 +1,159 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_Paypal_Payflow extends Mage_Payment_Block_Form_Ccsave
+{
+ /**
+ * Prevent any rendering
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return '';
+ }
+
+ /**
+ * Retrieve payment method model
+ *
+ * @return Mage_Payment_Model_Method_Abstract
+ */
+ public function getMethod()
+ {
+ $method = $this->getData('method');
+ if (!$method) {
+ $method = Mage::getModel('paypal/payflowpro');
+ $this->setData('method', $method);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Add Payflow Pro payment method form to payment XML object
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function addPaymentFormToXmlObj(Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj)
+ {
+ $method = $this->getMethod();
+ if (!$method) {
+ return $paymentItemXmlObj;
+ }
+ $formXmlObj = $paymentItemXmlObj->addChild('form');
+ $formXmlObj->addAttribute('name', 'payment_form_' . $method->getCode());
+ $formXmlObj->addAttribute('method', 'post');
+
+ $_ccType = $this->getInfoData('cc_type');
+ $ccTypes = '';
+
+ foreach ($this->getCcAvailableTypes() as $_typeCode => $_typeName) {
+ if (!$_typeCode) {
+ continue;
+ }
+ $ccTypes .= '
+ -
+
' . $_typeName . '
+ ' . $_typeCode . '
+ ';
+ }
+
+ $ccMonthes = '';
+
+ $_ccExpMonth = $this->getInfoData('cc_exp_month');
+ foreach ($this->getCcMonths() as $k => $v) {
+ if (!$k) {
+ continue;
+ }
+ $ccMonthes .= '
+ -
+
' . $v . '
+ ' . ($k ? $k : '') . '
+ ';
+ }
+
+ $ccYears = '';
+
+ $_ccExpYear = $this->getInfoData('cc_exp_year');
+ foreach ($this->getCcYears() as $k => $v) {
+ if (!$k) {
+ continue;
+ }
+ $ccYears .= '
+ -
+
' . $v . '
+ ' . ($k ? $k : '') . '
+ ';
+ }
+
+ $verification = '';
+ if ($this->hasVerification()) {
+ $verification =
+ '
+
+
+
+ ';
+ }
+
+ $xml = <<
+
+
+ $ccTypes
+
+
+
+
+
+
+
+
+
+ $ccMonthes
+
+
+
+
+ $ccYears
+
+
+ $verification
+
+EOT;
+ $fieldsetXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($xml);
+ $formXmlObj->appendChild($fieldsetXmlObj);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Purchaseorder.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Purchaseorder.php
new file mode 100644
index 0000000000..ce1546bb2b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Payment/Method/Purchaseorder.php
@@ -0,0 +1,90 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Payment_Method_Purchaseorder extends Mage_Payment_Block_Form_Purchaseorder
+{
+ /**
+ * Prevent any rendering
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ return '';
+ }
+
+ /**
+ * Retrieve payment method model
+ *
+ * @return Mage_Payment_Model_Method_Abstract
+ */
+ public function getMethod()
+ {
+ $method = $this->getData('method');
+ if (!$method) {
+ $method = Mage::getModel('payment/method_purchaseorder');
+ $this->setData('method', $method);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Add payment method form to payment XML object
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function addPaymentFormToXmlObj(Mage_XmlConnect_Model_Simplexml_Element $paymentItemXmlObj)
+ {
+ $method = $this->getMethod();
+ if (!$method) {
+ return $paymentItemXmlObj;
+ }
+ $formXmlObj = $paymentItemXmlObj->addChild('form');
+ $formXmlObj->addAttribute('name', 'payment_form_' . $method->getCode());
+ $formXmlObj->addAttribute('method', 'post');
+
+ $poNumber = $this->getInfoData('po_number');
+ $xml = <<
+
+
+EOT;
+ $fieldsetXmlObj = new Mage_XmlConnect_Model_Simplexml_Element($xml);
+ $formXmlObj->appendChild($fieldsetXmlObj);
+
+ return $paymentItemXmlObj;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Shipping/Method/Avaliable.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Shipping/Method/Avaliable.php
new file mode 100644
index 0000000000..de1ac3a9fb
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Checkout/Shipping/Method/Avaliable.php
@@ -0,0 +1,73 @@
+
+ */
+class Mage_XmlConnect_Block_Checkout_Shipping_Method_Avaliable extends Mage_Checkout_Block_Onepage_Shipping_Method_Available
+{
+ /**
+ * Render shipping methods xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $methodsXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $_shippingRateGroups = $this->getShippingRates();
+ if ($_shippingRateGroups) {
+ $store = $this->getQuote()->getStore();
+ $_sole = count($_shippingRateGroups) == 1;
+ foreach ($_shippingRateGroups as $code => $_rates) {
+ $methodXmlObj = $methodsXmlObj->addChild('method');
+ $methodXmlObj->addAttribute('label', $methodsXmlObj->xmlentities(strip_tags($this->getCarrierName($code))));
+ $ratesXmlObj = $methodXmlObj->addChild('rates');
+
+ $_sole = $_sole && count($_rates) == 1;
+ foreach ($_rates as $_rate) {
+ $rateXmlObj = $ratesXmlObj->addChild('rate');
+ $rateXmlObj->addAttribute('label', $methodsXmlObj->xmlentities(strip_tags($_rate->getMethodTitle())));
+ $rateXmlObj->addAttribute('code', $_rate->getCode());
+ if ($_rate->getErrorMessage()) {
+ $rateXmlObj->addChild('error_message', $methodsXmlObj->xmlentities(strip_tags($_rate->getErrorMessage())));
+ } else {
+ $price = Mage::helper('tax')->getShippingPrice($_rate->getPrice(), false, $this->getAddress());
+ $formattedPrice = $store->convertPrice($price, true, false);
+ $rateXmlObj->addAttribute('price', Mage::helper('xmlconnect')->formatPriceForXml($store->convertPrice($price, false, false)));
+ $rateXmlObj->addAttribute('formated_price', $formattedPrice);
+ }
+ }
+ }
+ } else {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Sorry, no quotes are available for this order at this time.'));
+ }
+ return $methodsXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cms/Page.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cms/Page.php
new file mode 100644
index 0000000000..eea430042d
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Cms/Page.php
@@ -0,0 +1,46 @@
+
+ */
+
+class Mage_XmlConnect_Block_Cms_Page extends Mage_Cms_Block_Page
+{
+ /**
+ * Page Id getter
+ *
+ * @return int
+ */
+ public function getPageId()
+ {
+ return $this->getRequest()->getParam('id');
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Configuration.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Configuration.php
new file mode 100644
index 0000000000..14623f747e
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Configuration.php
@@ -0,0 +1,113 @@
+
+ */
+
+class Mage_XmlConnect_Block_Configuration extends Mage_Core_Block_Template
+{
+ protected $_app;
+
+ /**
+ * Init current application
+ *
+ * @return Mage_XmlConnect_Block_Configuration
+ */
+ protected function _beforeToHtml()
+ {
+ $app = Mage::registry('current_app');
+ if ($app) {
+ $this->_app = $app;
+ } else {
+ $this->_app = Mage::getModel('xmlconnect/application');
+ $this->_app->loadDefaultConfiguration();
+ }
+ return $this;
+ }
+
+ /**
+ * Recursively build XML configuration tree
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $section
+ * @param array $subtree
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ protected function _buildRecursive($section, $subtree)
+ {
+ foreach ($subtree as $key => $value) {
+ if (is_array($value)) {
+ if ($key == 'fonts') {
+ $subsection = $section->addChild('fonts');
+ foreach ($value as $label=>$v) {
+ if (empty($v['name']) || empty($v['size']) || empty($v['color'])) {
+ continue;
+ }
+ $font = $subsection->addChild('font');
+ $font->addAttribute('label', $label);
+ $font->addAttribute('name', $v['name']);
+ $font->addAttribute('size', $v['size']);
+ $font->addAttribute('color', $v['color']);
+ }
+ } elseif ($key == 'pages') {
+ $subsection = $section->addChild('content');
+ foreach ($value as $page) {
+ $this->_buildRecursive($subsection->addChild('page'), $page);
+ }
+ } else {
+ $subsection = $section->addChild($key);
+ $this->_buildRecursive($subsection, $value);
+ }
+ } elseif ($value instanceof Mage_XmlConnect_Model_Tabs) {
+ foreach ($value->getRenderTabs() as $tab) {
+ $subsection = $section->addChild('tab');
+ $this->_buildRecursive($subsection, $tab);
+ }
+ } else {
+ $value = (string)$value;
+ if ($value != '') {
+ $section->addChild($key, $value);
+ }
+ }
+ }
+ }
+
+ /**
+ * Render block
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $xml = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $this->_buildRecursive($xml, $this->_app->getRenderConf());
+ return $xml->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Address/Form.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Address/Form.php
new file mode 100644
index 0000000000..c485389f65
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Address/Form.php
@@ -0,0 +1,178 @@
+
+ */
+class Mage_XmlConnect_Block_Customer_Address_Form extends Mage_Core_Block_Template
+{
+ /**
+ * Render customer address form xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $address = $this->getAddress();
+ $xmlModel = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ /**
+ * Init address object and save its data to variables
+ */
+ $addressId = (int)$this->getRequest()->getParam('id');
+ if ($addressId && $address && $address->getId()) {
+ $defaultBillingAddressId = Mage::getSingleton('customer/session')->getCustomer()->getDefaultBilling();
+ $defaultShippingAddressId = Mage::getSingleton('customer/session')->getCustomer()->getDefaultShipping();
+
+ $billingChecked = $addressId == $defaultBillingAddressId ? ' checked="1"' : '';
+ $shippingChecked = $addressId == $defaultShippingAddressId ? ' checked="1"' : '';
+
+ $firstname = $xmlModel->xmlentities(strip_tags($address->getFirstname()));
+ $lastname = $xmlModel->xmlentities(strip_tags($address->getLastname()));
+ $company = $xmlModel->xmlentities(strip_tags($address->getCompany()));
+ $street1 = $xmlModel->xmlentities(strip_tags($address->getStreet(1)));
+ $street2 = $xmlModel->xmlentities(strip_tags($address->getStreet(2)));
+ $city = $xmlModel->xmlentities(strip_tags($address->getCity()));
+ $regionId = $xmlModel->xmlentities($address->getRegionId());
+ $region = Mage::getModel('directory/region')->load($regionId)->getName();
+ if (!$region) {
+ $region = $address->getRegion();
+ }
+ $region = $xmlModel->xmlentities(strip_tags($region));
+ $postcode = $xmlModel->xmlentities(strip_tags($address->getPostcode()));
+ $countryId = $xmlModel->xmlentities($address->getCountryId());
+ $telephone = $xmlModel->xmlentities(strip_tags($address->getTelephone()));
+ $fax = $xmlModel->xmlentities(strip_tags($address->getFax()));
+ } else {
+ $firstname = $lastname = $company = $street1 = $street2 = $billingChecked = $shippingChecked = '';
+ $city = $region = $postcode = $telephone = $fax = '';
+ $countryId = $regionId = null;
+ }
+
+ $countries = $this->_getCountryOptions();
+
+ $regions = array();
+ $countryOptionsXml = '';
+ if (is_array($countries)) {
+ foreach ($countries as $key => $data) {
+ if ($data['value']) {
+ $regions = $this->_getRegionOptions($data['value']);
+ }
+ $countryOptionsXml .= '
+ -
+
' . $xmlModel->xmlentities((string)$data['label']) . '
+ ' . $xmlModel->xmlentities($data['value']) . ' ';
+ if (is_array($regions) && !empty($regions)) {
+ $countryOptionsXml .= '';
+ foreach ($regions as $_key => $_data) {
+ $countryOptionsXml .= '';
+ $countryOptionsXml .=
+ '' . $xmlModel->xmlentities((string)$_data['label']) . '
+ ' . $xmlModel->xmlentities($_data['value']) . ' ';
+ $countryOptionsXml .= ' ';
+ }
+ $countryOptionsXml .= ' ';
+ }
+ $countryOptionsXml .= ' ';
+ }
+ }
+ $countryOptionsXml .= ' ';
+
+ $xml = <<
+
+
+
+
+
+
+
+
+
+
+
+
+ $countryOptionsXml
+
+
+
+
+
+
+
+
+EOT;
+ return $xml;
+ }
+
+ /**
+ * Retrieve regions by country
+ *
+ * @param string $countryId
+ * @return array
+ */
+ protected function _getRegionOptions($countryId)
+ {
+ $cacheKey = 'DIRECTORY_REGION_SELECT_STORE'.Mage::app()->getStore()->getId().$countryId;
+ if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
+ $options = unserialize($cache);
+ } else {
+ $collection = Mage::getModel('directory/region')->getResourceCollection()
+ ->addCountryFilter($countryId)
+ ->load();
+ $options = $collection->toOptionArray();
+ if (Mage::app()->useCache('config')) {
+ Mage::app()->saveCache(serialize($options), $cacheKey, array('config'));
+ }
+ }
+ return $options;
+ }
+
+ /**
+ * Retrieve countries
+ *
+ * @return array
+ */
+ protected function _getCountryOptions()
+ {
+ $cacheKey = 'DIRECTORY_COUNTRY_SELECT_STORE_'.Mage::app()->getStore()->getCode();
+ if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
+ $options = unserialize($cache);
+ } else {
+ $collection = Mage::getModel('directory/country')->getResourceCollection()
+ ->loadByStore();
+ $options = $collection->toOptionArray();
+ if (Mage::app()->useCache('config')) {
+ Mage::app()->saveCache(serialize($options), $cacheKey, array('config'));
+ }
+ }
+ return $options;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Address/List.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Address/List.php
new file mode 100644
index 0000000000..16be94dd51
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Address/List.php
@@ -0,0 +1,127 @@
+
+ */
+class Mage_XmlConnect_Block_Customer_Address_List extends Mage_Core_Block_Template
+{
+ /**
+ * Render customer address list xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $addressXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
+
+ $_billingAddssesId = $customer->getDefaultBilling();
+ $_shippingAddssesId = $customer->getDefaultShipping();
+ $billingAddress = $customer->getAddressById($_billingAddssesId);
+ $shippingAddress = $customer->getAddressById($_shippingAddssesId);
+
+ if ($billingAddress && $billingAddress->getId()) {
+ $item = $addressXmlObj->addChild('item');
+ $item->addAttribute('label', Mage::helper('xmlconnect')->__('Default Billing Address'));
+ $item->addAttribute('default_billing', 1);
+ $this->prepareAddressData($billingAddress, $item);
+ }
+ if ($shippingAddress && $shippingAddress->getId()) {
+ $item = $addressXmlObj->addChild('item');
+ $item->addAttribute('label', Mage::helper('xmlconnect')->__('Default Shipping Address'));
+ $item->addAttribute('default_shipping', 1);
+ $this->prepareAddressData($shippingAddress, $item);
+ }
+ $_additionalAddresses = $customer->getAdditionalAddresses();
+ if ($_additionalAddresses) {
+ foreach ($_additionalAddresses as $_address) {
+ $item = $addressXmlObj->addChild('item');
+ $item->addAttribute('label', Mage::helper('xmlconnect')->__('Additional Address'));
+ $item->addAttribute('additional', 1);
+ $this->prepareAddressData($_address, $item);
+ }
+ }
+
+ return $addressXmlObj->asNiceXml();
+ }
+
+ /**
+ * Collect address data to xml node
+ * Remove objects from data array and escape data values
+ *
+ * @param Mage_Customer_Model_Address $address
+ * @param Mage_XmlConnect_Model_Simplexml_Element $item
+ * @return array
+ */
+ public function prepareAddressData(Mage_Customer_Model_Address $address, Mage_XmlConnect_Model_Simplexml_Element $item)
+ {
+ if (!$address) {
+ return array();
+ }
+
+ $attributes = Mage::helper('customer/address')->getAttributes();
+
+ $data = array(
+ 'entity_id' => $address->getId()
+ );
+
+ foreach ($attributes as $attribute) {
+ /* @var $attribute Mage_Customer_Model_Attribute */
+ if (!$attribute->getIsVisible()) {
+ continue;
+ }
+ if ($attribute->getAttributeCode() == 'country_id') {
+ $data['country'] = $address->getCountryModel()->getName();
+ $data['country_id'] = $address->getCountryId();
+ } else if ($attribute->getAttributeCode() == 'region') {
+ $data['region'] = $address->getRegion();
+ } else {
+ $dataModel = Mage_Customer_Model_Attribute_Data::factory($attribute, $address);
+ $value = $dataModel->outputValue(Mage_Customer_Model_Attribute_Data::OUTPUT_FORMAT_ONELINE);
+ if ($attribute->getFrontendInput() == 'multiline') {
+ $values = $dataModel->outputValue(Mage_Customer_Model_Attribute_Data::OUTPUT_FORMAT_ARRAY);
+ // explode lines
+ foreach ($values as $k => $v) {
+ $key = sprintf('%s%d', $attribute->getAttributeCode(), $k + 1);
+ $data[$key] = $v;
+ }
+ }
+ $data[$attribute->getAttributeCode()] = $value;
+ }
+ }
+
+ foreach ($data as $key => $value) {
+ if (!empty($value)) {
+ $item->addChild($key, $item->xmlentities($value));
+ }
+ }
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Form.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Form.php
new file mode 100644
index 0000000000..fc95df38f7
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Form.php
@@ -0,0 +1,96 @@
+
+ */
+class Mage_XmlConnect_Block_Customer_Form extends Mage_Core_Block_Template
+{
+ /**
+ * Render customer form xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $editFlag = (int)$this->getRequest()->getParam('edit');
+ $customer = $this->getCustomer();
+ $xmlModel = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ if ($editFlag == 1 && $customer && $customer->getId()) {
+ $firstname = $xmlModel->xmlentities(strip_tags($customer->getFirstname()));
+ $lastname = $xmlModel->xmlentities(strip_tags($customer->getLastname()));
+ $email = $xmlModel->xmlentities(strip_tags($customer->getEmail()));
+ } else {
+ $firstname = $lastname = $email = '';
+ }
+
+ if ($editFlag) {
+ $passwordManageXml = '
+
+
+
+
+
+
+
+ password
+
+
+ ';
+ } else {
+ $passwordManageXml = '
+
+
+
+ password
+
+
+ ';
+ }
+
+ $xml = <<
+
+
+
+
+
+
+
+
+ $passwordManageXml
+
+EOT;
+
+ return $xml;
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Order/List.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Order/List.php
new file mode 100644
index 0000000000..cab202faab
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Customer/Order/List.php
@@ -0,0 +1,75 @@
+
+ */
+class Mage_XmlConnect_Block_Customer_Order_List extends Mage_Core_Block_Template
+{
+ /**
+ * Linmitation for orders list
+ */
+ const ORDERS_LIST_LIMIT = 10;
+
+ /**
+ * Render customer orders list xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $ordersXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ $orders = Mage::getResourceModel('sales/order_collection')
+ ->addFieldToSelect('*')
+ ->addFieldToFilter('customer_id', Mage::getSingleton('customer/session')->getCustomer()->getId())
+ ->addFieldToFilter('state', array('in' => Mage::getSingleton('sales/order_config')->getVisibleOnFrontStates()))
+ ->setOrder('created_at', 'desc');
+
+ $orders->getSelect()->limit(self::ORDERS_LIST_LIMIT, 0);
+ $orders->load();
+
+ if (sizeof($orders->getItems())) {
+ foreach ($orders as $_order) {
+ $item = $ordersXmlObj->addChild('item');
+ $item->addChild('entity_id', $_order->getId());
+ $item->addChild('number', $_order->getRealOrderId());
+ $item->addChild('date', $this->formatDate($_order->getCreatedAtStoreDate()));
+ if ($_order->getShippingAddress()) {
+ $item->addChild('ship_to', $ordersXmlObj->xmlentities(strip_tags($_order->getShippingAddress()->getName())));
+ }
+ $item->addChild('total', $_order->getOrderCurrency()->formatPrecision($_order->getGrandTotal(), 2, array(), false, false));
+ $item->addChild('status', $_order->getStatusLabel());
+ }
+ }
+
+ return $ordersXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Home.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Home.php
new file mode 100644
index 0000000000..2368baa0a6
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Home.php
@@ -0,0 +1,84 @@
+
+ */
+
+class Mage_XmlConnect_Block_Home extends Mage_XmlConnect_Block_Catalog
+{
+
+ /**
+ * Category list limitation
+ */
+ const HOME_PAGE_CATEGORIES_COUNT = 6;
+
+ /**
+ * Render home category list xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $homeXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+
+ $categoryCollection = Mage::getResourceModel('xmlconnect/category_collection');
+ $categoryCollection->setStoreId(Mage::app()->getStore()->getId())
+ ->addParentIdFilter(Mage::app()->getStore()->getRootCategoryId())
+ ->setOrder('position', 'ASC')
+ ->setLimit(0, self::HOME_PAGE_CATEGORIES_COUNT);
+
+ if (sizeof($categoryCollection)) {
+ $itemsXmlObj = $homeXmlObj->addChild('categories');
+ }
+
+ foreach ($categoryCollection->getItems() as $item) {
+ $itemXmlObj = $itemsXmlObj->addChild('item');
+ $itemXmlObj->addChild('label', $homeXmlObj->xmlentities(strip_tags($item->getName())));
+ $itemXmlObj->addChild('entity_id', $item->getEntityId());
+ $itemXmlObj->addChild('content_type', $item->hasChildren() ? 'categories' : 'products');
+ $icon = Mage::helper('xmlconnect/catalog_category_image')->initialize($item, 'thumbnail')
+ ->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('category'));
+
+ $iconXml = $itemXmlObj->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+ }
+
+ $homeXmlObj->addChild('home_banner', '/current/media/catalog/category/banner_home.png');
+
+ return $homeXmlObj->asNiceXml();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Block/Wishlist.php b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Wishlist.php
new file mode 100644
index 0000000000..70ea51dddb
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Block/Wishlist.php
@@ -0,0 +1,113 @@
+
+ */
+
+class Mage_XmlConnect_Block_Wishlist extends Mage_Wishlist_Block_Customer_Wishlist
+{
+ /**
+ * Render customer wishlist xml
+ *
+ * @return string
+ */
+ protected function _toHtml()
+ {
+ $wishlistXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $hasMoreItems = 0;
+ /**
+ * Apply offset and count
+ */
+ $request= $this->getRequest();
+ $offset = (int)$request->getParam('offset', 0);
+ $count = (int)$request->getParam('count', 0);
+ $count = $count <= 0 ? 1 : $count;
+ if ($offset + $count < $this->getWishlist()->getSize()) {
+ $hasMoreItems = 1;
+ }
+ $this->getWishlist()->getSelect()->limit($count, $offset);
+
+ $wishlistXmlObj->addAttribute('items_count', $this->getWishlistItemsCount());
+ $wishlistXmlObj->addAttribute('has_more_items', $hasMoreItems);
+
+ if ($this->hasWishlistItems()) {
+ /**
+ * @var Mage_Wishlist_Model_Mysql4_Product_Collection
+ */
+ foreach ($this->getWishlist() as $item) {
+ $itemXmlObj = $wishlistXmlObj->addChild('item');
+ $itemXmlObj->addChild('item_id', $item->getWishlistItemId());
+ $itemXmlObj->addChild('entity_id', $item->getProductId());
+ $itemXmlObj->addChild('entity_type_id', $item->getTypeId());
+ $itemXmlObj->addChild('name', $wishlistXmlObj->xmlentities(strip_tags($item->getName())));
+ $itemXmlObj->addChild('in_stock', (int)$item->isSalable());
+ /**
+ * If product type is grouped than it has options as its grouped items
+ */
+ if ($item->getTypeId() == Mage_Catalog_Model_Product_Type_Grouped::TYPE_CODE) {
+ $item->setHasOptions(true);
+ }
+ $itemXmlObj->addChild('has_options', (int)$item->getHasOptions());
+
+ $icon = $this->helper('catalog/image')->init($item, 'small_image')
+ ->resize(Mage::helper('xmlconnect/image')->getImageSizeForContent('product_small'));
+
+ $iconXml = $itemXmlObj->addChild('icon', $icon);
+
+ $baseUrl = Mage::getBaseUrl('media');
+ $path = str_replace($baseUrl, '', $icon);
+ $file = Mage::getBaseDir('media') . DS . str_replace('/', DS, $path);
+
+ $iconXml->addAttribute('modification_time', filemtime($file));
+
+
+ $itemXmlObj->addChild('description', $wishlistXmlObj->xmlentities(strip_tags($item->getWishlistItemDescription())));
+ $itemXmlObj->addChild('added_date', $wishlistXmlObj->xmlentities($this->getFormatedDate($item->getAddedAt())));
+
+ if ($this->getChild('product_price')) {
+ $this->getChild('product_price')->setProduct($item)
+ ->setProductXmlObj($itemXmlObj)
+ ->collectProductPrices();
+ }
+
+ if (!$item->getRatingSummary()) {
+ Mage::getModel('review/review')
+ ->getEntitySummary($item, Mage::app()->getStore()->getId());
+ }
+
+ $itemXmlObj->addChild('rating_summary', round((int)$item->getRatingSummary()->getRatingSummary() / 10));
+ $itemXmlObj->addChild('reviews_count', $item->getRatingSummary()->getReviewsCount());
+ }
+ }
+
+ return $wishlistXmlObj->asNiceXml();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Controller/Action.php b/app/code/core/Mage/XmlConnect/XmlConnect/Controller/Action.php
new file mode 100644
index 0000000000..73211c4eb3
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Controller/Action.php
@@ -0,0 +1,102 @@
+getResponse()->setHeader('Content-type', 'text/xml; charset=UTF-8');
+
+ /**
+ * Load application by specified code and make sure that application exists
+ */
+ $cookieName = Mage_XmlConnect_Model_Application::APP_CODE_COOKIE_NAME;
+ $appCode = isset($_COOKIE[$cookieName]) ? (string) $_COOKIE[$cookieName] : '';
+ $screenSizeCookieName = Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_NAME;
+ $screenSize = isset($_COOKIE[$screenSizeCookieName]) ? (string) $_COOKIE[$screenSizeCookieName] : '';
+ if (!$appCode) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid app code.'), self::MESSAGE_STATUS_ERROR);
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
+ return;
+ }
+ $appModel = Mage::getModel('xmlconnect/application')->loadByCode($appCode);
+ $appModel->setScreenSize($screenSize);
+ if ($appModel && $appModel->getId()) {
+ Mage::app()->setCurrentStore(Mage::app()->getStore($appModel->getStoreId())->getCode());
+ Mage::getSingleton('core/locale')->emulate($appModel->getStoreId());
+ Mage::register('current_app', $appModel);
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid app code.'), self::MESSAGE_STATUS_ERROR);
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
+ return;
+ }
+ }
+
+ /**
+ * Validate response body
+ */
+ public function postDispatch()
+ {
+ parent::postDispatch();
+ $body = $this->getResponse()->getBody();
+ if (empty($body)) {
+ $this->_message(
+ Mage::helper('xmlconnect')->__('An error occurred while processing your request.'),
+ self::MESSAGE_STATUS_ERROR
+ );
+ }
+ }
+
+ /**
+ * Generate message xml and set it to response body
+ *
+ * @param string $text
+ * @param string $status
+ * @param string $type
+ * @param string $action
+ */
+ protected function _message($text, $status, $type='', $action='')
+ {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', $status);
+ $message->addChild('text', $text);
+ $this->getResponse()->setBody($message->asNiceXml());
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Catalog/Category/Image.php b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Catalog/Category/Image.php
new file mode 100644
index 0000000000..0ff82fcd65
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Catalog/Category/Image.php
@@ -0,0 +1,95 @@
+
+ */
+class Mage_XmlConnect_Helper_Catalog_Category_Image extends Mage_Catalog_Helper_Image
+{
+
+ /**
+ * Init
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param string $attributeName
+ * @param string $imageFile
+ * @return Mage_XmlConnect_Helper_Catalog_Category_Image
+ *
+ */
+ public function init(Mage_Catalog_Model_Product $product, $attributeName, $imageFile = null)
+ {
+ return $this;
+ }
+
+ /**
+ * Init image helper object
+ *
+ * @param Mage_Catalog_Model_Abstract $category
+ * @param string $attributeName
+ * @param string $imageFile
+ * @return Mage_XmlConnect_Helper_Catalog_Category_Image
+ */
+ public function initialize(Mage_Catalog_Model_Abstract $category, $attributeName, $imageFile = null)
+ {
+ $this->_reset();
+ $this->_setModel(Mage::getModel('xmlconnect/catalog_category_image'));
+ $this->_getModel()->setDestinationSubdir($attributeName);
+ $this->setProduct($category);
+
+ $this->setWatermark(Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_image"));
+ $this->setWatermarkImageOpacity(Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_imageOpacity"));
+ $this->setWatermarkPosition(Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_position"));
+ $this->setWatermarkSize(Mage::getStoreConfig("design/watermark/{$this->_getModel()->getDestinationSubdir()}_size"));
+
+ if ($imageFile) {
+ $this->setImageFile($imageFile);
+ } else {
+ /*
+ * add for work original size
+ */
+ $this->_getModel()->setBaseFile( $this->getProduct()->getData($this->_getModel()->getDestinationSubdir()) );
+ }
+ return $this;
+ }
+
+ /**
+ * Return placeholder image file path
+ *
+ * @return string
+ */
+ public function getPlaceholder()
+ {
+ if (!$this->_placeholder) {
+ $attr = $this->_getModel()->getDestinationSubdir();
+ $this->_placeholder = 'images/xmlconnect/catalog/category/placeholder/'.$attr.'.jpg';
+ }
+ return $this->_placeholder;
+ }
+
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Data.php b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Data.php
new file mode 100644
index 0000000000..43099e1779
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Data.php
@@ -0,0 +1,342 @@
+_getUrl() function to public
+ *
+ * @param string $route
+ * @param array $params
+ * @return array
+ */
+ public function getUrl($route, $params = array())
+ {
+ return $this->_getUrl($route, $params);
+ }
+
+
+ /**
+ * Retrieve country options array
+ *
+ * @return array
+ */
+ public function getCountryOptionsArray()
+ {
+ Varien_Profiler::start('TEST: '.__METHOD__);
+
+ $cacheKey = 'XMLCONNECT_COUNTRY_SELECT_STORE_'.Mage::app()->getStore()->getCode();
+ if (Mage::app()->useCache('config') && $cache = Mage::app()->loadCache($cacheKey)) {
+ $options = unserialize($cache);
+ } else {
+ $options = Mage::getModel('directory/country')
+ ->getResourceCollection()
+ ->loadByStore()
+ ->toOptionArray();
+ if (Mage::app()->useCache('config')) {
+ Mage::app()->saveCache(serialize($options), $cacheKey, array('config'));
+ }
+ }
+ Varien_Profiler::stop('TEST: '.__METHOD__);
+ return $options;
+ }
+
+ /**
+ * Get list of predefined and supported Devices
+ *
+ * @return array
+ */
+ static public function getSupportedDevices()
+ {
+ $devices = array (
+ 'iphone' => Mage::helper('xmlconnect')->__('iPhone')
+ );
+
+ return $devices;
+ }
+
+ /**
+ * Get list of predefined and supported Devices
+ *
+ * @return array
+ */
+ public function getStatusOptions()
+ {
+ $options = array (
+ Mage_XmlConnect_Model_Application::APP_STATUS_SUCCESS => Mage::helper('xmlconnect')->__('Submitted'),
+ Mage_XmlConnect_Model_Application::APP_STATUS_INACTIVE => Mage::helper('xmlconnect')->__('Not Submitted'),
+ );
+ return $options;
+ }
+
+ /**
+ * Retrieve supported device types as "html select options"
+ *
+ * @return array
+ */
+ public function getDeviceTypeOptions()
+ {
+ $devices = self::getSupportedDevices();
+ $options = array();
+ if (count($devices) > 1) {
+ $options[] = array('value' => '', 'label' => Mage::helper('xmlconnect')->__('Please Select Device Type'));
+ }
+ foreach ($devices as $type => $label) {
+ $options[] = array('value' => $type, 'label' => $label);
+ }
+ return $options;
+ }
+
+ /**
+ * Get default application tabs
+ *
+ * @return array
+ */
+ public function getDefaultApplicationDesignTabs()
+ {
+ if (!isset($this->_tabs)) {
+ $this->_tabs = array(
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('Home'),
+ 'image' => 'tab_home.png',
+ 'action' => 'Home',
+ ),
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('Shop'),
+ 'image' => 'tab_shop.png',
+ 'action' => 'Shop',
+ ),
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('Search'),
+ 'image' => 'tab_search.png',
+ 'action' => 'Search',
+ ),
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('Cart'),
+ 'image' => 'tab_cart.png',
+ 'action' => 'Cart',
+ ),
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('More'),
+ 'image' => 'tab_more.png',
+ 'action' => 'More',
+ ),
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('Account'),
+ 'image' => 'tab_account.png',
+ 'action' => 'Account',
+ ),
+ array(
+ 'label' => Mage::helper('xmlconnect')->__('More Info'),
+ 'image' => 'tab_page.png',
+ 'action' => 'AboutUs',
+ ),
+ );
+ }
+ return $this->_tabs;
+ }
+
+ /**
+ * Return array for tabs like label -> action array
+ *
+ * @return array
+ */
+ protected function _getTabLabelActionArray()
+ {
+ if (!isset($this->_tabLabelActionArray)) {
+ $this->_tabLabelActionArray = array();
+ foreach ($this->getDefaultApplicationDesignTabs() as $tab) {
+ $this->_tabLabelActionArray[$tab['action']] = $tab['label'];
+ }
+ }
+ return $this->_tabLabelActionArray;
+ }
+
+ /**
+ * Return Translated tab label for given $action
+ *
+ * @param string $action
+ * @return string|bool
+ */
+ public function getTabLabel($action)
+ {
+ $action = (string) $action;
+ $tabs = $this->_getTabLabelActionArray();
+ return (isset($tabs[$action])) ? $tabs[$action] : false;
+ }
+
+ /**
+ * Merges $changes array to $target array recursive, overwriting existing key, and adding new one
+ *
+ * @param mixed $target
+ * @param mixed $changes
+ * @return array
+ */
+ static public function arrayMergeRecursive($target, $changes)
+ {
+ if (!is_array($target)) {
+ $target = empty($target) ? array() : array($target);
+ }
+ if (!is_array($changes)) {
+ $changes = array($changes);
+ }
+ foreach ($changes as $key => $value) {
+ if (!array_key_exists($key, $target) and !is_numeric($key)) {
+ $target[$key] = $changes[$key];
+ continue;
+ }
+ if (is_array($value) or is_array($target[$key])) {
+ $target[$key] = self::arrayMergeRecursive($target[$key], $changes[$key]);
+ } else if (is_numeric($key)) {
+ if (!in_array($value, $target)) {
+ $target[] = $value;
+ }
+ } else {
+ $target[$key] = $value;
+ }
+ }
+
+ return $target;
+ }
+
+ /**
+ * Wrap $body with HTML4 headers
+ *
+ * @param string $body
+ * @return string
+ */
+ public function htmlize($body)
+ {
+ return << $v) {
+ if (!$k) {
+ continue;
+ }
+ $items[] = '
+ -
+
' . $v . '
+ ' . ($k ? $k : '') . '
+ ';
+ }
+ $result = implode('', $items);
+ return $result;
+ }
+
+ /**
+ * Return Solo Xml optional fieldset
+ *
+ * @param string $ssCcMonths
+ * @param string $ssCcYears
+ * @return string
+ */
+ public function getSoloXml($ssCcMonths, $ssCcYears)
+ {
+ // issue number ==== validate-cc-ukss cvv
+ $solo = <<
+
+
+ - SS
+ - SM
+ - SO
+
+
+
+
+
+
+
+ ;
+
+
+ $ssCcMonths
+
+
+
+
+ $ssCcYears
+
+
+
+EOT;
+ return $solo;
+ }
+
+ /**
+ * Format price for correct view inside xml strings
+ *
+ * @param float $price
+ * @return string
+ */
+ public function formatPriceForXml($price)
+ {
+ return sprintf('%01.2F', $price);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Image.php b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Image.php
new file mode 100644
index 0000000000..f182f4c19f
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Image.php
@@ -0,0 +1,622 @@
+getOriginalSizeUploadDir();
+
+ $this->_forcedConvertPng($field);
+
+ try {
+ $uploader = new Varien_File_Uploader($field);
+ $uploader->setAllowedExtensions(array('jpg', 'jpeg', 'gif', 'png'));
+ $uploader->setAllowRenameFiles(true);
+ $uploader->save($uploadDir);
+ $uploadedFilename = $uploader->getUploadedFileName();
+ $uploadedFilename = $this->_getResizedFilename($field, $uploadedFilename, true);
+ } catch (Exception $e) {
+ /**
+ * Hard coded exception catch
+ */
+ if ($e->getMessage() == 'Disallowed file type.') {
+ $filename = $_FILES[$field]['name'];
+ Mage::throwException(Mage::helper('xmlconnect')->__('Error while uploading file "%s". Disallowed file type. Only "jpg", "jpeg", "gif", "png" are allowed.', $filename));
+ } else {
+ Mage::logException($e);
+ }
+ }
+ return $uploadedFilename;
+ }
+
+ /**
+ * Return current screen_size parameter
+ *
+ * @return string
+ */
+ protected function _getScreenSize()
+ {
+ return Mage::registry('current_app')->getScreenSize();
+ }
+
+ /**
+ * Return correct system filename for current screenSize
+ *
+ * @param string $fieldPath
+ * @param string $fileName
+ * @param string $default
+ * @return string
+ */
+ protected function _getResizedFilename($fieldPath, $fileName, $default = false)
+ {
+ $fileName = basename($fileName);
+ if ($default) {
+ $dir = $this->getDefaultSizeUploadDir();
+ } else {
+ $dir = $this->getCustomSizeUploadDir($this->_getScreenSize());
+ }
+ $customSizeFileName = $dir . DS . $fileName;
+ $originalSizeFileName = $this->getOriginalSizeUploadDir(). DS . $fileName;
+ $error = false;
+ /**
+ * Compatibility with old versions of XmlConnect
+ */
+ if (!file_exists($originalSizeFileName)) {
+ $oldFileName = $this->getOldUploadDir() . DS . $fileName;
+ if (file_exists($oldFileName)) {
+ if (!(copy($oldFileName, $originalSizeFileName) &&
+ (is_readable($customSizeFileName) || chmod($customSizeFileName, 0644)))) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Error while processing file "%s".', $fileName));
+ }
+ } else {
+ Mage::throwException(Mage::helper('xmlconnect')->__('No such file "%s".', $fileName));
+ }
+ }
+
+ if ((!$error) && copy($originalSizeFileName, $customSizeFileName) &&
+ (is_readable($customSizeFileName) || chmod($customSizeFileName, 0644))) {
+ $this->_handleResize($fieldPath, $customSizeFileName);
+ } else {
+ $fileName = '';
+ if (isset($_FILES[$fieldPath]) && is_array($_FILES[$fieldPath]) && isset($_FILES[$fieldPath]['name'])) {
+ $fileName = $_FILES[$fieldPath]['name'];
+ }
+ Mage::throwException(Mage::helper('xmlconnect')->__('Error while uploading file "%s".', $fileName));
+ }
+ return $customSizeFileName;
+ }
+
+ /**
+ * Resize uploaded file
+ *
+ * @param string $fieldPath
+ * @param string $file
+ * @return void
+ */
+ protected function _handleResize($fieldPath, $file)
+ {
+ $nameParts = explode('/', $fieldPath);
+ array_shift($nameParts);
+ $conf = $this->getInterfaceImageLimits();
+ while (count($nameParts)) {
+ $next = array_shift($nameParts);
+ if (isset($conf[$next])) {
+ $conf = $conf[$next];
+ } else {
+ /**
+ * No config data - nothing to resize
+ */
+ return;
+ }
+ }
+
+ $image = new Varien_Image($file);
+ $width = $image->getOriginalWidth();
+ $height = $image->getOriginalHeight();
+
+ if (isset($conf['widthMax']) && ($conf['widthMax'] < $width)) {
+ $width = $conf['widthMax'];
+ } elseif (isset($conf['width'])) {
+ $width = $conf['width'];
+ }
+
+ if (isset($conf['heightMax']) && ($conf['heightMax'] < $height)) {
+ $height = $conf['heightMax'];
+ } elseif (isset($conf['height'])) {
+ $height = $conf['height'];
+ }
+
+ if (($width != $image->getOriginalWidth()) ||
+ ($height != $image->getOriginalHeight()) ) {
+ $image->keepTransparency(true);
+ $image->keepFrame(true);
+ $image->keepAspectRatio(true);
+ $image->backgroundColor(array(255, 255, 255));
+// $image->keepAspectRatio(false);
+ $image->resize($width, $height);
+ $image->save(null, basename($file));
+ }
+ }
+
+ /**
+ * Convert uploaded file to PNG
+ *
+ * @param string $field
+ */
+ protected function _forcedConvertPng($field)
+ {
+ $file =& $_FILES[$field];
+
+ $file['name'] = preg_replace('/\.(gif|jp[e]g)$/i', '.png', $file['name']);
+
+ list($x, $x, $fileType) = getimagesize($file['tmp_name']);
+ if ($fileType != IMAGETYPE_PNG ) {
+ switch( $fileType ) {
+ case IMAGETYPE_GIF:
+ $img = imagecreatefromgif($file['tmp_name']);
+ break;
+ case IMAGETYPE_JPEG:
+ $img = imagecreatefromjpeg($file['tmp_name']);
+ break;
+ default:
+ return;
+ }
+ imagealphablending($img, false);
+ imagesavealpha($img, true);
+ imagepng($img, $file['tmp_name']);
+ imagedestroy($img);
+ }
+ }
+
+ /**
+ * Retrieve xmlconnect images skin url
+ *
+ * @param string $name
+ * @return string
+ */
+ public function getSkinImagesUrl($name = null)
+ {
+ return Mage::getDesign()->getSkinUrl('images/xmlconnect/' . $name);
+ }
+
+ /**
+ * Return CustomSizeDirPrefix
+ *
+ * @return string
+ */
+ public function getCustomSizeDirPrefix()
+ {
+ return $this->_getScreenSize() . DS . 'custom';
+ }
+
+ /**
+ * Return FileDefaultSizeSuffixAsUrl
+ *
+ * @param string $fileName
+ * @return string
+ */
+ public function getFileDefaultSizeSuffixAsUrl($fileName)
+ {
+ return 'custom'.'/'.$this->_getScreenSize().'/'.basename($fileName);
+ }
+
+ /**
+ * Return getFileCustomDirSuffixAsUrl
+ *
+ * @param string $confPath
+ * @param string $fileName
+ * @return string
+ */
+ public function getFileCustomDirSuffixAsUrl($confPath, $fileName)
+ {
+ return 'custom'.'/'.$this->_getScreenSize().'/'.basename($this->_getResizedFilename($confPath, $fileName));
+ }
+
+ /**
+ * Return correct size for given $imageName and device screen_size
+ *
+ * @param string $imageName
+ * @return int
+ */
+ public function getImageSizeForContent($imageName)
+ {
+ $size = 0;
+ if (!isset($this->_content)) {
+ $app = Mage::registry('current_app');
+ if (!$app) {
+ return 0;
+ } else {
+ $imageLimits = $this->getImageLimits($this->_getScreenSize());
+ if (($imageLimits['content']) && is_array($imageLimits['content'])) {
+ $this->_content = $imageLimits['content'];
+ } else {
+ $this->_content = array();
+ }
+ }
+ }
+ $size = isset($this->_content[$imageName]) ? (int) $this->_content[$imageName] : 0;
+ return $size;
+ }
+
+ /**
+ * Return setting for interface images (image size limits)
+ *
+ * @return array
+ */
+ public function getInterfaceImageLimits()
+ {
+ if (!isset($this->_interface)) {
+ $imageLimits = $this->getImageLimits($this->_getScreenSize());
+ $this->_interface = $imageLimits['interface'];
+ }
+ return $this->_interface;
+ }
+
+ /**
+ * Return correct size for given $imageName and device screen_size
+ *
+ * @param string $imagePath
+ * @return int
+ */
+ public function getImageSizeForInterface($imagePath)
+ {
+ $size = 0;
+ if (!isset($this->_interfacePath[$imagePath])) {
+ $app = Mage::registry('current_app');
+ if (!$app) {
+ return 0;
+ } else {
+ $imageLimits = $this->getImageLimits($this->_getScreenSize());
+ $size = $this->findPath($imageLimits, $imagePath);
+ $this->_interfacePath[$imagePath] = $size;
+ }
+ }
+ $size = isset($this->_interfacePath[$imagePath]) ? (int) $this->_interfacePath[$imagePath] : 0;
+ return $size;
+ }
+
+
+ /**
+ * Ensure correct $screenSize value
+ *
+ * @param string $screenSize
+ * @return string
+ */
+ public function filterScreenSize($screenSize)
+ {
+
+ $screenSize = preg_replace('/[^0-9A-z_]/', '', $screenSize);
+ if (isset($this->_imageLimits[$screenSize])) {
+ return $screenSize;
+ }
+ $screenSizeExplodeArray = explode(self::XMLCONNECT_GLUE, $screenSize);
+ $version = '';
+ switch (count($screenSizeExplodeArray)) {
+ case 2:
+ $version = $screenSizeExplodeArray[1];
+ case 1:
+ $resolution = $screenSizeExplodeArray[0];
+ break;
+ default:
+ $resolution = Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_DEFAULT;
+ break;
+ }
+
+ $sourcePath = empty($version) ? Mage_XmlConnect_Model_Application::APP_SCREEN_SOURCE_DEFAULT : $version;
+ $xmlPath = 'screen_size/'.self::XMLCONNECT_GLUE.$resolution.'/'.$sourcePath.'/source';
+
+
+ $source = Mage::getStoreConfig($xmlPath);
+ if (!empty($source)) {
+ $screenSize = $resolution . (empty($version) ? '' : self::XMLCONNECT_GLUE.$version);
+ } else {
+ $screenSize = Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_DEFAULT;
+ }
+ return $screenSize;
+ }
+
+ /**
+ * Return correct size array for given device screen_size(320x480/640x960_a)
+ *
+ * @param string $screenSize
+ * @return array
+ */
+ public function getImageLimits($screenSize = Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_DEFAULT)
+ {
+ $defaultScreenSize = Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_DEFAULT;
+ $defaultScreenSource = Mage_XmlConnect_Model_Application::APP_SCREEN_SOURCE_DEFAULT;
+
+ $screenSize = preg_replace('/[^0-9A-z_]/', '', $screenSize);
+ if (isset($this->_imageLimits[$screenSize])) {
+ return $this->_imageLimits[$screenSize];
+ }
+ $screenSizeExplodeArray = explode(self::XMLCONNECT_GLUE, $screenSize);
+ $version = '';
+ switch (count($screenSizeExplodeArray)) {
+ case 2:
+ $version = $screenSizeExplodeArray[1];
+ case 1:
+ $resolution = $screenSizeExplodeArray[0];
+ break;
+ default:
+ $resolution = $defaultScreenSize;
+ break;
+ }
+
+ $sourcePath = empty($version) ? $defaultScreenSource : $version;
+ $xmlPath = 'screen_size/'.self::XMLCONNECT_GLUE.$resolution.'/'.$sourcePath;
+
+ $root = Mage::getStoreConfig($xmlPath);
+ $updates = array();
+ if (!empty($root)) {
+ $screenSize = $resolution . (empty($version) ? '' : self::XMLCONNECT_GLUE.$version);
+ $source = !empty($root['source']) ? $root['source'] : $defaultScreenSource;
+ $updates = isset($root['updates']) && is_array($root['updates']) ? $root['updates'] : array();
+ } else {
+ $screenSize = $defaultScreenSize;
+ $source = $defaultScreenSource;
+ }
+ $imageLimits = Mage::getStoreConfig('screen_size/'.$source);
+ if (!is_array($imageLimits)) {
+ $imageLimits = Mage::getStoreConfig('screen_size/default');
+ }
+
+ foreach ($updates as $update) {
+ $path = $update['path'];
+ $function = $update['function'];
+ switch ($function) {
+ case 'zoom':
+ $data = $update['data'];
+ $target =& $this->findPath($imageLimits, $path);
+ if (is_array($target)) {
+ array_walk_recursive($target, array($this, '_zoom'), $data);
+ } else {
+ $this->_zoom($target, null, $data);
+ }
+ break;
+ case 'update':
+ $data = $update['data'];
+ $target =& $this->findPath($imageLimits, $path);
+ $target = $data;
+ break;
+ case 'insert':
+ $data = $update['data'];
+ $target =& $this->findPath($imageLimits, $path);
+ if (($target !== null) && (is_array($target)) && (is_array($data))) {
+ foreach ($data as $key => $val) {
+ $target[$key] = $val;
+ }
+ }
+ break;
+ case 'delete':
+ $data = $update['data'];
+ $target =& $this->findPath($imageLimits, $path);
+ if (isset($target[$data])) {
+ unset($target[$data]);
+ }
+ break;
+ default:
+ break;
+ }
+
+ }
+ if (!is_array($imageLimits)) {
+ $imageLimits = array();
+ }
+
+ $this->_imageLimits[$screenSize] = $imageLimits;
+ return $imageLimits;
+ }
+
+ /**
+ * Return reference to the $path in $array
+ *
+ * @param array $array
+ * @param string $path
+ * @return &mixed //(reference)
+ */
+ public function &findPath(&$array, $path)
+ {
+ $target =& $array;
+ if ($path !== '/') {
+ $pathArray = explode('/', $path);
+ foreach ($pathArray as $node) {
+ if (is_array($target) && isset($target[$node])) {
+ $target =& $target[$node];
+ } else {
+ $targetNull = null;
+ return $targetNull;
+ }
+ }
+ }
+ return $target;
+ }
+
+ /**
+ * Multiply given $item by $value if non array
+ *
+ * @param mixed $item (argument to change)
+ * @param mixed $key (not used)
+ * @param string $value (contains float)
+ * @return void
+ */
+ protected function _zoom(&$item, $key, $value)
+ {
+ if (is_string($item)) {
+ $item = (int) round($item*$value);
+ }
+ }
+
+ /**
+ * Ensure $dir exists (if not then create one)
+ *
+ * @param string $dir
+ * @throw Mage_Core_Exception
+ */
+ protected function _verifyDirExist($dir)
+ {
+ $io = new Varien_Io_File();
+ $io->checkAndCreateFolder($dir);
+ }
+
+ /**
+ * Return customSizeUploadDir path
+ *
+ * @param string $screenSize
+ * @return string
+ */
+ public function getCustomSizeUploadDir($screenSize)
+ {
+ $screenSize = $this->filterScreenSize($screenSize);
+ $customDirRoot = Mage::getBaseDir('media') . DS . 'xmlconnect' . DS . 'custom';
+ $this->_verifyDirExist($customDirRoot);
+ $customDir = $customDirRoot . DS .$screenSize;
+ $this->_verifyDirExist($customDir);
+ return $customDir;
+ }
+
+ /**
+ * Return originalSizeUploadDir path
+ *
+ * @return string
+ */
+ public function getOriginalSizeUploadDir()
+ {
+ $dir = Mage::getBaseDir('media') . DS . 'xmlconnect' . DS . 'original';
+ $this->_verifyDirExist($dir);
+ return $dir;
+ }
+
+ /**
+ * Return oldUpload dir path (media/xmlconnect)
+ *
+ * @return string
+ */
+ public function getOldUploadDir()
+ {
+ $dir = Mage::getBaseDir('media') . DS . 'xmlconnect';
+ $this->_verifyDirExist($dir);
+ return $dir;
+ }
+
+ /**
+ * Return default size upload dir path
+ *
+ * @return string
+ */
+ public function getDefaultSizeUploadDir()
+ {
+ return $this->getCustomSizeUploadDir(Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_DEFAULT);
+ }
+
+ /**
+ * Return array for interface images paths in the config
+ *
+ * @return array
+ */
+ public function getInterfaceImagesPathsConf()
+ {
+ if (!isset($this->_confPaths)) {
+ $paths = $this->getInterfaceImagesPaths();
+ $this->_confPaths = array();
+ $len = strlen('conf/native/');
+ foreach ($paths as $path => $defaultFileName) {
+ $this->_confPaths[$path] = substr($path, $len);
+ }
+ }
+ return $this->_confPaths;
+ }
+
+ /**
+ * Return 1) default interface image path for specified $imagePath
+ * 2) array of image paths
+ *
+ * @param string $imagePath
+ * @return array|string
+ */
+ public function getInterfaceImagesPaths($imagePath = null)
+ {
+ $paths = array (
+ 'conf/native/navigationBar/icon' => 'smallIcon_1_6.png',
+ 'conf/native/body/bannerImage' => 'banner_1_2.png',
+ 'conf/native/body/backgroundImage' => 'accordion_open.png',
+ );
+ if ($imagePath == null) {
+ return $paths;
+ } else if (isset($paths[$imagePath])) {
+ return $paths[$imagePath];
+ } else {
+ return null;
+ }
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Iphone.php b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Iphone.php
new file mode 100644
index 0000000000..1cf20fb9e5
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Iphone.php
@@ -0,0 +1,341 @@
+ array(
+ 'body' => array(
+ 'backgroundColor' => '#ABABAB',
+ 'scrollBackgroundColor' => '#EDEDED',
+ ),
+ 'itemActions' => array(
+ 'relatedProductBackgroundColor' => '#404040',
+ ),
+ 'fonts' => array(
+ 'Title1' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '14',
+ 'color' => '#FEFEFE',
+ ),
+ 'Title2' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '12',
+ 'color' => '#222222',
+ ),
+ 'Title3' => array(
+ 'name' => 'HelveticaNeue',
+ 'size' => '13',
+ 'color' => '#000000',
+ ),
+ 'Title4' => array(
+ 'name' => 'HelveticaNeue',
+ 'size' => '12',
+ 'color' => '#FFFFFF',
+ ),
+ 'Title5' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '13',
+ 'color' => '#dc5f02',
+ ),
+ 'Title6' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '16',
+ 'color' => '#222222',
+ ),
+ 'Title7' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '13',
+ 'color' => '#000000',
+ ),
+ 'Title8' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '11',
+ 'color' => '#FFFFFF',
+ ),
+ 'Title9' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '12',
+ 'color' => '#FFFFFF',
+ ),
+ 'Text1' => array(
+ 'name' => 'HelveticaNeue-Bold',
+ 'size' => '12',
+ 'color' => '#777777',
+ ),
+ 'Text2' => array(
+ 'name' => 'HelveticaNeue',
+ 'size' => '10',
+ 'color' => '#555555',
+ ),
+ ),
+ ),
+ );
+ }
+
+ /**
+ * List of allowed fonts for iPhone application
+ *
+ * @return array
+ */
+ public function getFontList()
+ {
+ return array(
+ array(
+ 'value' => 'HiraKakuProN-W3',
+ 'label' => 'HiraKakuProN-W3',
+ ),
+ array(
+ 'value' => 'Courier',
+ 'label' => 'Courier',
+ ),
+ array(
+ 'value' => 'Courier-BoldOblique',
+ 'label' => 'Courier-BoldOblique',
+ ),
+ array(
+ 'value' => 'Courier-Oblique',
+ 'label' => 'Courier-Oblique',
+ ),
+ array(
+ 'value' => 'Courier-Bold',
+ 'label' => 'Courier-Bold',
+ ),
+ array(
+ 'value' => 'ArialMT',
+ 'label' => 'ArialMT',
+ ),
+ array(
+ 'value' => 'Arial-BoldMT',
+ 'label' => 'Arial-BoldMT',
+ ),
+ array(
+ 'value' => 'Arial-BoldItalicMT',
+ 'label' => 'Arial-BoldItalicMT',
+ ),
+ array(
+ 'value' => 'Arial-ItalicMT',
+ 'label' => 'Arial-ItalicMT',
+ ),
+ array(
+ 'value' => 'STHeitiTC-Light',
+ 'label' => 'STHeitiTC-Light',
+ ),
+ array(
+ 'value' => 'STHeitiTC-Medium',
+ 'label' => 'STHeitiTC-Medium',
+ ),
+ array(
+ 'value' => 'AppleGothic',
+ 'label' => 'AppleGothic',
+ ),
+ array(
+ 'value' => 'CourierNewPS-BoldMT',
+ 'label' => 'CourierNewPS-BoldMT',
+ ),
+ array(
+ 'value' => 'CourierNewPS-ItalicMT',
+ 'label' => 'CourierNewPS-ItalicMT',
+ ),
+ array(
+ 'value' => 'CourierNewPS-BoldItalicMT',
+ 'label' => 'CourierNewPS-BoldItalicMT',
+ ),
+ array(
+ 'value' => 'CourierNewPSMT',
+ 'label' => 'CourierNewPSMT',
+ ),
+ array(
+ 'value' => 'Zapfino',
+ 'label' => 'Zapfino',
+ ),
+ array(
+ 'value' => 'HiraKakuProN-W6',
+ 'label' => 'HiraKakuProN-W6',
+ ),
+ array(
+ 'value' => 'ArialUnicodeMS',
+ 'label' => 'ArialUnicodeMS',
+ ),
+ array(
+ 'value' => 'STHeitiSC-Medium',
+ 'label' => 'STHeitiSC-Medium',
+ ),
+ array(
+ 'value' => 'STHeitiSC-Light',
+ 'label' => 'STHeitiSC-Light',
+ ),
+ array(
+ 'value' => 'AmericanTypewriter',
+ 'label' => 'AmericanTypewriter',
+ ),
+ array(
+ 'value' => 'AmericanTypewriter-Bold',
+ 'label' => 'AmericanTypewriter-Bold',
+ ),
+ array(
+ 'value' => 'Helvetica-Oblique',
+ 'label' => 'Helvetica-Oblique',
+ ),
+ array(
+ 'value' => 'Helvetica-BoldOblique',
+ 'label' => 'Helvetica-BoldOblique',
+ ),
+ array(
+ 'value' => 'Helvetica',
+ 'label' => 'Helvetica',
+ ),
+ array(
+ 'value' => 'Helvetica-Bold',
+ 'label' => 'Helvetica-Bold',
+ ),
+ array(
+ 'value' => 'MarkerFelt-Thin',
+ 'label' => 'MarkerFelt-Thin',
+ ),
+ array(
+ 'value' => 'HelveticaNeue',
+ 'label' => 'HelveticaNeue',
+ ),
+ array(
+ 'value' => 'HelveticaNeue-Bold',
+ 'label' => 'HelveticaNeue-Bold',
+ ),
+ array(
+ 'value' => 'DBLCDTempBlack',
+ 'label' => 'DBLCDTempBlack',
+ ),
+ array(
+ 'value' => 'Verdana-Bold',
+ 'label' => 'Verdana-Bold',
+ ),
+ array(
+ 'value' => 'Verdana-BoldItalic',
+ 'label' => 'Verdana-BoldItalic',
+ ),
+ array(
+ 'value' => 'Verdana',
+ 'label' => 'Verdana',
+ ),
+ array(
+ 'value' => 'Verdana-Italic',
+ 'label' => 'Verdana-Italic',
+ ),
+ array(
+ 'value' => 'TimesNewRomanPSMT',
+ 'label' => 'TimesNewRomanPSMT',
+ ),
+ array(
+ 'value' => 'TimesNewRomanPS-BoldMT',
+ 'label' => 'TimesNewRomanPS-BoldMT',
+ ),
+ array(
+ 'value' => 'TimesNewRomanPS-BoldItalicMT',
+ 'label' => 'TimesNewRomanPS-BoldItalicMT',
+ ),
+ array(
+ 'value' => 'TimesNewRomanPS-ItalicMT',
+ 'label' => 'TimesNewRomanPS-ItalicMT',
+ ),
+ array(
+ 'value' => 'Georgia-Bold',
+ 'label' => 'Georgia-Bold',
+ ),
+ array(
+ 'value' => 'Georgia',
+ 'label' => 'Georgia',
+ ),
+ array(
+ 'value' => 'Georgia-BoldItalic',
+ 'label' => 'Georgia-BoldItalic',
+ ),
+ array(
+ 'value' => 'Georgia-Italic',
+ 'label' => 'Georgia-Italic',
+ ),
+ array(
+ 'value' => 'STHeitiJ-Medium',
+ 'label' => 'STHeitiJ-Medium',
+ ),
+ array(
+ 'value' => 'STHeitiJ-Light',
+ 'label' => 'STHeitiJ-Light',
+ ),
+ array(
+ 'value' => 'ArialRoundedMTBold',
+ 'label' => 'ArialRoundedMTBold',
+ ),
+ array(
+ 'value' => 'TrebuchetMS-Italic',
+ 'label' => 'TrebuchetMS-Italic',
+ ),
+ array(
+ 'value' => 'TrebuchetMS',
+ 'label' => 'TrebuchetMS',
+ ),
+ array(
+ 'value' => 'Trebuchet-BoldItalic',
+ 'label' => 'Trebuchet-BoldItalic',
+ ),
+ array(
+ 'value' => 'TrebuchetMS-Bold',
+ 'label' => 'TrebuchetMS-Bold',
+ ),
+ array(
+ 'value' => 'STHeitiK-Medium',
+ 'label' => 'STHeitiK-Medium',
+ ),
+ array(
+ 'value' => 'STHeitiK-Light',
+ 'label' => 'STHeitiK-Light',
+ ),
+ );
+ }
+
+ /**
+ * List of allowed font sizes for iPhone application
+ *
+ * @return array
+ */
+ public function getFontSizes()
+ {
+ $result = array( );
+ for ($i = 6; $i < 32; $i++) {
+ $result[] = array(
+ 'value' => $i,
+ 'label' => $i . ' pt',
+ );
+ }
+ return $result;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Payment.php b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Payment.php
new file mode 100644
index 0000000000..ed6262d333
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Payment.php
@@ -0,0 +1,42 @@
+ methodCode array
+ *
+ * @deprecated after 1.4.2.0
+ * @return array
+ */
+ public function getPaymentMethodCodeList()
+ {
+ return array();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Theme.php b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Theme.php
new file mode 100644
index 0000000000..2b6aad8988
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Helper/Theme.php
@@ -0,0 +1,174 @@
+ 'conf[native][navigationBar][tintColor]',
+ 'conf_native_body_primaryColor' => 'conf[native][body][primaryColor]',
+ 'conf_native_body_secondaryColor' => 'conf[native][body][secondaryColor]',
+ 'conf_native_categoryItem_backgroundColor' => 'conf[native][categoryItem][backgroundColor]',
+ 'conf_native_categoryItem_tintColor' => 'conf[native][categoryItem][tintColor]',
+
+ 'conf_extra_fontColors_header' => 'conf[extra][fontColors][header]',
+ 'conf_extra_fontColors_primary' => 'conf[extra][fontColors][primary]',
+ 'conf_extra_fontColors_secondary' => 'conf[extra][fontColors][secondary]',
+ 'conf_extra_fontColors_price' => 'conf[extra][fontColors][price]',
+
+ 'conf_native_body_backgroundColor' => 'conf[native][body][backgroundColor]',
+ 'conf_native_body_scrollBackgroundColor' => 'conf[native][body][scrollBackgroundColor]',
+ 'conf_native_itemActions_relatedProductBackgroundColor' => 'conf[native][itemActions][relatedProductBackgroundColor]'
+ );
+ return $themesArray;
+ }
+
+ /**
+ * Returns JSON ready Themes array
+ *
+ * @param bool $flushCache - load defaults
+ * @return array
+ */
+ public function getAllThemesArray($flushCache = false)
+ {
+ $result = array();
+ $themes = $this->getAllThemes($flushCache);
+ foreach ($themes as $theme) {
+ $result[$theme->getName()] = $theme->getFormData();
+ }
+ return $result;
+ }
+
+ /**
+ * Reads directory media/xmlconnect/themes/*
+ *
+ * @param bool $flushCache - Reads default color Themes
+ * @return array - (of Mage_XmlConnect_Model_Theme)
+ */
+ public function getAllThemes($flushCache = false)
+ {
+ if (!$this->_themeArray || $flushCache) {
+ $saveLibxmlErrors = libxml_use_internal_errors(TRUE);
+ $this->_themeArray = array();
+ $themeDir = Mage::getBaseDir('media') . DS . 'xmlconnect' . DS . 'themes';
+ $io = new Varien_Io_File();
+ $io->open(array('path' => $themeDir));
+
+ $fileList = $io->ls(Varien_Io_File::GREP_FILES);
+ foreach ($fileList as $file) {
+ $src = $themeDir . DS . $file['text'];
+ if (is_readable($src)) {
+ try {
+ $theme = Mage::getModel('xmlconnect/theme', $src);
+ $this->_themeArray[$theme->getName()] = $theme;
+ } catch (Exception $e) {
+ Mage::logException($e);
+ }
+ }
+ }
+ libxml_use_internal_errors($saveLibxmlErrors);
+ }
+ return $this->_themeArray;
+ }
+
+ /**
+ * Reset all theme color changes
+ * Copy media/xmlconnect/themes/default/* to media/xmlconnect/themes/*
+ *
+ * @return void
+ */
+ public function resetAllThemes()
+ {
+ $themeDir = Mage::getBaseDir('media') . DS . 'xmlconnect' . DS . 'themes';
+ $defaultThemeDir = Mage::getBaseDir('media') . DS . 'xmlconnect' . DS . 'themes' . DS . 'default';
+
+ $io = new Varien_Io_File();
+ $io->open(array('path'=>$defaultThemeDir));
+ $fileList = $io->ls(Varien_Io_File::GREP_FILES);
+ foreach ($fileList as $file) {
+ $f = $file['text'];
+ $src = $defaultThemeDir . DS . $f;
+ $dst = $themeDir . DS .$f;
+ if ($io->isWriteable($dst)) {
+ try {
+ if (!$io->cp($src, $dst)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Can\t copy file "%s" to "%s".', $src, $dst));
+ } else {
+ $io->chmod($dst, 0755);
+ }
+ } catch (Exception $e) {
+ Mage::logException($e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get theme object by name
+ *
+ * @param string $name
+ * @return Mage_XmlConnect_Model_Theme|null
+ */
+ public function getThemeByName($name)
+ {
+ $themes = $this->getAllThemes();
+ $theme = isset($themes[$name]) ? $themes[$name] : null;
+ return $theme;
+ }
+
+ /**
+ * Return predefined custom theme name
+ *
+ * @return string
+ */
+ public function getCustomThemeName()
+ {
+ return 'custom';
+ }
+
+ /**
+ * Return predefined default theme name
+ *
+ * @return string
+ */
+ public function getDefaultThemeName()
+ {
+ return 'default';
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Adminhtml/System/Config/Backend/Baseurl.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Adminhtml/System/Config/Backend/Baseurl.php
new file mode 100644
index 0000000000..cbebbf51a7
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Adminhtml/System/Config/Backend/Baseurl.php
@@ -0,0 +1,43 @@
+isValueChanged()) {
+ Mage::getModel('xmlconnect/application')->updateAllAppsUpdatedAtParameter();
+ }
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Adminhtml/System/Config/Backend/Currency/Default.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Adminhtml/System/Config/Backend/Currency/Default.php
new file mode 100644
index 0000000000..36749aa27b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Adminhtml/System/Config/Backend/Currency/Default.php
@@ -0,0 +1,43 @@
+isValueChanged()) {
+ Mage::getModel('xmlconnect/application')->updateAllAppsUpdatedAtParameter();
+ }
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Application.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Application.php
new file mode 100644
index 0000000000..20d60294a8
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Application.php
@@ -0,0 +1,728 @@
+
+ */
+class Mage_XmlConnect_Model_Application extends Mage_Core_Model_Abstract
+{
+
+ /**
+ * Application code cookie name
+ */
+ const APP_CODE_COOKIE_NAME = 'app_code';
+
+ /**
+ * Device screen size name
+ */
+ const APP_SCREEN_SIZE_NAME = 'screen_size';
+
+
+ /**
+ * Device screen size name
+ */
+ const APP_SCREEN_SIZE_DEFAULT = '320x480';
+
+ /**
+ * Device screen size source name
+ */
+ const APP_SCREEN_SOURCE_DEFAULT = 'default';
+
+ /**
+ * Application status "submitted" value
+ *
+ * @var int
+ */
+ const APP_STATUS_SUCCESS = 1;
+
+ /**
+ * Application status "not submitted" value
+ *
+ * @var int
+ */
+ const APP_STATUS_INACTIVE = 0;
+
+ /**
+ * Application prefix length of cutted part of deviceType and storeCode
+ *
+ * @var int
+ */
+ const APP_PREFIX_CUT_LENGTH = 3;
+
+ /**
+ * Images in "Params" history table
+ *
+ * @var array
+ */
+ protected $_imageIds = array('icon', 'loader_image', 'logo', 'big_logo');
+
+
+ /**
+ * Initialize application
+ */
+ protected function _construct()
+ {
+ $this->_init('xmlconnect/application');
+ }
+
+ /**
+ * Checks is it app is submitted
+ * (edit is premitted only before submission)
+ *
+ * @return bool
+ */
+ public function getIsSubmitted()
+ {
+ return $this->getStatus() == Mage_XmlConnect_Model_Application::APP_STATUS_SUCCESS;
+ }
+
+ /**
+ * Load data (flat array) for Varien_Data_Form
+ *
+ * @return array
+ */
+ public function getFormData()
+ {
+ $data = $this->getData();
+ return $this->_flatArray($data);
+ }
+
+ /**
+ * Load data (flat array) for Varien_Data_Form
+ *
+ * @param array $subtree
+ * @param string $prefix
+ * @return array
+ */
+ protected function _flatArray($subtree, $prefix=null)
+ {
+ $result = array();
+ foreach ($subtree as $key => $value) {
+ if (is_null($prefix)) {
+ $name = $key;
+ } else {
+ $name = $prefix . '[' . $key . ']';
+ }
+
+ if (is_array($value)) {
+ $result = array_merge($result, $this->_flatArray($value, $name));
+ } else {
+ $result[$name] = $value;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Like array_merge_recursive(), but string values is replaced
+ *
+ * @param array $a
+ * @param array $b
+ * @return array
+ */
+ protected function _configMerge (array $a, array $b)
+ {
+ $result = array();
+ $keys = array_unique(array_merge(array_keys($a), array_keys($b)));
+ foreach ($keys as $key) {
+ if (!isset($a[$key])) {
+ $result[$key] = $b[$key];
+ } elseif (!isset($b[$key])) {
+ $result[$key] = $a[$key];
+ } elseif (is_scalar($a[$key]) || is_scalar($b[$key])) {
+ $result[$key] = $b[$key];
+ } else {
+ $result[$key] = $this->_configMerge($a[$key], $b[$key]);
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Set default configuration data
+ */
+ public function loadDefaultConfiguration()
+ {
+ $this->setType('iphone');
+ $this->setCode($this->getCodePrefix());
+ $this->setConf(Mage::helper('xmlconnect/iphone')->getDefaultConfiguration());
+ }
+
+ /**
+ * Return first part for application code field
+ *
+ * @return string
+ */
+ public function getCodePrefix()
+ {
+ return substr(Mage::app()->getStore($this->getStoreId())->getCode(), 0, self::APP_PREFIX_CUT_LENGTH)
+ . substr($this->getType(), 0, self::APP_PREFIX_CUT_LENGTH);
+ }
+
+ /**
+ * Checks if application code field has autoincrement
+ *
+ * @return bool
+ */
+ public function isCodePrefixed()
+ {
+ $suffix = substr($this->getCode(), self::APP_PREFIX_CUT_LENGTH * 2);
+ return !empty($suffix);
+ }
+
+ /**
+ * Load application configuration
+ *
+ * @return array
+ */
+ public function prepareConfiguration()
+ {
+ return $this->getData('conf');
+ }
+
+ /**
+ * Get config formatted for rendering
+ *
+ * @return array
+ */
+ public function getRenderConf()
+ {
+ $result = Mage::helper('xmlconnect/iphone')->getDefaultConfiguration();
+ $result = $result['native'];
+ $extra = array();
+ if (isset($this->_data['conf'])) {
+ if (isset($this->_data['conf']['native'])) {
+ $result = $this->_configMerge($result, $this->_data['conf']['native']);
+ }
+ if (isset($this->_data['conf']['extra'])) {
+ $extra = $this->_data['conf']['extra'];
+ if (isset($extra['tabs'])) {
+ $tabs = Mage::getModel('xmlconnect/tabs', $extra['tabs']);
+ $result['tabBar']['tabs'] = $tabs;
+ }
+ if (isset($extra['fontColors'])) {
+ if (!empty($extra['fontColors']['header'])) {
+ $result['fonts']['Title1']['color'] = $extra['fontColors']['header'];
+ }
+ if (!empty($extra['fontColors']['primary'])) {
+ $result['fonts']['Title2']['color'] = $extra['fontColors']['primary'];
+ $result['fonts']['Title3']['color'] = $extra['fontColors']['primary'];
+ $result['fonts']['Text1']['color'] = $extra['fontColors']['primary'];
+ $result['fonts']['Text2']['color'] = $extra['fontColors']['primary'];
+ $result['fonts']['Title7']['color'] = $extra['fontColors']['primary'];
+ }
+ if (!empty($extra['fontColors']['secondary'])) {
+ $result['fonts']['Title4']['color'] = $extra['fontColors']['secondary'];
+ $result['fonts']['Title6']['color'] = $extra['fontColors']['secondary'];
+ $result['fonts']['Title8']['color'] = $extra['fontColors']['secondary'];
+ $result['fonts']['Title9']['color'] = $extra['fontColors']['secondary'];
+ }
+ if (!empty($extra['fontColors']['price'])) {
+ $result['fonts']['Title5']['color'] = $extra['fontColors']['price'];
+ }
+ }
+ }
+ }
+ $helperImage = Mage::helper('xmlconnect/image');
+ $screenSize = $this->getScreenSize();
+ $paths = $helperImage->getInterfaceImagesPathsConf();
+ foreach ($paths as $confPath => $dataPath) {
+ $imageNodeValue =& $helperImage->findPath($result, $dataPath);
+ if ($imageNodeValue) {
+ /**
+ * Creating file ending (some_inner/some_dir/filename.png) For url
+ */
+ $imageNodeValue = $helperImage->getFileCustomDirSuffixAsUrl($confPath, $imageNodeValue);
+ }
+ }
+ $result = $this->_absPath($result);
+ /**
+ * General configuration
+ */
+ $result['general']['updateTimeUTC'] = strtotime($this->getUpdatedAt());
+ $result['general']['browsingMode'] = $this->getBrowsingMode();
+ $result['general']['currencyCode'] = Mage::app()->getStore($this->getStoreId())->getDefaultCurrencyCode();
+ $result['general']['secureBaseUrl'] = Mage::getStoreConfig('web/secure/base_url', $this->getStoreId());
+ $maxRecipients = 0;
+ $allowGuest = 0;
+ if (Mage::getStoreConfig('sendfriend/email/enabled')) {
+ $maxRecipients = Mage::getStoreConfig('sendfriend/email/max_recipients');
+ $allowGuest = Mage::getStoreConfig('sendfriend/email/allow_guest');
+ }
+ $result['general']['emailToFriendMaxRecepients'] = $maxRecipients;
+ $result['general']['emailAllowGuest'] = $allowGuest;
+ $result['general']['primaryStoreLang'] = Mage::app()
+ ->getStore($this->getStoreId())->getConfig(Mage_Core_Model_Locale::XML_PATH_DEFAULT_LOCALE);
+ $result['general']['magentoVersion'] = Mage::getVersion();
+ $result['general']['copyright'] = Mage::getStoreConfig('design/footer/copyright', $this->getStoreId());
+
+ $result['general']['isAllowedGuestCheckout'] = Mage::getSingleton('checkout/session')
+ ->getQuote()->isAllowedGuestCheckout();
+
+ /**
+ * PayPal configuration
+ */
+ $result['paypal']['businessAccount'] = Mage::getModel('paypal/config')->businessAccount;
+ $result['paypal']['merchantLabel'] = $this->getData('conf/special/merchantLabel');
+
+ $isActive = 0;
+ if (isset($result['paypal']) && isset($result['paypal']['isActive'])) {
+ $isActive = (int)($result['paypal']['isActive'] && Mage::getModel('xmlconnect/payment_method_paypal_mep')->isAvailable(null, $this->getStoreId()));
+ }
+ $result['paypal']['isActive'] = $isActive;
+
+ return $result;
+ }
+
+ /**
+ * Return current screen_size parameter
+ *
+ * @return string
+ */
+ public function getScreenSize()
+ {
+ if (!isset($this->_data['screen_size'])) {
+ $this->_data['screen_size'] = self::APP_SCREEN_SIZE_DEFAULT;
+ }
+ return $this->_data['screen_size'];
+ }
+
+ /**
+ * Setter
+ * for current screen_size parameter
+ *
+ * @param string $screenSize
+ * @return this
+ */
+ public function setScreenSize($screenSize)
+ {
+ $this->_data['screen_size'] = Mage::helper('xmlconnect/image')->filterScreenSize((string) $screenSize);
+ return $this;
+ }
+
+ /**
+ * Return Enabled Tabs array from actual config
+ *
+ * @return array:
+ */
+ public function getEnabledTabsArray()
+ {
+ if ($this->getData('conf/extra/tabs')) {
+ return Mage::getModel('xmlconnect/tabs', $this->getData('conf/extra/tabs'))->getRenderTabs();
+ }
+ return array();
+ }
+
+ /**
+ * Change URLs to absolute
+ *
+ * @param array $subtree
+ * @return array
+ */
+ protected function _absPath($subtree)
+ {
+ foreach ($subtree as $key => $value) {
+ if (!empty($value)) {
+ if (is_array($value)) {
+ $subtree[$key] = $this->_absPath($value);
+ } elseif ((substr($key, -4) == 'icon') ||
+ (substr($key, -4) == 'Icon') ||
+ (substr($key, -5) == 'Image')) {
+ $subtree[$key] = Mage::getBaseUrl('media') . 'xmlconnect/' . $value;
+ }
+ }
+ }
+ return $subtree;
+ }
+
+ /**
+ * Return content pages
+ *
+ * @return array
+ */
+ public function getPages()
+ {
+ if (isset($this->_data['conf']['native']['pages'])) {
+ return $this->_data['conf']['native']['pages'];
+ }
+ return array();
+ }
+
+ /**
+ * Processing object before save data
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ protected function _beforeSave()
+ {
+ $conf = serialize($this->prepareConfiguration());
+ $this->setConfiguration($conf);
+ $this->setUpdatedAt(date('Y-m-d H:i:s', time()));
+ return $this;
+ }
+
+ /**
+ * Load configuration data (from serialized blob)
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ public function loadConfiguration()
+ {
+ $configuration = $this->getConfiguration();
+ if (!empty($configuration)) {
+ $configuration = unserialize($configuration);
+ $this->setData('conf', $configuration);
+ }
+ return $this;
+ }
+
+ /**
+ * Load application by code
+ *
+ * @param string $code
+ * @return Mage_XmlConnect_Model_Application
+ */
+ public function loadByCode($code)
+ {
+ $this->_getResource()->load($this, $code, 'code');
+ return $this;
+ }
+
+ /**
+ * Loads submit tab data from xmlconnect/history table
+ *
+ * @return bool
+ */
+ public function loadSubmit()
+ {
+ $isResubmitAction = false;
+ if ($this->getId()) {
+ $params = $this->getLastParams();
+ if (!empty($params)) {
+ // Using Pointer !
+ $conf = &$this->_data['conf'];
+ if (!isset($conf['submit_text']) || !is_array($conf['submit_text'])) {
+ $conf['submit_text'] = array();
+ }
+ if (!isset($conf['submit_restore']) || !is_array($conf['submit_restore'])) {
+ $conf['submit_restore'] = array();
+ }
+ foreach ($params as $id => $value) {
+ if (!in_array($id, $this->_imageIds)) {
+ $conf['submit_text'][$id] = $value;
+ } else {
+ $conf['submit_restore'][$id] = $value;
+ }
+ $isResubmitAction = true;
+ }
+ }
+ }
+ $this->setIsResubmitAction($isResubmitAction);
+ return $isResubmitAction;
+ }
+
+ /**
+ * Returns ( image[ ID ] => "SRC" ) array
+ *
+ * @return array
+ */
+ public function getImages()
+ {
+ $images = array();
+ $params = $this->getLastParams();
+
+ foreach ($this->_imageIds as $id) {
+ $path = $this->getData('conf/submit/'.$id);
+ $basename = null;
+ if (!empty($path)) {
+ /**
+ * Fetching data from session restored array
+ */
+ $basename = basename($path);
+ } else if (isset($params[$id])) {
+ /**
+ * Fetching data from submission history table record
+ *
+ * converting : "@\var\somedir\media\xmlconnect\form_icon_6.png" to "\var\somedir\media\xmlconnect\forn_icon_6.png"
+ */
+// $path = substr($params[$id], 1);
+ $basename = basename($params[$id]);
+ }
+ if (!empty($basename)) {
+ $images['conf/submit/'.$id] = Mage::getBaseUrl('media').'xmlconnect/'
+ . Mage::helper('xmlconnect/image')->getFileDefaultSizeSuffixAsUrl($basename);
+ }
+ }
+ return $images;
+ }
+
+ /**
+ * Return last submitted data from history table
+ *
+ * @return array
+ */
+ public function getLastParams()
+ {
+ if (!isset($this->_lastParams)) {
+ $this->_lastParams = Mage::getModel('xmlconnect/history')->getLastParams($this->getId());
+ }
+ return $this->_lastParams;
+ }
+
+ /**
+ * Validate application data
+ *
+ * @return array|bool
+ */
+ public function validate()
+ {
+ $errors = array();
+
+ $validateConf = $this->_validateConf();
+ if ($validateConf !== true) {
+ $errors = $validateConf;
+ }
+ if (!Zend_Validate::is($this->getName(), 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please enter "App Title".');
+ }
+
+ if (empty($errors)) {
+ return true;
+ }
+ return $errors;
+ }
+
+ /**
+ * Validate submit application data
+ *
+ * @param array $params
+ * @return array|bool
+ */
+ public function validateSubmit($params)
+ {
+ $errors = array();
+ $validateConf = $this->_validateConf();
+ if ($validateConf !== true) {
+ $errors = $validateConf;
+ }
+ if (!Zend_Validate::is(isset($params['title']) ? $params['title'] : null, 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please enter the Title.');
+ }
+
+ if (!Zend_Validate::is(isset($params['copyright']) ? $params['copyright'] : null, 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please enter the Copyright.');
+ }
+
+ if (empty($params['price_free'])) {
+ if (!Zend_Validate::is(isset($params['price']) ? $params['price'] : null, 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please enter the Price.');
+ }
+ }
+
+ if (!Zend_Validate::is(isset($params['country']) ? $params['country'] : null, 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please select at least one country.');
+ }
+
+ if ($this->getIsResubmitAction()) {
+ if (!Zend_Validate::is(
+ isset($params['resubmission_activation_key']) ? $params['resubmission_activation_key'] : null,
+ 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please enter the Resubmission Key.');
+ }
+ } else {
+ if (!Zend_Validate::is(isset($params['key']) ? $params['key'] : null, 'NotEmpty')) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please enter the Activation Key.');
+ }
+ }
+
+ if (empty($errors)) {
+ return true;
+ }
+ return $errors;
+ }
+
+ /**
+ * Check config for valid values
+ *
+ * @return bool|array
+ */
+ protected function _validateConf()
+ {
+ $errors = array();
+ $conf = $this->getConf();
+ $native = isset($conf['native']) && is_array($conf['native']) ? $conf['native'] : false;
+
+ if ( ($native === false)
+ || (!isset($native['navigationBar']) || !is_array($native['navigationBar'])
+ || !isset($native['navigationBar']['icon'])
+ || !Zend_Validate::is($native['navigationBar']['icon'], 'NotEmpty'))) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please upload an image for "Logo in Header" field from Design Tab.');
+ }
+
+ if ( ($native === false)
+ || (!isset($native['body']) || !is_array($native['body'])
+ || !isset($native['body']['bannerImage'])
+ || !Zend_Validate::is($native['body']['bannerImage'], 'NotEmpty'))) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please upload an image for "Banner on Home Screen" field from Design Tab.');
+ }
+
+ if (($native === false)
+ || (!isset($native['body']) || !is_array($native['body'])
+ || !isset($native['body']['backgroundImage'])
+ || !Zend_Validate::is($native['body']['backgroundImage'], 'NotEmpty'))) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please upload an image for "App Background" field from Design Tab.');
+ }
+
+ if (empty($errors)) {
+ return true;
+ }
+ return $errors;
+ }
+
+ /**
+ * Imports post/get data into the model
+ *
+ * @param array $data - $_REQUEST[]
+ * @return array
+ */
+ public function prepareSubmitParams($data)
+ {
+
+ $params = array();
+ if (isset($data['conf']) && is_array($data['conf'])) {
+
+ if (isset($data['conf']['submit_text']) && is_array($data['conf']['submit_text'])) {
+ $params = $data['conf']['submit_text'];
+ }
+
+ $params['name'] = $this->getName();
+ $params['code'] = $this->getCode();
+ $params['type'] = $this->getType();
+ $params['url'] = Mage::getBaseUrl() . 'xmlconnect/configuration/index/app_code/' . $this->getCode();
+ $params['magentoversion'] = Mage::getVersion();
+
+ if (isset($params['country']) && is_array($params['country'])) {
+ $params['country'] = implode(',', $params['country']);
+ }
+ if ($this->getIsResubmitAction()) {
+ if (isset($params['resubmission_activation_key'])) {
+ $params['resubmission_activation_key'] = trim($params['resubmission_activation_key']);
+ $params['key'] = $params['resubmission_activation_key'];
+ } else {
+ $params['key'] = '';
+ }
+ } else {
+ $params['key'] = isset($params['key']) ? trim($params['key']) : '';
+ }
+ // processing files :
+ $submit = array();
+ if (isset($this->_data['conf']['submit']) && is_array($this->_data['conf']['submit'])) {
+ $submit = $this->_data['conf']['submit'];
+ }
+
+ $submitRestore = array();
+ if (isset($this->_data['conf']['submit_restore']) && is_array($this->_data['conf']['submit_restore'])) {
+ $submitRestore = $this->_data['conf']['submit_restore'];
+ }
+
+ foreach ($this->_imageIds as $id) {
+ if (isset($submit[$id])) {
+ $params[$id] = '@' . $submit[$id];
+ } else if (isset($submitRestore[$id])) {
+ $params[$id] = $submitRestore[$id];
+ }
+ }
+ }
+ $this->setSubmitParams($params);
+ return $params;
+ }
+
+ /**
+ * Retrieve Store Id
+ *
+ * @return int
+ */
+ public function getStoreId()
+ {
+ if ($this->hasData('store_id')) {
+ return $this->getData('store_id');
+ }
+ return Mage::app()->getStore()->getId();
+ }
+
+ /**
+ * Getter, returns activation key for current application
+ *
+ * @return string|null
+ */
+ public function getActivationKey()
+ {
+ $key = null;
+ if (isset($this->_data['conf']) && is_array($this->_data['conf']) &&
+ isset($this->_data['conf']['submit_text']) && is_array($this->_data['conf']['submit_text']) &&
+ isset($this->_data['conf']['submit_text']['key'])) {
+
+ $key = $this->_data['conf']['submit_text']['key'];
+ }
+ return $key;
+ }
+
+ /**
+ * Perform update for all applications "updated at" parameter with current date
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ public function updateAllAppsUpdatedAtParameter()
+ {
+ $this->_getResource()->updateAllAppsUpdatedAtParameter();
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Catalog/Category/Image.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Catalog/Category/Image.php
new file mode 100644
index 0000000000..7753cae571
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Catalog/Category/Image.php
@@ -0,0 +1,191 @@
+
+ */
+class Mage_XmlConnect_Model_Catalog_Category_Image extends Mage_Catalog_Model_Product_Image
+{
+
+ /**
+ * Set filenames for base file and new file
+ *
+ * @param string $file
+ * @return Mage_Catalog_Model_Product_Image
+ */
+ public function setBaseFile($file)
+ {
+ $this->_isBaseFilePlaceholder = false;
+
+ if (($file) && (0 !== strpos($file, '/', 0))) {
+ $file = '/' . $file;
+ }
+ $baseDir = Mage::getSingleton('xmlconnect/catalog_category_media_config')->getBaseMediaPath();
+
+ if ('/no_selection' == $file) {
+ $file = null;
+ }
+ if ($file) {
+ if ((!file_exists($baseDir . $file)) || !$this->_checkMemory($baseDir . $file)) {
+ $file = null;
+ }
+ }
+ if (!$file) {
+ // check if placeholder defined in config
+ $isConfigPlaceholder = Mage::getStoreConfig("catalog/placeholder/{$this->getDestinationSubdir()}_placeholder");
+ $configPlaceholder = '/placeholder/' . $isConfigPlaceholder;
+ if ($isConfigPlaceholder && file_exists($baseDir . $configPlaceholder)) {
+ $file = $configPlaceholder;
+ } else {
+ // replace file with skin or default skin placeholder
+ $skinBaseDir = Mage::getDesign()->getSkinBaseDir();
+ $skinPlaceholder = "/images/xmlconnect/catalog/category/placeholder/{$this->getDestinationSubdir()}.jpg";
+ $file = $skinPlaceholder;
+ if (file_exists($skinBaseDir . $file)) {
+ $baseDir = $skinBaseDir;
+ } else {
+ $baseDir = Mage::getDesign()->getSkinBaseDir(array('_theme' => 'default'));
+ if (!file_exists($baseDir . $file)) {
+ $baseDir = Mage::getDesign()->getSkinBaseDir(array('_theme' => 'default', '_package' => 'base'));
+ }
+ }
+ }
+ $this->_isBaseFilePlaceholder = true;
+ }
+
+ $baseFile = $baseDir . $file;
+
+ if ((!$file) || (!file_exists($baseFile))) {
+ throw new Exception(Mage::helper('xmlconnect')->__('Image file was not found.'));
+ }
+
+ $this->_baseFile = $baseFile;
+
+ // build new filename (most important params)
+ $path = array(
+ Mage::getSingleton('xmlconnect/catalog_category_media_config')->getBaseMediaPath(),
+ 'cache',
+ Mage::app()->getStore()->getId(),
+ $path[] = $this->getDestinationSubdir()
+ );
+ if ((!empty($this->_width)) || (!empty($this->_height)))
+ $path[] = "{$this->_width}x{$this->_height}";
+
+ // add misk params as a hash
+ $miscParams = array(
+ ($this->_keepAspectRatio ? '' : 'non') . 'proportional',
+ ($this->_keepFrame ? '' : 'no') . 'frame',
+ ($this->_keepTransparency ? '' : 'no') . 'transparency',
+ ($this->_constrainOnly ? 'do' : 'not') . 'constrainonly',
+ $this->_rgbToString($this->_backgroundColor),
+ 'angle' . $this->_angle,
+ 'quality' . $this->_quality
+ );
+
+ // if has watermark add watermark params to hash
+ if ($this->getWatermarkFile()) {
+ $miscParams[] = $this->getWatermarkFile();
+ $miscParams[] = $this->getWatermarkImageOpacity();
+ $miscParams[] = $this->getWatermarkPosition();
+ $miscParams[] = $this->getWatermarkWidth();
+ $miscParams[] = $this->getWatermarkHeigth();
+ }
+
+ $path[] = md5(implode('_', $miscParams));
+
+ // append prepared filename
+ $this->_newFile = implode('/', $path) . $file; // the $file contains heading slash
+
+ return $this;
+ }
+
+ /**
+ * Get relative watermark file path
+ * or false if file not found
+ *
+ * @return string | bool
+ */
+ protected function _getWatermarkFilePath()
+ {
+ $filePath = false;
+
+ if (!$file = $this->getWatermarkFile()) {
+ return $filePath;
+ }
+
+ $baseDir = Mage::getSingleton('xmlconnect/catalog_category_media_config')->getBaseMediaPath();
+
+ if ( file_exists($baseDir . '/watermark/stores/' . Mage::app()->getStore()->getId() . $file) ) {
+ $filePath = $baseDir . '/watermark/stores/' . Mage::app()->getStore()->getId() . $file;
+ } elseif ( file_exists($baseDir . '/watermark/websites/' . Mage::app()->getWebsite()->getId() . $file) ) {
+ $filePath = $baseDir . '/watermark/websites/' . Mage::app()->getWebsite()->getId() . $file;
+ } elseif ( file_exists($baseDir . '/watermark/default/' . $file) ) {
+ $filePath = $baseDir . '/watermark/default/' . $file;
+ } elseif ( file_exists($baseDir . '/watermark/' . $file) ) {
+ $filePath = $baseDir . '/watermark/' . $file;
+ } else {
+ $baseDir = Mage::getDesign()->getSkinBaseDir();
+ if ( file_exists($baseDir . $file) ) {
+ $filePath = $baseDir . $file;
+ }
+ }
+
+ return $filePath;
+ }
+
+ /**
+ * Clear catalog cache
+ */
+ public function clearCache()
+ {
+ $directory = Mage::getBaseDir('media') . DS.'catalog'.DS.'category'.DS.'cache'.DS;
+ $io = new Varien_Io_File();
+ $io->rmdir($directory, true);
+ }
+
+ /**
+ * Convert array of 3 items (decimal r, g, b) to string of their hex values
+ *
+ * @param array $rgbArray
+ * @return string
+ */
+ protected function _rgbToString($rgbArray)
+ {
+ $result = array();
+ foreach ($rgbArray as $value) {
+ if (null === $value) {
+ $result[] = 'null';
+ } else {
+ $result[] = sprintf('%02s', dechex($value));
+ }
+ }
+ return implode($result);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Catalog/Category/Media/Config.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Catalog/Category/Media/Config.php
new file mode 100644
index 0000000000..cce12e6e7f
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Catalog/Category/Media/Config.php
@@ -0,0 +1,77 @@
+
+ */
+class Mage_XmlConnect_Model_Catalog_Category_Media_Config extends Mage_Catalog_Model_Product_Media_Config
+{
+ /**
+ * Getter , return Catalog baseMediaPath
+ *
+ * @return string
+ */
+ public function getBaseMediaPath()
+ {
+ return Mage::getBaseDir('media') . DS . 'catalog' . DS . 'category';
+ }
+
+ /**
+ * Getter, return catalog baseMediaUrl
+ *
+ * @return string
+ */
+ public function getBaseMediaUrl()
+ {
+ return Mage::getBaseUrl('media') . 'catalog/category';
+ }
+
+ /**
+ * Getter, return catalog baseMedia temporary dir path
+ *
+ * @return string
+ */
+ public function getBaseTmpMediaPath()
+ {
+ return Mage::getBaseDir('media') . DS . 'tmp' . DS . 'catalog' . DS . 'category';
+ }
+
+ /**
+ * Getter, return catalog baseMedia temporary dir URL
+ *
+ * @return string
+ */
+ public function getBaseTmpMediaUrl()
+ {
+ return Mage::getBaseUrl('media') . 'tmp/catalog/category';
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/History.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/History.php
new file mode 100644
index 0000000000..19e10dd801
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/History.php
@@ -0,0 +1,64 @@
+_init('xmlconnect/history');
+ }
+
+ /**
+ * Get array of existing images
+ *
+ * @param int $id application instance Id
+ * @return array
+ */
+ public function getLastParams($id)
+ {
+ return $this->_getResource()->getLastParams($id);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Application.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Application.php
new file mode 100644
index 0000000000..a42814d38a
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Application.php
@@ -0,0 +1,113 @@
+_init('xmlconnect/application', 'application_id');
+ }
+
+ /**
+ * Update Application Status field, insert data to history table
+ *
+ * @param int $applicationId
+ * @param string $status
+ * @return Mage_XmlConnect_Model_Mysql4_Application
+ */
+ public function updateApplicationStatus($applicationId, $status)
+ {
+ $this->_getWriteAdapter()->update(
+ $this->getMainTable(),
+ array('status' => $status),
+ $this->_getWriteAdapter()->quoteInto($this->getIdFieldName() . '=?', $applicationId)
+ );
+ return $this;
+ }
+
+ /**
+ * Processing object before save data
+ * Update app_code as Store + Device
+ *
+ * @param Mage_Core_Model_Abstract $object
+ * @return Mage_Core_Model_Abstract
+ */
+ protected function _beforeSave(Mage_Core_Model_Abstract $object)
+ {
+ if (!$object->getId()) {
+ $object->setCode($object->getCodePrefix());
+ }
+ return parent::_beforeSave($object);
+ }
+
+ /**
+ * Processing object after save data
+ * Update app_code as Store + Device + 123 (increment).
+ *
+ * @param Mage_Core_Model_Abstract $object
+ * @return Mage_Core_Model_Abstract
+ */
+ protected function _afterSave(Mage_Core_Model_Abstract $object)
+ {
+ $appCode = $object->getCode();
+ $isCodePrefixed = $object->isCodePrefixed();
+ if (!$isCodePrefixed) {
+ $this->_getWriteAdapter()->update(
+ $this->getMainTable(),
+ array('code' => $appCode . $object->getId()),
+ $this->_getWriteAdapter()->quoteInto($this->getIdFieldName() . '=?', $object->getId())
+ );
+ }
+ return parent::_afterSave($object);
+ }
+
+ /**
+ * Collect existing stores and type unique pairs
+ *
+ * @return array
+ */
+ public function getExistingStoreDeviceType()
+ {
+ $select = $this->_getWriteAdapter()->select()
+ ->from($this->getMainTable(), array('store_id', 'type'))
+ ->group(array('store_id', 'type'))
+ ->order(array('store_id', 'type'));
+ return $this->_getReadAdapter()->fetchAll($select, array('store_id', 'type'));
+ }
+
+ /**
+ * Update all applications "updated at" parameter with current date
+ *
+ * @return Mage_XmlConnect_Model_Mysql4_Application
+ */
+ public function updateAllAppsUpdatedAtParameter()
+ {
+ $select = $this->_getWriteAdapter()->update($this->getMainTable(), array('updated_at' => date('Y-m-d H:i:s')));
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Application/Collection.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Application/Collection.php
new file mode 100644
index 0000000000..9e94ea516e
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Application/Collection.php
@@ -0,0 +1,35 @@
+_init('xmlconnect/application');
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Category/Collection.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Category/Collection.php
new file mode 100644
index 0000000000..62e7cfaa28
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Category/Collection.php
@@ -0,0 +1,96 @@
+
+ */
+class Mage_XmlConnect_Model_Mysql4_Category_Collection
+ extends Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection
+{
+ /**
+ * Level of parent categories
+ */
+ const PARENT_CATEGORIES_LEVEL = 2;
+
+ /**
+ * Before collection load
+ *
+ * @return Mage_XmlConnect_Model_Mysql4_Category_Collection
+ */
+ protected function _beforeLoad()
+ {
+ $this->addNameToResult();
+ $this->addAttributeToSelect('thumbnail');
+ $this->addIsActiveFilter();
+ return parent::_beforeLoad();
+ }
+
+ /**
+ * Adding filter level
+ *
+ * @param string $level
+ * @return Mage_XmlConnect_Model_Mysql4_Category_Collection
+ */
+ public function addLevelExactFilter($level)
+ {
+ $this->getSelect()->where('e.level = ?', $level);
+ return $this;
+ }
+
+ /**
+ * Set limit collection
+ *
+ * @param int $offset
+ * @param int $count
+ * @return Mage_XmlConnect_Model_Mysql4_Category_Collection
+ */
+ public function setLimit($offset, $count)
+ {
+ $this->getSelect()->limit($count, $offset);
+ return $this;
+ }
+
+ /**
+ * Adding parentCategory filter
+ *
+ * @param int $parentId
+ * @return Mage_XmlConnect_Model_Mysql4_Category_Collection
+ */
+ public function addParentIdFilter($parentId)
+ {
+ if (!is_null($parentId)) {
+ $this->getSelect()->where('e.parent_id = ?', (int)$parentId);
+ } else {
+ $this->addLevelExactFilter(self::PARENT_CATEGORIES_LEVEL);
+ }
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Cms/Page/Collection.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Cms/Page/Collection.php
new file mode 100644
index 0000000000..947546aaa0
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Cms/Page/Collection.php
@@ -0,0 +1,63 @@
+
+ */
+
+class Mage_XmlConnect_Model_Mysql4_Cms_Page_Collection extends Mage_Cms_Model_Mysql4_Page_Collection
+{
+ /**
+ * Returns pairs identifier - title for unique identifiers
+ * and pairs identifier|page_id - title for non-unique after first
+ *
+ * @return array
+ */
+ public function toOptionIdArray()
+ {
+ $res = array();
+ $existingIdentifiers = array();
+ foreach ($this as $item) {
+ $identifier = $item->getData('identifier');
+
+ $data['value'] = $identifier;
+ $data['label'] = $item->getData('title');
+ if (in_array($identifier, $existingIdentifiers)) {
+ $data['value'] .= '|' . $item->getData('page_id');
+ } else {
+ $existingIdentifiers[] = $identifier;
+ }
+
+ $res[] = $data;
+ }
+
+ return $res;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Filter/Collection.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Filter/Collection.php
new file mode 100644
index 0000000000..eec097716c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Filter/Collection.php
@@ -0,0 +1,102 @@
+
+ */
+class Mage_XmlConnect_Model_Mysql4_Filter_Collection extends Varien_Data_Collection
+{
+ /**
+ * Set CategoryId filter
+ *
+ * @param int $categoryId
+ * @return Mage_XmlConnect_Model_Mysql4_Filter_Collection
+ */
+ public function setCategoryId($categoryId)
+ {
+ if ((int)$categoryId > 0) {
+ $this->addFilter('category_id', $categoryId);
+ }
+ return $this;
+ }
+
+ /**
+ * Load data
+ *
+ * @param bool $printQuery
+ * @param bool $logQuery
+ * @return Mage_XmlConnect_Model_Mysql4_Filter_Collection
+ */
+ public function load($printQuery = false, $logQuery = false)
+ {
+ if (empty($this->_items)) {
+ $layer = Mage::getSingleton('catalog/layer');
+ foreach ($this->_filters as $filter) {
+ if ('category_id' == $filter['field']) {
+ $layer->setCurrentCategory((int)$filter['value']);
+ }
+ }
+ if ($layer->getCurrentCategory()->getIsAnchor()) {
+ foreach ($layer->getFilterableAttributes() as $attributeItem) {
+ $filterModelName = 'catalog/layer_filter_attribute';
+ switch ($attributeItem->getAttributeCode()) {
+ case 'price':
+ $filterModelName = 'catalog/layer_filter_price';
+ break;
+ case 'decimal':
+ $filterModelName = 'catalog/layer_filter_decimal';
+ break;
+ default:
+ $filterModelName = 'catalog/layer_filter_attribute';
+ break;
+ }
+
+ $filterModel = Mage::getModel($filterModelName);
+ $filterModel->setLayer($layer)->setAttributeModel($attributeItem);
+ $filterValues = new Varien_Data_Collection;
+ foreach ($filterModel->getItems() as $valueItem) {
+ $valueObject = new Varien_Object();
+ $valueObject->setLabel($valueItem->getLabel());
+ $valueObject->setValueString($valueItem->getValueString());
+ $valueObject->setProductsCount($valueItem->getCount());
+ $filterValues->addItem($valueObject);
+ }
+ $item = new Varien_Object;
+ $item->setCode($attributeItem->getAttributeCode());
+ $item->setName($filterModel->getName());
+ $item->setValues($filterValues);
+ $this->addItem($item);
+ }
+ }
+ }
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/History.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/History.php
new file mode 100644
index 0000000000..ec2a49a662
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/History.php
@@ -0,0 +1,85 @@
+_init('xmlconnect/history', 'history_id');
+
+ }
+
+ /**
+ * Serialization for 'params' variable
+ *
+ * @param Mage_Core_Model_Abstract $object
+ * @return Mage_Core_Model_Abstract
+ */
+ protected function _beforeSave(Mage_Core_Model_Abstract $object)
+ {
+ $object->setParams(serialize($object->getParams()));
+ return parent::_beforeSave($object);
+ }
+
+ /**
+ * Deserialization for 'params' variable
+ *
+ * @param Mage_Core_Model_Abstract $object
+ * @return Mage_Core_Model_Abstract
+ */
+ protected function _afterLoad(Mage_Core_Model_Abstract $object)
+ {
+ $object->setParams(unserialize($object->getParams()));
+ return parent::_afterLoad($object);
+ }
+
+ /**
+ * Returns array of existing images
+ *
+ * @param int $id - application instance Id
+ *
+ * @return array
+ */
+ public function getLastParams($id)
+ {
+ $paramArray = array();
+ $idFieldName = Mage::getModel('xmlconnect/application')->getIdFieldName();
+ $select = $this->_getReadAdapter()->select()
+ ->from($this->getMainTable(), 'params')
+ ->where($idFieldName . '=?', $id)
+ ->order(array('created_at DESC'));
+
+ $params = $this->_getReadAdapter()->fetchOne($select);
+
+ if (isset($params)) {
+ $paramArray = unserialize($params);
+ }
+ return $paramArray;
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/History/Collection.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/History/Collection.php
new file mode 100644
index 0000000000..4c727d9e75
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/History/Collection.php
@@ -0,0 +1,69 @@
+
+ */
+class Mage_XmlConnect_Model_Mysql4_History_Collection
+ extends Mage_Core_Model_Mysql4_Collection_Abstract
+{
+ /**
+ * Internal constructor
+ */
+ protected function _construct()
+ {
+ $this->_init('xmlconnect/history');
+ }
+
+ /**
+ * Filter collection by store
+ *
+ * @param int $storeId
+ * @return Mage_Core_Model_Mysql4_Collection_Abstract
+ */
+ public function addStoreFilter($storeId)
+ {
+ $this->addFieldToFilter('store_id', $storeId);
+ return $this;
+ }
+
+ /**
+ * Filter collection by application_id
+ *
+ * @param int $applicationId
+ * @return Mage_Core_Model_Mysql4_Collection_Abstract
+ */
+ public function addApplicationFilter($applicationId)
+ {
+ $this->addFieldToFilter('application_id', $applicationId);
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Setup.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Setup.php
new file mode 100644
index 0000000000..c8c61b0cbb
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Mysql4/Setup.php
@@ -0,0 +1,29 @@
+
+ */
+class Mage_XmlConnect_Model_Observer
+{
+ /**
+ * List of config field names which changing affects mobile applications behaviour
+ *
+ * @var array
+ */
+ protected $_appDependOnConfigFieldPathes = array(
+ 'paypal/general/business_account',
+ 'sendfriend/email/max_recipients',
+ 'sendfriend/email/allow_guest',
+ 'general/locale/code',
+ 'currency/options/default'
+ );
+
+ /**
+ * Update all applications "updated at" parameter with current date on save some configurations
+ *
+ * @param Varien_Event_Observer $observer
+ */
+ public function changeUpdatedAtParamOnConfigSave($observer)
+ {
+ $configData = $observer->getEvent()->getConfigData();
+ if ($configData && (int)$configData->isValueChanged() && in_array($configData->getPath(), $this->_appDependOnConfigFieldPathes)) {
+ Mage::getModel('xmlconnect/application')->updateAllAppsUpdatedAtParameter();
+ }
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Payment/Method/Paypal/Mep.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Payment/Method/Paypal/Mep.php
new file mode 100644
index 0000000000..384c169a9b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Payment/Method/Paypal/Mep.php
@@ -0,0 +1,85 @@
+
+ */
+class Mage_XmlConnect_Model_Payment_Method_Paypal_Mep extends Mage_Paypal_Model_Express
+{
+ /**
+ * Store MEP payment method code
+ */
+ const MEP_METHOD_CODE = 'paypal_mep';
+
+ protected $_code = self::MEP_METHOD_CODE;
+
+ protected $_canUseInternal = false;
+ protected $_canUseForMultishipping = false;
+ protected $_isInitializeNeeded = false;
+ protected $_canUseCheckout = false;
+ protected $_canManageRecurringProfiles = false;
+
+ /**
+ * Get config peyment action url
+ * Used to universalize payment actions when processing payment place
+ *
+ * @return string
+ */
+ public function getConfigPaymentAction()
+ {
+ return Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE_CAPTURE;
+ }
+
+ /**
+ * Check whether payment method can be used
+ *
+ * @param Mage_Sales_Model_Quote $quote
+ * @return bool
+ */
+ public function isAvailable($quote = null)
+ {
+ return Mage::getModel('paypal/config')
+ ->setStoreId(Mage::app()->getStore()->getId())
+ ->isMethodAvailable(Mage_Paypal_Model_Config::METHOD_WPP_EXPRESS);
+ }
+
+ /**
+ * Capture payment
+ *
+ * @param Varien_Object $payment
+ * @param float $amount
+ * @return Mage_Payment_Model_Abstract
+ */
+ public function capture(Varien_Object $payment, $amount)
+ {
+ $transactionId = $payment->getAdditionalInformation(Mage_XmlConnect_Model_Paypal_Mep_Checkout::PAYMENT_INFO_TRANSACTION_ID);
+ $payment->setTransactionId($transactionId);
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Paypal/Mep/Checkout.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Paypal/Mep/Checkout.php
new file mode 100644
index 0000000000..aeef37f69b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Paypal/Mep/Checkout.php
@@ -0,0 +1,305 @@
+_checkoutSession = Mage::getSingleton('checkout/session');
+ if (isset($params['quote']) && $params['quote'] instanceof Mage_Sales_Model_Quote) {
+ $this->_quote = $params['quote'];
+ } else {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Quote instance is required.'));
+ }
+ }
+
+ /**
+ * Prepare quote, reserve order ID for specified quote
+ *
+ * @return string
+ */
+ public function initCheckout()
+ {
+ $this->_quote->reserveOrderId()->save();
+
+ /**
+ * Reset multishipping flag before any manipulations with quote address
+ * addAddress method for quote object related on this flag
+ */
+ if ($this->_quote->getIsMultiShipping()) {
+ $this->_quote->setIsMultiShipping(false);
+ $this->_quote->save();
+ }
+
+ /*
+ * want to load the correct customer information by assigning to address
+ * instead of just loading from sales/quote_address
+ */
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
+ if ($customer) {
+ $this->_quote->assignCustomer($customer);
+ }
+ if (!Mage::getSingleton('customer/session')->isLoggedIn()
+ && Mage::getSingleton('checkout/session')->getQuote()->isAllowedGuestCheckout()) {
+ $this->_prepareGuestQuote();
+ }
+ return $this->_quote->getReservedOrderId();
+ }
+
+ /**
+ * Save shipping and billing address information to quote
+ *
+ * @param array $data
+ * @return array
+ */
+ public function saveShipping($data)
+ {
+ if (empty($data)) {
+ return array('error' => 1, 'message' => Mage::helper('xmlconnect')->__('Invalid data.'));
+ }
+
+ $address = $this->_quote->getBillingAddress();
+ /**
+ * Start hard code data
+ *
+ * @todo remove this hard code
+ */
+ $data['country_id'] = 'US';
+ if (Mage::getSingleton('customer/session')->isLoggedIn()) {
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
+ $data['firstname'] = $customer->getFirstname();
+ $data['lastname'] = $customer->getLastname();
+
+ } else {
+ $data['firstname'] = Mage::helper('xmlconnect')->__('Guest');
+ $data['lastname'] = Mage::helper('xmlconnect')->__('Guest');
+ }
+ /**
+ * End hard code
+ */
+
+ $address->addData($data);
+
+ $this->_ignoreAddressValidation();
+
+ $address->implodeStreetAddress();
+
+ if (!$this->_quote->isVirtual()) {
+ $billing = clone $address;
+ $billing->unsAddressId()->unsAddressType();
+ $shipping = $this->_quote->getShippingAddress();
+ $shippingMethod = $shipping->getShippingMethod();
+ $shipping->addData($billing->getData())
+ ->setSameAsBilling(1)
+ ->setShippingMethod($shippingMethod)
+ ->setCollectShippingRates(true);
+ }
+
+ $this->_quote->collectTotals()->save();
+ return array();
+ }
+
+ /**
+ * Specify quote shipping method
+ *
+ * @param string $shippingMethod
+ * @return array
+ */
+ public function saveShippingMethod($shippingMethod)
+ {
+ if (empty($shippingMethod)) {
+ return array('error' => 1, 'message' => Mage::helper('xmlconnect')->__('Invalid shipping method.'));
+ }
+ $rate = $this->_quote->getShippingAddress()->getShippingRateByCode($shippingMethod);
+ if (!$rate) {
+ return array('error' => 1, 'message' => Mage::helper('xmlconnect')->__('Invalid shipping method.'));
+ }
+ if (!$this->_quote->getIsVirtual() && $shippingAddress = $this->_quote->getShippingAddress()) {
+ if ($shippingMethod != $shippingAddress->getShippingMethod()) {
+ $this->_ignoreAddressValidation();
+ $this->_quote->getShippingAddress()
+ ->setShippingMethod($shippingMethod);
+ $this->_quote->collectTotals()
+ ->save();
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * Specify quote payment method
+ *
+ * @param array $data
+ * @return array
+ */
+ public function savePayment($data)
+ {
+ if ($this->_quote->isVirtual()) {
+ $this->_quote->getBillingAddress()->setPaymentMethod($this->_methodType);
+ } else {
+ $this->_quote->getShippingAddress()->setPaymentMethod($this->_methodType);
+ }
+
+ $payment = $this->_quote->getPayment();
+ $data['method'] = $this->_methodType;
+ $payment->importData($data);
+
+ $email = isset($data['payer']) ? $data['payer'] : null;
+ $payment->setAdditionalInformation(self::PAYMENT_INFO_PAYER_EMAIL, $email);
+ $payment->setAdditionalInformation(self::PAYMENT_INFO_TRANSACTION_ID, isset($data['transaction_id']) ? $data['transaction_id'] : null);
+ $this->_quote->setCustomerEmail($email);
+
+ $this->_quote->collectTotals()->save();
+
+ return array();
+ }
+
+ /**
+ * Place the order when customer returned from paypal
+ * Until this moment all quote data must be valid
+ *
+ * @return array
+ */
+ public function saveOrder()
+ {
+ $this->_ignoreAddressValidation();
+
+ $order = Mage::getModel('sales/service_quote', $this->_quote)->submit();
+ $this->_quote->save();
+
+ /**
+ * Prepare session to success or cancellation page
+ */
+ $quoteId = $this->_quote->getId();
+ $this->_getCheckoutSession()
+ ->setLastQuoteId($quoteId)
+ ->setLastSuccessQuoteId($quoteId)
+ ->setLastOrderId($order->getId())
+ ->setLastRealOrderId($order->getIncrementId());
+
+ if ($order->getState() == Mage_Sales_Model_Order::STATE_PROCESSING) {
+ try {
+ $order->sendNewOrderEmail();
+ } catch (Exception $e) {
+ Mage::logException($e);
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * Get last order increment id by order id
+ *
+ * @return string
+ */
+ public function getLastOrderId()
+ {
+ $lastId = $this->_getCheckoutSession()->getLastOrderId();
+ $orderId = false;
+ if ($lastId) {
+ $order = Mage::getModel('sales/order');
+ $order->load($lastId);
+ $orderId = $order->getIncrementId();
+ }
+ return $orderId;
+ }
+
+ /**
+ * Make sure addresses will be saved without validation errors
+ */
+ protected function _ignoreAddressValidation()
+ {
+ $this->_quote->getBillingAddress()->setShouldIgnoreValidation(true);
+ if (!$this->_quote->getIsVirtual()) {
+ $this->_quote->getShippingAddress()->setShouldIgnoreValidation(true);
+ }
+ }
+
+ /**
+ * Get frontend checkout session object
+ *
+ * @return Mage_Checkout_Model_Session
+ */
+ protected function _getCheckoutSession()
+ {
+ return $this->_checkoutSession;
+ }
+
+ /**
+ * Prepare quote for guest checkout order submit
+ *
+ * @return Mage_XmlConnect_Model_Paypal_Mep_Checkout
+ */
+ protected function _prepareGuestQuote()
+ {
+ $quote = $this->_quote;
+ $quote->setCustomerId(null)
+ ->setCustomerIsGuest(true)
+ ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Simplexml/Element.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Simplexml/Element.php
new file mode 100644
index 0000000000..3898687512
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Simplexml/Element.php
@@ -0,0 +1,86 @@
+
+ */
+class Mage_XmlConnect_Model_Simplexml_Element extends Varien_Simplexml_Element
+{
+ /**
+ * Appends $source to current node
+ *
+ * @param Mage_XmlConnect_Model_Simplexml_Element $source
+ * @return Mage_XmlConnect_Model_Simplexml_Element
+ */
+ public function appendChild($source)
+ {
+ if (sizeof($source->children())) {
+ /**
+ * @see http://bugs.php.net/bug.php?id=41867 , fixed in 5.2.4
+ */
+ if (version_compare(phpversion(), '5.2.4', '<')===true) {
+ $name = $source->children()->getName();
+ } else {
+ $name = $source->getName();
+ }
+ $child = $this->addChild($name);
+ } else {
+ $child = $this->addChild($source->getName(), $this->xmlentities($source));
+ }
+ $child->setParent($this);
+
+ $attributes = $source->attributes();
+ foreach ($attributes as $key=>$value) {
+ $child->addAttribute($key, $this->xmlAttribute($value));
+ }
+
+ foreach ($source->children() as $sourceChild) {
+ $child->appendChild($sourceChild);
+ }
+ return $this;
+ }
+
+ /**
+ * Converts meaningful xml character (") to xml attribute specification
+ *
+ * @param string $value
+ * @return string|this
+ */
+ public function xmlAttribute($value = null)
+ {
+ if (is_null($value)) {
+ $value = $this;
+ }
+ $value = (string)$value;
+
+ $value = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $value);
+
+ return $value;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Tabs.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Tabs.php
new file mode 100644
index 0000000000..67d222ba77
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Tabs.php
@@ -0,0 +1,114 @@
+_enabledTabs = Mage::helper('xmlconnect')->getDefaultApplicationDesignTabs();
+ if (is_string($data)) {
+ $data = json_decode($data);
+ if (is_object($data)) {
+ $this->_enabledTabs = $data->enabledTabs;
+ $this->_disabledTabs = $data->disabledTabs;
+ }
+ }
+ $this->_translateLabel($this->_enabledTabs);
+ $this->_translateLabel($this->_disabledTabs);
+ }
+
+ /**
+ * Translate Label fields
+ *
+ * @param &array $tabItems
+ * @return this
+ */
+ protected function _translateLabel(&$tabItems)
+ {
+ if (is_array($tabItems)) {
+ foreach ($tabItems as $id => $tab) {
+ if (isset($tab->label)) {
+ $temp = $tabItems[$id];
+ $temp->label = Mage::helper('xmlconnect')->getTabLabel($tab->action);
+ }
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Getter for enabled tabs
+ *
+ * @return array
+ */
+ public function getEnabledTabs()
+ {
+ return $this->_enabledTabs;
+ }
+
+ /**
+ * Getter for disabled tabs
+ *
+ * @return array
+ */
+ public function getDisabledTabs()
+ {
+ return $this->_disabledTabs;
+ }
+
+ /**
+ * Collect tabs with images
+ *
+ * @return array
+ */
+ public function getRenderTabs()
+ {
+ $result = array();
+ foreach ($this->_enabledTabs as $tab) {
+ $tab->image = Mage::getDesign()->getSkinUrl('images/xmlconnect/' . $tab->image);
+ $result[] = $tab;
+ }
+ return $result;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/Model/Theme.php b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Theme.php
new file mode 100644
index 0000000000..97d8970273
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/Model/Theme.php
@@ -0,0 +1,204 @@
+_file = $file;
+ if (!file_exists($file)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('File doesn\'t exist "%s".', $file));
+ }
+ if (!is_readable($file)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Can\'t read file "%s".', $file));
+ }
+ $text = file_get_contents($file);
+ try {
+ $this->_xml = simplexml_load_string($text);
+ } catch (Exception $e) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Can\'t load XML.'));
+ }
+ if (empty($this->_xml)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Invalid XML.'));
+ }
+ $this->_conf = $this->_xmlToArray($this->_xml->configuration);
+ $this->_conf = $this->_conf['configuration'];
+ if (!is_array($this->_conf)) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Wrong theme format.'));
+ }
+ }
+
+ /**
+ * Get theme xml as array
+ *
+ * @param array $xml
+ * @return array
+ */
+ protected function _xmlToArray($xml)
+ {
+ $result = array();
+ foreach ($xml as $key => $value) {
+ if (count($value)) {
+ $result[$key] = $this->_xmlToArray($value);
+ } else {
+ $result[$key] = (string) $value;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Getter for theme name
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return (string) $this->_xml->manifest->name;
+ }
+
+ /**
+ * Getter for theme Label
+ *
+ * @return string
+ */
+ public function getLabel()
+ {
+ return (string) $this->_xml->manifest->label;
+ }
+
+ /**
+ * Load data (flat array) for Varien_Data_Form
+ *
+ * @return array
+ */
+ public function getFormData()
+ {
+ return $this->_flatArray($this->_conf, 'conf');
+ }
+
+ /**
+ * Load data (flat array) for Varien_Data_Form
+ *
+ * @param array $subtree
+ * @param string $prefix
+ * @return array
+ */
+ protected function _flatArray($subtree, $prefix=null)
+ {
+ $result = array();
+ foreach ($subtree as $key => $value) {
+ if (is_null($prefix)) {
+ $name = $key;
+ } else {
+ $name = $prefix . '[' . $key . ']';
+ }
+
+ if (is_array($value)) {
+ $result = array_merge($result, $this->_flatArray($value, $name));
+ } else {
+ $result[$name] = $value;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Validate input Array, recursive
+ *
+ * @param array $data
+ * @param array $xml
+ * @return array
+ */
+ protected function _validateFormInput($data, $xml=NULL)
+ {
+ $root = false;
+ $result = array();
+ if (is_null($xml)) {
+ $root = true;
+ $data = array('configuration' => $data);
+ $xml = $this->_xml->configuration;
+ }
+ foreach ($xml as $key => $value) {
+ if (isset($data[$key])) {
+ if (is_array($data[$key])) {
+ $result[$key] = $this->_validateFormInput($data[$key], $value);
+ } else {
+ $result[$key] = $data[$key];
+ }
+ }
+ }
+ if ($root) {
+ $result = $result['configuration'];
+ }
+ return $result;
+ }
+
+ /**
+ * Build XML object recursively from $data array
+ *
+ * @param SimpleXMLElement $parent
+ * @param array $data
+ * @return void
+ */
+ protected function _buildRecursive($parent, $data)
+ {
+ foreach ($data as $key=>$value) {
+ if (is_array($value)) {
+ $this->_buildRecursive($parent->addChild($key), $value);
+ } else {
+ $parent->addChild($key, $value);
+ }
+ }
+ }
+
+ /**
+ * Import data into theme form $data array, and save XML to file
+ *
+ * @param array $data
+ * @return void
+ */
+ public function importAndSaveData($data)
+ {
+ $xml = new SimpleXMLElement(''.$this->_xml->manifest->asXML().' ');
+ $this->_buildRecursive($xml->addChild('configuration'), $this->_validateFormInput($data));
+ clearstatcache();
+ if (is_writeable($this->_file)) {
+ file_put_contents($this->_file, $xml->asXML());
+ } else {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Can\'t write to file "%s".', $this->_file));
+ }
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/Adminhtml/MobileController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/Adminhtml/MobileController.php
new file mode 100644
index 0000000000..36aee8290c
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/Adminhtml/MobileController.php
@@ -0,0 +1,732 @@
+getRequest()->getParam($paramName);
+ $app = Mage::getModel('xmlconnect/application');
+ if ($id) {
+ $app->load($id);
+ if ($app->getId()) {
+ $app->loadConfiguration();
+ }
+ } else {
+ $app->loadDefaultConfiguration();
+ }
+ Mage::register('current_app', $app);
+ return $app;
+ }
+
+ /**
+ * Restore data from session $_POST and $_FILES (processed)
+ *
+ * @param array $data
+ * @return array|null
+ */
+ protected function _restoreSessionFilesFormData($data)
+ {
+ $filesData = Mage::getSingleton('adminhtml/session')->getUploadedFilesFormData(true);
+ if (!empty($filesData) && is_array($filesData)) {
+ if (!is_array($data)) {
+ $data = array();
+ }
+ foreach ($filesData as $filePath => $fileName) {
+ $target =& $data;
+ $this->_injectFieldToArray($target, $filePath, $fileName);
+ }
+ }
+ return $data;
+ }
+
+
+ /**
+ * Set value into multidimensional array 'conf/native/navigationBar/icon'
+ *
+ * @param &array $target // pointer to target array
+ * @param string $fieldPath //'conf/native/navigationBar/icon'
+ * @param mixed $fieldValue // 'Some Value' || 12345 || array(1=>3, 'aa'=>43)
+ * @param string $delimiter // path delimiter
+ * @return null
+ */
+ protected function _injectFieldToArray(&$target, $fieldPath, $fieldValue, $delimiter = '/')
+ {
+ $nameParts = explode($delimiter, $fieldPath);
+ foreach ($nameParts as $next) {
+ if (!isset($target[$next])) {
+ $target[$next] = array();
+ }
+ $target =& $target[$next];
+ }
+ $target = $fieldValue;
+ return null;
+ }
+
+ /**
+ * Mobile applications management
+ *
+ * @return void
+ */
+ public function indexAction()
+ {
+ $this->loadLayout();
+ $this->_setActiveMenu('xmlconnect/mobile');
+ $this->renderLayout();
+ }
+
+ /**
+ * Create new app
+ */
+ public function newAction()
+ {
+ $this->_forward('edit');
+ }
+
+ /**
+ * Submission Action, loads application data
+ */
+ public function submissionAction()
+ {
+ try {
+ $app = $this->_initApp();
+ if (!$app->getId()) {
+ $this->_getSession()->addError(Mage::helper('xmlconnect')->__('App does not exist.'));
+ $this->_redirect('*/*/');
+ return;
+ }
+ $app->loadSubmit();
+ if ((bool) Mage::getSingleton('adminhtml/session')->getLoadSessionFlag(true)) {
+ $data = $this->_restoreSessionFilesFormData(Mage::getSingleton('adminhtml/session')->getFormSubmissionData(true));
+ if (!empty($data)) {
+ $app->setData(Mage::helper('xmlconnect')->arrayMergeRecursive($app->getData(), $data));
+ }
+ }
+
+ $this->loadLayout();
+ $this->_setActiveMenu('xmlconnect/mobile');
+ $this->renderLayout();
+ } catch (Mage_Core_Exception $e) {
+ $this->_getSession()->addError($e->getMessage());
+ if (isset($app)) {
+ $this->_redirect('*/*/edit', array('application_id' => $app->getId()));
+ } else {
+ $this->_redirect('*/*/');
+ }
+ } catch (Exception $e) {
+ $this->_getSession()->addException($e, Mage::helper('xmlconnect')->__('Can\'t open submission form.'));
+ if (isset($app)) {
+ $this->_redirect('*/*/edit', array('application_id' => $app->getId()));
+ } else {
+ $this->_redirect('*/*/');
+ }
+ }
+ }
+
+ /**
+ * Edit app form
+ *
+ * @return void
+ */
+ public function editAction()
+ {
+ $redirectBack = false;
+ try {
+ $id = (int) $this->getRequest()->getParam('application_id');
+ $app = $this->_initApp();
+
+ if (!$app->getId() && $id) {
+ $this->_getSession()->addError(Mage::helper('xmlconnect')->__('App does not exist.'));
+ $this->_redirect('*/*/');
+ return;
+ }
+ $app->loadSubmit();
+ if ((bool) Mage::getSingleton('adminhtml/session')->getLoadSessionFlag(true)) {
+ $newAppData = $this->_restoreSessionFilesFormData(Mage::getSingleton('adminhtml/session')->getFormData(true));
+ if (!empty($newAppData)) {
+ $app->setData(Mage::helper('xmlconnect')->arrayMergeRecursive($app->getData(), $newAppData));
+ }
+ }
+ $this->loadLayout();
+ $this->_setActiveMenu('xmlconnect/mobile');
+ $this->renderLayout();
+ } catch (Mage_Core_Exception $e) {
+ $this->_getSession()->addError($e->getMessage());
+ $redirectBack = true;
+ } catch (Exception $e) {
+ $this->_getSession()->addError(Mage::helper('xmlconnect')->__('Unable to load application form.'));
+ $redirectBack = true;
+ Mage::logException($e);
+ }
+ if ($redirectBack) {
+ $this->_redirect('*/*/');
+ return;
+ }
+ }
+
+ /**
+ * Submit POST application action
+ */
+ public function submissionPostAction()
+ {
+ $data = $this->getRequest()->getPost();
+ try {
+ $isError = false;
+ if (!empty($data)) {
+ Mage::getSingleton('adminhtml/session')->setFormSubmissionData($this->_filterFormDataForSession($data));
+ }
+ /** @var $app Mage_XmlConnect_Model_Application */
+ $app = $this->_initApp('key');
+ $app->loadSubmit();
+ $newAppData = $this->_processUploadedFiles($app->getData(), true);
+ if (!empty($newAppData)) {
+ $app->setData(Mage::helper('xmlconnect')->arrayMergeRecursive($app->getData(), $newAppData));
+ }
+ $params = $app->prepareSubmitParams($data);
+ $errors = $app->validateSubmit($params);
+ if ($errors !== true) {
+ foreach ($errors as $err) {
+ $this->_getSession()->addError($err);
+ }
+ $isError = true;
+ }
+ if (!$isError) {
+ $this->_processPostRequest();
+ $history = Mage::getModel('xmlconnect/history');
+ $history->setData(array(
+ 'params' => $params,
+ 'application_id' => $app->getId(),
+ 'created_at' => Mage::getModel('core/date')->date(),
+ 'store_id' => $app->getStoreId(),
+ 'title' => isset($params['title']) ? $params['title'] : '',
+ 'code' => $app->getCode(),
+ 'activation_key' => isset($params['resubmission_activation_key']) ?
+ $params['resubmission_activation_key'] : $params['key'],
+ ));
+ $history->save();
+ $app->getResource()->updateApplicationStatus($app->getId(),
+ Mage_XmlConnect_Model_Application::APP_STATUS_SUCCESS);
+ $this->_getSession()->addSuccess(Mage::helper('xmlconnect')->__('App has been submitted.'));
+ $this->_clearSessionData();
+ $this->_redirect('*/*/edit', array('application_id' => $app->getId()));
+ } else {
+ Mage::getSingleton('adminhtml/session')->setLoadSessionFlag(true);
+ $this->_redirect('*/*/submission', array('application_id' => $app->getId()));
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_getSession()->addError($e->getMessage());
+ if (isset($app)) {
+ Mage::getSingleton('adminhtml/session')->setLoadSessionFlag(true);
+ $this->_redirect('*/*/submission', array('application_id' => $app->getId()));
+ } else {
+ $this->_redirect('*/*/');
+ }
+ } catch (Exception $e) {
+ $this->_getSession()->addException($e, Mage::helper('xmlconnect')->__('Can\'t submit application.'));
+ Mage::logException($e);
+ if (isset($app)) {
+ Mage::getSingleton('adminhtml/session')->setLoadSessionFlag(true);
+ $this->_redirect('*/*/submission', array('application_id' => $app->getId()));
+ } else {
+ $this->_redirect('*/*/');
+ }
+ }
+ }
+
+ /**
+ * Format post/get data for session storage
+ *
+ * @param array $data - $_REQUEST[]
+ * @return array
+ */
+ protected function _filterFormDataForSession($data)
+ {
+ $params = null;
+ if (isset($data['conf']) && is_array($data['conf'])) {
+ if (isset($data['conf']['submit_text']) && is_array($data['conf']['submit_text'])) {
+ $params = &$data['conf']['submit_text'];
+ }
+ }
+ if (isset($params['country']) && is_array($params['country'])) {
+ $data['conf']['submit_text']['country'] = implode(',', $params['country']);
+ }
+ return $data;
+ }
+
+ /**
+ * Clear session data
+ * Used after successful save/submit action
+ *
+ * @return this
+ */
+ protected function _clearSessionData()
+ {
+ Mage::getSingleton('adminhtml/session')->unsFormData();
+ Mage::getSingleton('adminhtml/session')->unsFormSubmissionData();
+ Mage::getSingleton('adminhtml/session')->unsUploadedFilesFormData();
+ return $this;
+ }
+
+ /**
+ * Send HTTP POST request to magentocommerce.com
+ *
+ * @return void
+ */
+ protected function _processPostRequest()
+ {
+ try {
+ $app = Mage::registry('current_app');
+ $params = $app->getSubmitParams();
+
+ $appConnectorUrl = Mage::getStoreConfig('xmlconnect/mobile_application/magentocommerce_url');
+ $ch = curl_init($appConnectorUrl . $params['key']);
+
+ // set URL and other appropriate options
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 60);
+
+ // Execute the request.
+ $result = curl_exec($ch);
+ $succeeded = curl_errno($ch) == 0 ? true : false;
+
+ // close cURL resource, and free up system resources
+ curl_close($ch);
+
+ // Assert that we received an expected message in reponse.
+ $resultArray = json_decode($result, true);
+
+ $app->setResult($result);
+ $success = (isset($resultArray['success'])) && ($resultArray['success'] === true);
+
+ $app->setSuccess($success);
+ if (!$app->getSuccess()) {
+ $message = '';
+ $message = isset($resultArray['message']) ? $resultArray['message']: '';
+ if (is_array($message)) {
+ $message = implode(' ,', $message);
+ }
+ Mage::throwException(Mage::helper('xmlconnect')->__('Submit App failure. %s', $message));
+ }
+ } catch (Exception $e) {
+ throw $e;
+ }
+ }
+
+ /**
+ * Save action
+ */
+ public function saveAction()
+ {
+ $data = $this->getRequest()->getPost();
+ $redirectBack = $this->getRequest()->getParam('back', false);
+ $redirectSubmit = $this->getRequest()->getParam('submitapp', false);
+ $app = false;
+ $isError = false;
+ if ($data) {
+ Mage::getSingleton('adminhtml/session')->setFormData($data);
+ try {
+ $id = $this->getRequest()->getParam('application_id');
+ $app = $this->_initApp();
+ if (!$app->getId() && $id) {
+ $this->_getSession()->addError(Mage::helper('xmlconnect')->__('App does not exist.'));
+ $this->_redirect('*/*/');
+ return;
+ }
+ $app->addData($this->_preparePostData($data));
+ $app->addData($this->_processUploadedFiles($app->getData()));
+ $errors = $app->validate();
+ if ($errors !== true) {
+ foreach ($errors as $err) {
+ $this->_getSession()->addError($err);
+ }
+ $isError = true;
+ }
+ if (!$isError) {
+ $this->_saveThemeAction($data, 'current_theme');
+ $app->save();
+ $this->_getSession()->addSuccess(Mage::helper('xmlconnect')->__('App has been saved.'));
+ $this->_clearSessionData();
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_getSession()->addException($e, $e->getMessage());
+ $isError = true;
+ $redirectBack = true;
+ } catch (Exception $e) {
+ $this->_getSession()->addException($e, Mage::helper('xmlconnect')->__('Unable to save app.'));
+ $isError = true;
+ $redirectBack = true;
+ Mage::logException($e);
+ }
+ }
+ if (!$isError && $app->getId() && $redirectSubmit) {
+ $this->_redirect('*/*/submission', array('application_id' => $app->getId()));
+ } else if ($isError || ($app->getId() && $redirectBack)) {
+ if ($isError) {
+ Mage::getSingleton('adminhtml/session')->setLoadSessionFlag(true);
+ }
+ $this->_redirect('*/*/edit', array('application_id' => $app->getId()));
+ } else {
+ $this->_redirect('*/*/');
+ }
+ }
+
+ /**
+ * Save changes to theme
+ *
+ * @param array $data
+ * @param string $paramId
+ */
+ protected function _saveThemeAction($data, $paramId = 'saveTheme')
+ {
+ try {
+ $themeName = $this->getRequest()->getParam($paramId, false);
+ if ($themeName) {
+ if ($themeName == Mage::helper('xmlconnect/theme')->getCustomThemeName()) {
+ $theme = Mage::helper('xmlconnect/theme')->getThemeByName($themeName);
+ if ($theme instanceof Mage_XmlConnect_Model_Theme) {
+ if ($paramId == 'saveTheme') {
+ $convertedConf = $this->_convertPost($data);
+ } else {
+ if (isset($data['conf'])) {
+ $convertedConf = $data['conf'];
+ } else {
+ $response = array('error' => true, 'message' => Mage::helper('xmlconnect')->__('Cannot save theme "%s". Incorrect data received', $themeName));
+ }
+ }
+ $theme->importAndSaveData($convertedConf);
+ $response = Mage::helper('xmlconnect/theme')->getAllThemesArray(true);
+ } else {
+ $response = array('error' => true, 'message' => Mage::helper('xmlconnect')->__('Cannot load theme "%s".', $themeName));
+ }
+ } else {
+ $response = Mage::helper('xmlconnect/theme')->getAllThemesArray(true);
+ }
+ } else {
+ $response = array('error' => true, 'message' => Mage::helper('xmlconnect')->__('Theme name is not set.'));
+ }
+ } catch (Mage_Core_Exception $e) {
+ $response = array(
+ 'error' => true,
+ 'message' => $e->getMessage(),
+ );
+ } catch (Exception $e) {
+ $response = array(
+ 'error' => true,
+ 'message' => Mage::helper('xmlconnect')->__('Can\'t save theme.')
+ );
+ }
+ if (is_array($response)) {
+ $response = Mage::helper('core')->jsonEncode($response);
+ $this->getResponse()->setBody($response);
+ }
+ }
+
+ /**
+ * Converts native Ajax data from flat to real array
+ * Convert array key->value pairs inside array like:
+ * "conf_native_bar_tintcolor" => $val to $conf['native']['bar']['tintcolor'] => $val
+ *
+ * @param array $data $_POST
+ * @return array
+ */
+ protected function _convertPost($data)
+ {
+ $conf = array();
+ foreach ($data as $key => $val) {
+ $parts = explode('_', $key);
+ // "4" - is number of expected params conf_native_bar_tintcolor in correct data
+ if (is_array($parts) && (count($parts) == 4)) {
+ @list($key0, $key1, $key2, $key3) = $parts;
+ if (!isset($conf[$key1])) {
+ $conf[$key1] = array();
+ }
+ if (!isset($conf[$key1][$key2])) {
+ $conf[$key1][$key2] = array();
+ }
+ $conf[$key1][$key2][$key3] = $val;
+ }
+ }
+ return $conf;
+ }
+
+ /**
+ * Save Theme action
+ */
+ public function saveThemeAction()
+ {
+ $data = $this->getRequest()->getPost();
+ $response = false;
+ $this->_saveThemeAction($data);
+ }
+
+ /**
+ * Save Theme action
+ */
+ public function resetThemeAction()
+ {
+ $response = false;
+ try {
+ Mage::helper('xmlconnect/theme')->resetAllThemes();
+ $response = Mage::helper('xmlconnect/theme')->getAllThemesArray(true);
+ } catch (Mage_Core_Exception $e) {
+ $response = array(
+ 'error' => true,
+ 'message' => $e->getMessage(),
+ );
+ } catch (Exception $e) {
+ $response = array(
+ 'error' => true,
+ 'message' => Mage::helper('xmlconnect')->__('Can\'t reset theme.')
+ );
+ }
+ if (is_array($response)) {
+ $response = Mage::helper('core')->jsonEncode($response);
+ $this->getResponse()->setBody($response);
+ }
+ }
+
+ /**
+ * Preview Home action handler
+ */
+ public function previewHomeAction()
+ {
+ $this->_previewAction('preview_home_content');
+ }
+
+ /**
+ * Preview Catalog action handler
+ */
+ public function previewCatalogAction()
+ {
+ $this->_previewAction('preview_catalog_content');
+ }
+
+ /**
+ * Preview action implementation
+ *
+ * @param string $block
+ */
+ protected function _previewAction($block)
+ {
+ $redirectBack = false;
+ $app = false;
+ try {
+ $app = $this->_initApp();
+ if (!$this->getRequest()->getParam('submission_action')) {
+ $app->addData($this->_preparePostData($this->getRequest()->getPost()));
+ }
+ $app->addData($this->_processUploadedFiles($app->getData()));
+
+ $this->loadLayout(FALSE);
+ $preview = $this->getLayout()->getBlock($block);
+ $preview->setConf($app->getRenderConf());
+ $this->renderLayout();
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_getSession()->addException($e, $e->getMessage());
+ $redirectBack = true;
+ } catch (Exception $e) {
+ $this->_getSession()->addException($e, Mage::helper('xmlconnect')->__('Unable to process preview.'));
+ $redirectBack = true;
+ }
+ if (isset($app) && $redirectBack) {
+ $this->_redirect('*/*/edit', array('application_id' => $app->getId()));
+ } else {
+ $this->_redirect('*/*/');
+ }
+ }
+
+ /**
+ * Delete action
+ */
+ public function deleteAction()
+ {
+ try {
+ $app = $this->_initApp();
+ if (!$app->getIsSubmitted()) {
+ $app->delete();
+ $this->_getSession()->addSuccess(Mage::helper('xmlconnect')->__('App has been deleted.'));
+ } else {
+ Mage::throwException(Mage::helper('xmlconnect')->__('It\'s not allowed to delete submitted application.'));
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_getSession()->addException($e, $e->getMessage());
+ } catch (Exception $e) {
+ $this->_getSession()->addException($e, Mage::helper('xmlconnect')->__('Unable to find an app to delete.'));
+ }
+ $this->_redirect('*/*/');
+ }
+
+ /**
+ * Check the permission to run it
+ *
+ * @return boolean
+ */
+ protected function _isAllowed()
+ {
+ return Mage::getSingleton('admin/session')->isAllowed('xmlconnect');
+ }
+
+ /**
+ * List application submit history
+ */
+ public function historyAction()
+ {
+ $this->loadLayout();
+ $this->_setActiveMenu('xmlconnect/history');
+ $this->renderLayout();
+ }
+
+ /**
+ * Render apps grid
+ */
+ public function gridAction()
+ {
+ $this->loadLayout(false);
+ $this->_setActiveMenu('xmlconnect/mobile');
+ $this->renderLayout();
+ }
+
+ /**
+ * Process all uploaded files
+ * setup filenames to the configuration return array
+ *
+ * @param array $data
+ * @param bool $restore
+ * @return array
+ */
+ protected function _processUploadedFiles($data, $restore = false)
+ {
+ if ($restore === true) {
+ $this->_uploadedFiles = Mage::getSingleton('adminhtml/session')->getUploadedFilesFormDataSubmit();
+ }
+ if (!isset($this->_uploadedFiles) || !is_array($this->_uploadedFiles)) {
+ $this->_uploadedFiles = array();
+ }
+
+ if (!empty($_FILES)) {
+ foreach ($_FILES as $field => $file) {
+ if (!empty($file['name']) && is_scalar($file['name'])) {
+ $uploadedFileName = Mage::helper('xmlconnect/image')->handleUpload($field, $data);
+ if (!empty($uploadedFileName)) {
+ $this->_uploadedFiles[$field] = $uploadedFileName;
+ }
+ }
+ }
+ }
+ foreach ($this->_uploadedFiles as $fieldPath => $fileName) {
+ $this->_injectFieldToArray($data, $fieldPath, $fileName);
+ }
+ Mage::getSingleton('adminhtml/session')->setUploadedFilesFormData($this->_uploadedFiles);
+ if ($restore === true) {
+ Mage::getSingleton('adminhtml/session')->setUploadedFilesFormDataSubmit($this->_uploadedFiles);
+ }
+ return $data;
+ }
+
+
+
+
+
+
+ /**
+ * Prepare post data
+ *
+ * Retains previous data in the object.
+ *
+ * @param array $arr
+ * @return array
+ */
+ public function _preparePostData(array $arr)
+ {
+ unset($arr['code']);
+ if (isset($arr['conf']['new_pages']) && isset($arr['conf']['new_pages']['ids'])
+ && isset($arr['conf']['new_pages']['labels'])) {
+
+ $newPages = array();
+ foreach ($arr['conf']['new_pages']['ids'] as $key=>$value) {
+ $newPages[$key]['id'] = trim($value);
+ }
+ foreach ($arr['conf']['new_pages']['labels'] as $key=>$value) {
+ $newPages[$key]['label'] = trim($value);
+ }
+ if (!isset($arr['conf']['native']['pages'])) {
+ $arr['conf']['native']['pages'] = array();
+ }
+ foreach ($newPages as $key => $page) {
+ if (empty($page['id']) || empty($page['label'])) {
+ unset($newPages[$key]);
+ }
+ }
+ if (!empty($newPages)) {
+ $arr['conf']['native']['pages'] = array_merge($arr['conf']['native']['pages'], $newPages);
+ }
+ unset($arr['conf']['new_pages']);
+ }
+ /**
+ * Restoring current_theme over selected but not applied theme
+ */
+ if (isset($arr['current_theme'])) {
+ $arr['conf']['extra']['theme'] = $arr['current_theme'];
+ }
+ if (!isset($arr['conf']['defaultCheckout'])) {
+ $arr['conf']['defaultCheckout'] = array();
+ }
+ if (!isset($arr['conf']['defaultCheckout']['isActive'])) {
+ $arr['conf']['defaultCheckout']['isActive'] = 0;
+ }
+
+ if (!isset($arr['conf']['paypal'])) {
+ $arr['conf']['paypal'] = array();
+ }
+ if (!isset($arr['conf']['paypal']['isActive'])) {
+ $arr['conf']['paypal']['isActive'] = 0;
+ }
+ return $arr;
+ }
+
+ /**
+ * Submission history grid action on submission history tab
+ */
+ public function submissionHistoryGridAction()
+ {
+ $this->_initApp();
+ $this->loadLayout();
+ $this->renderLayout();
+ }
+}
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CartController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CartController.php
new file mode 100644
index 0000000000..9974097be3
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CartController.php
@@ -0,0 +1,319 @@
+
+ */
+
+class Mage_XmlConnect_CartController extends Mage_XmlConnect_Controller_Action
+{
+ /**
+ * Shopping cart display action
+ */
+ public function indexAction()
+ {
+ $messages = array();
+ $cart = $this->_getCart();
+ if ($cart->getQuote()->getItemsCount()) {
+ $cart->init();
+ $cart->save();
+
+ if (!$this->_getQuote()->validateMinimumAmount()) {
+ $warning = Mage::getStoreConfig('sales/minimum_order/description');
+ $messages[parent::MESSAGE_STATUS_WARNING][] = $warning;
+ }
+ }
+
+ foreach ($cart->getQuote()->getMessages() as $message) {
+ if ($message) {
+ $messages[$message->getType()][] = $message->getText();
+ }
+ }
+
+ /**
+ * if customer enteres shopping cart we should mark quote
+ * as modified bc he can has checkout page in another window.
+ */
+ $this->_getSession()->setCartWasUpdated(true);
+
+ $this->loadLayout(false)->getLayout()->getBlock('xmlconnect.cart')->setMessages($messages);
+ $this->renderLayout();
+ }
+
+ /**
+ * Update shoping cart data action
+ */
+ public function updateAction()
+ {
+ try {
+ $cartData = $this->getRequest()->getParam('cart');
+ if (is_array($cartData)) {
+ $filter = new Zend_Filter_LocalizedToNormalized(
+ array('locale' => Mage::app()->getLocale()->getLocaleCode())
+ );
+ foreach ($cartData as $index => $data) {
+ if (isset($data['qty'])) {
+ $cartData[$index]['qty'] = $filter->filter($data['qty']);
+ }
+ }
+ $cart = $this->_getCart();
+ if (! $cart->getCustomerSession()->getCustomer()->getId() && $cart->getQuote()->getCustomerId()) {
+ $cart->getQuote()->setCustomerId(null);
+ }
+ $cart->updateItems($cartData)
+ ->save();
+ }
+ $this->_getSession()->setCartWasUpdated(true);
+ $this->_message(Mage::helper('xmlconnect')->__('Cart has been updated.'), parent::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t update cart.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Get request for product add to cart procedure
+ *
+ * @param mixed $requestInfo
+ * @return Varien_Object
+ */
+ protected function _getProductRequest($requestInfo)
+ {
+ if ($requestInfo instanceof Varien_Object) {
+ $request = $requestInfo;
+ } elseif (is_numeric($requestInfo)) {
+ $request = new Varien_Object();
+ $request->setQty($requestInfo);
+ } else {
+ $request = new Varien_Object($requestInfo);
+ }
+
+ if (!$request->hasQty()) {
+ $request->setQty(1);
+ }
+ return $request;
+ }
+
+ /**
+ * Add product to shopping cart action
+ *
+ * @return void
+ */
+ public function addAction()
+ {
+ $cart = $this->_getCart();
+ $params = $this->getRequest()->getParams();
+ try {
+ if (isset($params['qty'])) {
+ $filter = new Zend_Filter_LocalizedToNormalized(
+ array('locale' => Mage::app()->getLocale()->getLocaleCode())
+ );
+ $params['qty'] = $filter->filter($params['qty']);
+ }
+
+ $product = null;
+ $productId = (int) $this->getRequest()->getParam('product');
+ if ($productId) {
+ $_product = Mage::getModel('catalog/product')
+ ->setStoreId(Mage::app()->getStore()->getId())
+ ->load($productId);
+ if ($_product->getId()) {
+ $product = $_product;
+ }
+ }
+ $related = $this->getRequest()->getParam('related_product');
+
+ /**
+ * Check product availability
+ */
+ if (!$product) {
+ $this->_message(Mage::helper('xmlconnect')->__('Product is unavailable.'), parent::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ if ($product->isConfigurable()) {
+
+ $request = $this->_getProductRequest($params);
+ $cartCandidates = $product->getTypeInstance(true)->prepareForCart($request, $product);
+ /**
+ * Hardcoded Configurable product default
+ */
+ $minSaleQty = ((isset($params['qty']) ? $params['qty'] : 0) > 1) ? $params['qty'] : 1;
+ if (is_array($cartCandidates)) {
+ foreach ($cartCandidates as $candidate) {
+ $current = $candidate->getStockItem()->getMinSaleQty();
+ if ($minSaleQty < $current) {
+ $minSaleQty = $current;
+ }
+ }
+ }
+ if ($minSaleQty) {
+ $params['qty'] = $minSaleQty;
+ }
+ }
+
+ $cart->addProduct($product, $params);
+ if (!empty($related)) {
+ $cart->addProductsByIds(explode(',', $related));
+ }
+
+ $cart->save();
+
+ $this->_getSession()->setCartWasUpdated(true);
+
+ /**
+ * @todo remove wishlist observer processAddToCart
+ */
+ Mage::dispatchEvent('checkout_cart_add_product_complete',
+ array('product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse())
+ );
+
+ if (!$this->_getSession()->getNoCartRedirect(true)) {
+ $message = Mage::helper('xmlconnect')->__('%s has been added to your cart.', Mage::helper('core')->htmlEscape($product->getName()));
+ if ($cart->getQuote()->getHasError()) {
+ $message .= Mage::helper('xmlconnect')->__(' But cart has some errors.');
+ }
+ $this->_message($message, parent::MESSAGE_STATUS_SUCCESS);
+ }
+ } catch (Mage_Core_Exception $e) {
+ if ($this->_getSession()->getUseNotice(true)) {
+ $this->_message($e->getMessage(), parent::MESSAGE_STATUS_ERROR);
+ } else {
+ $this->_message(implode("\n", array_unique(explode("\n", $e->getMessage()))), parent::MESSAGE_STATUS_ERROR);
+ }
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t add item to shopping cart.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Delete shoping cart item action
+ */
+ public function deleteAction()
+ {
+ $id = (int) $this->getRequest()->getParam('item_id');
+ if ($id) {
+ try {
+ $this->_getCart()->removeItem($id)->save();
+ $this->_message(Mage::helper('xmlconnect')->__('Item has been deleted from cart.'), parent::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), parent::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t remove the item.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+ }
+
+ /**
+ * Initialize coupon
+ */
+ public function couponAction()
+ {
+ /**
+ * No reason continue with empty shopping cart
+ */
+ if (!$this->_getQuote()->getItemsCount()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Shopping cart is empty.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ $couponCode = (string) $this->getRequest()->getParam('coupon_code');
+ if ($this->getRequest()->getParam('remove') == 1) {
+ $couponCode = '';
+ }
+ $oldCouponCode = $this->_getQuote()->getCouponCode();
+
+ if (!strlen($couponCode) && !strlen($oldCouponCode)) {
+ $this->_message(Mage::helper('xmlconnect')->__('Coupon code is empty.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ try {
+ $this->_getQuote()->getShippingAddress()->setCollectShippingRates(true);
+ $this->_getQuote()->setCouponCode(strlen($couponCode) ? $couponCode : '')
+ ->collectTotals()
+ ->save();
+
+ if ($couponCode) {
+ if ($couponCode == $this->_getQuote()->getCouponCode()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Coupon code %s was applied.', strip_tags($couponCode)), parent::MESSAGE_STATUS_SUCCESS);
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Coupon code %s is not valid.', strip_tags($couponCode)), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Coupon code was canceled.'), parent::MESSAGE_STATUS_SUCCESS);
+ }
+
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t apply the coupon code.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Get shopping cart summary and flag is_virtual
+ */
+ public function infoAction()
+ {
+ $this->_getQuote()->collectTotals()->save();
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Retrieve shopping cart model object
+ *
+ * @return Mage_Checkout_Model_Cart
+ */
+ protected function _getCart()
+ {
+ return Mage::getSingleton('checkout/cart');
+ }
+
+ /**
+ * Get checkout session model instance
+ *
+ * @return Mage_Checkout_Model_Session
+ */
+ protected function _getSession()
+ {
+ return Mage::getSingleton('checkout/session');
+ }
+
+ /**
+ * Get current active quote instance
+ *
+ * @return Mage_Sales_Model_Quote
+ */
+ protected function _getQuote()
+ {
+ return $this->_getCart()->getQuote();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CatalogController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CatalogController.php
new file mode 100644
index 0000000000..8568c78e33
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CatalogController.php
@@ -0,0 +1,276 @@
+
+ */
+
+class Mage_XmlConnect_CatalogController extends Mage_XmlConnect_Controller_Action
+{
+ /**
+ * Category list
+ */
+ public function categoryAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Filter product list
+ */
+ public function filtersAction()
+ {
+ try{
+ $this->loadLayout(false);
+ $this->renderLayout();
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ Mage::logException($e);
+ $this->_message(Mage::helper('xmlconnect')->__('An error occurred while loading category filters.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Product information
+ */
+ public function productAction()
+ {
+ try {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to load product info.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Product options list
+ */
+ public function productOptionsAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+
+ /**
+ * Product gallery images list
+ */
+ public function productGalleryAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Product reviews list
+ */
+ public function productReviewsAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Add new review
+ */
+ public function productReviewAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Perform search products
+ */
+ public function searchAction()
+ {
+ $_helper = Mage::helper('catalogsearch');
+ $queryParam = str_replace('%20', ' ', $this->getRequest()->getParam('query'));
+ $this->getRequest()->setParam($_helper->getQueryParamName(), $queryParam);
+ $query = $_helper->getQuery();
+ /* @var $query Mage_CatalogSearch_Model_Query */
+
+ $query->setStoreId(Mage::app()->getStore()->getId());
+ //
+ // return Mage::helper('catalogsearch')->__('Minimum Search query length is %s', $this->_getQuery()->getMinQueryLength());
+ //
+ if ($query->getQueryText()) {
+ if ($_helper->isMinQueryLength()) {
+ $query->setId(0)
+ ->setIsActive(1)
+ ->setIsProcessed(1);
+ } else {
+ if ($query->getId()) {
+ $query->setPopularity($query->getPopularity()+1);
+ } else {
+ $query->setPopularity(1);
+ }
+
+ if ($query->getRedirect()) {
+ $query->save();
+ $this->getResponse()->setRedirect($query->getRedirect());
+ return;
+ } else {
+ $query->prepare();
+ }
+ }
+
+ $_helper->checkNotes();
+
+ if (!$_helper->isMinQueryLength()) {
+ $query->save();
+ }
+ }
+
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Retrieve suggestions based on search query
+ */
+ public function searchSuggestAction()
+ {
+ $this->getRequest()->setParam('q', $this->getRequest()->getParam('query'));
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Send product link to friend action
+ *
+ * @return this
+ */
+ public function sendEmailAction()
+ {
+ /* @var $helper Mage_Sendfriend_Helper_Data */
+ $helper = Mage::helper('sendfriend');
+ /* @var $session Mage_Customer_Model_Session */
+ $session = Mage::getSingleton('customer/session');
+
+ if (!$helper->isEnabled()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Tell a Friend is disabled.'), self::MESSAGE_STATUS_ERROR);
+ return $this;
+ }
+
+ if (!$helper->isAllowForGuest() && !$session->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return $this;
+ }
+
+ /**
+ * Initialize product
+ */
+ $productId = (int)$this->getRequest()->getParam('product_id');
+ if (!$productId) {
+ $this->_message(Mage::helper('xmlconnect')->__('No product selected.'), self::MESSAGE_STATUS_ERROR);
+ return $this;
+ }
+ $product = Mage::getModel('catalog/product')
+ ->load($productId);
+ if (!$product->getId() || !$product->isVisibleInCatalog()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Selected product is unavailable.'), self::MESSAGE_STATUS_ERROR);
+ return $this;
+ }
+
+ Mage::register('product', $product);
+
+ /**
+ * Initialize send friend model
+ */
+ $model = Mage::getModel('sendfriend/sendfriend');
+ $model->setRemoteAddr(Mage::helper('core/http')->getRemoteAddr(true));
+ $model->setCookie(Mage::app()->getCookie());
+ $model->setWebsiteId(Mage::app()->getStore()->getWebsiteId());
+
+ Mage::register('send_to_friend_model', $model);
+
+ if ($model->getMaxSendsToFriend()) {
+// $this->_message(Mage::helper('xmlconnect')->__('Messages cannot be sent more than %d times in an hour.', $model->getMaxSendsToFriend()), self::MESSAGE_STATUS_WARNING);
+// return $this;
+ }
+
+ $data = $this->getRequest()->getPost();
+
+ if (!$data) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return $this;
+ }
+
+ $sender = (array)$this->getRequest()->getPost('sender');
+ if ($session->isLoggedIn()) {
+ $sender['email'] = $session->getCustomer()->getEmail();
+ $sender['name'] = $session->getCustomer()->getFirstName() . ' ' . $session->getCustomer()->getLastName();
+ }
+
+ /**
+ * Initialize category and set it to product
+ */
+ $categoryId = $this->getRequest()->getParam('category_id', null);
+ if ($categoryId) {
+ $category = Mage::getModel('catalog/category')
+ ->load($categoryId);
+ $product->setCategory($category);
+ Mage::register('current_category', $category);
+ }
+
+ $model->setSender($sender);
+ $model->setRecipients($this->getRequest()->getPost('recipients'));
+ $model->setProduct($product);
+
+ try {
+ $validate = $model->validate();
+ if ($validate === true) {
+ $model->send();
+ $this->_message(Mage::helper('xmlconnect')->__('Tell a Friend link has been sent.'), self::MESSAGE_STATUS_SUCCESS);
+ return;
+ } else {
+ if (is_array($validate)) {
+ $this->_message(implode(' ', $validate), self::MESSAGE_STATUS_ERROR);
+ return;
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('There were some problems with the data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Some emails were not sent.'), self::MESSAGE_STATUS_ERROR);
+ }
+
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CheckoutController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CheckoutController.php
new file mode 100644
index 0000000000..8ed89734e4
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CheckoutController.php
@@ -0,0 +1,336 @@
+
+ */
+
+class Mage_XmlConnect_CheckoutController extends Mage_XmlConnect_Controller_Action
+{
+
+ /**
+ * Make sure customer is logged in
+ *
+ * @return void
+ */
+ public function preDispatch()
+ {
+ parent::preDispatch();
+ if (!Mage::getSingleton('customer/session')->isLoggedIn()
+ && !Mage::getSingleton('checkout/session')->getQuote()->isAllowedGuestCheckout()) {
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ }
+
+ /**
+ * Get one page checkout model
+ *
+ * @return Mage_Checkout_Model_Type_Onepage
+ */
+ public function getOnepage()
+ {
+ return Mage::getSingleton('checkout/type_onepage');
+ }
+
+ /**
+ * Onepage Checkout page
+ */
+ public function indexAction()
+ {
+ if (!Mage::helper('checkout')->canOnepageCheckout()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Onepage checkout is disabled.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ $quote = $this->getOnepage()->getQuote();
+ if ($quote->getHasError()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Cart has some errors.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ } else if (!$quote->hasItems()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Cart is empty.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ } else if (!$quote->validateMinimumAmount()) {
+ $error = Mage::getStoreConfig('sales/minimum_order/error_message');
+ $this->_message($error, self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ Mage::getSingleton('checkout/session')->setCartWasUpdated(false);
+ $this->getOnepage()->initCheckout();
+
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Display customer new billing addrress form
+ */
+ public function newBillingAddressFormAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Display customer new shipping addrress form
+ */
+ public function newShippingAddressFormAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Billing addresses list action
+ */
+ public function billingAddressAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Save billing address to current quote using onepage model
+ */
+ public function saveBillingAddressAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ $data = $this->getRequest()->getPost('billing', array());
+ $customerAddressId = $this->getRequest()->getPost('billing_address_id', false);
+ if (isset($data['email'])) {
+ $data['email'] = trim($data['email']);
+ }
+ $result = $this->getOnepage()->saveBilling($data, $customerAddressId);
+ if (!isset($result['error'])) {
+ $this->_message(Mage::helper('xmlconnect')->__('Billing address has been set.'), self::MESSAGE_STATUS_SUCCESS);
+ } else {
+ if (!is_array($result['message'])) {
+ $result['message'] = array($result['message']);
+ }
+ $this->_message(implode('. ', $result['message']), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Shipping addresses list action
+ */
+ public function shippingAddressAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Save shipping address to current quote using onepage model
+ */
+ public function saveShippingAddressAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ $data = $this->getRequest()->getPost('shipping', array());
+ $customerAddressId = $this->getRequest()->getPost('shipping_address_id', false);
+ $result = $this->getOnepage()->saveShipping($data, $customerAddressId);
+ if (!isset($result['error'])) {
+ $this->_message(Mage::helper('xmlconnect')->__('Shipping address has been set.'), self::MESSAGE_STATUS_SUCCESS);
+ } else {
+ if (!is_array($result['message'])) {
+ $result['message'] = array($result['message']);
+ }
+ $this->_message(implode('. ', $result['message']), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Get shipping methods for current quote
+ */
+ public function shippingMethodsAction()
+ {
+ try {
+ $result = array('error' => Mage::helper('xmlconnect')->__('Error.'));
+ $this->getOnepage()->getQuote()->getShippingAddress()->setCollectShippingRates(true);
+ $this->getOnepage()->getQuote()->collectTotals()->save();
+ $this->loadLayout(false);
+ $this->renderLayout();
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $result['error'] = $e->getMessage();
+ }
+ $this->_message($result['error'], self::MESSAGE_STATUS_ERROR);
+ }
+
+ /**
+ * Shipping method save action
+ */
+ public function saveShippingMethodAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ $data = $this->getRequest()->getPost('shipping_method', '');
+ $result = $this->getOnepage()->saveShippingMethod($data);
+ if (!isset($result['error'])) {
+ $this->_message(Mage::helper('xmlconnect')->__('Shipping method has been set.'), self::MESSAGE_STATUS_SUCCESS);
+ } else {
+ if (!is_array($result['message'])) {
+ $result['message'] = array($result['message']);
+ }
+ Mage::dispatchEvent('checkout_controller_onepage_save_shipping_method', array('request'=>$this->getRequest(), 'quote'=>$this->getOnepage()->getQuote()));
+ $this->_message(implode('. ', $result['message']), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+
+ /**
+ * Save checkout method
+ */
+ public function saveMethodAction()
+ {
+ if ($this->getRequest()->isPost()) {
+ $method = (string) $this->getRequest()->getPost('method');
+ $result = $this->getOnepage()->saveCheckoutMethod($method);
+ if (!isset($result['error'])) {
+ $this->_message(Mage::helper('xmlconnect')->__('Payment Method has been set.'), self::MESSAGE_STATUS_SUCCESS);
+ } else {
+ if (!is_array($result['message'])) {
+ $result['message'] = array($result['message']);
+ }
+ $this->_message(implode('. ', $result['message']), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+ }
+
+ /**
+ * Get payment methods action
+ */
+ public function paymentMethodsAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Save payment action
+ */
+ public function savePaymentAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ try {
+ // set payment to quote
+ $result = array();
+ $data = $this->getRequest()->getPost('payment', array());
+ $result = $this->getOnepage()->savePayment($data);
+ $this->_message(Mage::helper('xmlconnect')->__('Payment method was successfully set.'), self::MESSAGE_STATUS_SUCCESS);
+ return;
+ } catch (Mage_Payment_Exception $e) {
+ $result['error'] = $e->getMessage();
+ } catch (Mage_Core_Exception $e) {
+ $result['error'] = $e->getMessage();
+ } catch (Exception $e) {
+ Mage::logException($e);
+ $result['error'] = Mage::helper('xmlconnect')->__('Unable to set payment method.');
+ }
+ $this->_message($result['error'], self::MESSAGE_STATUS_ERROR);
+ }
+
+ /**
+ * Order summary info action
+ */
+ public function orderReviewAction()
+ {
+ $this->getOnepage()->getQuote()->collectTotals()->save();
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Create order action
+ */
+ public function saveOrderAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ try {
+ if ($requiredAgreements = Mage::helper('checkout')->getRequiredAgreementIds()) {
+ $postedAgreements = array_keys($this->getRequest()->getPost('agreement', array()));
+ if ($diff = array_diff($requiredAgreements, $postedAgreements)) {
+ $error = Mage::helper('xmlconnect')->__('Please agree to all the terms and conditions before placing the order.');
+ $this->_message($error, self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ }
+ if ($data = $this->getRequest()->getPost('payment', false)) {
+ $this->getOnepage()->getQuote()->getPayment()->importData($data);
+ }
+ $this->getOnepage()->saveOrder();
+
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_SUCCESS);
+
+ $orderId = $this->getOnepage()->getLastOrderId();
+
+ $text = Mage::helper('xmlconnect')->__('Thank you for your purchase! ');
+ $text .= Mage::helper('xmlconnect')->__('Your order # is: %s. ', $orderId);
+ $text .= Mage::helper('xmlconnect')->__('You will receive an order confirmation email with details of your order and a link to track its progress.');
+ $message->addChild('text', $text);
+
+ $message->addChild('order_id', $orderId);
+
+ $this->getOnepage()->getQuote()->save();
+ $this->getOnepage()->getCheckout()->clear();
+
+ $this->getResponse()->setBody($message->asNiceXml());
+ return;
+ } catch (Mage_Core_Exception $e) {
+ Mage::logException($e);
+ Mage::helper('checkout')->sendPaymentFailedEmail($this->getOnepage()->getQuote(), $e->getMessage());
+ $error = $e->getMessage();
+ } catch (Exception $e) {
+ Mage::logException($e);
+ Mage::helper('checkout')->sendPaymentFailedEmail($this->getOnepage()->getQuote(), $e->getMessage());
+ $error = Mage::helper('xmlconnect')->__('An error occurred while processing your order. Please contact us or try again later.');
+ }
+ $this->getOnepage()->getQuote()->save();
+
+ $this->_message($error, self::MESSAGE_STATUS_ERROR);
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CmsController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CmsController.php
new file mode 100644
index 0000000000..99140755a2
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CmsController.php
@@ -0,0 +1,54 @@
+
+ */
+
+class Mage_XmlConnect_CmsController extends Mage_XmlConnect_Controller_Action
+{
+
+ /**
+ * Declare content type header
+ */
+ public function preDispatch()
+ {
+ parent::preDispatch();
+ $this->getResponse()->setHeader('Content-type', 'text/html; charset=UTF-8');
+ }
+
+ /**
+ * Category list
+ *
+ */
+ public function pageAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/ConfigurationController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/ConfigurationController.php
new file mode 100644
index 0000000000..2c1d58d593
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/ConfigurationController.php
@@ -0,0 +1,132 @@
+
+ */
+
+class Mage_XmlConnect_ConfigurationController extends Mage_Core_Controller_Front_Action
+{
+ /**
+ * Declare content type header
+ */
+ public function preDispatch()
+ {
+ parent::preDispatch();
+ $this->getResponse()->setHeader('Content-type', 'text/xml; charset=UTF-8');
+ }
+
+ /**
+ * Initialize application
+ *
+ * @return Mage_XmlConnect_Model_Application
+ */
+ protected function _initApp()
+ {
+
+ $cookieName = Mage_XmlConnect_Model_Application::APP_CODE_COOKIE_NAME;
+ $screenSizeCookieName = Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_NAME;
+ $code = $this->getRequest()->getParam($cookieName);
+ $screenSize = (string) $this->getRequest()->getParam($screenSizeCookieName);
+ $app = Mage::getModel('xmlconnect/application');
+ if ($app) {
+ $app->loadByCode($code);
+ Mage::app()->setCurrentStore(Mage::app()->getStore($app->getStoreId())->getCode());
+ Mage::getSingleton('core/locale')->emulate($app->getStoreId());
+ $app->setScreenSize($screenSize);
+ if (!$app->getId()) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('App with specified code does not exist.'));
+ }
+ $app->loadConfiguration();
+ } else {
+ Mage::throwException(Mage::helper('xmlconnect')->__('App code required.'));
+ }
+ Mage::register('current_app', $app);
+ return $app;
+ }
+
+ /**
+ * Default action
+ */
+ public function indexAction()
+ {
+ try {
+
+ $app = $this->_initApp();
+
+ $cookieToSetArray = array (
+ array(
+ 'cookieName' => Mage_XmlConnect_Model_Application::APP_CODE_COOKIE_NAME,
+ 'paramName' => 'app_code',
+ 'value' => $app->getCode()),
+ array(
+ 'cookieName' => Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_NAME,
+ 'paramName' => Mage_XmlConnect_Model_Application::APP_SCREEN_SIZE_NAME,
+ 'value' => $app->getScreenSize())
+ );
+ foreach ($cookieToSetArray as $item) {
+ if (!isset($_COOKIE[$item['cookieName']]) ||
+ (isset($_COOKIE[$item['cookieName']]) &&
+ ($_COOKIE[$item['cookieName']] != $this->getRequest()->getParam($item['paramName'])))
+ ) {
+ /**
+ * @todo add management of cookie expire to application admin panel
+ */
+ $cookieExpireOffset = 3600 * 24 * 30;
+ Mage::getSingleton('core/cookie')->set($item['cookieName'], $item['value'], $cookieExpireOffset, '/', null, null, true);
+ }
+ }
+
+ if ($this->getRequest()->getParam('updated_at')) {
+ $updatedAt = strtotime($app->getUpdatedAt());
+ $loadedAt = (int) $this->getRequest()->getParam('updated_at');
+ if ($loadedAt >= $updatedAt) {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', Mage_XmlConnect_Controller_Action::MESSAGE_STATUS_SUCCESS);
+ $message->addChild('no_changes', '1');
+ $this->getResponse()->setBody($message->asNiceXml());
+ return;
+ }
+ }
+ $this->loadLayout(false);
+ $this->renderLayout();
+ } catch (Mage_Core_Exception $e) {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', Mage_XmlConnect_Controller_Action::MESSAGE_STATUS_ERROR);
+ $message->addChild('text', $e->getMessage());
+ $this->getResponse()->setBody($message->asNiceXml());
+ } catch (Exception $e) {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', Mage_XmlConnect_Controller_Action::MESSAGE_STATUS_ERROR);
+ $message->addChild('text', Mage::helper('xmlconnect')->__('Can\'t show configuration.'));
+ Mage::logException($e);
+ $this->getResponse()->setBody($message->asNiceXml());
+ }
+
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CustomerController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CustomerController.php
new file mode 100644
index 0000000000..27f0e0feb2
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/CustomerController.php
@@ -0,0 +1,545 @@
+
+ */
+
+class Mage_XmlConnect_CustomerController extends Mage_XmlConnect_Controller_Action
+{
+ /**
+ * Customer authentification action
+ *
+ * @return void
+ */
+ public function loginAction()
+ {
+ $session = $this->_getSession();
+ $request = $this->getRequest();
+ if ($session->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('You are already logged in.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ if ($request->isPost()) {
+ $user = $request->getParam('username');
+ $pass = $request->getParam('password');
+ try {
+ if ($session->login($user, $pass)) {
+ if ($session->getCustomer()->getIsJustConfirmed()) {
+ $session->getCustomer()->sendNewAccountEmail('confirmed');
+ }
+ $this->_message(Mage::helper('xmlconnect')->__('Authentication complete.'), self::MESSAGE_STATUS_SUCCESS);
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Invalid login or password.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } catch (Mage_Core_Exception $e) {
+ switch ($e->getCode()) {
+ case Mage_Customer_Model_Customer::EXCEPTION_EMAIL_NOT_CONFIRMED:
+ // TODO: resend configmation email message with action
+ break;
+ case Mage_Customer_Model_Customer::EXCEPTION_INVALID_EMAIL_OR_PASSWORD:
+ $message = $e->getMessage();
+ break;
+ default:
+ $message = $e->getMessage();
+ }
+ $this->_message($message, self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer authentication problem.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Login and password are required.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Customer logout
+ *
+ */
+ public function logoutAction()
+ {
+ try {
+ $this->_getSession()->logout();
+ $this->_message(Mage::helper('xmlconnect')->__('Logout complete.'), self::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer logout problem.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Customer registration/edit account form
+ *
+ * @return void
+ */
+ public function formAction()
+ {
+ $customer = null;
+ $editFlag = (int)$this->getRequest()->getParam('edit');
+ if ($editFlag == 1) {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ $customer = $this->_getSession()->getCustomer();
+ }
+
+ $this->loadLayout(false)->getLayout()->getBlock('xmlconnect.customer.form')->setCustomer($customer);
+ $this->renderLayout();
+ }
+
+ /**
+ * Change customer data action
+ *
+ * @return void
+ */
+ public function editAction()
+ {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ if ($this->getRequest()->isPost()) {
+ $customer = $this->_getSession()->getCustomer();
+
+ /* @var $customerForm Mage_Customer_Model_Form */
+ $customerForm = Mage::getModel('customer/form');
+ $customerForm->setFormCode('customer_account_edit')
+ ->setEntity($customer);
+
+ $customerData = $customerForm->extractData($this->getRequest());
+
+ $errors = array();
+ $customerErrors = $customerForm->validateData($customerData);
+ if ($customerErrors !== true) {
+ $errors = array_merge($customerErrors, $errors);
+ } else {
+ $customerForm->compactData($customerData);
+ $customerErrors = $customer->validate();
+ if (is_array($customerErrors)) {
+ $errors = array_merge($customerErrors, $errors);
+ }
+ }
+
+ if ($this->getRequest()->getParam('change_password')) {
+ $currPass = $this->getRequest()->getPost('current_password');
+ $newPass = $this->getRequest()->getPost('password');
+ $confPass = $this->getRequest()->getPost('confirmation');
+
+ if (empty($currPass) || empty($newPass) || empty($confPass)) {
+ $errors[] = Mage::helper('xmlconnect')->__('Password fields cannot be empty.');
+ }
+
+ if ($newPass != $confPass) {
+ $errors[] = Mage::helper('xmlconnect')->__('Please make sure your passwords match.');
+ }
+
+ $oldPass = $this->_getSession()->getCustomer()->getPasswordHash();
+ if (strpos($oldPass, ':')) {
+ list($_salt, $salt) = explode(':', $oldPass);
+ } else {
+ $salt = false;
+ }
+
+ if ($customer->hashPassword($currPass, $salt) == $oldPass) {
+ $customer->setPassword($newPass);
+ } else {
+ $errors[] = Mage::helper('xmlconnect')->__('Invalid current password.');
+ }
+ }
+
+ if (!empty($errors)) {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_ERROR);
+ $message->addChild('text', implode(' ', $errors));
+ $this->getResponse()->setBody($message->asNiceXml());
+ return;
+ }
+
+ try {
+ $customer->save();
+ $this->_getSession()->setCustomer($customer);
+ $this->_message(Mage::helper('xmlconnect')->__('Account information has been saved.'), self::MESSAGE_STATUS_SUCCESS);
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t save the customer.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('POST data is not valid.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Save customer account
+ *
+ * @return void
+ */
+ public function saveAction()
+ {
+ $session = $this->_getSession();
+ $request = $this->getRequest();
+ if ($session->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('You are already logged in.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ $session->setEscapeMessages(true); // prevent XSS injection in user input
+ if ($request->isPost()) {
+ $errors = array();
+
+ /* @var $customer Mage_Customer_Model_Customer */
+ $customer = Mage::registry('current_customer');
+ if (is_null($customer)) {
+ $customer = Mage::getModel('customer/customer');
+ }
+
+ /* @var $customerForm Mage_Customer_Model_Form */
+ $customerForm = Mage::getModel('customer/form');
+ $customerForm->setFormCode('customer_account_create')
+ ->setEntity($customer);
+
+ $customerData = $customerForm->extractData($this->getRequest());
+
+ if ($this->getRequest()->getParam('is_subscribed', false)) {
+ $customer->setIsSubscribed(1);
+ }
+
+ /**
+ * Initialize customer group id
+ */
+ $customer->getGroupId();
+
+ try {
+ $customerErrors = $customerForm->validateData($customerData);
+ if ($customerErrors !== true) {
+ $errors = array_merge($customerErrors, $errors);
+ } else {
+ $customerForm->compactData($customerData);
+ $customer->setPassword($this->getRequest()->getPost('password'));
+ $customer->setConfirmation($this->getRequest()->getPost('confirmation'));
+ $customerErrors = $customer->validate();
+ if (is_array($customerErrors)) {
+ $errors = array_merge($customerErrors, $errors);
+ }
+ }
+
+ $validationResult = count($errors) == 0;
+ if (true === $validationResult) {
+ $customer->save();
+
+ if ($customer->isConfirmationRequired()) {
+ $customer->sendNewAccountEmail('confirmation', $session->getBeforeAuthUrl());
+ $message = Mage::helper('xmlconnect')->__('Account confirmation is required. Please check your email for the confirmation link.');
+ $messageXmlObj = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $messageXmlObj->addChild('status', self::MESSAGE_STATUS_SUCCESS);
+ $messageXmlObj->addChild('text', $message);
+ $messageXmlObj->addChild('confirmation', 1);
+ $this->getResponse()->setBody($messageXmlObj->asNiceXml());
+ return;
+ } else {
+ $session->setCustomerAsLoggedIn($customer);
+ $customer->sendNewAccountEmail('registered');
+ $this->_message(Mage::helper('xmlconnect')->__('Thank you for registering!'), self::MESSAGE_STATUS_SUCCESS);
+ return;
+ }
+ } else {
+ if (is_array($errors)) {
+ $message = implode("\n", $errors);
+ } else {
+ $message = Mage::helper('xmlconnect')->__('Invalid customer data.');
+ }
+ $this->_message($message, self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ } catch (Mage_Core_Exception $e) {
+ if ($e->getCode() === Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS) {
+ $message = Mage::helper('xmlconnect')->__('An account with this email address already exists.');
+ $session->setEscapeMessages(false);
+ } else {
+ $message = $e->getMessage();
+ }
+ $this->_message($message, self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t save the customer.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+ }
+
+ /**
+ * Send new password to customer by specified email
+ *
+ * @return void
+ */
+ public function forgotPasswordAction()
+ {
+ $email = $this->getRequest()->getPost('email');
+ if ($email) {
+ if (!Zend_Validate::is($email, 'EmailAddress')) {
+ $this->_message(Mage::helper('xmlconnect')->__('Invalid email address.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ $customer = Mage::getModel('customer/customer')
+ ->setWebsiteId(Mage::app()->getStore()->getWebsiteId())
+ ->loadByEmail($email);
+
+ if ($customer->getId()) {
+ try {
+ $newPassword = $customer->generatePassword();
+ $customer->changePassword($newPassword, false);
+ $customer->sendPasswordReminderEmail();
+ $this->_message(Mage::helper('xmlconnect')->__('A new password has been sent.'), self::MESSAGE_STATUS_SUCCESS);
+
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Problem changing or sending password.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('This email address was not found in our records.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer email not specified.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Customer addresses list
+ *
+ * @return void
+ */
+ public function addressAction()
+ {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+
+ if (count($this->_getSession()->getCustomer()->getAddresses())) {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ } else {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_ERROR);
+ $message->addChild('is_empty_address_book', 1);
+ $this->getResponse()->setBody($message->asNiceXml());
+ }
+ }
+
+ /**
+ * Customer add/edit address form
+ *
+ * @return void
+ */
+ public function addressFormAction()
+ {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+
+ $address = Mage::getModel('customer/address');
+
+ /**
+ * Init address object
+ */
+ $addressId = (int)$this->getRequest()->getParam('id');
+ if ($addressId) {
+ $address->load($addressId);
+ if ($address->getCustomerId() != $this->_getSession()->getCustomerId()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified address does not exist.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ }
+
+ $this->loadLayout(false)->getLayout()->getBlock('xmlconnect.customer.address.form')->setAddress($address);
+ $this->renderLayout();
+ }
+
+ /**
+ * Remove customer address
+ *
+ * @return void
+ */
+ public function deleteAddressAction()
+ {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+
+ $addressId = $this->getRequest()->getParam('id', false);
+
+ if ($addressId) {
+ $address = Mage::getModel('customer/address')->load($addressId);
+
+ // Validate address_id <=> customer_id
+ if ($address->getCustomerId() != $this->_getSession()->getCustomerId()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Address does not belong to this customer.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ try {
+ $address->delete();
+ $this->_message(Mage::helper('xmlconnect')->__('Address has been deleted.'), self::MESSAGE_STATUS_SUCCESS);
+ } catch (Exception $e) {
+ Mage::logException($e);
+ $this->_message(Mage::helper('xmlconnect')->__('An error occurred while deleting the address.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+ }
+
+ /**
+ * Add/Save customer address
+ *
+ * @return void
+ */
+ public function saveAddressAction()
+ {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+
+ // Save data
+ if ($this->getRequest()->isPost()) {
+ $customer = $this->_getSession()->getCustomer();
+ /* @var $address Mage_Customer_Model_Address */
+ $address = Mage::getModel('customer/address');
+ $addressId = $this->getRequest()->getParam('id');
+ if ($addressId) {
+ $existsAddress = $customer->getAddressById($addressId);
+ if ($existsAddress->getId() && $existsAddress->getCustomerId() == $customer->getId()) {
+ $address->setId($existsAddress->getId());
+ }
+ }
+
+ $errors = array();
+
+ /* @var $addressForm Mage_Customer_Model_Form */
+ $addressForm = Mage::getModel('customer/form');
+ $addressForm->setFormCode('customer_address_edit')
+ ->setEntity($address);
+ $addressData = $addressForm->extractData($this->getRequest());
+ $addressErrors = $addressForm->validateData($addressData);
+ if ($addressErrors !== true) {
+ $errors = $addressErrors;
+ }
+
+ try {
+ $addressForm->compactData($addressData);
+ $address->setCustomerId($customer->getId())
+ ->setIsDefaultBilling($this->getRequest()->getParam('default_billing', false))
+ ->setIsDefaultShipping($this->getRequest()->getParam('default_shipping', false));
+
+ $addressErrors = $address->validate();
+ if ($addressErrors !== true) {
+ $errors = array_merge($errors, $addressErrors);
+ }
+
+ $addressValidation = count($errors) == 0;
+
+ if (true === $addressValidation) {
+ $address->save();
+
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_SUCCESS);
+ $message->addChild('text', Mage::helper('xmlconnect')->__('Address has been saved.'));
+ $message->addChild('address_id', $address->getId());
+ $this->getResponse()->setBody($message->asNiceXml());
+ return;
+ } else {
+ if (is_array($addressValidation)) {
+ $this->_message(implode('. ', $addressValidation), self::MESSAGE_STATUS_ERROR);
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t save address.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ Mage::logException($e);
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t save address.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Address data not specified.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Customer orders list
+ *
+ * @return void
+ */
+ public function orderListAction()
+ {
+ if (!$this->_getSession()->isLoggedIn()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Check if customer is loggined
+ */
+ public function isLogginedAction()
+ {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('is_loggined', (int)$this->_getSession()->isLoggedIn());
+ $this->getResponse()->setBody($message->asNiceXml());
+ }
+
+ /**
+ * Filtering posted data. Converting localized data if needed
+ *
+ * @param array $data
+ * @return array
+ */
+ protected function _filterPostData($data)
+ {
+ $data = $this->_filterDates($data, array('dob'));
+ return $data;
+ }
+
+ /**
+ * Get customer session model
+ *
+ * @return Mage_Customer_Model_Session
+ */
+ protected function _getSession()
+ {
+ return Mage::getSingleton('customer/session');
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/IndexController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/IndexController.php
new file mode 100644
index 0000000000..784929b953
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/IndexController.php
@@ -0,0 +1,46 @@
+
+ */
+
+class Mage_XmlConnect_IndexController extends Mage_XmlConnect_Controller_Action
+{
+
+ /**
+ * Default action
+ *
+ */
+ public function indexAction()
+ {
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/Paypal/MepController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/Paypal/MepController.php
new file mode 100644
index 0000000000..8ed7196993
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/Paypal/MepController.php
@@ -0,0 +1,279 @@
+
+ */
+
+class Mage_XmlConnect_Paypal_MepController extends Mage_XmlConnect_Controller_Action
+{
+ /**
+ * Store MEP checkout model instance
+ *
+ * @var Mage_XmlConnect_Model_Paypal_Mep_Checkout
+ */
+ protected $_checkout = null;
+
+ /**
+ * Store Quote mdoel instance
+ *
+ * @var Mage_Sales_Model_Quote
+ */
+ protected $_quote = false;
+
+ /**
+ * Make sure customer is logged in
+ *
+ * @return void
+ */
+ public function preDispatch()
+ {
+ parent::preDispatch();
+ if (!Mage::getSingleton('customer/session')->isLoggedIn()
+ && !Mage::getSingleton('checkout/session')->getQuote()->isAllowedGuestCheckout()) {
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ }
+
+ /**
+ * Start MEP Checkout
+ */
+ public function indexAction()
+ {
+ try {
+ $this->_initCheckout();
+ $reservedOrderId = $this->_checkout->initCheckout();
+ $this->_message(Mage::helper('xmlconnect')->__('Checkout has been initialized.'), self::MESSAGE_STATUS_SUCCESS);
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to start MEP Checkout.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Save shipping address to current quote using onepage model
+ */
+ public function saveShippingAddressAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ try {
+ $this->_initCheckout();
+ $data = $this->getRequest()->getPost('shipping', array());
+ $result = $this->_checkout->saveShipping($data);
+ if (!isset($result['error'])) {
+ $this->_message(Mage::helper('xmlconnect')->__('Shipping address has been set.'), self::MESSAGE_STATUS_SUCCESS);
+ } else {
+ if (!is_array($result['message'])) {
+ $result['message'] = array($result['message']);
+ }
+ $this->_message(implode('. ', $result['message']), self::MESSAGE_STATUS_ERROR);
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to save shipping address.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Get shipping methods for current quote
+ */
+ public function shippingMethodsAction()
+ {
+ try {
+ $this->_initCheckout();
+ $this->loadLayout(false);
+ $this->renderLayout();
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to get shipping methods list.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Shipping method save action
+ */
+ public function saveShippingMethodAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ try {
+ $this->_initCheckout();
+ $data = $this->getRequest()->getPost('shipping_method', '');
+ $result = $this->_checkout->saveShippingMethod($data);
+ if (!isset($result['error'])) {
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_SUCCESS);
+ $message->addChild('text', Mage::helper('xmlconnect')->__('Shipping method has been set.'));
+ if ($this->_getQuote()->isVirtual()) {
+ $quoteAddress = $this->_getQuote()->getBillingAddress();
+ } else {
+ $quoteAddress = $this->_getQuote()->getShippingAddress();
+ }
+ $taxAmount = Mage::helper('core')->currency($quoteAddress->getBaseTaxAmount(), false, false);
+ $message->addChild('tax_amount', Mage::helper('xmlconnect')->formatPriceForXml($taxAmount));
+ $this->getResponse()->setBody($message->asNiceXml());
+ } else {
+ if (!is_array($result['message'])) {
+ $result['message'] = array($result['message']);
+ }
+ $this->_message(implode('. ', $result['message']), self::MESSAGE_STATUS_ERROR);
+ }
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to save shipping method.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Shopping cart totals
+ */
+ public function cartTotalsAction()
+ {
+ try {
+ $this->_initCheckout();
+ $this->loadLayout(false);
+ $this->renderLayout();
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to collect cart totals.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Submit the order
+ */
+ public function saveOrderAction()
+ {
+ if (!$this->getRequest()->isPost()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified invalid data.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+ try {
+ /**
+ * Init checkout
+ */
+ $this->_initCheckout();
+
+ /**
+ * Set payment data
+ */
+ $data = $this->getRequest()->getPost('payment', array());
+ $this->_checkout->savePayment($data);
+
+ /**
+ * Place order
+ */
+ $this->_checkout->saveOrder();
+
+ /**
+ * Format success report
+ */
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_SUCCESS);
+
+ $orderId = $this->_checkout->getLastOrderId();
+
+ $text = Mage::helper('xmlconnect')->__('Thank you for your purchase! ');
+ $text .= Mage::helper('xmlconnect')->__('Your order # is: %s. ', $orderId);
+ $text .= Mage::helper('xmlconnect')->__('You will receive an order confirmation email with details of your order and a link to track its progress.');
+ $message->addChild('text', $text);
+
+ $message->addChild('order_id', $orderId);
+ $this->getResponse()->setBody($message->asNiceXml());
+ return;
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Unable to place the order.'), self::MESSAGE_STATUS_ERROR);
+ Mage::logException($e);
+ }
+ }
+
+ /**
+ * Instantiate quote and checkout
+ *
+ * @throws Mage_Core_Exception
+ */
+ protected function _initCheckout()
+ {
+
+ $quote = $this->_getQuote();
+ if (!$quote->hasItems() || $quote->getHasError()) {
+ Mage::throwException(Mage::helper('xmlconnect')->__('Unable to initialize MEP Checkout.'));
+ }
+ if (!$quote->validateMinimumAmount()) {
+ $error = Mage::getStoreConfig('sales/minimum_order/error_message');
+ Mage::throwException($error);
+ }
+ $this->_getCheckoutSession()->setCartWasUpdated(false);
+
+ $this->_checkout = Mage::getSingleton('xmlconnect/paypal_mep_checkout', array('quote' => $quote));
+ }
+
+ /**
+ * Return checkout session object
+ *
+ * @return Mage_Checkout_Model_Session
+ */
+ protected function _getCheckoutSession()
+ {
+ return Mage::getSingleton('checkout/session');
+ }
+
+ /**
+ * Return checkout quote object
+ *
+ * @return Mage_Sale_Model_Quote
+ */
+ protected function _getQuote()
+ {
+ if (!$this->_quote) {
+ $this->_quote = $this->_getCheckoutSession()->getQuote();
+ }
+ return $this->_quote;
+ }
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/controllers/WishlistController.php b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/WishlistController.php
new file mode 100644
index 0000000000..1986c84aba
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/controllers/WishlistController.php
@@ -0,0 +1,294 @@
+
+ */
+
+class Mage_XmlConnect_WishlistController extends Mage_XmlConnect_Controller_Action
+{
+
+ /**
+ * Check if customer is logged in
+ *
+ * @return void
+ */
+ public function preDispatch()
+ {
+ parent::preDispatch();
+ if (!$this->_getCustomerSession()->isLoggedIn()) {
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
+ $this->_message(Mage::helper('xmlconnect')->__('Customer not logged in.'), self::MESSAGE_STATUS_ERROR);
+ return ;
+ }
+ }
+
+ /**
+ * Get customer session model
+ *
+ * @return Mage_Customer_Model_Session
+ */
+ protected function _getCustomerSession()
+ {
+ return Mage::getSingleton('customer/session');
+ }
+
+ /**
+ * Retrieve wishlist object
+ *
+ * @return Mage_Wishlist_Model_Wishlist|false
+ */
+ protected function _getWishlist()
+ {
+ try {
+ $wishlist = Mage::getModel('wishlist/wishlist')
+ ->loadByCustomer($this->_getCustomerSession()->getCustomer(), true);
+ Mage::register('wishlist', $wishlist);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ return false;
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t create wishlist.'), self::MESSAGE_STATUS_ERROR);
+ return false;
+ }
+ return $wishlist;
+ }
+
+ /**
+ * Display customer wishlist
+ */
+ public function indexAction()
+ {
+ $this->_getWishlist();
+ $this->loadLayout(false);
+ $this->renderLayout();
+ }
+
+ /**
+ * Adding new item
+ */
+ public function addAction()
+ {
+ $session = $this->_getCustomerSession();
+ $wishlist = $this->_getWishlist();
+ if (!$wishlist) {
+ return;
+ }
+
+ $request = $this->getRequest();
+ $productId = (int)$request->getParam('product');
+ if (!$productId) {
+ $this->_message(Mage::helper('xmlconnect')->__('Product was not specified.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ $product = Mage::getModel('catalog/product')->load($productId);
+ if (!$product->getId() || !$product->isVisibleInCatalog()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t specify product.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ try {
+ $item = $wishlist->addNewItem($product->getId());
+ if (strlen(trim((string)$request->getParam('description')))) {
+ $item->setDescription($request->getParam('description'))
+ ->save();
+ }
+ $wishlist->save();
+
+ Mage::dispatchEvent('wishlist_add_product', array('wishlist'=>$wishlist, 'product'=>$product));
+
+ Mage::helper('wishlist')->calculate();
+
+ $message = Mage::helper('xmlconnect')->__('%1$s has been added to your wishlist.', $product->getName());
+ $this->_message($message, self::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('An error occurred while adding item to wishlist.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Remove item
+ */
+ public function removeAction()
+ {
+ $wishlist = $this->_getWishlist();
+ $id = (int) $this->getRequest()->getParam('item');
+ $item = Mage::getModel('wishlist/item')->load($id);
+
+ if ($item->getWishlistId() == $wishlist->getId()) {
+ try {
+ $item->delete();
+ $wishlist->save();
+ $this->_message(Mage::helper('xmlconnect')->__('Item has been removed from wishlist.'), self::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch(Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('An error occurred while removing item from wishlist.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('Specified item does not exist in wishlist.'), self::MESSAGE_STATUS_ERROR);
+ }
+
+ Mage::helper('wishlist')->calculate();
+ }
+
+ /**
+ * Clear wishlist action
+ */
+ public function clearAction()
+ {
+ $wishlist = $this->_getWishlist();
+ $items = $wishlist->getItemCollection();
+
+ try {
+ foreach ($items as $item) {
+ $item->delete();
+ }
+ $wishlist->save();
+ $this->_message(Mage::helper('xmlconnect')->__('Wishlist has been cleared.'), self::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ } catch(Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('An error occurred while removing items from wishlist.'), self::MESSAGE_STATUS_ERROR);
+ }
+
+ Mage::helper('wishlist')->calculate();
+ }
+
+ /**
+ * Update wishlist item comments
+ */
+ public function updateAction()
+ {
+ $post = $this->getRequest()->getPost();
+ if ($post && isset($post['description']) && is_array($post['description'])) {
+ $wishlist = $this->_getWishlist();
+ if (!$wishlist) {
+ return;
+ }
+ $updatedItems = 0;
+ $problemsFlag = false;
+
+ foreach ($post['description'] as $itemId => $description) {
+ $item = Mage::getModel('wishlist/item')->load($itemId);
+ $description = (string) $description;
+ if ($item->getWishlistId() != $wishlist->getId()) {
+ continue;
+ }
+ try {
+ $item->setDescription($description)
+ ->save();
+ $updatedItems++;
+ } catch (Exception $e) {
+ $problemsFlag = true;
+ }
+ }
+
+ // save wishlist model for setting date of last update
+ if ($updatedItems) {
+ try {
+ $wishlist->save();
+ if ($problemsFlag) {
+ $message = Mage::helper('xmlconnect')->__('Wishlist has been updated. But there are accrued some errors while updating some items.');
+ } else {
+ $message = Mage::helper('xmlconnect')->__('Wishlist has been updated.');
+ }
+ $this->_message($message, self::MESSAGE_STATUS_SUCCESS);
+ }
+ catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Items were updated. But can\'t update wishlist.'), self::MESSAGE_STATUS_SUCCESS);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('No items were updated.'), self::MESSAGE_STATUS_ERROR);
+ }
+ } else {
+ $this->_message(Mage::helper('xmlconnect')->__('No items were specifed to update.'), self::MESSAGE_STATUS_ERROR);
+ }
+ }
+
+ /**
+ * Add wishlist item to shopping cart and remove from wishlist
+ *
+ * If Product has required options - item removed from wishlist and redirect
+ * to product view page with message about needed defined required options
+ *
+ */
+ public function cartAction()
+ {
+ $wishlist = $this->_getWishlist();
+ if (!$wishlist) {
+ return;
+ }
+ $itemId = (int)$this->getRequest()->getParam('item');
+
+ /* @var $item Mage_Wishlist_Model_Item */
+ $item = Mage::getModel('wishlist/item')->load($itemId);
+
+ if (!$item->getId() || $item->getWishlistId() != $wishlist->getId()) {
+ $this->_message(Mage::helper('xmlconnect')->__('Invalid item or wishlist.'), self::MESSAGE_STATUS_ERROR);
+ return;
+ }
+
+ /* @var $session Mage_Wishlist_Model_Session */
+ $session = Mage::getSingleton('wishlist/session');
+ $cart = Mage::getSingleton('checkout/cart');
+
+ try {
+ $item->addToCart($cart, true);
+ $cart->save()->getQuote()->collectTotals();
+ $wishlist->save();
+
+ Mage::helper('wishlist')->calculate();
+
+ $this->_message(Mage::helper('xmlconnect')->__('Item has been added to cart.'), self::MESSAGE_STATUS_SUCCESS);
+ } catch (Mage_Core_Exception $e) {
+ if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_NOT_SALABLE) {
+ $this->_message(Mage::helper('xmlconnect')->__('Product(s) currently out of stock.'), self::MESSAGE_STATUS_ERROR);
+ } else if ($e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_HAS_REQUIRED_OPTIONS ||
+ $e->getCode() == Mage_Wishlist_Model_Item::EXCEPTION_CODE_IS_GROUPED_PRODUCT) {
+ $item->delete();
+
+ $message = new Mage_XmlConnect_Model_Simplexml_Element(' ');
+ $message->addChild('status', self::MESSAGE_STATUS_SUCCESS);
+ $message->addChild('has_required_options', 1);
+ $message->addChild('product_id', $item->getProductId());
+ $this->getResponse()->setBody($message->asNiceXml());
+ } else {
+ $this->_message($e->getMessage(), self::MESSAGE_STATUS_ERROR);
+ }
+ } catch (Exception $e) {
+ $this->_message(Mage::helper('xmlconnect')->__('Can\'t add item to shopping cart.'), self::MESSAGE_STATUS_ERROR);
+ }
+
+ Mage::helper('wishlist')->calculate();
+ }
+
+}
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/adminhtml.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/adminhtml.xml
new file mode 100644
index 0000000000..ce9192bc6b
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/adminhtml.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ Mobile
+ 35
+
+
+ Manage Apps
+ 10
+ adminhtml/mobile
+
+
+ Submission History
+ 20
+ adminhtml/mobile/history
+
+
+
+
+
+
+
+
+
+ Mobile
+ 100
+
+
+ Manage Apps
+ 10
+
+
+ Submission History
+ 20
+
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/config.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/config.xml
new file mode 100644
index 0000000000..28a67a2846
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/config.xml
@@ -0,0 +1,299 @@
+
+
+
+
+
+ 1.4.0.8
+
+
+
+
+
+ Mage_XmlConnect_Model
+ xmlconnect_mysql4
+
+
+ Mage_XmlConnect_Model_Mysql4
+
+
+
+
+
+
+
+
+
+ Mage_XmlConnect_Block
+
+
+
+
+ Mage_XmlConnect_Helper
+
+
+
+
+
+ Mage_XmlConnect
+ Mage_XmlConnect_Model_Mysql4_Setup
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Mage_XmlConnect_Adminhtml
+
+
+
+
+
+
+
+
+
+ xmlconnect.xml
+
+
+
+
+
+
+
+ Mage_XmlConnect.csv
+
+
+
+
+
+
+
+
+ xmlconnect/observer
+ changeUpdatedAtParamOnConfigSave
+
+
+
+
+
+
+
+
+ standard
+
+ Mage_XmlConnect
+ xmlconnect
+
+
+
+
+
+
+ xmlconnect.xml
+
+
+
+
+
+
+
+ Mage_XmlConnect.csv
+
+
+
+
+
+
+
+
+ 1
+ xmlconnect/payment_method_paypal_mep
+ PayPal Mobile Payments Library
+ 0
+ paypal
+
+
+
+
+
+
+ 70
+ 130
+ 80
+ 280
+ 40
+
+
+
+
+ 150 35
+
+
+ 320 40
+
+
+ 35
+ 35
+ 35
+ 35
+ 35
+
+
+ 320 230
+ 90 120
+ 320 367
+ 320 90
+ 30 90
+ 136 28
+ 107 37
+ 320 37
+
+
+ 320 20
+
+
+ 320 90
+ 40 40
+ 40 40
+ 40 40
+ 40 40
+ 40 40
+ 20 20
+ 20 20
+ 20 20
+ 20 20
+
+
+
+ 512 512
+ 320 460
+ 57 57
+ 100 100
+
+
+
+ <_320x480>
+
+ default
+
+
+ default
+
+
+ interface/native/tabBar
+ zoom
+ 1.02857
+
+
+
+
+ default
+
+
+ interface/native/tabBar
+
+ zoom
+ 1.31428
+
+
+
+
+ default
+
+
+ interface/native/tabBar
+
+ zoom
+ 2.05714
+
+
+
+
+
+ <_640x960>
+
+ default
+
+
+ /
+ zoom
+ 2.0
+
+
+
+
+
+
+
+ www.magentocommerce.com/mobile/activate/
+ http://www.magentocommerce.com/product/mobile
+ http://www.magentocommerce.com/product/mobile#resubmission
+
+
+
+ 5
+
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/system.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/system.xml
new file mode 100644
index 0000000000..48b396ecab
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/system.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ xmlconnect/adminhtml_system_config_backend_baseurl
+
+
+
+
+
+
+
+
+
+
+ xmlconnect/adminhtml_system_config_backend_currency_default
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/custom.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/custom.xml
new file mode 100644
index 0000000000..8a7cd4c196
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/custom.xml
@@ -0,0 +1,34 @@
+
+
+
+
+ custom
+ Custom Colors
+ 1.0
+ 1.4.0.2
+ #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00 #0FDE00
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/default.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/default.xml
new file mode 100644
index 0000000000..2d9b55d174
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/default.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+ default
+ Default Theme
+ 1.0
+ 1.4.0.2
+
+
+
+
+#363D40
+
+
+#A8A8A8
+#E76E01
+#ABABAB
+#EDEDED
+
+
+#D13B00
+#F3F3F3
+
+
+#F3F3F3
+
+
+
+
+
+#222222
+#FFFFFF
+#D55000
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/funk_leaf.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/funk_leaf.xml
new file mode 100644
index 0000000000..e167c1dd2a
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/funk_leaf.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+ funk_leaf
+ Funk Leaf
+ 1.0
+ 1.4.0.2
+
+
+
+
+#024800
+
+
+#ABABAB
+#7CD500
+#8CDE9C
+#FFFFFF
+
+
+#566101
+#FFFFFF
+
+
+#FFFFFF
+
+
+
+
+
+#222222
+#3E3F3F
+#025600
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/hot_red.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/hot_red.xml
new file mode 100644
index 0000000000..75be7bfc17
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/hot_red.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+ hot_red
+ Hot Red
+ 1.0
+ 1.4.0.2
+
+
+
+
+#C91E00
+
+
+#A8A8A8
+#C92B01
+#FFFFFF
+#FFFFFF
+
+
+#A32301
+#FFFFFF
+
+
+#E00000
+
+
+
+
+
+#222222
+#FFFFFF
+#CA1800
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/sky_blue.xml b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/sky_blue.xml
new file mode 100644
index 0000000000..27dec5ab5f
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/etc/themes/sky_blue.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+ sky_blue
+ Sky Blue
+ 1.0
+ 1.4.0.2
+
+
+
+
+#4B7282
+
+
+#ABABAB
+#B7D0DA
+#FFFFFF
+#FFFFFF
+
+
+#2C434D
+#FFFFFF
+
+
+#FFFFFF
+
+
+
+
+
+#222222
+#FFFFFF
+#406474
+
+
+
+
diff --git a/app/code/core/Mage/XmlConnect/XmlConnect/sql/xmlconnect_setup/mysql4-install-1.4.0.8.php b/app/code/core/Mage/XmlConnect/XmlConnect/sql/xmlconnect_setup/mysql4-install-1.4.0.8.php
new file mode 100644
index 0000000000..c34bba35af
--- /dev/null
+++ b/app/code/core/Mage/XmlConnect/XmlConnect/sql/xmlconnect_setup/mysql4-install-1.4.0.8.php
@@ -0,0 +1,97 @@
+startSetup();
+
+$installer->run("
+CREATE TABLE IF NOT EXISTS `{$installer->getTable('xmlconnect_application')}` (
+ `application_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `code` varchar(32) NOT NULL,
+ `type` varchar(32) DEFAULT NULL,
+ `store_id` smallint(5) unsigned DEFAULT NULL,
+ `active_from` date DEFAULT NULL,
+ `active_to` date DEFAULT NULL,
+ `updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `configuration` blob,
+ `status` tinyint(1) NOT NULL DEFAULT '0',
+ `browsing_mode` tinyint(1) DEFAULT '0',
+ PRIMARY KEY (`application_id`),
+ UNIQUE KEY `UNQ_XMLCONNECT_APPLICATION_CODE` (`code`),
+ KEY `FK_XMLCONNECT_APPLICAION_STORE` (`store_id`),
+ CONSTRAINT `FK_XMLCONNECT_APPLICAION_STORE` FOREIGN KEY (`store_id`) REFERENCES `{$installer->getTable('core_store')}` (`store_id`) ON DELETE SET NULL ON UPDATE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+CREATE TABLE IF NOT EXISTS `{$installer->getTable('xmlconnect_history')}` (
+ `history_id` int(11) NOT NULL AUTO_INCREMENT,
+ `application_id` smallint(5) unsigned NOT NULL,
+ `created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `store_id` smallint(5) unsigned DEFAULT NULL,
+ `params` blob,
+ `title` varchar(200) DEFAULT NULL,
+ `activation_key` varchar(255) NOT NULL,
+ `code` varchar(255) NOT NULL,
+ PRIMARY KEY (`history_id`),
+ KEY `FK_XMLCONNECT_HISTORY_APPLICATION` (`application_id`),
+ CONSTRAINT `FK_XMLCONNECT_HISTORY_APPLICATION` FOREIGN KEY (`application_id`) REFERENCES `{$installer->getTable('xmlconnect_application')}` (`application_id`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+");
+
+$entityTypeId = $installer->getEntityTypeId('catalog_category');
+$attributeSetId = $installer->getDefaultAttributeSetId($entityTypeId);
+$attributeGroupId = $installer->getDefaultAttributeGroupId($entityTypeId, $attributeSetId);
+
+$installer->addAttribute('catalog_category', 'thumbnail', array(
+ 'type' => 'varchar',
+ 'backend' => 'catalog/category_attribute_backend_image',
+ 'frontend' => '',
+ 'label' => 'Thumbnail Image',
+ 'input' => 'image',
+ 'class' => '',
+ 'source' => '',
+ 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
+ 'visible' => true,
+ 'required' => false,
+ 'user_defined' => false,
+ 'default' => '',
+ 'searchable' => false,
+ 'filterable' => false,
+ 'comparable' => false,
+ 'visible_on_front' => false,
+ 'unique' => false,
+));
+
+$installer->addAttributeToGroup(
+ $entityTypeId,
+ $attributeSetId,
+ $attributeGroupId,
+ 'thumbnail',
+ '4'
+);
+
+$installer->endSetup();
diff --git a/app/design/adminhtml/default/default/layout/authorizenet.xml b/app/design/adminhtml/default/default/layout/authorizenet.xml
new file mode 100644
index 0000000000..11e8f64531
--- /dev/null
+++ b/app/design/adminhtml/default/default/layout/authorizenet.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+ mage/directpost.js
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/bundle.xml b/app/design/adminhtml/default/default/layout/bundle.xml
index c7423dac4b..2b4b8c5138 100644
--- a/app/design/adminhtml/default/default/layout/bundle.xml
+++ b/app/design/adminhtml/default/default/layout/bundle.xml
@@ -98,5 +98,21 @@ Layout handle for budle products
bundle bundle/adminhtml_sales_order_items_renderer bundle/sales/creditmemo/view/items/renderer.phtml
+
+
+
+ bundle bundle/catalog_product_configuration
+
+
+
+
+
+ select bundle/adminhtml_catalog_product_composite_fieldset_options_type_select
+ multi bundle/adminhtml_catalog_product_composite_fieldset_options_type_multi
+ radio bundle/adminhtml_catalog_product_composite_fieldset_options_type_radio
+ checkbox bundle/adminhtml_catalog_product_composite_fieldset_options_type_checkbox
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/catalog.xml b/app/design/adminhtml/default/default/layout/catalog.xml
index 62845d3cd2..30e26ded1b 100644
--- a/app/design/adminhtml/default/default/layout/catalog.xml
+++ b/app/design/adminhtml/default/default/layout/catalog.xml
@@ -66,6 +66,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -240,4 +276,39 @@ Layout handle for configurable products
+
+
+
+ text catalog/product_view_options_type_text catalog/product/composite/fieldset/options/type/text.phtml
+ file catalog/product_view_options_type_file catalog/product/composite/fieldset/options/type/file.phtml
+ select catalog/product_view_options_type_select catalog/product/composite/fieldset/options/type/select.phtml
+ date catalog/product_view_options_type_date catalog/product/composite/fieldset/options/type/date.phtml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/compiler.xml b/app/design/adminhtml/default/default/layout/compiler.xml
index 81a0692fa4..942468ef32 100644
--- a/app/design/adminhtml/default/default/layout/compiler.xml
+++ b/app/design/adminhtml/default/default/layout/compiler.xml
@@ -27,9 +27,9 @@
-->
-
+
-
+
diff --git a/app/design/adminhtml/default/default/layout/connect.xml b/app/design/adminhtml/default/default/layout/connect.xml
new file mode 100644
index 0000000000..1b63ada8f9
--- /dev/null
+++ b/app/design/adminhtml/default/default/layout/connect.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ package_info tab_package
+ release_info tab_release
+ authors tab_authors
+ dependencies tab_depends
+ contents tab_contents
+ load_local_package tab_local
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/customer.xml b/app/design/adminhtml/default/default/layout/customer.xml
index 9a5b08b36c..91c9ff0702 100644
--- a/app/design/adminhtml/default/default/layout/customer.xml
+++ b/app/design/adminhtml/default/default/layout/customer.xml
@@ -33,6 +33,11 @@
+ mage/adminhtml/product/composite/configure.js
+ varien/configurable.js
+
+
+
@@ -52,4 +57,7 @@
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/dataflow.xml b/app/design/adminhtml/default/default/layout/dataflow.xml
index 004c22e6aa..1dfae43002 100644
--- a/app/design/adminhtml/default/default/layout/dataflow.xml
+++ b/app/design/adminhtml/default/default/layout/dataflow.xml
@@ -29,7 +29,7 @@
-
+
@@ -41,6 +41,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/app/design/adminhtml/default/default/layout/downloadable.xml b/app/design/adminhtml/default/default/layout/downloadable.xml
index 7a7b0d3ad0..885e4d6522 100644
--- a/app/design/adminhtml/default/default/layout/downloadable.xml
+++ b/app/design/adminhtml/default/default/layout/downloadable.xml
@@ -82,5 +82,16 @@
downloadable downloadable/adminhtml_sales_items_column_downloadable_name downloadable/sales/items/column/downloadable/creditmemo/name.phtml
-
+
+
+
+ downloadable downloadable/catalog_product_configuration
+
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/giftmessage.xml b/app/design/adminhtml/default/default/layout/giftmessage.xml
new file mode 100644
index 0000000000..12ca9f5479
--- /dev/null
+++ b/app/design/adminhtml/default/default/layout/giftmessage.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/importexport.xml b/app/design/adminhtml/default/default/layout/importexport.xml
new file mode 100644
index 0000000000..d7fe41c19c
--- /dev/null
+++ b/app/design/adminhtml/default/default/layout/importexport.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/newsletter.xml b/app/design/adminhtml/default/default/layout/newsletter.xml
index b85db7ffc0..80c90e996e 100644
--- a/app/design/adminhtml/default/default/layout/newsletter.xml
+++ b/app/design/adminhtml/default/default/layout/newsletter.xml
@@ -37,20 +37,30 @@
-
-
-
+
-
+
+
+
+ newsletter/preview/iframeswitcher.phtml
+
+
+
+
+
- newsletter/template/preview/iframeswitcher.phtml
+ newsletter/preview/iframeswitcher.phtml
-
+
-
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/layout/sales.xml b/app/design/adminhtml/default/default/layout/sales.xml
index 04612f924e..87759d8c37 100644
--- a/app/design/adminhtml/default/default/layout/sales.xml
+++ b/app/design/adminhtml/default/default/layout/sales.xml
@@ -73,6 +73,11 @@
+
+ mage/adminhtml/giftmessage.js
+ mage/adminhtml/giftoptions.js
+ mage/adminhtml/giftoptions/tooltip.js
+
@@ -86,10 +91,16 @@
qty adminhtml/sales_items_column_qty sales/items/column/qty.phtml
name adminhtml/sales_items_column_name sales/items/column/name.phtml
name adminhtml/sales_items_column_name_grouped sales/items/column/name.phtml grouped
+
+
+
+
-
+
+
+
+
+
+
+
+ xmlconnect/boxes.css
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ images accordion_images
+ themes accordion_themes
+ tabs accordion_tabs
+
+
+
+
+
+
+
+
+ general_section mobile_edit_tab_general
+ design_section mobile_edit_tab_design
+ content_section mobile_edit_tab_content
+ payment_methods mobile_edit_tab_payment
+ history_grid mobile_edit_tab_submission_history_grid
+
+
+
+
+
+
+ xmlconnect/dropdown.css
+ xmlconnect/styles.css
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ submission_section mobile_submission_tab_container
+
+
+
+
+
+
+ xmlconnect/styles.css
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/api/role_users_grid_js.phtml b/app/design/adminhtml/default/default/template/api/role_users_grid_js.phtml
index 712cce5f85..edc3498994 100644
--- a/app/design/adminhtml/default/default/template/api/role_users_grid_js.phtml
+++ b/app/design/adminhtml/default/default/template/api/role_users_grid_js.phtml
@@ -36,9 +36,9 @@
function registerUserRole(grid, element, checked){
if(checked){
- inRoleUsers[element.value] = 0;
+ inRoleUsers.set(element.value, 0);
} else {
- inRoleUsers.remove(element.value);
+ inRoleUsers.unset(element.value);
}
$('in_role_user').value = inRoleUsers.toQueryString();
grid.reloadParams = {'in_role_user[]':inRoleUsers.keys()};
@@ -54,11 +54,11 @@
if (warning && checkBoxes.size() > 0) {
if ( !confirm("__('Warning!\r\nThis action will remove this user from already assigned role\r\nAre you sure?') ?>") ) {
checkbox[0].checked = false;
- for(i in checkBoxes) {
- if( checkBoxes[i].status == 1) {
- checkBoxes[i].object.checked = true;
+ checkBoxes.each(function(elem) {
+ if (elem.value.status == 1) {
+ elem.value.object.checked = true;
}
- }
+ });
return false;
}
warning = false;
@@ -71,25 +71,27 @@
function roleUsersRowInit(grid, row){
var checkbox = $(row).getElementsByClassName('checkbox')[0];
if (checkbox) {
- checkBoxes[checkbox.value] = {'status' : ((checkbox.checked) ? 1 : 0), 'object' : checkbox};
+ checkBoxes.set(checkbox.value, {'status' : ((checkbox.checked) ? 1 : 0), 'object' : checkbox});
}
}
- function myhandler(o)
+ function myhandler(obj)
{
if (checkBoxes.size() > 0) {
if ( !confirm("__('Warning!\r\nThis action will remove those users from already assigned roles\r\nAre you sure?') ?>") ) {
- o.checked = false;
- for(i in checkBoxes) {
- if( checkBoxes[i].status == 1) {
- checkBoxes[i].object.checked = true;
+ obj.checked = false;
+ checkBoxes.each(function(elem) {
+ if (elem.value.status == 1) {
+ elem.value.object.checked = true;
}
- }
+ });
return false;
}
warning = false;
}
- for(i in checkBoxes) getJsObjectName() ?>.setCheckboxChecked(checkBoxes[i].object, o.checked);
+ checkBoxes.each(function(elem) {
+ getJsObjectName() ?>.setCheckboxChecked(elem.value.object, obj.checked);
+ });
}
getJsObjectName() ?>.rowClickCallback = roleUsersRowClick;
diff --git a/app/design/adminhtml/default/default/template/authorizenet/directpost/iframe.phtml b/app/design/adminhtml/default/default/template/authorizenet/directpost/iframe.phtml
new file mode 100644
index 0000000000..b548da0537
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/authorizenet/directpost/iframe.phtml
@@ -0,0 +1,55 @@
+
+getParams();
+$_helper = $this->helper('authorizenet');
+?>
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/authorizenet/directpost/info.phtml b/app/design/adminhtml/default/default/template/authorizenet/directpost/info.phtml
new file mode 100644
index 0000000000..3c3def13b3
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/authorizenet/directpost/info.phtml
@@ -0,0 +1,157 @@
+
+getMethodCode();
+$_method = $_form->getMethod();
+$_controller = $this->helper('authorizenet')->getControllerName();
+$_orderUrl = $this->helper('authorizenet')->getPlaceOrderAdminUrl();
+?>
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/bundle.phtml b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/bundle.phtml
new file mode 100644
index 0000000000..e7b531e1be
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/bundle.phtml
@@ -0,0 +1,99 @@
+
+
+
+decorateArray($this->getOptions()); ?>
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/checkbox.phtml b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/checkbox.phtml
new file mode 100644
index 0000000000..cd4c566098
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/checkbox.phtml
@@ -0,0 +1,51 @@
+
+
+getOption(); ?>
+getSelections(); ?>
+getRequired()) echo ' class="required"' ?>>getRequired()) echo '* ' ?>htmlEscape($_option->getTitle()) ?>
+decoratedIsLast){?> class="last">
+
+
diff --git a/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/multi.phtml b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/multi.phtml
new file mode 100644
index 0000000000..0c248eb0a0
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/multi.phtml
@@ -0,0 +1,48 @@
+
+
+getOption(); ?>
+getSelections(); ?>
+getRequired()) echo ' class="required"' ?>>getRequired()) echo '* ' ?>htmlEscape($_option->getTitle()) ?>
+decoratedIsLast){?> class="last">
+
+ getRequired()): ?>
+ getSelectionQtyTitlePrice($_selections[0]) ?>
+
+
+
+ getRequired()): ?>
+ __('None') ?>
+
+
+ _isSelected($_selection)) echo ' selected="selected"' ?>isSaleable()) echo ' disabled="disabled"' ?>>getSelectionQtyTitlePrice($_selection, false) ?>
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/radio.phtml b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/radio.phtml
new file mode 100644
index 0000000000..32e2601656
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/radio.phtml
@@ -0,0 +1,64 @@
+
+
+getOption(); ?>
+getSelections(); ?>
+getDefaultSelection(); ?>
+_getDefaultValues(); ?>
+
+
+
+ __('Qty:') ?> id="bundle-option-getId() ?>-qty-input" class="input-text qty" type="text" name="bundle_option_qty[getId() ?>]" value=""/>
+
+ getRequired()) echo ' class="required"' ?>>getRequired()) echo '* ' ?>htmlEscape($_option->getTitle()) ?>
+
+decoratedIsLast){?> class="last">
+
+
diff --git a/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/select.phtml b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/select.phtml
new file mode 100644
index 0000000000..0f323df6cf
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/bundle/product/composite/fieldset/options/type/select.phtml
@@ -0,0 +1,54 @@
+
+
+getOption(); ?>
+getSelections(); ?>
+getDefaultSelection(); ?>
+_getDefaultValues(); ?>
+
+
+
+ __('Qty:') ?> id="bundle-option-getId() ?>-qty-input" class="input-text qty" type="text" name="bundle_option_qty[getId() ?>]" value=""/>
+
+ getRequired()) echo ' class="required"' ?>>getRequired()) echo '* ' ?>htmlEscape($_option->getTitle()) ?>
+
+decoratedIsLast){?> class="last">
+
+ _showSingle()): ?>
+ getSelectionTitlePrice($_selections[0]) ?>
+
+
+
+ __('Choose a selection...') ?>
+
+ _isSelected($_selection)) echo ' selected="selected"' ?>isSaleable()) echo ' disabled="disabled"' ?>>getSelectionTitlePrice($_selection, false) ?>
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/bundle/sales/order/view/items/renderer.phtml b/app/design/adminhtml/default/default/template/bundle/sales/order/view/items/renderer.phtml
index dadde151e9..22ff296d06 100644
--- a/app/design/adminhtml/default/default/template/bundle/sales/order/view/items/renderer.phtml
+++ b/app/design/adminhtml/default/default/template/bundle/sales/order/view/items/renderer.phtml
@@ -333,7 +333,6 @@
-
@@ -411,53 +410,4 @@
- canDisplayGiftmessage()): ?>
-
-
- canDisplayContainer()): ?>
-
-
-
-
- canDisplayContainer()): ?>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml b/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml
index 708d3d3d9c..f0761e741d 100644
--- a/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml
+++ b/app/design/adminhtml/default/default/template/catalog/category/edit/form.phtml
@@ -169,7 +169,7 @@
var currentNode = tree.getNodeById(categoryId);
if (currentNode) {
- if (params['general[is_active]']) {
+ if (parseInt(params['general[is_active]'])) {
var oldClass = 'no-active-category';
var newClass = 'active-category';
} else {
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/configure.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/configure.phtml
new file mode 100644
index 0000000000..492caede7e
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/configure.phtml
@@ -0,0 +1,54 @@
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/configurable.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/configurable.phtml
new file mode 100644
index 0000000000..9472f9e35e
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/configurable.phtml
@@ -0,0 +1,52 @@
+
+
+
+getProduct(); ?>
+decorateArray($this->getAllowAttributes()); ?>
+isSaleable() && count($_attributes)):?>
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/custom_options.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/custom_options.phtml
new file mode 100644
index 0000000000..7253c5123a
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/custom_options.phtml
@@ -0,0 +1,34 @@
+
+
+
+
__('Custom Options') ?>
+
+
+ Custom Options Fields
+
+
\ No newline at end of file
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/grouped.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/grouped.phtml
new file mode 100644
index 0000000000..33f674956a
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/grouped.phtml
@@ -0,0 +1,93 @@
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options.phtml
new file mode 100644
index 0000000000..e3e94af043
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options.phtml
@@ -0,0 +1,45 @@
+
+
+
+decorateArray($this->getOptions()); ?>
+
+
+getChildHtml('options_js') ?>
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/js.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/js.phtml
new file mode 100644
index 0000000000..447e5c552c
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/js.phtml
@@ -0,0 +1,106 @@
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/date.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/date.phtml
new file mode 100644
index 0000000000..af5f0b3f61
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/date.phtml
@@ -0,0 +1,94 @@
+
+
+getOption(); ?>
+getId(); ?>
+getIsRequire()) echo ' class="required"' ?>>getIsRequire()) echo '* ' ?>escapeHtml($_option->getTitle()) ?>
+ getFormatedPrice() ?>
+decoratedIsLast){?> class="last">
+
+getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE_TIME
+ || $_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE): ?>
+
+ getDateHtml() ?>
+
+ useCalendar()): ?>
+
+
+
+
+
+getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_DATE_TIME
+ || $_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_TIME): ?>
+ getTimeHtml() ?>
+
+
+
+
+
\ No newline at end of file
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/default.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/default.phtml
new file mode 100644
index 0000000000..a86783f878
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/default.phtml
@@ -0,0 +1,31 @@
+
+
+getOption(); ?>
+
+ escapeHtml($option->getTitle()) ?>
+
\ No newline at end of file
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/file.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/file.phtml
new file mode 100644
index 0000000000..101fb5ae2c
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/file.phtml
@@ -0,0 +1,99 @@
+
+getOption(); ?>
+getFileInfo(); ?>
+hasData() ? true : false; ?>
+getId() . '_file'; ?>
+
+
+
+
+
+
+
+getIsRequire()) echo ' class="required"' ?>>getIsRequire()) echo '* ' ?>htmlEscape($_option->getTitle()) ?>
+ getFormatedPrice() ?>
+decoratedIsLast){?> class="last">
+
+ getTitle(); ?>
+
+ __('Change') ?>
+
+
+ __('Delete') ?>
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/select.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/select.phtml
new file mode 100644
index 0000000000..aa2cec0e8e
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/select.phtml
@@ -0,0 +1,39 @@
+
+
+getOption(); ?>
+getIsRequire()) echo ' class="required"' ?>>getIsRequire()) echo '* ' ?>escapeHtml($_option->getTitle()) ?>
+decoratedIsLast){?> class="last">
+
+ getValuesHtml() ?>
+ getIsRequire()): ?>
+ getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_RADIO || $_option->getType() == Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX): ?>
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/text.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/text.phtml
new file mode 100644
index 0000000000..cd5441dda5
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/options/type/text.phtml
@@ -0,0 +1,42 @@
+
+
+getOption(); ?>
+getIsRequire()) echo ' class="required"' ?>>getIsRequire()) echo '* ' ?>escapeHtml($_option->getTitle()) ?>
+ getFormatedPrice() ?>
+decoratedIsLast){?> class="last">
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/qty.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/qty.phtml
new file mode 100644
index 0000000000..8af048b408
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/qty.phtml
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/simple.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/simple.phtml
new file mode 100644
index 0000000000..d1119168e9
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/simple.phtml
@@ -0,0 +1,34 @@
+
+
+
+
__('Simple Product') ?>
+
+
+ Simple Product Fields
+
+
\ No newline at end of file
diff --git a/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/virtual.phtml b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/virtual.phtml
new file mode 100644
index 0000000000..6b86e00aab
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/composite/fieldset/virtual.phtml
@@ -0,0 +1,34 @@
+
+
+
+
__('Virtual Product') ?>
+
+
+ Virtual Product Fields
+
+
\ No newline at end of file
diff --git a/app/design/adminhtml/default/default/template/catalog/product/edit/action/attribute.phtml b/app/design/adminhtml/default/default/template/catalog/product/edit/action/attribute.phtml
index e0053d7d7e..2219c8f596 100644
--- a/app/design/adminhtml/default/default/template/catalog/product/edit/action/attribute.phtml
+++ b/app/design/adminhtml/default/default/template/catalog/product/edit/action/attribute.phtml
@@ -40,5 +40,22 @@
getBlockHtml('formkey')?>
diff --git a/app/design/adminhtml/default/default/template/catalog/product/price.phtml b/app/design/adminhtml/default/default/template/catalog/product/price.phtml
new file mode 100644
index 0000000000..164ba7a70b
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/catalog/product/price.phtml
@@ -0,0 +1,380 @@
+
+
+
+helper('core');
+ $_weeeHelper = $this->helper('weee');
+ $_taxHelper = $this->helper('tax');
+
+ $_product = $this->getProduct();
+ $_id = $_product->getId();
+ $_storeId = $_product->getStoreId();
+ $_website = Mage::app()->getStore($_storeId)->getWebsite();
+
+ $_weeeSeparator = '';
+ $_simplePricesTax = ($_taxHelper->displayPriceIncludingTax() || $_taxHelper->displayBothPrices());
+ $_minimalPriceValue = $_product->getMinimalPrice();
+ $_minimalPrice = $_taxHelper->getPrice($_product, $_minimalPriceValue, $_simplePricesTax);
+?>
+
+
+getPrice($_product, $_minimalPriceValue, $includingTax = null);
+$_inclTax = $_taxHelper->getPrice($_product, $_minimalPriceValue, $includingTax = true);
+?>
+getAmount($_product, null, null, $_website); ?>
+typeOfDisplay($_product, array(1,2,4))): ?>
+ getAmount($_product, null, null, $_website); ?>
+ getProductWeeeAttributesForDisplay($_product); ?>
+
+
+
+getPrice($_product, $_product->getPrice()) ?>
+getPrice($_product, $_product->getPrice(), $_simplePricesTax) ?>
+getPrice($_product, $_product->getFinalPrice()) ?>
+getPrice($_product, $_product->getFinalPrice(), true) ?>
+getPriceDisplayType(); ?>
+
+ displayBothPrices()): ?>
+ typeOfDisplay($_product, 0)): // including ?>
+
+ helper('tax')->__('Excl. Tax:') ?>
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount,true,false) ?>
+
+
+ typeOfDisplay($_product, 1)): // incl. + weee ?>
+
+ helper('tax')->__('Excl. Tax:') ?>
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+ (
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount(), $_storeId, true, true); ?>
+
+
+ )
+
+ typeOfDisplay($_product, 4)): // incl. + weee ?>
+
+ helper('tax')->__('Excl. Tax:') ?>
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+ (
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount()+$_weeeTaxAttribute->getTaxAmount(), $_storeId, true, true); ?>
+
+
+ )
+
+ typeOfDisplay($_product, 2)): // excl. + weee + final ?>
+
+ helper('tax')->__('Excl. Tax:') ?>
+
+ currencyByStore($_price, $_storeId, true, false) ?>
+
+
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount(), $_storeId, true, true); ?>
+
+
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+
+ helper('tax')->__('Excl. Tax:') ?>
+
+ currencyByStore($_price, $_storeId, true, false) ?>
+
+
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax, $_storeId, true, false) ?>
+
+
+
+
+ typeOfDisplay($_product, 0)): // including ?>
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, true) ?>
+
+ typeOfDisplay($_product, 1)): // incl. + weee ?>
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, true) ?>
+
+
(
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount(), $_storeId, true, true); ?>
+
+
+ )
+ typeOfDisplay($_product, 4)): // incl. + weee ?>
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, true) ?>
+
+
(
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount()+$_weeeTaxAttribute->getTaxAmount(), $_storeId, true, true); ?>
+
+
+ )
+ typeOfDisplay($_product, 2)): // excl. + weee + final ?>
+
currencyByStore($_price, $_storeId, true, true) ?>
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount(), $_storeId, true, true); ?>
+
+
+
+ currencyByStore($_price+$_weeeTaxAmount, $_storeId, true, true) ?>
+
+
+
+ currencyByStore($_price, $_storeId, true, true) ?>
+
+
+
+
+ getOriginalAmount($_product); ?>
+
+ typeOfDisplay($_product, 0)): // including ?>
+
+ __('Regular Price:') ?>
+
+ currencyByStore($_regularPrice+$_originalWeeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ displayBothPrices()): ?>
+
+ __('Special Price:') ?>
+
+ __('Excl. Tax:') ?>
+
+ currencyByStore($_finalPrice+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ __('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+
+
+ __('Special Price:') ?>
+
+ currencyByStore($_finalPrice+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+
+ typeOfDisplay($_product, 1)): // incl. + weee ?>
+
+ __('Regular Price:') ?>
+
+ currencyByStore($_regularPrice+$_originalWeeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+
+ __('Special Price:') ?>
+
+ __('Excl. Tax:') ?>
+
+ currencyByStore($_finalPrice+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+ (
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount(), $_storeId, true, true); ?>
+
+
+ )
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ typeOfDisplay($_product, 4)): // incl. + weee ?>
+
+ __('Regular Price:') ?>
+
+ currencyByStore($_regularPrice+$_originalWeeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+
+ __('Special Price:') ?>
+
+ __('Excl. Tax:') ?>
+
+ currencyByStore($_finalPrice+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+ (
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount()+$_weeeTaxAttribute->getTaxAmount(), $_storeId, true, true); ?>
+
+
+ )
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+ typeOfDisplay($_product, 2)): // excl. + weee + final ?>
+
+ __('Regular Price:') ?>
+
+ currencyByStore($_regularPrice, $_storeId, true, false) ?>
+
+
+
+
+ __('Special Price:') ?>
+
+ __('Excl. Tax:') ?>
+
+ currencyByStore($_finalPrice, $_storeId, true, false) ?>
+
+
+
+
+ getName(); ?>: currencyByStore($_weeeTaxAttribute->getAmount(), $_storeId, true, true); ?>
+
+
+
+ __('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax+$_weeeTaxAmount, $_storeId, true, false) ?>
+
+
+
+
+
+ __('Regular Price:') ?>
+
+ currencyByStore($_regularPrice, $_storeId, true, false) ?>
+
+
+
+ displayBothPrices()): ?>
+
+ __('Special Price:') ?>
+
+ __('Excl. Tax:') ?>
+
+ currencyByStore($_finalPrice, $_storeId, true, false) ?>
+
+
+
+ helper('tax')->__('Incl. Tax:') ?>
+
+ currencyByStore($_finalPriceInclTax, $_storeId, true, false) ?>
+
+
+
+
+
+ __('Special Price:') ?>
+
+ currencyByStore($_finalPrice, $_storeId, true, false) ?>
+
+
+
+
+
+
+
+getDisplayMinimalPrice() && $_minimalPriceValue && $_minimalPriceValue < $_product->getFinalPrice()): ?>
+
+
+ typeOfDisplay($_product, array(0, 1, 4))): ?>
+
+
+
+ getUseLinkForAsLowAs()):?>
+
+
+
+
+ __('As low as:') ?>
+
+ currencyByStore($_minimalPriceDisplayValue, $_storeId, true, false) ?>
+
+ getUseLinkForAsLowAs()):?>
+
+
+
+
+getDisplayMinimalPrice() && $_minimalPrice && $_minimalPrice < $_finalPrice): */ ?>
+
diff --git a/app/design/adminhtml/default/default/template/connect/extension/custom/authors.phtml b/app/design/adminhtml/default/default/template/connect/extension/custom/authors.phtml
new file mode 100644
index 0000000000..3f6c30009f
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/connect/extension/custom/authors.phtml
@@ -0,0 +1,91 @@
+
+
+
+
+ getFormHtml() ?>
+
+
+
+
+ __("Authors") ?>
+
+
+
+ __("Name") ?> *
+ __("User") ?> *
+ __("Email") ?> *
+ __("Remove") ?>
+
+
+
+
+
+
+
+ getAddAuthorButtonHtml() ?>
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/connect/extension/custom/contents.phtml b/app/design/adminhtml/default/default/template/connect/extension/custom/contents.phtml
new file mode 100644
index 0000000000..e3827ed91f
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/connect/extension/custom/contents.phtml
@@ -0,0 +1,91 @@
+
+
+
+ getFormHtml() ?>
+
+
+
+
+
+ __("Contents") ?>
+
+
+
diff --git a/app/design/adminhtml/default/default/template/connect/extension/custom/depends.phtml b/app/design/adminhtml/default/default/template/connect/extension/custom/depends.phtml
new file mode 100644
index 0000000000..3be89e3569
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/connect/extension/custom/depends.phtml
@@ -0,0 +1,137 @@
+
+
+ getFormHtml() ?>
+
+
+
+
+
+ __("Packages") ?>
+
+
+
+
+
+
+
+ __("Extensions") ?>
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/extensions/custom/load.phtml b/app/design/adminhtml/default/default/template/connect/extension/custom/load.phtml
similarity index 92%
rename from app/design/adminhtml/default/default/template/extensions/custom/load.phtml
rename to app/design/adminhtml/default/default/template/connect/extension/custom/load.phtml
index 4c81e1b43a..2bb7d06adb 100644
--- a/app/design/adminhtml/default/default/template/extensions/custom/load.phtml
+++ b/app/design/adminhtml/default/default/template/connect/extension/custom/load.phtml
@@ -20,7 +20,7 @@
*
* @category design
* @package default_default
- * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
+ * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
?>
diff --git a/app/design/adminhtml/default/default/template/connect/extension/custom/package.phtml b/app/design/adminhtml/default/default/template/connect/extension/custom/package.phtml
new file mode 100644
index 0000000000..20377a46b4
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/connect/extension/custom/package.phtml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+ getFormHtml() ?>
+
diff --git a/app/design/adminhtml/default/default/template/extensions/custom/release.phtml b/app/design/adminhtml/default/default/template/connect/extension/custom/release.phtml
similarity index 91%
rename from app/design/adminhtml/default/default/template/extensions/custom/release.phtml
rename to app/design/adminhtml/default/default/template/connect/extension/custom/release.phtml
index 6bf7d785b1..47f5c773a5 100644
--- a/app/design/adminhtml/default/default/template/extensions/custom/release.phtml
+++ b/app/design/adminhtml/default/default/template/connect/extension/custom/release.phtml
@@ -20,7 +20,7 @@
*
* @category design
* @package default_default
- * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
+ * @copyright Copyright (c) 2010 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
?>
diff --git a/app/design/adminhtml/default/default/template/customer/edit/addlisttype.phtml b/app/design/adminhtml/default/default/template/customer/edit/addlisttype.phtml
new file mode 100644
index 0000000000..994b07bf52
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/customer/edit/addlisttype.phtml
@@ -0,0 +1,37 @@
+
+
diff --git a/app/design/adminhtml/default/default/template/customer/edit/tab/view/grid/item.phtml b/app/design/adminhtml/default/default/template/customer/edit/tab/view/grid/item.phtml
new file mode 100644
index 0000000000..b99d97955e
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/customer/edit/tab/view/grid/item.phtml
@@ -0,0 +1,46 @@
+
+
+getProduct();
+ $options = $this->getOptionList();
+?>
+
+
+ escapeHtml($product->getName())?>
+
+
+
escapeHtml($product->getName())?>
+
+
+ escapeHtml($option['label']) ?>
+ getFormattedOptionValue($option) ?>
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/customer/tab/addresses.phtml b/app/design/adminhtml/default/default/template/customer/tab/addresses.phtml
index 33d14cb36e..87b17d8f5f 100644
--- a/app/design/adminhtml/default/default/template/customer/tab/addresses.phtml
+++ b/app/design/adminhtml/default/default/template/customer/tab/addresses.phtml
@@ -112,7 +112,7 @@
getFormObject()->setHtmlIdPrefix($_templatePrefix)
- ->setValues(array())
+ ->setValues(array('country_id' => Mage::helper('core')->getDefaultCountry($customer->getStore())))
->setFieldNameSuffix('address['.$_templatePrefix.']');
?>
getFormObject()->getHtml() ?>
@@ -135,6 +135,7 @@ addressesModel.prototype = {
this.formContainer= $('address_form_container');
this.baseItemId = 'new_item';
+ this.defaultCountries = getDefaultCountriesJson(); ?>;
this.itemContentTemplate = new Template('helper('customer/address')->getFormat('js_template')?>');
this.onNewAddressClick = this.addNewAddress.bindAsEventListener(this);
@@ -218,6 +219,10 @@ addressesModel.prototype = {
$('_item'+this.itemCount+'firstname').value = $('_accountfirstname').value;
$('_item'+this.itemCount+'lastname').value = $('_accountlastname').value;
+ if ($('_accountwebsite_id').value !== '' && undefined !== this.defaultCountries[$('_accountwebsite_id').value]) {
+ $('_item'+this.itemCount+'country_id').value = this.defaultCountries[$('_accountwebsite_id').value];
+ }
+
Element.hide(newForm);
var template = '';
deleteButtonId ++;
diff --git a/app/design/adminhtml/default/default/template/customer/tab/cart.phtml b/app/design/adminhtml/default/default/template/customer/tab/cart.phtml
index 8a7bf3dd9a..cc4d682803 100644
--- a/app/design/adminhtml/default/default/template/customer/tab/cart.phtml
+++ b/app/design/adminhtml/default/default/template/customer/tab/cart.phtml
@@ -24,6 +24,7 @@
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
?>
+
getCartHeader()): ?>
-isSingleStoreMode() ): ?>
-getChildHtml('store_switcher');?>
-
getBlockHtml('formkey')?>
@@ -58,25 +56,11 @@
-isSingleStoreMode()): ?>
-
-
+
-
diff --git a/app/design/adminhtml/default/default/template/page/js/translate.phtml b/app/design/adminhtml/default/default/template/page/js/translate.phtml
index 307444bb86..ba0e1257f3 100644
--- a/app/design/adminhtml/default/default/template/page/js/translate.phtml
+++ b/app/design/adminhtml/default/default/template/page/js/translate.phtml
@@ -28,7 +28,7 @@ $_data = array(
'Please select an option.' => $this->__('Please select an option.'),
'This is a required field.' => $this->__('This is a required field.'),
'Please enter a valid number in this field.' => $this->__('Please enter a valid number in this field.'),
- 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.' => $this->__('Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.'),
+ 'Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.' => $this->__('Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.'),
'Please use letters only (a-z) in this field.' => $this->__('Please use letters only (a-z) in this field.'),
'Please use in this field only "a-z,0-9,_".' => $this->__('Please use in this field only "a-z,0-9,_".'),
'Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.' => $this->__('Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed.'),
diff --git a/app/design/adminhtml/default/default/template/paygate/form/cc.phtml b/app/design/adminhtml/default/default/template/paygate/form/cc.phtml
new file mode 100644
index 0000000000..4d5c33d532
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/paygate/form/cc.phtml
@@ -0,0 +1,74 @@
+
+getPartialAuthorizationFormMessage(); ?>
+isPartialAuthorization(); ?>
+
+
+
+getChildHtml('method_form_block') ?>
diff --git a/app/design/adminhtml/default/default/template/paygate/info/cc.phtml b/app/design/adminhtml/default/default/template/paygate/info/cc.phtml
new file mode 100644
index 0000000000..dda250f7e2
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/paygate/info/cc.phtml
@@ -0,0 +1,56 @@
+
+
+getHideTitle()): ?>
+ htmlEscape($this->getMethod()->getTitle()) ?>
+
+
+getCards();
+ $showCount = count($cards) > 1;
+?>
+
+
+ $card): ?>
+
+ __('Credit Card %s'), $key + 1); ?>
+
+
+ class="offset">
+
+
+ $_value):?>
+
+ escapeHtml($_label)?>:
+ getValueAsArray($_value, true), "\n"))?>
+
+
+
+
+
+
+
diff --git a/app/design/adminhtml/default/default/template/paygate/info/pdf.phtml b/app/design/adminhtml/default/default/template/paygate/info/pdf.phtml
new file mode 100644
index 0000000000..e00552d27e
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/paygate/info/pdf.phtml
@@ -0,0 +1,43 @@
+
+
+getCards();
+ $showCount = count($cards) > 1;
+?>
+
+getMethod()->getTitle() ?>{{pdf_row_separator}}
+ $card): ?>
+
+ __('Credit Card %s'), $key + 1); ?>
+ {{pdf_row_separator}}
+
+
+ $_value):?>
+ : getValueAsArray($_value), ' ')?>{{pdf_row_separator}}
+
+
diff --git a/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/global.phtml b/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/global.phtml
index d5c4ae6e4d..2431e36ba8 100644
--- a/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/global.phtml
+++ b/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/global.phtml
@@ -77,6 +77,7 @@ Event.observe(window, 'load', function() {
Element.observe('paypal_account_merchant_country', 'change', pConfig.trackMerchantCountry.bind(pConfig));
Element.observe('paypal_global_wpp', 'click', pConfig.trackWpp.bind(pConfig));
Element.observe('paypal_global_wpp_pe', 'click', pConfig.trackWppPe.bind(pConfig));
+ Element.observe('paypal_global_payflow_link', 'click', pConfig.trackWppPl.bind(pConfig));
Element.observe('paypal_global_verisign', 'click', pConfig.trackPayflowpro.bind(pConfig));
['ec','wps','ecpe'].each(function(m) {
Element.observe(pConfig.getMethodSwitcher(m).id, 'click', pConfig.trackMethod.bind(pConfig, m));
@@ -85,6 +86,7 @@ Event.observe(window, 'load', function() {
pConfig.trackMerchantCountry();
pConfig.trackBusinessAccount();
pConfig.trackWpp();
+ pConfig.trackWppPl();
pConfig.trackWppPe();
pConfig.trackWps();
['ec','wps','ecpe'].each(function(m) {
@@ -103,6 +105,7 @@ PaypalConfig.prototype = {
wps: $H({switcher: 'wps', fieldset: 'wps'}),
wpp: $H({switcher: 'wpp', fieldset: 'wpp'}),
wpppe: $H({switcher: 'wpp_pe', fieldset: 'wpp_pe'}),
+ wpppl: $H({switcher: 'payflow_link', fieldset: 'payflow_link'}),
ecpe: $H({switcher: 'express_pe', fieldset: 'express_pe'}),
payflowpro: $H({switcher: 'verisign', fieldset: 'verisign'})
});
@@ -334,6 +337,11 @@ PaypalConfig.prototype = {
this.trackWps();
},
+ trackWppPl: function()
+ {
+ this.trackMethod('wpppl');
+ },
+
trackPayflowpro: function()
{
this.trackMethod('payflowpro');
@@ -344,7 +352,12 @@ PaypalConfig.prototype = {
{
var wpppeEnabled = this.getMethodSwitcher('wpppe').checked;
if (wpppeEnabled) {
- this.enableMethod('ecpe',true);
+ // Do not enable ecpe based on wpppe state on page load
+ if (!this.fastMode) {
+ this.enableMethod('ecpe',true);
+ } else {
+ this.markMethodAsReadonly('ecpe', true);
+ }
this.disableMethod('ec',true);
return;
} else {
diff --git a/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/store.phtml b/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/store.phtml
new file mode 100644
index 0000000000..5fb0bda4c0
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/paypal/system/config/fieldset/store.phtml
@@ -0,0 +1,99 @@
+
+
+
diff --git a/app/design/adminhtml/default/default/template/paypal/system/config/payflowlink/info.phtml b/app/design/adminhtml/default/default/template/paypal/system/config/payflowlink/info.phtml
new file mode 100644
index 0000000000..ce5b8f3bc6
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/paypal/system/config/payflowlink/info.phtml
@@ -0,0 +1,87 @@
+
+
+
+
__('Important: ') ?>
+ __('To use Payflow Link, you must configure your Payflow Link account on the Paypal website.') ?>
+ __('Once you log into your Payflow Link account, navigate to the Service Settings - Hosted Checkout Pages - Set Up menu and set the options described below') ?>
+
+ __('Required settings') ?>
+ __(' note that the URLs provided below are the correct values for your current website): ') ?>
+
+
+
__('Note:') ?>
+
+
+ __('Do not set any fields in the Billing and Shipping Information block as editable in your Payflow accout.') ?>
+
+
+ __('Do not enable AVS or CSC options. The do not work when using Payflow Link Silent Mode.') ?>
+
+
+ __('If your Magento instance is used for multiple websites, you must configure a separate Payflow Link account for each website.') ?>
+
+
+ __('Make sure that you configure the design settings for the Payflow Link form in your Payflow link account.') ?>
+
+
+
diff --git a/app/design/adminhtml/default/default/template/sales/order/address/form.phtml b/app/design/adminhtml/default/default/template/sales/order/address/form.phtml
new file mode 100644
index 0000000000..9e2cf30148
--- /dev/null
+++ b/app/design/adminhtml/default/default/template/sales/order/address/form.phtml
@@ -0,0 +1,43 @@
+
+
+
+
+
+ __('Changing address information will not recalculate shipping, tax or other order amount.') ?>
+
+
+
+
+
+
+
getHeaderText() ?>
+
+
+ getForm()->toHtml() ?>
+
+
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/data.phtml b/app/design/adminhtml/default/default/template/sales/order/create/data.phtml
index d54dd39e79..73094b8969 100644
--- a/app/design/adminhtml/default/default/template/sales/order/create/data.phtml
+++ b/app/design/adminhtml/default/default/template/sales/order/create/data.phtml
@@ -61,9 +61,8 @@
-
- getChildHtml('giftmessage') ?>
-
+ getChildHtml('gift_options') ?>
+
__('Order History') ?>
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/giftmessage.phtml b/app/design/adminhtml/default/default/template/sales/order/create/giftmessage.phtml
index eb0450c3a8..4eeea016da 100644
--- a/app/design/adminhtml/default/default/template/sales/order/create/giftmessage.phtml
+++ b/app/design/adminhtml/default/default/template/sales/order/create/giftmessage.phtml
@@ -24,36 +24,30 @@
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
?>
+
getItems(); ?>
helper('giftmessage/message')->getIsMessagesAvailable('main', $this->getQuote(), $this->getStoreId()) || $_items): ?>
-
+
-
-
__('Gift Message') ?>
-
+
__('Gift Message for the Entire Order') ?>
-
+
helper('giftmessage/message')->getIsMessagesAvailable('main', $this->getQuote(), $this->getStoreId())): ?>
-
__('Add a gift message for the entire order ') ?>
+ __('You can leave a box blank if you don\'t wish to add a gift message for whole order') ?>
getFormHtml($this->getQuote(), 'main') ?>
-
-
-
-
__('Add a gift message for each gift item ') ?>
-
-
-
getName() ?>
- getFormHtml($_item, 'item'); ?>
-
-
-
-
+
+
+
+
+ getFormHtml($_item, 'item'); ?>
+
+
@@ -62,3 +56,4 @@
order.giftmessageFieldsBind('order-giftmessage');
+
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml b/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml
index f1e2e2c75d..7890336c3d 100644
--- a/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml
+++ b/app/design/adminhtml/default/default/template/sales/order/create/items/grid.phtml
@@ -40,9 +40,6 @@
- isGiftMessagesAvailable()): ?>
-
-
@@ -53,9 +50,6 @@
helper('sales')->__('Discount') ?>
helper('sales')->__('Row Subtotal') ?>
- isGiftMessagesAvailable()): ?>
- helper('sales')->__('Gift') ?>
-
helper('sales')->__('Action') ?>
@@ -77,64 +71,61 @@
-
-
+
+
+
- isGiftMessagesAvailable()): ?>
-
-
- helper('sales')->__('Product') ?>
+ helper('sales')->__('Product') ?>
helper('sales')->__('Price') ?>
helper('sales')->__('Qty') ?>
helper('sales')->__('Subtotal') ?>
helper('sales')->__('Discount') ?>
helper('sales')->__('Row Subtotal') ?>
- isGiftMessagesAvailable()): ?>
- helper('sales')->__('Gift') ?>
-
helper('sales')->__('Action') ?>
- helper('sales')->__('Total %d product(s)', count($_items)) ?>
+ helper('sales')->__('Total %d product(s)', count($_items)) ?>
helper('sales')->__('Subtotal:') ?>
formatPrice($this->getSubtotal()) ?>
formatPrice($this->getDiscountAmount()) ?>
formatPrice($this->getSubtotalWithDiscount()) ?>
- isGiftMessagesAvailable()): ?>colspan="2">
+
-
-
- htmlEscape($_item->getName()) ?>
+
+
+
+ htmlEscape($_item->getName()) ?>
helper('sales')->__('SKU') ?>:
', Mage::helper('catalog')->splitSku($this->htmlEscape($_item->getSku()))); ?>
-
-
- getCustomOptions($_item))): ?>
-
-
-
__('Custom Options') ?>
-
getCustomOptions($_item)): ?>htmlEscape($this->getCustomOptions($_item)) ?>
-
getMessage(false)): ?>
- getMessage(false) as $message): ?>
-
-
+ getHasError()): ?>
+
+
helper('sales')->__('This product has not been configured.') ?>
+
+
+ getMessage(false) as $message): ?>
+
+
+
+
+ getConfigureButtonHtml($_item) ?>
+
@@ -400,11 +391,6 @@
- isGiftMessagesAvailable()): ?>
-
- isAllowedForGiftMessage($_item)): ?> checked="checked"isGiftMessagesAvailable($_item)): ?> disabled="disabled"/>
-
-
@@ -416,8 +402,9 @@
+ getItemExtraInfo($_item)->toHtml(); ?>
+
-
-
getChildHtml() ?>
+
getChildHtml();?>
+
+isGiftMessagesAvailable()) : ?>
+
+
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/js.phtml b/app/design/adminhtml/default/default/template/sales/order/create/js.phtml
index 33b7e2edbe..82789d5990 100644
--- a/app/design/adminhtml/default/default/template/sales/order/create/js.phtml
+++ b/app/design/adminhtml/default/default/template/sales/order/create/js.phtml
@@ -26,4 +26,12 @@
?>
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/sidebar.phtml b/app/design/adminhtml/default/default/template/sales/order/create/sidebar.phtml
index 5920bc62da..f0e1b8929c 100644
--- a/app/design/adminhtml/default/default/template/sales/order/create/sidebar.phtml
+++ b/app/design/adminhtml/default/default/template/sales/order/create/sidebar.phtml
@@ -39,3 +39,27 @@
getChildHtml('bottom_button'); ?>
+
diff --git a/app/design/adminhtml/default/default/template/sales/order/create/sidebar/items.phtml b/app/design/adminhtml/default/default/template/sales/order/create/sidebar/items.phtml
index 324ed84549..2277683463 100644
--- a/app/design/adminhtml/default/default/template/sales/order/create/sidebar/items.phtml
+++ b/app/design/adminhtml/default/default/template/sales/order/create/sidebar/items.phtml
@@ -24,6 +24,7 @@
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
?>
+