diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index de3ea51e0f..b09f515d9a 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -1,3 +1,751 @@
+==== 1.6.1.0 ====
+
+=== Major Highlights ===
+Added two-step password reset flow
+
+=== Improvements ===
+XmlConnect package release v22.0
+Added support for using Shift-Click to select a range of grid rows when clicking check boxes
+Added ability to register during checkout when using PayPal Express
+Updated PayflowLink HSS user interface in checkout
+"Add to Wishlist", "Add to Compare" were added on the Product Details Page for configurable, bundled and downloadable products
+Updated webservices API
+
+=== Changes ===
+TheFind integration was removed
+Google Optimizer was removed (it will be supported as a core extension)
+Improved how discounts are applied to sub products
+
+=== Fixes ===
+Fixed Incorrect tax summary if taxes applied has different priorities
+Fixed Shipping method extension after disable module returns error
+Fixed Approved Review of a product is not displayed in the catalog
+Fixed Special price is not considered for bundle dynamic products in "Your Customization" block
+Fixed Incorrect behavior of changing quantity for composite products in Wishlist tab of customer's page in backend
+Fixed MAP: Exc. Tax. amount is not shown on product's page when set apply map = 'On Gesture'
+Fixed There has been an error processing your request is displayed by searching in Manage Checkout Terms and Conditions
+Fixed Button Reorder is absent when Order contains Configurable product
+Fixed Unable to place order if several tax rates with different priorities applied to bundle product
+Fixed Incorrect Tracking Request to shipping carrier (in case with FedEx)
+Fixed 'Click for price' not clickable after pressing 'Review' link in category
+Fixed XML Connect: Impossible to submit application
+Fixed MAP: with IE8 JS error appears in catalog
+Fixed Error message appears after successful checkout with PayPal Express Checkout on IE9
+Fixed Incorrect invoice document creation behaviour for bundle dynamic product
+Fixed XML Connect: Impossible to save template
+Fixed Wrong focusing in WYSIWYG on IE9, impossible to save data after inserting content
+Fixed Unable to set zero price for item in bundle product
+Fixed Incorrect tax summary if several tax rates with different priorities applied to bundle product
+Fixed Unable to create order from backend if Tax Calculation Method Based On = Unit Price/Row Total
+Fixed Incorrect Tracking Request to shipping carrier (in case with FedEx)
+Fixed Incorrect tax summary for partial documents if Tax Calculation Method Based On = Row Total/Unit Price
+Fixed Problems with partial authorization process (Authorize.net) during Admin Order creation
+Fixed Incorrect HTML markup of Installer page in IE7 and IE9
+Fixed "Apply Rules" button works incorrect in some cases
+Fixed Incorrect behavior of changing quantity for composite products in Wishlist tab of customer's page in backend
+Fixed Incorrect tax summary if product prices exclude tax
+Fixed Redirect to blank page, when click Add Wishlist on the Bundle product page
+Fixed Reviews not showing in category list page
+Fixed QTY is wrong calculated for Bundle, Virtual, Simple, Configurable, Downloadable products after editing them in wishlist
+Fixed Customer is redirected to shopping cart page instead to the "Ship to Multiple Addresses" page after login or register as a new customer
+Fixed Configurable product with selected option is deleted from wishlist after updating another configurable product
+Fixed After redirecting to product using tag 'click for price' doesn't work
+Fixed "Notify for Quantity Below" doesn't work
+Fixed Pending Reviews RSS doesn't show reviews, created for products, that are assigned not to Main Website
+Fixed Authorize Direct Post: no successful notification about place order if do 'Edit' or 'Reorder'
+Fixed Impossible to place Order with Payfowlink when Payment Action = Sale
+Fixed Poll shows incorrect percentage
+Fixed Message 'Cannot specify wishlist item.' is displayed by configuring products in wishlist in back-end
+Fixed Billing Agreements: Order status is not updated if do actions from sandbox PayPal account
+Fixed Additional authorization transaction is not displayed in Order's Transactions tab
+Fixed Unable to update already created role by Admin
+Fixed CDN Secure URL is used instead of non-secure
+Fixed Attributes name disappeared during sorting
+Fixed Typo in app/design/adminhtml/default/default/template/paypal/system/config/payflowlink/info.phtml
+Fixed Report of Reviews shows all customer reviews when select certain user
+Fixed Address Line Formats Incorrectly on PDF Invoices
+Fixed Can't search transactions by order_id in manager.paypal.com
+Fixed Wishlist Index Controller does unneeded logging of exception
+Fixed Incorrect SQL generated in review product collection resource
+Fixed Added shipping address rates collecting schedule for shipping method when shipping information step bypassed
+Fixed Customer marked as guest in "Newsletter Subscribers" grid, after subscribing to newsletters in Google Checkout
+Fixed Error is displayed by unchecking "Same As Billing Address" by creating order in admin
+Fixed Tooltip doesn't appear if you put mouse pointer in to disabled package type field (in case with USPS Domestic)
+Fixed Unable to select custom theme with underscores in name when creating a widget instance
+Fixed When Redirect to Shopping Cart = No, choosing Remove item from shopping cart sidebar while editing an item leads to endless redirect loop
+Fixed Saved CC form is not displayed, when there are no other available payment methods except Saved CC
+Fixed It's impossible to create Catalog Price Rule
+Fixed Fatal error on Multiple Addresses Checkout
+Fixed Package Types that not available for current Shipping Method displayed in Create Packages pop-up
+Fixed Stock item product getter not correspond to product setter
+- added method getProduct()
+Fixed Admin user interface: mistakes in labels names
+Fixed Typo in Mage_Eav_Model_Resource_Entity_Attribute_Option model
+Fixed Billing Agreement error
+Fixed Payflow Link UI Changes
+Fixed 'Website Payments Pro' impossible to place order during onepage checkout
+Fixed Table rates works incorrect with asterisk
+Fixed Typo in Category Resource Model
+Fixed 3D secure with Saved CC works incorrectly
+- removed unrelated message which told validation failed (even if it has actually succeeded) when trying to re-validate a card
+Fixed Bug in Role Permission
+Fixed Orders placed via Google Checkout were not created on the Magento side
+Fixed When using direct Export, the _super_product_sku and _super_product_option on the configurable product does not match
+Fixed Composite product price in grid is displayed incorrectly with some currencies due to JS regexp problem
+Fixed No error message on Payflow link iframe
+Fixed Flex uploader elements overlaps hovering menu items in backend
+Fixed Unable to upload images in Magento installed on local server
+Fixed Configurable Products - Use Default (attribute name) does not work correctly on IE9
+Fixed Capture failed when Verification Authorization Amount is set to Zero
+Fixed Attribute is sorted like a string even when Input Validation for Store Owner is an Integer Number
+Fixed Void and Cancel Order doesn't work (PayflowLink HSS)
+Fixed Grand Total (Excl Tax) with negative value displays in the printed Credit Memo
+Fixed Resource model of Media module is wrongly declared
+Fixed Constraint violation with core_cache_tag table
+Fixed Misprint in \downloader\lib\Mage\Connect\Validator.php
+Fixed XMLRPC API attribute status changing
+Fixed Typo in Mage_Rss_Block_Catalog_Category::_toHtml() method
+Fixed Incorrect tax summary for partial credit memos/invoices
+Fixed SSL is not used for links in email templates when admin area is configured to use HTTPS
+Fixed Incorrect style on product page
+Fixed Error is displayed by editing product or by creating product on back-end in IE8
+Fixed Catalog price rules for composite products changes
+Fixed Moving modules to the correct place
+Fixed Wishlist shows items per store scope, not website
+Fixed Products in Wishlist disappears, when Store View is changed
+Fixed Wrong Comments History in notification of order creation/cancellation
+Fixed In AJAX popup fields "From" and "To" have behavior as mandatory fields
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed Product price lower than 0 (after catalog price rule applying)
+Fixed Google Checkout throws error if Zip Range is used for Tax Rate
+- changed part of XML request to Google responsible for postal codes
+- made changes to correctly fetch tax rules for postal code ranges
+Fixed Website config object is not being cached
+Fixed Select groups in grid view doesn't work under IE7
+Fixed No products name in Popular tags report file .csv
+Fixed Qty Increments should work when it was defined in the default scope configuration
+Fixed Products in catalog displays as "out of stock"
+Fixed "Get help for this page" in each tab under System->Configuration links to the same help page
+Fixed Unable to translate submenu
+Fixed Redirect to main page of front-end during deleting Product Tax Class which is used in Tax Rule
+Fixed Redirect to base URL should consider full request URI string
+Fixed Incorrect transparency of PNG image in indexed non-alpha mode
+Fixed Problem of generation URL between different domains
+Fixed There are no server side validation of first character of Attribute Code (it should be letter)
+Fixed Edit Order without creating new one functionality saves invalid changes in non-default customer address attributes
+Fixed Frontend: If second customer logs in and does not select the "Remember Me" then the previous long-term cookie does not removes
+Fixed Admin can Reorder order with status On Hold
+Fixed Frontend: After new customer registration with "Remember Me" and pressing "Logout" the long-term cookie session doesn't apply if in configuration on backend ""Remember Me" Default Value" - No
+Fixed Tax not displaying on PayPal side for Express orders
+Fixed Wishlist: Not configured grouped product has unneeded link "Show Details"
+Fixed Removed the ability to work with customise admin url through the parameter base_url
+Fixed Roles not displaying selected resources
+Fixed Unable to use Import when compiler is enabled
+Fixed Missing Translation Capability in Transactional Email Variable
+Fixed productConfigure is undefined error is occurred during creation Order in Backend in IE8 browser
+Fixed Zend Full Page Cache. Lifetime of the cookie is not equal to specified on "Cookie Lifetime" field
+Fixed Incorrect price values for Bundle Product
+Fixed Link does not pass validation if ends with .html
+Fixed Incorrect Customs Value in Create Packages in case when price value contains decimals
+Fixed Incorrect reports with updated_at filter
+Fixed paypal_payment_transaction_clean job takes credentials form default config instead of website for Payflow Link
+Fixed Wrong schedule time setup for paypal_payment_transaction_clean job for Payflow Link
+Fixed Backend Error message "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'qwe' for key 2" appears after saving new Email Template with existing name
+Fixed Rule Conditions logic
+Fixed Error appears after Customer Group saving with name length more than 32
+Fixed Category product index run time
+Fixed Sidebar cart is missing composite product options on category page
+Fixed Missed validation for space character at the begin of unique fields
+- improved validation of Attribute Set Name and validation of unique fields in Mage_Core_Model_Resource_Db_Abstract class
+Fixed Ability to input uppercase, space, specials symbols in Order Status Code
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed No ability to create Shipping Label with "plus-four codes" Zip Code (in case with USPS Domestic)
+Fixed Changing language twice -> Error 404
+Fixed The sort order in products page doesn't work
+Fixed When a grouped product with configured price=0 is added to the wishlist and shared, adding the product to the cart leads to 404 error
+Fixed Media Saves Incorrect Cached Config
+- added options that disallow saving cache
+Fixed Bundle Product items shows randomly instead of according to option
+Fixed Ajax loader does not appears after click on Verify Card on Payflow Link
+Fixed "Google Checkout - Carrier" in Magento backend as shipping method rather than the actual shipping method chosen
+Fixed JavaScript error appears in checkout because of PSC after press 'Proceed to Checkout'
+Fixed Admin user interface: mistakes in labels names
+Fixed Problems with grid sorting on edit customer backend page
+Fixed It is possible to change the price of the Bundle product from fixed to the dynamic at my store
+Fixed Set special price via Catalog Product API is not working
+Fixed Price is wrong calculated for bundle product with a zero price for its items on product details page
+- subitem price calculation were fixed
+Fixed Layout issue appears in IE9 on the grids (example Customers)
+Fixed Impossible to press 'Continue' button to place in onepage
+Fixed "Add to Wishlist", "Add to Compare" aren't presented for Configurable, bundle, downloadable, simple products on Product Details Page
+Fixed Register during checkout with PayPal Express Checkout
+Fixed Extension Packager does not read recursive directory if include expression use file mask
+Fixed Newsletter Subscription Confirmation Message
+Fixed Discount is wrong calculated for Shopping Cart Price Rules when some of them created with Coupon and another without Coupon
+Fixed Subtotal (Incl.Tax) on invoices must not include tax applied to shipping amount
+- shippingTax amount were excluded from subTotal value
+Fixed "Maximum shipping amount allowed to refund" message shows amount excl. tax if Display Shipping Amount set to Including Tax
+- adjusted function to include tax into allowed amount for shipping refund
+Fixed Display Out of Stock Products must not be considered during admin order creation
+Fixed Check box is not working correctly under "prices" of the Bundle products
+Fixed CSS class missing
+Fixed Frontend: JavaScript error appears if user registered on Checkout Page
+Fixed Website config object is not being cached
+- added functionality for memcache backend to split down data that is larger than slab size into chunks
+Fixed Removed the ability to work with base_url
+Fixed Custom design should be updated via import functionality
+Fixed JS error during onepage checkout
+Fixed Unable to translate "First name" and "Last name" fields on "Create an Account" page
+Fixed After upgrading dashboard "Top 5 Search Terms" grid doesn't show search terms
+
+
+
+==== 1.6.1.0-rc1 ====
+
+=== Major Highlights ===
+Added two-step password reset flow
+
+=== Improvements ===
+XmlConnect package release v22.0
+Added support for using Shift-Click to select a range of grid rows when clicking check boxes
+Added ability to register during checkout when using PayPal Express
+Updated PayflowLink HSS user interface in checkout
+"Add to Wishlist", "Add to Compare" were added on the Product Details Page for configurable, bundled and downloadable products
+
+=== Changes ===
+TheFind integration was removed
+Google Optimizer was removed (it will be supported as a core extension)
+Improved how discounts are applied to sub products
+
+=== Fixes ===
+Fixed Incorrect behavior of changing quantity for composite products in Wishlist tab of customer's page in backend
+Fixed Incorrect tax summary if product prices exclude tax
+Fixed Redirect to blank page, when click Add Wishlist on the Bundle product page
+Fixed Reviews not showing in category list page
+Fixed QTY is wrong calculated for Bundle, Virtual, Simple, Configurable, Downloadable products after editing them in wishlist
+Fixed Customer is redirected to shopping cart page instead to the "Ship to Multiple Addresses" page after login or register as a new customer
+Fixed Configurable product with selected option is deleted from wishlist after updating another configurable product
+Fixed After redirecting to product using tag 'click for price' doesn't work
+Fixed "Notify for Quantity Below" doesn't work
+Fixed Pending Reviews RSS doesn't show reviews, created for products, that are assigned not to Main Website
+Fixed Authorize Direct Post: no successful notification about place order if do 'Edit' or 'Reorder'
+Fixed Impossible to place Order with Payfowlink when Payment Action = Sale
+Fixed Poll shows incorrect percentage
+Fixed Message 'Cannot specify wishlist item.' is displayed by configuring products in wishlist in back-end
+Fixed Billing Agreements: Order status is not updated if do actions from sandbox PayPal account
+Fixed Additional authorization transaction is not displayed in Order's Transactions tab
+Fixed Unable to update already created role by Admin
+Fixed CDN Secure URL is used instead of non-secure
+Fixed Attributes name disappeared during sorting
+Fixed Typo in app/design/adminhtml/default/default/template/paypal/system/config/payflowlink/info.phtml
+Fixed Report of Reviews shows all customer reviews when select certain user
+Fixed Address Line Formats Incorrectly on PDF Invoices
+Fixed Can't search transactions by order_id in manager.paypal.com
+Fixed Wishlist Index Controller does unneeded logging of exception
+Fixed Incorrect SQL generated in review product collection resource
+Fixed Added shipping address rates collecting schedule for shipping method when shipping information step bypassed
+Fixed Customer marked as guest in "Newsletter Subscribers" grid, after subscribing to newsletters in Google Checkout
+Fixed Error is displayed by unchecking "Same As Billing Address" by creating order in admin
+Fixed Tooltip doesn't appear if you put mouse pointer in to disabled package type field (in case with USPS Domestic)
+Fixed Unable to select custom theme with underscores in name when creating a widget instance
+Fixed When Redirect to Shopping Cart = No, choosing Remove item from shopping cart sidebar while editing an item leads to endless redirect loop
+Fixed Saved CC form is not displayed, when there are no other available payment methods except Saved CC
+Fixed It's impossible to create Catalog Price Rule
+Fixed Fatal error on Multiple Addresses Checkout
+Fixed Package Types that not available for current Shipping Method displayed in Create Packages pop-up
+Fixed Stock item product getter not correspond to product setter
+- added method getProduct()
+Fixed Admin user interface: mistakes in labels names
+Fixed Typo in Mage_Eav_Model_Resource_Entity_Attribute_Option model
+Fixed Billing Agreement error
+Fixed Payflow Link UI Changes
+Fixed 'Website Payments Pro' impossible to place order during onepage checkout
+Fixed Table rates works incorrect with asterisk
+Fixed Typo in Category Resource Model
+Fixed 3D secure with Saved CC works incorrectly
+- removed unrelated message which told validation failed (even if it has actually succeeded) when trying to re-validate a card
+Fixed Bug in Role Permission
+Fixed Orders placed via Google Checkout were not created on the Magento side
+Fixed When using direct Export, the _super_product_sku and _super_product_option on the configurable product does not match
+Fixed Composite product price in grid is displayed incorrectly with some currencies due to JS regexp problem
+Fixed No error message on Payflow link iframe
+Fixed Flex uploader elements overlaps hovering menu items in backend
+Fixed Unable to upload images in Magento installed on local server
+Fixed Configurable Products - Use Default (attribute name) does not work correctly on IE9
+Fixed Capture failed when Verification Authorization Amount is set to Zero
+Fixed Attribute is sorted like a string even when Input Validation for Store Owner is an Integer Number
+Fixed Void and Cancel Order doesn't work (PayflowLink HSS)
+Fixed Grand Total (Excl Tax) with negative value displays in the printed Credit Memo
+Fixed Resource model of Media module is wrongly declared
+Fixed Constraint violation with core_cache_tag table
+Fixed Misprint in \downloader\lib\Mage\Connect\Validator.php
+Fixed XMLRPC API attribute status changing
+Fixed Typo in Mage_Rss_Block_Catalog_Category::_toHtml() method
+Fixed Incorrect tax summary for partial credit memos/invoices
+Fixed SSL is not used for links in email templates when admin area is configured to use HTTPS
+Fixed Incorrect style on product page
+Fixed Error is displayed by editing product or by creating product on back-end in IE8
+Fixed Catalog price rules for composite products changes
+Fixed Moving modules to the correct place
+Fixed Wishlist shows items per store scope, not website
+Fixed Products in Wishlist disappears, when Store View is changed
+Fixed Wrong Comments History in notification of order creation/cancellation
+Fixed In AJAX popup fields "From" and "To" have behavior as mandatory fields
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed Product price lower than 0 (after catalog price rule applying)
+Fixed Google Checkout throws error if Zip Range is used for Tax Rate
+- changed part of XML request to Google responsible for postal codes
+- made changes to correctly fetch tax rules for postal code ranges
+Fixed Website config object is not being cached
+Fixed Select groups in grid view doesn't work under IE7
+Fixed No products name in Popular tags report file .csv
+Fixed Qty Increments should work when it was defined in the default scope configuration
+Fixed Products in catalog displays as "out of stock"
+Fixed "Get help for this page" in each tab under System->Configuration links to the same help page
+Fixed Unable to translate submenu
+Fixed Redirect to main page of front-end during deleting Product Tax Class which is used in Tax Rule
+Fixed Redirect to base URL should consider full request URI string
+Fixed Incorrect transparency of PNG image in indexed non-alpha mode
+Fixed Problem of generation URL between different domains
+Fixed There are no server side validation of first character of Attribute Code (it should be letter)
+Fixed Edit Order without creating new one functionality saves invalid changes in non-default customer address attributes
+Fixed Frontend: If second customer logs in and does not select the "Remember Me" then the previous long-term cookie does not removes
+Fixed Admin can Reorder order with status On Hold
+Fixed Frontend: After new customer registration with "Remember Me" and pressing "Logout" the long-term cookie session doesn't apply if in configuration on backend ""Remember Me" Default Value" - No
+Fixed Tax not displaying on PayPal side for Express orders
+Fixed Wishlist: Not configured grouped product has unneeded link "Show Details"
+Fixed Removed the ability to work with customise admin url through the parameter base_url
+Fixed Roles not displaying selected resources
+Fixed Unable to use Import when compiler is enabled
+Fixed Missing Translation Capability in Transactional Email Variable
+Fixed productConfigure is undefined error is occurred during creation Order in Backend in IE8 browser
+Fixed Zend Full Page Cache. Lifetime of the cookie is not equal to specified on "Cookie Lifetime" field
+Fixed Incorrect price values for Bundle Product
+Fixed Link does not pass validation if ends with .html
+Fixed Incorrect Customs Value in Create Packages in case when price value contains decimals
+Fixed Incorrect reports with updated_at filter
+Fixed paypal_payment_transaction_clean job takes credentials form default config instead of website for Payflow Link
+Fixed Wrong schedule time setup for paypal_payment_transaction_clean job for Payflow Link
+Fixed Backend Error message "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'qwe' for key 2" appears after saving new Email Template with existing name
+Fixed Rule Conditions logic
+Fixed Error appears after Customer Group saving with name length more than 32
+Fixed Category product index run time
+Fixed Sidebar cart is missing composite product options on category page
+Fixed Missed validation for space character at the begin of unique fields
+- improved validation of Attribute Set Name and validation of unique fields in Mage_Core_Model_Resource_Db_Abstract class
+Fixed Ability to input uppercase, space, specials symbols in Order Status Code
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed No ability to create Shipping Label with "plus-four codes" Zip Code (in case with USPS Domestic)
+Fixed Changing language twice -> Error 404
+Fixed The sort order in products page doesn't work
+Fixed When a grouped product with configured price=0 is added to the wishlist and shared, adding the product to the cart leads to 404 error
+Fixed Media Saves Incorrect Cached Config
+- added options that disallow saving cache
+Fixed Bundle Product items shows randomly instead of according to option
+Fixed Ajax loader does not appears after click on Verify Card on Payflow Link
+Fixed "Google Checkout - Carrier" in Magento backend as shipping method rather than the actual shipping method chosen
+Fixed JavaScript error appears in checkout because of PSC after press 'Proceed to Checkout'
+Fixed Admin user interface: mistakes in labels names
+Fixed Problems with grid sorting on edit customer backend page
+Fixed It is possible to change the price of the Bundle product from fixed to the dynamic at my store
+Fixed Set special price via Catalog Product API is not working
+Fixed Price is wrong calculated for bundle product with a zero price for its items on product details page
+- subitem price calculation were fixed
+Fixed Layout issue appears in IE9 on the grids (example Customers)
+Fixed Impossible to press 'Continue' button to place in onepage
+Fixed "Add to Wishlist", "Add to Compare" aren't presented for Configurable, bundle, downloadable, simple products on Product Details Page
+Fixed Register during checkout with PayPal Express Checkout
+Fixed Extension Packager does not read recursive directory if include expression use file mask
+Fixed Newsletter Subscription Confirmation Message
+Fixed Discount is wrong calculated for Shopping Cart Price Rules when some of them created with Coupon and another without Coupon
+Fixed Subtotal (Incl.Tax) on invoices must not include tax applied to shipping amount
+- shippingTax amount were excluded from subTotal value
+Fixed "Maximum shipping amount allowed to refund" message shows amount excl. tax if Display Shipping Amount set to Including Tax
+- adjusted function to include tax into allowed amount for shipping refund
+Fixed Display Out of Stock Products must not be considered during admin order creation
+Fixed Check box is not working correctly under "prices" of the Bundle products
+Fixed CSS class missing
+Fixed Frontend: JavaScript error appears if user registered on Checkout Page
+Fixed Website config object is not being cached
+- added functionality for memcache backend to split down data that is larger than slab size into chunks
+Fixed Removed the ability to work with base_url
+Fixed Custom design should be updated via import functionality
+Fixed JS error during onepage checkout
+Fixed Unable to translate "First name" and "Last name" fields on "Create an Account" page
+Fixed After upgrading dashboard "Top 5 Search Terms" grid doesn't show search terms
+
+
+
+==== 1.6.1.0-beta1 ====
+
+=== Major Highlights ===
+Added two-step password reset flow
+
+=== Improvements ===
+Added support for using Shift-Click to select a range of grid rows when clicking check boxes
+Added ability to register during checkout when using PayPal Express
+Updated PayflowLink HSS user interface in checkout
+"Add to Wishlist", "Add to Compare" were added on the Product Details Page for configurable, bundled and downloadable products
+
+=== Changes ===
+TheFind integration was removed
+Google Optimizer was removed (it will be supported as a core extension)
+Improved how discounts are applied to sub products
+
+=== Fixes ===
+Fixed Saved CC form is not displayed, when there are no other available payment methods except Saved CC
+Fixed It's impossible to create Catalog Price Rule
+Fixed Fatal error on Multiple Addresses Checkout
+Fixed Package Types that not available for current Shipping Method displayed in Create Packages pop-up
+Fixed Stock item product getter not correspond to product setter
+- added method getProduct()
+Fixed Admin user interface: mistakes in labels names
+Fixed Typo in Mage_Eav_Model_Resource_Entity_Attribute_Option model
+Fixed Billing Agreement error
+Fixed Payflow Link UI Changes
+Fixed 'Website Payments Pro' impossible to place order during onepage checkout
+Fixed Table rates works incorrect with asterisk
+Fixed Typo in Category Resource Model
+Fixed 3D secure with Saved CC works incorrectly
+- removed unrelated message which told validation failed (even if it has actually succeeded) when trying to re-validate a card
+Fixed Bug in Role Permission
+Fixed Orders placed via Google Checkout were not created on the Magento side
+Fixed When using direct Export, the _super_product_sku and _super_product_option on the configurable product does not match
+Fixed Composite product price in grid is displayed incorrectly with some currencies due to JS regexp problem
+Fixed No error message on Payflow link iframe
+Fixed Flex uploader elements overlaps hovering menu items in backend
+Fixed Unable to upload images in Magento installed on local server
+Fixed Configurable Products - Use Default (attribute name) does not work correctly on IE9
+Fixed Capture failed when Verification Authorization Amount is set to Zero
+Fixed Attribute is sorted like a string even when Input Validation for Store Owner is an Integer Number
+Fixed Void and Cancel Order doesn't work (PayflowLink HSS)
+Fixed Grand Total (Excl Tax) with negative value displays in the printed Credit Memo
+Fixed Resource model of Media module is wrongly declared
+Fixed Constraint violation with core_cache_tag table
+Fixed Misprint in \downloader\lib\Mage\Connect\Validator.php
+Fixed XMLRPC API attribute status changing
+Fixed Typo in Mage_Rss_Block_Catalog_Category::_toHtml() method
+Fixed Incorrect tax summary for partial credit memos/invoices
+Fixed SSL is not used for links in email templates when admin area is configured to use HTTPS
+Fixed Incorrect style on product page
+Fixed Error is displayed by editing product or by creating product on back-end in IE8
+Fixed Catalog price rules for composite products changes
+Fixed Moving modules to the correct place
+Fixed Wishlist shows items per store scope, not website
+Fixed Products in Wishlist disappears, when Store View is changed
+Fixed Wrong Comments History in notification of order creation/cancellation
+Fixed In AJAX popup fields "From" and "To" have behavior as mandatory fields
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed Product price lower than 0 (after catalog price rule applying)
+Fixed Google Checkout throws error if Zip Range is used for Tax Rate
+- changed part of XML request to Google responsible for postal codes
+- made changes to correctly fetch tax rules for postal code ranges
+Fixed Website config object is not being cached
+Fixed Select groups in grid view doesn't work under IE7
+Fixed No products name in Popular tags report file .csv
+Fixed Qty Increments should work when it was defined in the default scope configuration
+Fixed Products in catalog displays as "out of stock"
+Fixed "Get help for this page" in each tab under System->Configuration links to the same help page
+Fixed Unable to translate submenu
+Fixed Redirect to main page of front-end during deleting Product Tax Class which is used in Tax Rule
+Fixed Redirect to base URL should consider full request URI string
+Fixed Incorrect transparency of PNG image in indexed non-alpha mode
+Fixed Problem of generation URL between different domains
+Fixed There are no server side validation of first character of Attribute Code (it should be letter)
+Fixed Edit Order without creating new one functionality saves invalid changes in non-default customer address attributes
+Fixed Frontend: If second customer logs in and does not select the "Remember Me" then the previous long-term cookie does not removes
+Fixed Admin can Reorder order with status On Hold
+Fixed Frontend: After new customer registration with "Remember Me" and pressing "Logout" the long-term cookie session doesn't apply if in configuration on backend ""Remember Me" Default Value" - No
+Fixed Tax not displaying on PayPal side for Express orders
+Fixed Wishlist: Not configured grouped product has unneeded link "Show Details"
+Fixed Removed the ability to work with customise admin url through the parameter base_url
+Fixed Roles not displaying selected resources
+Fixed Unable to use Import when compiler is enabled
+Fixed Missing Translation Capability in Transactional Email Variable
+Fixed productConfigure is undefined error is occurred during creation Order in Backend in IE8 browser
+Fixed Zend Full Page Cache. Lifetime of the cookie is not equal to specified on "Cookie Lifetime" field
+Fixed Incorrect price values for Bundle Product
+Fixed Link does not pass validation if ends with .html
+Fixed Incorrect Customs Value in Create Packages in case when price value contains decimals
+Fixed Incorrect reports with updated_at filter
+Fixed paypal_payment_transaction_clean job takes credentials form default config instead of website for Payflow Link
+Fixed Wrong schedule time setup for paypal_payment_transaction_clean job for Payflow Link
+Fixed Backend Error message "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'qwe' for key 2" appears after saving new Email Template with existing name
+Fixed Rule Conditions logic
+Fixed Error appears after Customer Group saving with name length more than 32
+Fixed Category product index run time
+Fixed Sidebar cart is missing composite product options on category page
+Fixed Missed validation for space character at the begin of unique fields
+- improved validation of Attribute Set Name and validation of unique fields in Mage_Core_Model_Resource_Db_Abstract class
+Fixed Ability to input uppercase, space, specials symbols in Order Status Code
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed No ability to create Shipping Label with "plus-four codes" Zip Code (in case with USPS Domestic)
+Fixed Changing language twice -> Error 404
+Fixed The sort order in products page doesn't work
+Fixed When a grouped product with configured price=0 is added to the wishlist and shared, adding the product to the cart leads to 404 error
+Fixed Media Saves Incorrect Cached Config
+- added options that disallow saving cache
+Fixed Bundle Product items shows randomly instead of according to option
+Fixed Unable to place order with Payflow Link if store credit or reward point applied
+Fixed Ajax loader does not appears after click on Verify Card on Payflow Link
+Fixed "Google Checkout - Carrier" in Magento backend as shipping method rather than the actual shipping method chosen
+Fixed JavaScript error appears in checkout because of PSC after press 'Proceed to Checkout'
+Fixed Admin user interface: mistakes in labels names
+Fixed Problems with grid sorting on edit customer backend page
+Fixed It is possible to change the price of the Bundle product from fixed to the dynamic at my store
+Fixed Set special price via Catalog Product API is not working
+Fixed Price is wrong calculated for bundle product with a zero price for its items on product details page
+- subitem price calculation were fixed
+Fixed Layout issue appears in IE9 on the grids (example Customers)
+Fixed Impossible to press 'Continue' button to place in onepage
+Fixed "Add to Wishlist", "Add to Compare" aren't presented for Configurable, bundle, downloadable, simple products on Product Details Page
+Fixed Register during checkout with PayPal Express Checkout
+Fixed Extension Packager does not read recursive directory if include expression use file mask
+Fixed Newsletter Subscription Confirmation Message
+Fixed Discount is wrong calculated for Shopping Cart Price Rules when some of them created with Coupon and another without Coupon
+Fixed Subtotal (Incl.Tax) on invoices must not include tax applied to shipping amount
+- shippingTax amount were excluded from subTotal value
+Fixed "Maximum shipping amount allowed to refund" message shows amount excl. tax if Display Shipping Amount set to Including Tax
+- adjusted function to include tax into allowed amount for shipping refund
+Fixed Display Out of Stock Products must not be considered during admin order creation
+Fixed Check box is not working correctly under "prices" of the Bundle products.
+Fixed CSS class missing
+Fixed Frontend: JavaScript error appears if user registered on Checkout Page
+Fixed Website config object is not being cached
+- added functionality for memcache backend to split down data that is larger than slab size into chunks
+Fixed Removed the ability to work with base_url
+Fixed Custom design should be updated via import functionality
+Fixed JS error during onepage checkout
+Fixed Unable to translate "First name" and "Last name" fields on "Create an Account" page
+Fixed After upgrading dashboard "Top 5 Search Terms" grid doesn't show search terms
+
+
+
+==== 1.6.1.0-alpha1 ====
+
+=== Major Highlights ===
+Added two-step password reset flow
+
+=== Improvements ===
+Added support for using Shift-Click to select a range of grid rows when clicking check boxes
+Added ability to register during checkout when using PayPal Express
+Updated PayflowLink HSS user interface in checkout
+"Add to Wishlist", "Add to Compare" were added on the Product Details Page for configurable, bundled and downloadable products
+
+=== Changes ===
+TheFind integration was removed
+Google Optimizer was removed (it will be supported as a core extension)
+Improved how discounts are applied to sub products
+
+=== Fixes ===
+Fixed When using direct Export, the _super_product_sku and _super_product_option on the configurable product does not match
+Fixed Composite product price in grid is displayed incorrectly with some currencies due to JS regexp problem
+Fixed No error message on Payflow link iframe
+Fixed Flex uploader elements overlaps hovering menu items in backend
+Fixed Unable to upload images in Magento installed on local server
+Fixed Configurable Products - Use Default (attribute name) does not work correctly on IE9
+Fixed Capture failed when Verification Authorization Amount is set to Zero
+Fixed Attribute is sorted like a string even when Input Validation for Store Owner is an Integer Number
+Fixed Void and Cancel Order doesn't work (PayflowLink HSS)
+Fixed Grand Total (Excl Tax) with negative value displays in the printed Credit Memo
+Fixed Resource model of Media module is wrongly declared
+Fixed Constraint violation with core_cache_tag table
+Fixed Misprint in \downloader\lib\Mage\Connect\Validator.php
+Fixed XMLRPC API attribute status changing
+Fixed Typo in Mage_Rss_Block_Catalog_Category::_toHtml() method
+Fixed Incorrect tax summary for partial credit memos/invoices
+Fixed SSL is not used for links in email templates when admin area is configured to use HTTPS
+Fixed Incorrect style on product page
+Fixed Error is displayed by editing product or by creating product on back-end in IE8
+Fixed Catalog price rules for composite products changes
+Fixed Moving modules to the correct place
+Fixed Wishlist shows items per store scope, not website
+Fixed Products in Wishlist disappears, when Store View is changed
+Fixed Wrong Comments History in notification of order creation/cancellation
+Fixed In AJAX popup fields "From" and "To" have behavior as mandatory fields
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed Product price lower than 0 (after catalog price rule applying)
+Fixed Google Checkout throws error if Zip Range is used for Tax Rate
+- changed part of XML request to Google responsible for postal codes
+- made changes to correctly fetch tax rules for postal code ranges
+Fixed Website config object is not being cached
+Fixed Select groups in grid view doesn't work under IE7
+Fixed No products name in Popular tags report file .csv
+Fixed Qty Increments should work when it was defined in the default scope configuration
+Fixed Products in catalog displays as "out of stock"
+Fixed "Get help for this page" in each tab under System->Configuration links to the same help page
+Fixed Unable to translate submenu
+Fixed Redirect to main page of front-end during deleting Product Tax Class which is used in Tax Rule
+Fixed Redirect to base URL should consider full request URI string
+Fixed Incorrect transparency of PNG image in indexed non-alpha mode
+Fixed Problem of generation URL between different domains
+Fixed There are no server side validation of first character of Attribute Code (it should be letter)
+Fixed Edit Order without creating new one functionality saves invalid changes in non-default customer address attributes
+Fixed Frontend: If second customer logs in and does not select the "Remember Me" then the previous long-term cookie does not removes
+Fixed Admin can Reorder order with status On Hold
+Fixed Frontend: After new customer registration with "Remember Me" and pressing "Logout" the long-term cookie session doesn't apply if in configuration on backend ""Remember Me" Default Value" - No
+Fixed Tax not displaying on PayPal side for Express orders
+Fixed Wishlist: Not configured grouped product has unneeded link "Show Details"
+Fixed Removed the ability to work with customise admin url through the parameter base_url
+Fixed Roles not displaying selected resources
+Fixed Unable to use Import when compiler is enabled
+Fixed Missing Translation Capability in Transactional Email Variable
+Fixed productConfigure is undefined error is occurred during creation Order in Backend in IE8 browser
+Fixed Zend Full Page Cache. Lifetime of the cookie is not equal to specified on "Cookie Lifetime" field
+Fixed Incorrect price values for Bundle Product
+Fixed Link does not pass validation if ends with .html
+Fixed Incorrect Customs Value in Create Packages in case when price value contains decimals
+Fixed Incorrect reports with updated_at filter
+Fixed paypal_payment_transaction_clean job takes credentials form default config instead of website for Payflow Link
+Fixed Wrong schedule time setup for paypal_payment_transaction_clean job for Payflow Link
+Fixed Backend Error message "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'qwe' for key 2" appears after saving new Email Template with existing name
+Fixed Rule Conditions logic
+Fixed Error appears after Customer Group saving with name length more than 32
+Fixed Category product index run time
+Fixed Sidebar cart is missing composite product options on category page
+Fixed Missed validation for space character at the begin of unique fields
+- improved validation of Attribute Set Name and validation of unique fields in Mage_Core_Model_Resource_Db_Abstract class
+Fixed Ability to input uppercase, space, specials symbols in Order Status Code
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed No ability to create Shipping Label with "plus-four codes" Zip Code (in case with USPS Domestic)
+Fixed Changing language twice -> Error 404
+Fixed The sort order in products page doesn't work
+Fixed When a grouped product with configured price=0 is added to the wishlist and shared, adding the product to the cart leads to 404 error
+Fixed Media Saves Incorrect Cached Config
+- added options that disallow saving cache
+Fixed Bundle Product items shows randomly instead of according to option
+Fixed Unable to place order with Payflow Link if store credit or reward point applied
+Fixed Ajax loader does not appears after click on Verify Card on Payflow Link
+Fixed "Google Checkout - Carrier" in Magento backend as shipping method rather than the actual shipping method chosen
+Fixed JavaScript error appears in checkout because of PSC after press 'Proceed to Checkout'
+Fixed Admin user interface: mistakes in labels names
+Fixed Problems with grid sorting on edit customer backend page
+Fixed It is possible to change the price of the Bundle product from fixed to the dynamic at my store
+Fixed Set special price via Catalog Product API is not working
+Fixed Price is wrong calculated for bundle product with a zero price for its items on product details page
+- subitem price calculation were fixed
+Fixed Layout issue appears in IE9 on the grids (example Customers)
+Fixed Impossible to press 'Continue' button to place in onepage
+Fixed "Add to Wishlist", "Add to Compare" aren't presented for Configurable, bundle, downloadable, simple products on Product Details Page
+Fixed Register during checkout with PayPal Express Checkout
+Fixed Extension Packager does not read recursive directory if include expression use file mask
+Fixed Newsletter Subscription Confirmation Message
+Fixed Discount is wrong calculated for Shopping Cart Price Rules when some of them created with Coupon and another without Coupon
+Fixed Subtotal (Incl.Tax) on invoices must not include tax applied to shipping amount
+- shippingTax amount were excluded from subTotal value
+Fixed "Maximum shipping amount allowed to refund" message shows amount excl. tax if Display Shipping Amount set to Including Tax
+- adjusted function to include tax into allowed amount for shipping refund
+Fixed Display Out of Stock Products must not be considered during admin order creation
+Fixed Check box is not working correctly under "prices" of the Bundle products.
+Fixed CSS class missing
+Fixed Frontend: JavaScript error appears if user registered on Checkout Page
+Fixed Website config object is not being cached
+- added functionality for memcache backend to split down data that is larger than slab size into chunks
+Fixed Removed the ability to work with base_url
+Fixed Custom design should be updated via import functionality
+Fixed JS error during onepage checkout
+Fixed Unable to translate "First name" and "Last name" fields on "Create an Account" page
+Fixed After upgrading dashboard "Top 5 Search Terms" grid doesn't show search terms
+
+
+
+==== 1.6.x-devel-119961 ====
+
+=== Fixes ===
+Fixed Wrong Comments History in notification of order creation/cancellation
+Fixed In AJAX popup fields "From" and "To" have behavior as mandatory fields
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed Product price lower than 0 (after catalog price rule applying)
+Fixed Google Checkout throws error if Zip Range is used for Tax Rate
+- changed part of XML request to Google responsible for postal codes
+- made changes to correctly fetch tax rules for postal code ranges
+Fixed Website config object is not being cached
+Fixed Select groups in grid view doesn't work under IE7
+Fixed No products name in Popular tags report file .csv
+Fixed Qty Increments should work when it was defined in the default scope configuration
+Fixed Products in catalog displays as "out of stock"
+Fixed "Get help for this page" in each tab under System->Configuration links to the same help page
+Fixed Unable to translate submenu
+Fixed Redirect to main page of front-end during deleting Product Tax Class which is used in Tax Rule
+Fixed Redirect to base URL should consider full request URI string
+
+
+
+==== 1.6.x-devel-119217 ====
+
+=== Fixes ===
+Fixed Incorrect transparency of PNG image in indexed non-alpha mode
+Fixed Problem of generation URL between different domains
+Fixed There are no server side validation of first character of Attribute Code (it should be letter)
+Fixed Edit Order without creating new one functionality saves invalid changes in non-default customer address attributes
+Fixed Frontend: If second customer logs in and does not select the "Remember Me" then the previous long-term cookie does not removes
+Fixed Admin can Reorder order with status On Hold
+Fixed Frontend: After new customer registration with "Remember Me" and pressing "Logout" the long-term cookie session doesn't apply if in configuration on backend ""Remember Me" Default Value" - No
+Fixed Tax not displaying on PayPal side for Express orders
+Fixed Wishlist: Not configured grouped product has unneeded link "Show Details"
+Fixed Removed the ability to work with customise admin url through the parameter base_url
+Fixed Roles not displaying selected resources
+Fixed Unable to use Import when compiler is enabled
+Fixed Missing Translation Capability in Transactional Email Variable
+Fixed productConfigure is undefined error is occurred during creation Order in Backend in IE8 browser
+Fixed Zend Full Page Cache. Lifetime of the cookie is not equal to specified on "Cookie Lifetime" field
+Fixed Incorrect price values for Bundle Product
+Fixed Link does not pass validation if ends with .html
+Fixed Incorrect Customs Value in Create Packages in case when price value contains decimals
+Fixed Incorrect reports with updated_at filter
+Fixed paypal_payment_transaction_clean job takes credentials form default config instead of website for Payflow Link
+Fixed Wrong schedule time setup for paypal_payment_transaction_clean job for Payflow Link
+Fixed Backend Error message "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'qwe' for key 2" appears after saving new Email Template with existing name
+Fixed Rule Conditions logic
+Fixed Error appears after Customer Group saving with name length more than 32
+Fixed Category product index run time
+Fixed Sidebar cart is missing composite product options on category page
+Fixed Missed validation for space character at the begin of unique fields
+- improved validation of Attribute Set Name and validation of unique fields in Mage_Core_Model_Resource_Db_Abstract class
+Fixed Ability to input uppercase, space, specials symbols in Order Status Code
+Fixed Filter by Allow Countries not working for Customer Address Form in the Backend
+Fixed No ability to create Shipping Label with "plus-four codes" Zip Code (in case with USPS Domestic)
+Fixed Changing language twice -> Error 404
+Fixed The sort order in products page doesn't work
+Fixed When a grouped product with configured price=0 is added to the wishlist and shared, adding the product to the cart leads to 404 error
+Fixed Media Saves Incorrect Cached Config
+- added options that disallow saving cache
+Fixed Bundle Product items shows randomly instead of according to option
+Fixed Unable to place order with Payflow Link if store credit or reward point applied
+Fixed Ajax loader does not appears after click on Verify Card on Payflow Link
+Fixed "Google Checkout - Carrier" in Magento backend as shipping method rather than the actual shipping method chosen
+Fixed JavaScript error appears in checkout because of PSC after press 'Proceed to Checkout'
+Fixed Admin user interface: mistakes in labels names
+Fixed Problems with grid sorting on edit customer backend page
+Fixed It is possible to change the price of the Bundle product from fixed to the dynamic at my store
+Fixed Set special price via Catalog Product API is not working
+Fixed Price is wrong calculated for bundle product with a zero price for its items on product details page
+- subitem price calculation were fixed
+Fixed Layout issue appears in IE9 on the grids (example Customers)
+Fixed Impossible to press 'Continue' button to place in onepage
+Fixed "Add to Wishlist", "Add to Compare" aren't presented for Configurable, bundle, downloadable, simple products on Product Details Page
+Fixed Register during checkout with PayPal Express Checkout
+Fixed Extension Packager does not read recursive directory if include expression use file mask
+Fixed Newsletter Subscription Confirmation Message
+Fixed Discount is wrong calculated for Shopping Cart Price Rules when some of them created with Coupon and another without Coupon
+Fixed Subtotal (Incl.Tax) on invoices must not include tax applied to shipping amount
+- shippingTax amount were excluded from subTotal value
+Fixed "Maximum shipping amount allowed to refund" message shows amount excl. tax if Display Shipping Amount set to Including Tax
+- adjusted function to include tax into allowed amount for shipping refund
+Fixed Display Out of Stock Products must not be considered during admin order creation
+Fixed Check box is not working correctly under "prices" of the Bundle products.
+Fixed CSS class missing
+Fixed Frontend: JavaScript error appears if user registered on Checkout Page
+Fixed Website config object is not being cached
+- added functionality for memcache backend to split down data that is larger than slab size into chunks
+Fixed Removed the ability to work with base_url
+Fixed Custom design should be updated via import functionality
+Fixed JS error during onepage checkout
+Fixed Unable to translate "First name" and "Last name" fields on "Create an Account" page
+Fixed After upgrading dashboard "Top 5 Search Terms" grid doesn't show search terms
+
+
+
==== 1.6.0.0 ====
=== Major Highlights ===
diff --git a/app/Mage.php b/app/Mage.php
index 3760a1ce98..4d50995d90 100644
--- a/app/Mage.php
+++ b/app/Mage.php
@@ -152,7 +152,7 @@ public static function getVersionInfo()
return array(
'major' => '1',
'minor' => '6',
- 'revision' => '0',
+ 'revision' => '1',
'patch' => '0',
'stability' => '',
'number' => '',
diff --git a/app/code/community/Find/Feed/Block/Adminhtml/Edit/Codes/Edit/Form.php b/app/code/community/Find/Feed/Block/Adminhtml/Edit/Codes/Edit/Form.php
deleted file mode 100644
index 473ba001ac..0000000000
--- a/app/code/community/Find/Feed/Block/Adminhtml/Edit/Codes/Edit/Form.php
+++ /dev/null
@@ -1,124 +0,0 @@
-
- */
-class Find_Feed_Block_Adminhtml_Edit_Codes_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
-{
- /**
- * Import codes list
- *
- * @return array
- */
- protected function _getImportCodeList()
- {
- $attributes = Mage::getConfig()->getNode(Find_Feed_Model_Import::XML_NODE_FIND_FEED_ATTRIBUTES)->children();
- $result = array();
- foreach ($attributes as $node) {
- $label = trim((string)$node->label);
- if ($label) {
- $result[$label] = $label;
- }
- }
-
- return $result;
- }
-
- /**
- * Magento entity type list for eav attributes
- *
- * @return array
- */
- protected function _getCatalogEntityType()
- {
- return Mage::getSingleton('eav/config')->getEntityType('catalog_product')->getId();
- }
-
-
- /**
- * Magento eav attributes list
- *
- * @return array
- */
- protected function _getEavAttributeList()
- {
- $result = array();
- $collection = Mage::getResourceModel('catalog/product_attribute_collection');
- foreach ($collection as $model) {
- $result[$model->getAttributeCode()] = $model->getAttributeCode();
- }
- return $result;
- }
-
- /**
- * Prepare form
- *
- * @return Varien_Object
- */
- protected function _prepareForm()
- {
- $form = new Varien_Data_Form(array(
- 'id' => 'import_item_form',
- 'method' => 'post'
- ));
-
- $fieldset = $form->addFieldset('generate_fieldset', array(
- 'legend' => Mage::helper('find_feed')->__('Item params')
- ));
- $fieldset->addField('import_code', 'select', array(
- 'label' => Mage::helper('find_feed')->__('Import code'),
- 'name' => 'import_code',
- 'required' => true,
- 'options' => $this->_getImportCodeList()
- ));
- $fieldset->addField('eav_code', 'select', array(
- 'label' => Mage::helper('find_feed')->__('Eav code'),
- 'name' => 'eav_code',
- 'required' => true,
- 'options' => $this->_getEavAttributeList()
- ));
-
- $source = Mage::getModel('eav/entity_attribute_source_boolean');
- $isImportedOptions = $source->getOptionArray();
-
- $fieldset->addField('is_imported', 'select', array(
- 'label' => Mage::helper('find_feed')->__('Is imported'),
- 'name' => 'is_imported',
- 'value' => 1,
- 'options' => $isImportedOptions
- ));
- $form->setUseContainer(true);
-
- $this->setForm($form);
- return parent::_prepareForm();
- }
-}
diff --git a/app/code/community/Find/Feed/Block/Adminhtml/List/Codes/Grid.php b/app/code/community/Find/Feed/Block/Adminhtml/List/Codes/Grid.php
deleted file mode 100644
index 9b07c41ef5..0000000000
--- a/app/code/community/Find/Feed/Block/Adminhtml/List/Codes/Grid.php
+++ /dev/null
@@ -1,131 +0,0 @@
-
- */
-class Find_Feed_Block_Adminhtml_List_Codes_Grid extends Mage_Adminhtml_Block_Widget_Grid
-{
- /**
- * Initialize grid settings
- *
- */
- protected function _construct()
- {
- parent::_construct();
-
- $this->setId('find_feed_list_codes');
- $this->setUseAjax(true);
- }
-
- /**
- * Prepare codes collection
- *
- * @return Find_Feed_Block_Adminhtml_List_Codes_Grid
- */
- protected function _prepareCollection()
- {
- $collection = Mage::getResourceModel('find_feed/codes_collection');
- $this->setCollection($collection);
- return parent::_prepareCollection();
- }
-
- /**
- * Configuration of grid
- *
- * @return $this
- */
- protected function _prepareColumns()
- {
- $this->addColumn('import_code', array(
- 'header'=> Mage::helper('find_feed')->__('Feed code'),
- 'width' => '80px',
- 'type' => 'text',
- 'index' => 'import_code'
- ));
-
- $this->addColumn('eav_code', array(
- 'header'=> Mage::helper('find_feed')->__('Eav code'),
- 'width' => '80px',
- 'type' => 'text',
- 'index' => 'eav_code'
- ));
-
- $source = Mage::getModel('eav/entity_attribute_source_boolean');
- $isImportedOptions = $source->getOptionArray();
-
- $this->addColumn('is_imported', array(
- 'header' => Mage::helper('find_feed')->__('In feed'),
- 'width' => '100px',
- 'index' => 'is_imported',
- 'type' => 'options',
- 'options' => $isImportedOptions
- ));
- return parent::_prepareColumns();
- }
-
- /**
- * Prepare massaction
- *
- * @return $this
- */
- protected function _prepareMassaction()
- {
- $this->setMassactionIdField('code_id');
- $this->getMassactionBlock()->setFormFieldName('code_id');
-
- $this->getMassactionBlock()->addItem('enable', array(
- 'label' => Mage::helper('find_feed')->__('Import'),
- 'url' => $this->getUrl('*/codes_grid/massEnable'),
- 'selected' => true,
- ));
- $this->getMassactionBlock()->addItem('disable', array(
- 'label' => Mage::helper('find_feed')->__('Not import'),
- 'url' => $this->getUrl('*/codes_grid/massDisable'),
- ));
- $this->getMassactionBlock()->addItem('delete', array(
- 'label' => Mage::helper('find_feed')->__('Delete'),
- 'url' => $this->getUrl('*/codes_grid/delete'),
- ));
-
- return $this;
- }
-
- /**
- * Return Grid URL for AJAX query
- *
- * @return string
- */
- public function getGridUrl()
- {
- return $this->getUrl('*/codes_grid/grid', array('_current'=>true));
- }
-}
diff --git a/app/code/community/Find/Feed/Block/Adminhtml/List/Items/Grid.php b/app/code/community/Find/Feed/Block/Adminhtml/List/Items/Grid.php
deleted file mode 100644
index bdea413002..0000000000
--- a/app/code/community/Find/Feed/Block/Adminhtml/List/Items/Grid.php
+++ /dev/null
@@ -1,183 +0,0 @@
-
- */
-class Find_Feed_Block_Adminhtml_List_Items_Grid extends Mage_Adminhtml_Block_Widget_Grid
-{
- /**
- * Initialize grid settings
- *
- */
- protected function _construct()
- {
- parent::_construct();
-
- $this->setId('find_feed_list_items');
- $this->setDefaultSort('id');
- $this->setUseAjax(true);
- }
-
- /**
- * Return Current work store
- *
- * @return Mage_Core_Model_Store
- */
- protected function _getStore()
- {
- return Mage::app()->getStore();
- }
-
- /**
- * Prepare product collection
- *
- * @return Find_Feed_Block_Adminhtml_List_Items_Grid
- */
- protected function _prepareCollection()
- {
- $collection = Mage::getModel('catalog/product')->getCollection()
- ->setStore($this->_getStore())
- ->addAttributeToSelect('name')
- ->addAttributeToSelect('sku')
- ->addAttributeToSelect('price')
- ->addAttributeToSelect('attribute_set_id')
- ->addAttributeToSelect('is_imported');
- $this->setCollection($collection);
-
- return parent::_prepareCollection();
- }
-
- /**
- * Prepare grid columns
- *
- * @return Find_Feed_Block_Adminhtml_List_Items_Grid
- */
- protected function _prepareColumns()
- {
- $this->addColumn('id', array(
- 'header' => Mage::helper('find_feed')->__('ID'),
- 'sortable' => true,
- 'width' => '60px',
- 'index' => 'entity_id'
- ));
-
- $this->addColumn('name', array(
- 'header' => Mage::helper('find_feed')->__('Product Name'),
- 'index' => 'name',
- 'column_css_class' => 'name'
- ));
-
- $this->addColumn('type', array(
- 'header' => Mage::helper('find_feed')->__('Type'),
- 'width' => '60px',
- 'index' => 'type_id',
- 'type' => 'options',
- 'options' => Mage::getSingleton('catalog/product_type')->getOptionArray(),
- ));
-
- $entityTypeId = Mage::helper('find_feed')->getProductEntityType();
- $sets = Mage::getResourceModel('eav/entity_attribute_set_collection')
- ->setEntityTypeFilter($entityTypeId)
- ->load()
- ->toOptionHash();
-
- $this->addColumn('set_name', array(
- 'header' => Mage::helper('find_feed')->__('Attrib. Set Name'),
- 'width' => '100px',
- 'index' => 'attribute_set_id',
- 'type' => 'options',
- 'options' => $sets,
- ));
-
- $this->addColumn('sku', array(
- 'header' => Mage::helper('find_feed')->__('SKU'),
- 'width' => '80px',
- 'index' => 'sku',
- 'column_css_class' => 'sku'
- ));
-
- $this->addColumn('price', array(
- 'header' => Mage::helper('find_feed')->__('Price'),
- 'align' => 'center',
- 'type' => 'currency',
- 'currency_code' => $this->_getStore()->getCurrentCurrencyCode(),
- 'rate' => $this->_getStore()->getBaseCurrency()->getRate($this->_getStore()->getCurrentCurrencyCode()),
- 'index' => 'price'
- ));
-
- $source = Mage::getModel('eav/entity_attribute_source_boolean');
- $isImportedOptions = $source->getOptionArray();
-
- $this->addColumn('is_imported', array(
- 'header' => Mage::helper('find_feed')->__('In feed'),
- 'width' => '100px',
- 'index' => 'is_imported',
- 'type' => 'options',
- 'options' => $isImportedOptions
- ));
-
- return parent::_prepareColumns();
- }
-
- /**
- * Prepare massaction
- *
- * @return Find_Feed_Block_Adminhtml_List_Items_Grid
- */
- protected function _prepareMassaction()
- {
- $this->setMassactionIdField('entity_id');
- $this->getMassactionBlock()->setFormFieldName('item_id');
-
- $this->getMassactionBlock()->addItem('enable', array(
- 'label' => Mage::helper('find_feed')->__('Publish'),
- 'url' => $this->getUrl('*/items_grid/massEnable'),
- 'selected' => true,
- ));
- $this->getMassactionBlock()->addItem('disable', array(
- 'label' => Mage::helper('find_feed')->__('Not publish'),
- 'url' => $this->getUrl('*/items_grid/massDisable'),
- ));
-
- return $this;
- }
-
- /**
- * Return Grid URL for AJAX query
- *
- * @return string
- */
- public function getGridUrl()
- {
- return $this->getUrl('*/*/grid', array('_current'=>true));
- }
-}
diff --git a/app/code/community/Find/Feed/Helper/Data.php b/app/code/community/Find/Feed/Helper/Data.php
deleted file mode 100755
index 52ceaac3ff..0000000000
--- a/app/code/community/Find/Feed/Helper/Data.php
+++ /dev/null
@@ -1,69 +0,0 @@
-getNode(Find_Feed_Model_Import::XML_NODE_FIND_FEED_ATTRIBUTES);
- $attributeRequired = array();
- foreach ($attributeConfig->children() as $ac) {
- if ((int)$ac->required) {
- $attributeRequired[] = (string)$ac->label;
- }
- }
-
- foreach ($attributeRequired as $value) {
- if (!isset($attributes[$value])) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Product entity type
- *
- * @return int
- */
- public function getProductEntityType()
- {
- return Mage::getSingleton('eav/config')->getEntityType('catalog_product')->getId();
- }
-}
diff --git a/app/code/community/Find/Feed/Model/Adminhtml/System/Source/Cron/Frequency.php b/app/code/community/Find/Feed/Model/Adminhtml/System/Source/Cron/Frequency.php
deleted file mode 100644
index 442298e460..0000000000
--- a/app/code/community/Find/Feed/Model/Adminhtml/System/Source/Cron/Frequency.php
+++ /dev/null
@@ -1,63 +0,0 @@
- 'Daily',
- 'value' => self::DAILY),
- array(
- 'label' => 'Weekly',
- 'value' => self::WEEKLY),
- array(
- 'label' => 'Monthly',
- 'value' => self::MONTHLY),
- array(
- 'label' => 'Every minute',
- 'value' => self::EVERY_MINUTE)
- );
- }
-}
diff --git a/app/code/community/Find/Feed/Model/Import.php b/app/code/community/Find/Feed/Model/Import.php
deleted file mode 100755
index c97ca991a3..0000000000
--- a/app/code/community/Find/Feed/Model/Import.php
+++ /dev/null
@@ -1,271 +0,0 @@
-processImport();
- }
-
- /**
- * TheFind feed process import
- */
- public function processImport()
- {
- $file = $this->_createFile();
- if ($file) {
- $this->_deleteFtpFiles();
- $this->_sendFile($file);
- if (!$this->_deleteFile($file)) {
- Mage::throwException(Mage::helper('find_feed')->__("FTP: Can't delete files"));
- }
- }
- }
-
- /**
- * Create temp csv file and write export
- *
- * @return mixed
- */
- protected function _createFile()
- {
- $dir = $this->_getTmpDir();
- $fileName = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FINDFEED_FILENAME);
- if (!$dir || !$fileName) {
- return false;
- }
-
- if (!($attributes = $this->_getImportAttributes()) || count($attributes) <= 0) {
- return false;
- }
-
- $headers = array_keys($attributes);
-
- $file = new Varien_Io_File;
- $file->checkAndCreateFolder($dir);
- $file->cd($dir);
- $file->streamOpen($fileName, 'w+');
- $file->streamLock();
- $file->streamWriteCsv($headers, self::SEPARATOR, self::ENCLOSURE);
-
- $productCollectionPrototype = Mage::getResourceModel('catalog/product_collection');
- $productCollectionPrototype->setPageSize(self::COLLECTION_PAGE_SIZE);
- $pageNumbers = $productCollectionPrototype->getLastPageNumber();
- unset($productCollectionPrototype);
-
- for ($i = 1; $i <= $pageNumbers; $i++) {
- $productCollection = Mage::getResourceModel('catalog/product_collection');
- $productCollection->addAttributeToSelect($attributes);
- $productCollection->addAttributeToFilter('is_imported', 1);
- $productCollection->setPageSize(self::COLLECTION_PAGE_SIZE);
- $productCollection->setCurPage($i)->load();
- foreach ($productCollection as $product) {
- $attributesRow = array();
- foreach ($attributes as $key => $value) {
- if ($this->_checkAttributeSource($product, $value)) {
- if (is_array($product->getAttributeText($value))) {
- $attributesRow[$key] = implode(', ', $product->getAttributeText($value));
- } else {
- $attributesRow[$key] = $product->getAttributeText($value);
- }
- } else {
- $attributesRow[$key] = $product->getData($value);
- }
- }
- $file->streamWriteCsv($attributesRow, self::SEPARATOR, self::ENCLOSURE);
- }
- unset($productCollection);
- }
-
- $file->streamUnlock();
- $file->streamClose();
-
- if ($file->fileExists($fileName)) {
- return $fileName;
- }
- return false;
- }
-
- /**
- * Check attribute source
- *
- * @param Mage_Catalog_Model_Product $product
- * @param string $value
- * @return bool
- */
- protected function _checkAttributeSource($product, $value)
- {
- if (!array_key_exists($value, $this->_attributeSources)) {
- $this->_attributeSources[$value] = $product->getResource()->getAttribute($value)->usesSource();
- }
- return $this->_attributeSources[$value];
- }
-
- /**
- * List import codes (attribute map) model
- *
- * @return mixed
- */
- protected function _getImportAttributes()
- {
- $attributes = Mage::getResourceModel('find_feed/codes_collection')
- ->getImportAttributes();
-
- if (!Mage::helper('find_feed')->checkRequired($attributes)) {
- return false;
- }
- return $attributes;
- }
-
- /**
- * Send file to remote ftp server
- *
- * @param string $fileName
- */
- protected function _sendFile($fileName)
- {
- $dir = $this->_getTmpDir();
- $ftpServer = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_SERVER);
- $ftpUserName = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_USER);
- $ftpPass = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_PASSWORD);
- $ftpPath = trim(Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_PATH), '/');
- if ($ftpPath) {
- $ftpPath = $ftpPath.'/';
- }
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, 'ftp://'.$ftpUserName.':'.$ftpPass.'@'.$ftpServer.'/'.$ftpPath.$fileName);
- curl_setopt($ch, CURLOPT_UPLOAD, 1);
- curl_setopt($ch, CURLOPT_INFILE, fopen($dir.$fileName, 'r'));
- curl_setopt($ch, CURLOPT_INFILESIZE, filesize($dir.$fileName));
- curl_exec($ch);
- curl_close($ch);
- }
-
- /**
- * Delete all files in current feed ftp directory
- *
- * @return bool
- */
- protected function _deleteFtpFiles()
- {
- if (is_callable('ftp_connect')) {
- $ftpServer = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_SERVER);
- $ftpUserName = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_USER);
- $ftpPass = Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_PASSWORD);
- $ftpPath = trim(Mage::getStoreConfig(self::XML_PATH_SETTINGS_FTP_PATH), '/');
- if ($ftpPath) {
- $ftpPath = $ftpPath.'/';
- }
-
- try {
- $connId = ftp_connect($ftpServer);
-
- $loginResult = ftp_login($connId, $ftpUserName, $ftpPass);
- if (!$loginResult) {
- return false;
- }
- ftp_pasv($connId, true);
-
- $ftpDir = $ftpPath?$ftpPath:'.';
- $nlist = ftp_nlist($connId, $ftpDir);
- if ($nlist === false) {
- return false;
- }
- foreach ($nlist as $file) {
- if (!preg_match('/\.[xX][mM][lL]$/', $file)) {
- ftp_delete($connId, $file);
- }
- }
-
- ftp_close($connId);
- } catch (Exception $e) {
- Mage::log($e->getMessage());
- return false;
- }
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Current tmp directory
- *
- * @return string
- */
- protected function _getTmpDir()
- {
- return Mage::getBaseDir('var') . DS . 'export' . DS . 'find_feed' . DS;
- }
-
- /**
- * Delete tmp file
- *
- * @param string $fileName
- * @return true
- */
- protected function _deleteFile($fileName)
- {
- $dir = $this->_getTmpDir();
- $file = new Varien_Io_File;
- if ($file->fileExists($dir . $fileName, true)) {
- $file->cd($dir);
- $file->rm($fileName);
- }
- return true;
- }
-}
diff --git a/app/code/community/Find/Feed/Model/Mysql4/Codes.php b/app/code/community/Find/Feed/Model/Mysql4/Codes.php
deleted file mode 100644
index c9eaff6f78..0000000000
--- a/app/code/community/Find/Feed/Model/Mysql4/Codes.php
+++ /dev/null
@@ -1,35 +0,0 @@
-getStore();
- $website = $observer->getWebsite();
- $groups['settings']['fields']['cron_schedule']['value'] = $this->_getSchedule();
-
- Mage::getModel('adminhtml/config_data')
- ->setSection('feed')
- ->setWebsite($website)
- ->setStore($store)
- ->setGroups($groups)
- ->save();
- }
-
- /**
- * Transform system settings option to cron schedule string
- *
- * @return string
- */
- protected function _getSchedule()
- {
- $data = Mage::app()->getRequest()->getPost('groups');
-
- $frequency = !empty($data['settings']['fields']['cron_frequency']['value'])?
- $data['settings']['fields']['cron_frequency']['value']:
- 0;
- $hours = !empty($data['settings']['fields']['cron_hours']['value'])?
- $data['settings']['fields']['cron_hours']['value']:
- 0;
-
- $schedule = "0 $hours ";
-
- switch ($frequency) {
- case Find_Feed_Model_Adminhtml_System_Source_Cron_Frequency::DAILY:
- $schedule .= "* * *";
- break;
- case Find_Feed_Model_Adminhtml_System_Source_Cron_Frequency::WEEKLY:
- $schedule .= "* * 1";
- break;
- case Find_Feed_Model_Adminhtml_System_Source_Cron_Frequency::MONTHLY:
- $schedule .= "1 * *";
- break;
- case Find_Feed_Model_Adminhtml_System_Source_Cron_Frequency::EVERY_MINUTE:
- $schedule = "0-59 * * * *";
- break;
- default:
- $schedule .= "* */1 *";
- break;
- }
-
- return $schedule;
- }
-}
diff --git a/app/code/community/Find/Feed/controllers/Adminhtml/Codes/GridController.php b/app/code/community/Find/Feed/controllers/Adminhtml/Codes/GridController.php
deleted file mode 100644
index 5d323df366..0000000000
--- a/app/code/community/Find/Feed/controllers/Adminhtml/Codes/GridController.php
+++ /dev/null
@@ -1,161 +0,0 @@
-loadLayout();
- $this->renderLayout();
- }
-
- /**
- * Grid action
- *
- */
- public function gridAction()
- {
- $this->loadLayout();
- $this->getResponse()->setBody($this->getLayout()->createBlock('find_feed/adminhtml_list_codes_grid')->toHtml());
- }
-
- /**
- * Grid edit form action
- *
- */
- public function editFormAction()
- {
- $this->loadLayout();
- $this->getResponse()->setBody($this->getLayout()->createBlock('find_feed/adminhtml_edit_codes')->toHtml());
- }
-
- /**
- * Save grid edit form action
- *
- */
- public function saveFormAction()
- {
- $codeId = $this->getRequest()->getParam('code_id');
- $response = new Varien_Object();
- try {
- $model = Mage::getModel('find_feed/codes');
- if ($codeId) {
- $model->load($codeId);
- }
- $model->setImportCode($this->getRequest()->getParam('import_code'));
- $model->setEavCode($this->getRequest()->getParam('eav_code'));
- $model->setIsImported(intval($this->getRequest()->getParam('is_imported')));
- $model->save();
- $response->setError(0);
- } catch(Exception $e) {
- $response->setError(1);
- $response->setMessage('Save error');
- }
- $this->getResponse()->setBody($response->toJson());
- }
-
- /**
- * Codes (attribute map) list for mass action
- *
- * @return array
- */
- protected function _getMassActionCodes()
- {
- $idList = $this->getRequest()->getParam('code_id');
- if (!empty($idList)) {
- $codes = array();
- foreach ($idList as $id) {
- $model = Mage::getModel('find_feed/codes');
- if ($model->load($id)) {
- array_push($codes, $model);
- }
- }
- return $codes;
- } else {
- return array();
- }
- }
-
- /**
- * Set imported codes (attribute map) mass action
- */
- public function massEnableAction()
- {
- $updatedCodes = 0;
- foreach ($this->_getMassActionCodes() as $code) {
- $code->setIsImported(1);
- $code->save();
- $updatedCodes++;
- }
- if ($updatedCodes > 0) {
- $this->_getSession()->addSuccess(Mage::helper('find_feed')->__("%s codes imported", $updatedCodes));
- }
- $this->_redirect('*/*/index');
- }
-
- /**
- * Set not imported codes (attribute map) mass action
- */
- public function massDisableAction()
- {
- $updatedCodes = 0;
- foreach ($this->_getMassActionCodes() as $code) {
- $code->setIsImported(0);
- $code->save();
- $updatedCodes++;
- }
- if ($updatedCodes > 0) {
- $this->_getSession()->addSuccess(Mage::helper('find_feed')->__("%s codes not imported", $updatedCodes));
- }
- $this->_redirect('*/*/index');
- }
-
- /**
- * Delete codes (attribute map) mass action
- */
- public function deleteAction()
- {
- $updatedCodes = 0;
- foreach ($this->_getMassActionCodes() as $code) {
- $code->delete();
- $updatedCodes++;
- }
- if ($updatedCodes > 0) {
- $this->_getSession()->addSuccess(Mage::helper('find_feed')->__("%s codes deleted", $updatedCodes));
- }
- $this->_redirect('*/*/index');
- }
-}
diff --git a/app/code/community/Find/Feed/controllers/Adminhtml/Items/GridController.php b/app/code/community/Find/Feed/controllers/Adminhtml/Items/GridController.php
deleted file mode 100644
index 19272957fd..0000000000
--- a/app/code/community/Find/Feed/controllers/Adminhtml/Items/GridController.php
+++ /dev/null
@@ -1,115 +0,0 @@
-loadLayout();
- $this->renderLayout();
- }
-
- /**
- * Grid action
- */
- public function gridAction()
- {
- $this->loadLayout();
- $this->getResponse()->setBody($this->getLayout()->createBlock('find_feed/adminhtml_list_items_grid')->toHtml());
- }
-
- /**
- * Product list for mass action
- *
- * @return array
- */
- protected function _getMassActionProducts()
- {
- $idList = $this->getRequest()->getParam('item_id');
- if (!empty($idList)) {
- $products = array();
- foreach ($idList as $id) {
- $model = Mage::getModel('catalog/product');
- if ($model->load($id)) {
- array_push($products, $model);
- }
- }
- return $products;
- } else {
- return array();
- }
- }
-
- /**
- * Add product to feed mass action
- */
- public function massEnableAction()
- {
- $idList = $this->getRequest()->getParam('item_id');
- $updateAction = Mage::getModel('catalog/product_action');
- $attrData = array(
- 'is_imported' => 1
- );
- $updatedProducts = count($idList);
- if ($updatedProducts) {
- try {
- $updateAction->updateAttributes($idList, $attrData, Mage::app()->getStore()->getId());
- Mage::getModel('find_feed/import')->processImport();
- $this->_getSession()->addSuccess(Mage::helper('find_feed')->__("%s product in feed.", $updatedProducts));
- } catch (Exception $e) {
- $this->_getSession()->addError(Mage::helper('find_feed')->__("Unable to process an import. ") . $e->getMessage());
- }
- }
- $this->_redirect('*/*/index');
- }
-
- /**
- * Not add product to feed mass action
- */
- public function massDisableAction()
- {
- $updatedProducts = 0;
- foreach ($this->_getMassActionProducts() as $product) {
- $product->setIsImported(0);
- $product->save();
- $updatedProducts++;
- }
- if ($updatedProducts) {
- Mage::getModel('find_feed/import')->processImport();
- $this->_getSession()->addSuccess(Mage::helper('find_feed')->__("%s product not in feed.", $updatedProducts));
- }
- $this->_redirect('*/*/index');
- }
-}
diff --git a/app/code/community/Find/Feed/etc/adminhtml.xml b/app/code/community/Find/Feed/etc/adminhtml.xml
deleted file mode 100644
index e83e3adc23..0000000000
--- a/app/code/community/Find/Feed/etc/adminhtml.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
diff --git a/app/code/community/Find/Feed/etc/config.xml b/app/code/community/Find/Feed/etc/config.xml
deleted file mode 100755
index 7c7452a187..0000000000
--- a/app/code/community/Find/Feed/etc/config.xml
+++ /dev/null
@@ -1,481 +0,0 @@
-
-
-
-
-
- 1.6.0.0
-
-
-
-
-
- Find_Feed_Model
- find_feed_resource
-
-
- Find_Feed_Model_Resource
- find_feed_mysql4
-
-
-
find_feed_import_codes
-
-
-
-
-
-
-
- Find_Feed
- Find_Feed_Model_Resource_Setup
-
-
-
-
- Find_Feed_Block
-
-
-
- Find_Feed_Helper
-
-
-
-
-
-
-
-
- find_feed/observer
- saveSystemConfig
-
-
-
-
-
-
-
-
-
-
-
-
-
- Feed
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- feed/settings/cron_schedule
-
-
- find_feed/import::dispatch
-
-
-
-
-
-
-
-
-
- Find_Feed_Adminhtml
-
-
-
-
-
-
-
-
-
- find
-
-
-
-
-
-
-
-
- feed.xml
-
-
-
-
-
-
- 1
-
-
-
- 1
-
-
-
- 1
-
-
-
- 1
-
-
-
- 1
-
-
-
- 0
-
-
-
- 0
- UPC-EAN
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
- 0
-
-
-
-
diff --git a/app/code/community/Find/Feed/etc/system.xml b/app/code/community/Find/Feed/etc/system.xml
deleted file mode 100755
index 46a8d5dc09..0000000000
--- a/app/code/community/Find/Feed/etc/system.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
-
-
- 300
-
-
-
-
-
- find
- 100
- 1
- 1
- 1
-
-
-
- text
- 200
- 1
- 1
- 1
-
-
-
-
-
-
- text
- 10
- 1
- 1
- 1
-
-
-
- text
- 15
- 1
- 1
- 1
-
-
-
- text
- 20
- 1
- 1
- 1
- here to get started.]]>
-
-
-
- password
- 30
- 1
- 1
- 1
-
-
-
- text
- 30
- 1
- 1
- 1
-
-
- 40
-
- select
- adminhtml/system_config_source_yesno
- 1
- 1
- 1
-
-
-
- select
- find_feed/adminhtml_system_source_cron_frequency
- 60
- 1
- 1
- 1
-
-
-
- select
- find_feed/adminhtml_system_source_cron_hours
- 70
- 1
- 1
- 1
-
-
-
-
-
-
-
diff --git a/app/code/community/Find/Feed/sql/find_feed_setup/install-1.6.0.0.php b/app/code/community/Find/Feed/sql/find_feed_setup/install-1.6.0.0.php
deleted file mode 100644
index 04cd448c99..0000000000
--- a/app/code/community/Find/Feed/sql/find_feed_setup/install-1.6.0.0.php
+++ /dev/null
@@ -1,74 +0,0 @@
-startSetup();
-/**
- * Create table 'find_feed/feed_import_codes'
- */
-$table = $installer->getConnection()
- ->newTable($installer->getTable('find_feed/feed_import_codes'))
- ->addColumn('code_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
- 'identity' => true,
- 'unsigned' => true,
- 'nullable' => false,
- 'primary' => true,
- ), 'Code id')
- ->addColumn('import_code', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array(
- 'nullable' => false,
- ), 'Import type')
- ->addColumn('eav_code', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array(
- 'nullable' => false,
- ), 'EAV code')
- ->addColumn('is_imported', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
- 'nullable' => false,
- ), 'Is imported')
- ->setComment('Find feed import codes');
-$installer->getConnection()->createTable($table);
-
-$this->addAttribute('catalog_product', 'is_imported', array(
- 'group' => 'General',
- 'type' => 'int',
- 'input' => 'select',
- 'label' => 'In feed',
- 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
- 'visible' => 1,
- 'required' => 0,
- 'visible_on_front' => 0,
- 'is_html_allowed_on_front' => 0,
- 'is_configurable' => 0,
- 'source' => 'eav/entity_attribute_source_boolean',
- 'searchable' => 0,
- 'filterable' => 0,
- 'comparable' => 0,
- 'unique' => false,
- 'user_defined' => false,
- 'is_user_defined' => false,
- 'used_in_product_listing' => true
-));
-
-$installer->endSetup();
diff --git a/app/code/community/Find/Feed/sql/find_feed_setup/mysql4-install-0.0.1.php b/app/code/community/Find/Feed/sql/find_feed_setup/mysql4-install-0.0.1.php
deleted file mode 100755
index 7545aab007..0000000000
--- a/app/code/community/Find/Feed/sql/find_feed_setup/mysql4-install-0.0.1.php
+++ /dev/null
@@ -1,41 +0,0 @@
-startSetup();
-
-$this->run("
-
-CREATE TABLE {$this->getTable('find_feed_import_codes')} (
- `code_id` int(10) unsigned NOT NULL auto_increment,
- `import_code` varchar(255) NOT NULL,
- `eav_code` varchar(255) NOT NULL,
- `is_imported` int(10) unsigned NOT NULL,
- PRIMARY KEY (`code_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
-");
-
-$this->endSetup();
diff --git a/app/code/community/Find/Feed/sql/find_feed_setup/mysql4-upgrade-0.0.1-0.0.2.php b/app/code/community/Find/Feed/sql/find_feed_setup/mysql4-upgrade-0.0.1-0.0.2.php
deleted file mode 100644
index a7f84e24c5..0000000000
--- a/app/code/community/Find/Feed/sql/find_feed_setup/mysql4-upgrade-0.0.1-0.0.2.php
+++ /dev/null
@@ -1,50 +0,0 @@
-startSetup();
-
-$this->addAttribute('catalog_product', 'is_imported', array(
- 'group' => 'General',
- 'type' => 'int',
- 'input' => 'select',
- 'label' => 'In feed',
- 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
- 'visible' => 1,
- 'required' => 0,
- 'visible_on_front' => 0,
- 'is_html_allowed_on_front' => 0,
- 'is_configurable' => 0,
- 'source' => 'eav/entity_attribute_source_boolean',
- 'searchable' => 0,
- 'filterable' => 0,
- 'comparable' => 0,
- 'unique' => false,
- 'user_defined' => false,
- 'is_user_defined' => false,
- 'used_in_product_listing' => true
-));
-
-$this->endSetup();
diff --git a/app/code/community/Find/Feed/Block/Adminhtml/Edit/Codes.php b/app/code/core/Mage/Admin/Helper/Data.php
similarity index 55%
rename from app/code/community/Find/Feed/Block/Adminhtml/Edit/Codes.php
rename to app/code/core/Mage/Admin/Helper/Data.php
index e150b1538f..cc480c9385 100644
--- a/app/code/community/Find/Feed/Block/Adminhtml/Edit/Codes.php
+++ b/app/code/core/Mage/Admin/Helper/Data.php
@@ -18,47 +18,44 @@
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
- * @category
- * @package _storage
+ * @category Mage
+ * @package Mage_Admin
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-
/**
- * Attribute map edit codes form container block
+ * Admin Data Helper
*
- * @category Find
- * @package Find_Feed
+ * @category Mage
+ * @package Mage_Admin
* @author Magento Core Team
*/
-class Find_Feed_Block_Adminhtml_Edit_Codes extends Mage_Adminhtml_Block_Widget_Form_Container
+class Mage_Admin_Helper_Data extends Mage_Core_Helper_Abstract
{
/**
- * Initialize form container
+ * Configuration path to expiration period of reset password link
+ */
+ const XML_PATH_ADMIN_RESET_PASSWORD_LINK_EXPIRATION_PERIOD
+ = 'default/admin/emails/password_reset_link_expiration_period';
+
+ /**
+ * Generate unique token for reset password confirmation link
*
+ * @return string
*/
- public function __construct()
+ public function generateResetPasswordLinkToken()
{
- $this->_blockGroup = 'find_feed';
- $this->_controller = 'adminhtml_edit_codes';
-
- parent::__construct();
-
- $this->_removeButton('back');
- $url = $this->getUrl('*/codes_grid/saveForm');
- $this->_updateButton('save', 'onclick', 'saveNewImportItem(\''.$url.'\')');
- $this->_updateButton('reset', 'label', 'Close');
- $this->_updateButton('reset', 'onclick', 'closeNewImportItem()');
+ return Mage::helper('core')->uniqHash();
}
/**
- * Return Form Header text
+ * Retrieve customer reset password link expiration period in days
*
- * @return string
+ * @return int
*/
- public function getHeaderText()
+ public function getResetPasswordLinkExpirationPeriod()
{
- return Mage::helper('find_feed')->__('Import attribute map');
+ return (int) Mage::getConfig()->getNode(self::XML_PATH_ADMIN_RESET_PASSWORD_LINK_EXPIRATION_PERIOD);
}
}
diff --git a/app/code/core/Mage/Admin/Model/Observer.php b/app/code/core/Mage/Admin/Model/Observer.php
index ebc30aa242..c685beb3c0 100644
--- a/app/code/core/Mage/Admin/Model/Observer.php
+++ b/app/code/core/Mage/Admin/Model/Observer.php
@@ -27,23 +27,35 @@
/**
* Admin observer model
*
- * @category Mage
- * @package Mage_Admin
+ * @category Mage
+ * @package Mage_Admin
* @author Magento Core Team
*/
class Mage_Admin_Model_Observer
{
- public function actionPreDispatchAdmin($event)
+ /**
+ * Handler for controller_action_predispatch event
+ *
+ * @param Varien_Event_Observer $observer
+ * @return boolean
+ */
+ public function actionPreDispatchAdmin($observer)
{
- $session = Mage::getSingleton('admin/session');
- /* @var $session Mage_Admin_Model_Session */
+ $session = Mage::getSingleton('admin/session');
+ /** @var $session Mage_Admin_Model_Session */
$request = Mage::app()->getRequest();
$user = $session->getUser();
- if ($request->getActionName() == 'forgotpassword' || $request->getActionName() == 'logout') {
+ $requestedActionName = $request->getActionName();
+ $openActions = array(
+ 'forgotpassword',
+ 'resetpassword',
+ 'resetpasswordpost',
+ 'logout'
+ );
+ if (in_array($requestedActionName, $openActions)) {
$request->setDispatched(true);
- }
- else {
+ } else {
if($user) {
$user->reload();
}
@@ -61,8 +73,7 @@ public function actionPreDispatchAdmin($event)
->setControllerName('index')
->setActionName('deniedIframe')
->setDispatched(false);
- }
- elseif($request->getParam('isAjax')) {
+ } elseif($request->getParam('isAjax')) {
$request->setParam('forwarded', true)
->setControllerName('index')
->setActionName('deniedJson')
diff --git a/app/code/core/Mage/Admin/Model/User.php b/app/code/core/Mage/Admin/Model/User.php
index d2721714c1..f9b37bebcd 100644
--- a/app/code/core/Mage/Admin/Model/User.php
+++ b/app/code/core/Mage/Admin/Model/User.php
@@ -60,22 +60,41 @@
*/
class Mage_Admin_Model_User extends Mage_Core_Model_Abstract
{
+ /**
+ * Configuration pathes for email templates and identities
+ */
const XML_PATH_FORGOT_EMAIL_TEMPLATE = 'admin/emails/forgot_email_template';
const XML_PATH_FORGOT_EMAIL_IDENTITY = 'admin/emails/forgot_email_identity';
const XML_PATH_STARTUP_PAGE = 'admin/startup/page';
+
+ /**
+ * Minimum length of admin password
+ */
const MIN_PASSWORD_LENGTH = 7;
+ /**
+ * Model event prefix
+ *
+ * @var string
+ */
protected $_eventPrefix = 'admin_user';
/**
+ * Admin role
+ *
* @var Mage_Admin_Model_Roles
*/
protected $_role;
+ /**
+ * Available resources flag
+ *
+ * @var boolean
+ */
protected $_hasAvailableResources = true;
/**
- * Varien constructor
+ * Initialize user model
*/
protected function _construct()
{
@@ -105,13 +124,15 @@ protected function _beforeSave()
$data['username'] = $this->getUsername();
}
- if ($this->getNewPassword()) { // change password
+ if ($this->getNewPassword()) {
+ // Change password
$data['password'] = $this->_getEncodedPassword($this->getNewPassword());
- } elseif ($this->getPassword() && $this->getPassword() != $this->getOrigData('password')) { // new user password
+ } elseif ($this->getPassword() && $this->getPassword() != $this->getOrigData('password')) {
+ // New user password
$data['password'] = $this->_getEncodedPassword($this->getPassword());
}
- if ( !is_null($this->getIsActive()) ) {
+ if (!is_null($this->getIsActive())) {
$data['is_active'] = intval($this->getIsActive());
}
@@ -146,6 +167,11 @@ public function saveRelations()
return $this;
}
+ /**
+ * Retrieve user roles
+ *
+ * @return array
+ */
public function getRoles()
{
return $this->_getResource()->getRoles($this);
@@ -168,30 +194,55 @@ public function getRole()
return $this->_role;
}
+ /**
+ * Unassign user from his current role
+ *
+ * @return Mage_Admin_Model_User
+ */
public function deleteFromRole()
{
$this->_getResource()->deleteFromRole($this);
return $this;
}
+ /**
+ * Check if such combination role/user exists
+ *
+ * @return boolean
+ */
public function roleUserExists()
{
$result = $this->_getResource()->roleUserExists($this);
- return ( is_array($result) && count($result) > 0 ) ? true : false;
+ return (is_array($result) && count($result) > 0) ? true : false;
}
+ /**
+ * Assign user to role
+ *
+ * @return Mage_Admin_Model_User
+ */
public function add()
{
$this->_getResource()->add($this);
return $this;
}
+ /**
+ * Check if user exists based on its id, username and email
+ *
+ * @return boolean
+ */
public function userExists()
{
$result = $this->_getResource()->userExists($this);
- return ( is_array($result) && count($result) > 0 ) ? true : false;
+ return (is_array($result) && count($result) > 0) ? true : false;
}
+ /**
+ * Retrieve admin user collection
+ *
+ * @return Mage_Admin_Model_Resource_User_Collection
+ */
public function getCollection() {
return Mage::getResourceModel('admin/user_collection');
}
@@ -200,32 +251,54 @@ public function getCollection() {
* Send email with new user password
*
* @return Mage_Admin_Model_User
+ * @deprecated deprecated since version 1.6.1.0
*/
public function sendNewPasswordEmail()
{
- $translate = Mage::getSingleton('core/translate');
- /* @var $translate Mage_Core_Model_Translate */
- $translate->setTranslateInline(false);
-
- Mage::getModel('core/email_template')
- ->setDesignConfig(array('area' => 'adminhtml', 'store' => $this->getStoreId()))
- ->sendTransactional(
- Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_TEMPLATE),
- Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_IDENTITY),
- $this->getEmail(),
- $this->getName(),
- array('user' => $this, 'password' => $this->getPlainPassword()));
+ return $this;
+ }
- $translate->setTranslateInline(true);
+ /**
+ * Send email with reset password confirmation link
+ *
+ * @return Mage_Admin_Model_User
+ */
+ public function sendPasswordResetConfirmationEmail()
+ {
+ /** @var $mailer Mage_Core_Model_Email_Template_Mailer */
+ $mailer = Mage::getModel('core/email_template_mailer');
+ $emailInfo = Mage::getModel('core/email_info');
+ $emailInfo->addTo($this->getEmail(), $this->getName());
+ $mailer->addEmailInfo($emailInfo);
+
+ // Set all required params and send emails
+ $mailer->setSender(Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_IDENTITY));
+ $mailer->setStoreId(0);
+ $mailer->setTemplateId(Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_TEMPLATE));
+ $mailer->setTemplateParams(array(
+ 'user' => $this
+ ));
+ $mailer->send();
return $this;
}
+ /**
+ * Retrieve user name
+ *
+ * @param string $separator
+ * @return string
+ */
public function getName($separator = ' ')
{
return $this->getFirstname() . $separator . $this->getLastname();
}
+ /**
+ * Retrieve user identifier
+ *
+ * @return mixed
+ */
public function getId()
{
return $this->getUserId();
@@ -301,6 +374,11 @@ public function login($username, $password)
return $this;
}
+ /**
+ * Reload current user
+ *
+ * @return Mage_Admin_Model_User
+ */
public function reload()
{
$id = $this->getId();
@@ -309,20 +387,38 @@ public function reload()
return $this;
}
+ /**
+ * Load user by its username
+ *
+ * @param string $username
+ * @return Mage_Admin_Model_User
+ */
public function loadByUsername($username)
{
$this->setData($this->getResource()->loadByUsername($username));
return $this;
}
+ /**
+ * Check if user is assigned to any role
+ *
+ * @param int|Mage_Core_Admin_Model_User $user
+ * @return null|boolean|array
+ */
public function hasAssigned2Role($user)
{
return $this->getResource()->hasAssigned2Role($user);
}
- protected function _getEncodedPassword($pwd)
+ /**
+ * Retrieve encoded password
+ *
+ * @param string $password
+ * @return string
+ */
+ protected function _getEncodedPassword($password)
{
- return Mage::helper('core')->getHash($pwd, 2);
+ return Mage::helper('core')->getHash($password, 2);
}
/**
@@ -425,7 +521,9 @@ public function validate()
$errors[] = Mage::helper('adminhtml')->__('Password must be at least of %d characters.', self::MIN_PASSWORD_LENGTH);
}
- if (!preg_match('/[a-z]/iu', $this->getNewPassword()) || !preg_match('/[0-9]/u', $this->getNewPassword())) {
+ if (!preg_match('/[a-z]/iu', $this->getNewPassword())
+ || !preg_match('/[0-9]/u', $this->getNewPassword())
+ ) {
$errors[] = Mage::helper('adminhtml')->__('Password must include both numeric and alphabetic characters.');
}
@@ -444,4 +542,55 @@ public function validate()
return $errors;
}
+ /**
+ * Change reset password link token
+ *
+ * Stores new reset password link token and its creation time
+ *
+ * @param string $newResetPasswordLinkToken
+ * @return Mage_Admin_Model_User
+ * @throws Mage_Core_Exception
+ */
+ public function changeResetPasswordLinkToken($newResetPasswordLinkToken) {
+ if (!is_string($newResetPasswordLinkToken) || empty($newResetPasswordLinkToken)) {
+ throw Mage::exception('Mage_Core', Mage::helper('adminhtml')->__('Invalid password reset token.'));
+ }
+ $this->setRpToken($newResetPasswordLinkToken);
+ $currentDate = Varien_Date::now(true);
+ $this->setRpTokenCreatedAt($currentDate);
+
+ return $this;
+ }
+
+ /**
+ * Check if current reset password link token is expired
+ *
+ * @return boolean
+ */
+ public function isResetPasswordLinkTokenExpired()
+ {
+ $resetPasswordLinkToken = $this->getRpToken();
+ $resetPasswordLinkTokenCreatedAt = $this->getRpTokenCreatedAt();
+
+ if (empty($resetPasswordLinkToken) || empty($resetPasswordLinkTokenCreatedAt)) {
+ return true;
+ }
+
+ $tokenExpirationPeriod = Mage::helper('admin')->getResetPasswordLinkExpirationPeriod();
+
+ $currentDate = Varien_Date::now(true);
+ $currentTimestamp = Varien_Date::toTimestamp($currentDate);
+ $tokenTimestamp = Varien_Date::toTimestamp($resetPasswordLinkTokenCreatedAt);
+ if ($tokenTimestamp > $currentTimestamp) {
+ return true;
+ }
+
+ $dayDifference = floor(($currentTimestamp - $tokenTimestamp) / (24 * 60 * 60));
+ if ($dayDifference >= $tokenExpirationPeriod) {
+ return true;
+ }
+
+ return false;
+ }
+
}
diff --git a/app/code/core/Mage/Admin/etc/config.xml b/app/code/core/Mage/Admin/etc/config.xml
index b4ce4f3093..8446743297 100644
--- a/app/code/core/Mage/Admin/etc/config.xml
+++ b/app/code/core/Mage/Admin/etc/config.xml
@@ -28,7 +28,7 @@
- 1.6.0.0
+ 1.6.1.0
@@ -56,6 +56,11 @@
+
+
+ Mage_Admin_Helper
+
+
@@ -74,6 +79,7 @@
admin_emails_forgot_email_templategeneral
+ 3
diff --git a/app/code/core/Mage/GoogleOptimizer/sql/googleoptimizer_setup/mysql4-install-0.1.0.php b/app/code/core/Mage/Admin/sql/admin_setup/mysql4-upgrade-1.6.0.0-1.6.1.0.php
similarity index 56%
rename from app/code/core/Mage/GoogleOptimizer/sql/googleoptimizer_setup/mysql4-install-0.1.0.php
rename to app/code/core/Mage/Admin/sql/admin_setup/mysql4-upgrade-1.6.0.0-1.6.1.0.php
index 38da846c8a..8a48a5be82 100644
--- a/app/code/core/Mage/GoogleOptimizer/sql/googleoptimizer_setup/mysql4-install-0.1.0.php
+++ b/app/code/core/Mage/Admin/sql/admin_setup/mysql4-upgrade-1.6.0.0-1.6.1.0.php
@@ -19,32 +19,30 @@
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Admin
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+/** @var $installer Mage_Core_Model_Resource_Setup */
$installer = $this;
-/* @var $installer Mage_Core_Model_Resource_Setup */
-
$installer->startSetup();
-$installer->run("
-
-DROP TABLE IF EXISTS {$this->getTable('googleoptimizer/code')};
-CREATE TABLE {$this->getTable('googleoptimizer/code')} (
- `code_id` int(10) unsigned NOT NULL auto_increment,
- `entity_id` int(10) unsigned NOT NULL,
- `entity_type` varchar(50) NOT NULL default '',
- `store_id` smallint(5) unsigned NOT NULL,
- `control_script` text,
- `tracking_script` text,
- `conversion_script` text,
- PRIMARY KEY (`code_id`),
- KEY `GOOGLEOPTIMIZER_CODE_STORE` (`store_id`),
- CONSTRAINT `FK_GOOGLEOPTIMIZER_CODE_STORE` FOREIGN KEY (`store_id`) REFERENCES `{$this->getTable('core/store')}` (`store_id`) ON DELETE CASCADE ON UPDATE CASCADE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+// Add reset password link token column
+$installer->getConnection()->addColumn($installer->getTable('admin/user'), 'rp_token', array(
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
+ 'length' => 256,
+ 'nullable' => true,
+ 'default' => null,
+ 'comment' => 'Reset Password Link Token'
+));
- ");
+// Add reset password link token creation date column
+$installer->getConnection()->addColumn($installer->getTable('admin/user'), 'rp_token_created_at', array(
+ 'type' => Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
+ 'nullable' => true,
+ 'default' => null,
+ 'comment' => 'Reset Password Link Token Creation Date'
+));
$installer->endSetup();
diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit.php
index 69e4f777a1..1eb19e6042 100644
--- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit.php
+++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Edit.php
@@ -42,16 +42,4 @@ public function __construct()
parent::__construct();
$this->setTemplate('catalog/category/edit.phtml');
}
-
- protected function _prepareLayout()
- {
- $category = Mage::registry('current_category');
- if (Mage::app()->getConfig()->getModuleConfig('Mage_GoogleOptimizer')->is('active', true)
- && Mage::helper('googleoptimizer')->isOptimizerActive($category->getStoreId())) {
- $this->setChild('googleoptimizer_js',
- $this->getLayout()->createBlock('googleoptimizer/js')->setTemplate('googleoptimizer/js.phtml')
- );
- }
- return parent::_prepareLayout();
- }
}
diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php
index 8417c19290..33c03fd777 100644
--- a/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php
+++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tabs.php
@@ -147,7 +147,10 @@ protected function _prepareLayout()
$this->addTab('products', array(
'label' => Mage::helper('catalog')->__('Category Products'),
- 'content' => $this->getLayout()->createBlock('adminhtml/catalog_category_tab_product', 'category.product.grid')->toHtml(),
+ 'content' => $this->getLayout()->createBlock(
+ 'adminhtml/catalog_category_tab_product',
+ 'category.product.grid'
+ )->toHtml(),
));
// dispatch event add custom tabs
@@ -155,17 +158,6 @@ protected function _prepareLayout()
'tabs' => $this
));
- /**
- * @todo Adding tab in observer
- */
- if (Mage::app()->getConfig()->getModuleConfig('Mage_GoogleOptimizer')->is('active', true)
- && Mage::helper('googleoptimizer')->isOptimizerActive($this->getCategory()->getStoreId())) {
- $this->addTab('googleoptimizer', array(
- 'label' => Mage::helper('googleoptimizer')->__('Category View Optimization'),
- 'content' => $this->getLayout()->createBlock('googleoptimizer/adminhtml_catalog_category_edit_tab_googleoptimizer')->toHtml(),
- ));
- }
-
/*$this->addTab('features', array(
'label' => Mage::helper('catalog')->__('Feature Products'),
'content' => 'Feature Products'
diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit/Form.php b/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit/Form.php
index d442aa3b36..5466380aec 100644
--- a/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit/Form.php
+++ b/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit/Form.php
@@ -44,12 +44,16 @@ protected function _prepareLayout()
$fieldset = $form->addFieldset('base_fieldset', array('legend'=>Mage::helper('customer')->__('Group Information')));
+ $validateClass = sprintf('required-entry validate-length maximum-length-%d',
+ Mage_Customer_Model_Group::GROUP_CODE_MAX_LENGTH);
$name = $fieldset->addField('customer_group_code', 'text',
array(
'name' => 'code',
'label' => Mage::helper('customer')->__('Group Name'),
'title' => Mage::helper('customer')->__('Group Name'),
- 'class' => 'required-entry',
+ 'note' => Mage::helper('customer')->__('Maximum length must be less then %s symbols',
+ Mage_Customer_Model_Group::GROUP_CODE_MAX_LENGTH),
+ 'class' => $validateClass,
'required' => true,
)
);
diff --git a/app/code/core/Mage/Adminhtml/Block/Page/Menu.php b/app/code/core/Mage/Adminhtml/Block/Page/Menu.php
index f92f9af252..3b2d86e386 100644
--- a/app/code/core/Mage/Adminhtml/Block/Page/Menu.php
+++ b/app/code/core/Mage/Adminhtml/Block/Page/Menu.php
@@ -27,6 +27,9 @@
/**
* Adminhtml menu block
*
+ * @method Mage_Adminhtml_Block_Page_Menu setAdditionalCacheKeyInfo(array $cacheKeyInfo)
+ * @method array getAdditionalCacheKeyInfo()
+ *
* @category Mage
* @package Mage_Adminhtml
* @author Magento Core Team
@@ -71,12 +74,18 @@ public function getCacheLifetime()
*/
public function getCacheKeyInfo()
{
- return array(
+ $cacheKeyInfo = array(
'admin_top_nav',
$this->getActive(),
Mage::getSingleton('admin/session')->getUser()->getId(),
Mage::app()->getLocale()->getLocaleCode()
);
+ // Add additional key parameters if needed
+ $additionalCacheKeyInfo = $this->getAdditionalCacheKeyInfo();
+ if (is_array($additionalCacheKeyInfo) && !empty($additionalCacheKeyInfo)) {
+ $cacheKeyInfo = array_merge($cacheKeyInfo, $additionalCacheKeyInfo);
+ }
+ return $cacheKeyInfo;
}
/**
diff --git a/app/code/core/Mage/GoogleOptimizer/Model/Mysql4/Code/Collection.php b/app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Js.php
similarity index 82%
rename from app/code/core/Mage/GoogleOptimizer/Model/Mysql4/Code/Collection.php
rename to app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Js.php
index 75447ad631..34cee5950f 100644
--- a/app/code/core/Mage/GoogleOptimizer/Model/Mysql4/Code/Collection.php
+++ b/app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Js.php
@@ -19,19 +19,18 @@
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Adminhtml
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-
/**
- * Google Optimizer collection
+ * description
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Adminhtml
* @author Magento Core Team
*/
-class Mage_GoogleOptimizer_Model_Mysql4_Code_Collection extends Mage_GoogleOptimizer_Model_Resource_Code_Collection
+class Mage_Adminhtml_Block_Promo_Catalog_Edit_Js extends Mage_Adminhtml_Block_Template
{
}
diff --git a/app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Tab/Actions.php b/app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Tab/Actions.php
index 964eed53ba..ec29c1ca1c 100644
--- a/app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Tab/Actions.php
+++ b/app/code/core/Mage/Adminhtml/Block/Promo/Catalog/Edit/Tab/Actions.php
@@ -28,8 +28,7 @@
* description
*
* @category Mage
- * @category Mage
- * @package Mage_Adminhtml
+ * @package Mage_Adminhtml
* @author Magento Core Team
*/
class Mage_Adminhtml_Block_Promo_Catalog_Edit_Tab_Actions
@@ -80,38 +79,69 @@ protected function _prepareForm()
{
$model = Mage::registry('current_promo_catalog_rule');
- //$form = new Varien_Data_Form(array('id' => 'edit_form1', 'action' => $this->getData('action'), 'method' => 'post'));
$form = new Varien_Data_Form();
$form->setHtmlIdPrefix('rule_');
- $fieldset = $form->addFieldset('action_fieldset', array('legend'=>Mage::helper('salesrule')->__('Update Prices Using the Following Information')));
+ $fieldset = $form->addFieldset('action_fieldset', array(
+ 'legend' => Mage::helper('catalogrule')->__('Update Prices Using the Following Information')
+ )
+ );
$fieldset->addField('simple_action', 'select', array(
- 'label' => Mage::helper('salesrule')->__('Apply'),
+ 'label' => Mage::helper('catalogrule')->__('Apply'),
'name' => 'simple_action',
- 'options' => array(
- 'by_percent' => Mage::helper('salesrule')->__('By Percentage of the Original Price'),
- 'by_fixed' => Mage::helper('salesrule')->__('By Fixed Amount'),
- 'to_percent' => Mage::helper('salesrule')->__('To Percentage of the Original Price'),
- 'to_fixed' => Mage::helper('salesrule')->__('To Fixed Amount'),
+ 'options' => array(
+ 'by_percent' => Mage::helper('catalogrule')->__('By Percentage of the Original Price'),
+ 'by_fixed' => Mage::helper('catalogrule')->__('By Fixed Amount'),
+ 'to_percent' => Mage::helper('catalogrule')->__('To Percentage of the Original Price'),
+ 'to_fixed' => Mage::helper('catalogrule')->__('To Fixed Amount'),
),
));
$fieldset->addField('discount_amount', 'text', array(
- 'name' => 'discount_amount',
- 'required' => true,
- 'class' => 'validate-not-negative-number',
- 'label' => Mage::helper('salesrule')->__('Discount Amount'),
+ 'name' => 'discount_amount',
+ 'required' => true,
+ 'class' => 'validate-not-negative-number',
+ 'label' => Mage::helper('catalogrule')->__('Discount Amount'),
+ ));
+
+ $fieldset->addField('sub_is_enable', 'select', array(
+ 'name' => 'sub_is_enable',
+ 'label' => Mage::helper('catalogrule')->__('Enable Discount to Subproducts'),
+ 'title' => Mage::helper('catalogrule')->__('Enable Discount to Subproducts'),
+ 'onchange' => 'hideShowSubproductOptions(this);',
+ 'values' => array(
+ 0 => Mage::helper('catalogrule')->__('No'),
+ 1 => Mage::helper('catalogrule')->__('Yes')
+ )
+ ));
+
+ $fieldset->addField('sub_simple_action', 'select', array(
+ 'label' => Mage::helper('catalogrule')->__('Apply'),
+ 'name' => 'sub_simple_action',
+ 'options' => array(
+ 'by_percent' => Mage::helper('catalogrule')->__('By Percentage of the Original Price'),
+ 'by_fixed' => Mage::helper('catalogrule')->__('By Fixed Amount'),
+ 'to_percent' => Mage::helper('catalogrule')->__('To Percentage of the Original Price'),
+ 'to_fixed' => Mage::helper('catalogrule')->__('To Fixed Amount'),
+ ),
+ ));
+
+ $fieldset->addField('sub_discount_amount', 'text', array(
+ 'name' => 'sub_discount_amount',
+ 'required' => true,
+ 'class' => 'validate-not-negative-number',
+ 'label' => Mage::helper('catalogrule')->__('Discount Amount'),
));
$fieldset->addField('stop_rules_processing', 'select', array(
- 'label' => Mage::helper('salesrule')->__('Stop Further Rules Processing'),
- 'title' => Mage::helper('salesrule')->__('Stop Further Rules Processing'),
+ 'label' => Mage::helper('catalogrule')->__('Stop Further Rules Processing'),
+ 'title' => Mage::helper('catalogrule')->__('Stop Further Rules Processing'),
'name' => 'stop_rules_processing',
- 'options' => array(
- '1' => Mage::helper('salesrule')->__('Yes'),
- '0' => Mage::helper('salesrule')->__('No'),
+ 'options' => array(
+ '1' => Mage::helper('catalogrule')->__('Yes'),
+ '0' => Mage::helper('catalogrule')->__('No'),
),
));
diff --git a/app/code/core/Mage/Adminhtml/Block/Report/Tag/Popular/Detail/Grid.php b/app/code/core/Mage/Adminhtml/Block/Report/Tag/Popular/Detail/Grid.php
index 66de6ca950..5067ac356c 100644
--- a/app/code/core/Mage/Adminhtml/Block/Report/Tag/Popular/Detail/Grid.php
+++ b/app/code/core/Mage/Adminhtml/Block/Report/Tag/Popular/Detail/Grid.php
@@ -40,24 +40,30 @@ public function __construct()
$this->setId('tag_grid');
}
+ /**
+ * Prepare collection for grid
+ *
+ * @return Mage_Adminhtml_Block_Report_Tag_Popular_Detail_Grid
+ */
protected function _prepareCollection()
{
-
- $collection = Mage::getResourceModel('reports/tag_customer_collection')
- ->addStatusFilter(Mage::getModel('tag/tag')->getApprovedStatus())
+ /* @var $collection Mage_Reports_Model_Resource_Tag_Customer_Collection */
+ $collection = Mage::getResourceModel('reports/tag_customer_collection');
+ $collection->addStatusFilter(Mage::getModel('tag/tag')->getApprovedStatus())
->addTagFilter($this->getRequest()->getParam('id'))
- ->addDescOrder();
+ ->addDescOrder()
+ ->addProductName();
$this->setCollection($collection);
return parent::_prepareCollection();
}
- protected function _afterLoadCollection()
- {
- $this->getCollection()->addProductName();
- }
-
+ /**
+ * Form columns for the grid
+ *
+ * @return Mage_Adminhtml_Block_Report_Tag_Popular_Detail_Grid
+ */
protected function _prepareColumns()
{
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Form/Abstract.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Form/Abstract.php
index 15b3ad601c..5b29721c3d 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Form/Abstract.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Form/Abstract.php
@@ -141,7 +141,8 @@ protected function _addAttributesToForm($attributes, Varien_Data_Form_Abstract $
$renderers = $this->_getAdditionalFormElementRenderers();
foreach ($attributes as $attribute) {
- /* @var $attribute Mage_Customer_Model_Attribute */
+ /** @var $attribute Mage_Customer_Model_Attribute */
+ $attribute->setStoreId(Mage::getSingleton('adminhtml/session_quote')->getStoreId());
$inputType = $attribute->getFrontend()->getInputType();
if ($inputType) {
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage/Form.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage/Form.php
index 0f09b3f239..6848bb0e48 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage/Form.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Giftmessage/Form.php
@@ -233,9 +233,6 @@ protected function _prepareVisibleFields(Varien_Data_Form_Element_Fieldset $fiel
'label' => Mage::helper('sales')->__('Message'),
'rows' => '5',
'cols' => '20',
- 'onchange' => 'giftMessagesController.toogleRequired(\'' . $this->_getFieldId('message')
- . '\', [\'' . $this->_getFieldId('sender')
- . '\', \'' . $this->_getFieldId('recipient') . '\']);'
)
);
return $this;
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Search/Grid.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Search/Grid.php
index 181c4600bc..df9604407d 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Search/Grid.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Create/Search/Grid.php
@@ -87,14 +87,20 @@ protected function _addColumnFilterToCollection($column)
return $this;
}
+ /**
+ * Prepare collection to be displayed in the grid
+ *
+ * @return Mage_Adminhtml_Block_Sales_Order_Create_Search_Grid
+ */
protected function _prepareCollection()
{
$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
- $collection = Mage::getModel('catalog/product')->getCollection()
+ /* @var $collection Mage_Catalog_Model_Resource_Product_Collection */
+ $collection = Mage::getModel('catalog/product')->getCollection();
+ $collection
->setStore($this->getStore())
->addAttributeToSelect($attributes)
->addAttributeToSelect('sku')
- ->addMinimalPrice()
->addStoreFilter()
->addAttributeToFilter('type_id', array_keys(
Mage::getConfig()->getNode('adminhtml/sales/order/create/available_product_types')->asArray()
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Creditmemo/View.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Creditmemo/View.php
index 579ac45f0e..56314c13c0 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Creditmemo/View.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Creditmemo/View.php
@@ -188,7 +188,7 @@ public function getEmailUrl()
public function getPrintUrl()
{
return $this->getUrl('*/*/print', array(
- 'invoice_id' => $this->getCreditmemo()->getId()
+ 'creditmemo_id' => $this->getCreditmemo()->getId()
));
}
@@ -201,10 +201,18 @@ public function updateBackButtonUrl($flag)
{
if ($flag) {
if ($this->getCreditmemo()->getBackUrl()) {
- return $this->_updateButton('back', 'onclick', 'setLocation(\'' . $this->getCreditmemo()->getBackUrl() . '\')');
+ return $this->_updateButton(
+ 'back',
+ 'onclick',
+ 'setLocation(\'' . $this->getCreditmemo()->getBackUrl() . '\')'
+ );
}
- return $this->_updateButton('back', 'onclick', 'setLocation(\'' . $this->getUrl('*/sales_creditmemo/') . '\')');
+ return $this->_updateButton(
+ 'back',
+ 'onclick',
+ 'setLocation(\'' . $this->getUrl('*/sales_creditmemo/') . '\')'
+ );
}
return $this;
}
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Status/New/Form.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Status/New/Form.php
index 8ff7e3432c..075dc18602 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Status/New/Form.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Status/New/Form.php
@@ -61,7 +61,7 @@ protected function _prepareForm()
array(
'name' => 'status',
'label' => Mage::helper('sales')->__('Status Code'),
- 'class' => 'required-entry',
+ 'class' => 'required-entry validate-code',
'required' => true,
)
);
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php
index e36cbafcf2..fc89023963 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/Totals/Tax.php
@@ -42,33 +42,20 @@ public function getFullTaxInfo()
{
/** @var $source Mage_Sales_Model_Order */
$source = $this->getOrder();
- $info = array();
- if ($source instanceof Mage_Sales_Model_Order) {
-
- $rates = Mage::getModel('sales/order_tax')->getCollection()->loadByOrder($source)->toArray();
- $info = Mage::getSingleton('tax/calculation')->reproduceProcess($rates['items']);
- /**
- * Set right tax amount from invoice
- * (In $info tax invalid when invoice is partial)
- */
- /** @var $blockInvoice Mage_Adminhtml_Block_Sales_Order_Invoice_Totals */
-// $blockInvoice = $this->getLayout()->getBlock('tax');
- /** @var $invoice Mage_Sales_Model_Order_Invoice */
-// $invoice = $blockInvoice->getSource();
-// $items = $invoice->getItemsCollection();
- $i = 0;
- /** @var $item Mage_Sales_Model_Order_Invoice_Item */
-// foreach ($items as $item) {
-// $info[$i]['hidden'] = $item->getHiddenTaxAmount();
-// $info[$i]['amount'] = $item->getTaxAmount();
-// $info[$i]['base_amount'] = $item->getBaseTaxAmount();
-// $info[$i]['base_real_amount'] = $item->getBaseTaxAmount();
-// $i++;
-// }
+ $taxClassAmount = array();
+ if ($source instanceof Mage_Sales_Model_Order) {
+ $taxClassAmount = Mage::helper('tax')->getCalculatedTaxes($source);
+ if (empty($taxClassAmount)) {
+ $rates = Mage::getModel('sales/order_tax')->getCollection()->loadByOrder($source)->toArray();
+ $taxClassAmount = Mage::getSingleton('tax/calculation')->reproduceProcess($rates['items']);
+ } else {
+ $shippingTax = Mage::helper('tax')->getShippingTax($source);
+ $taxClassAmount = array_merge($shippingTax, $taxClassAmount);
+ }
}
- return $info;
+ return $taxClassAmount;
}
/**
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php
index 3a923bca61..13296a7c69 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/View.php
@@ -58,7 +58,12 @@ public function __construct()
));
// see if order has non-editable products as items
$nonEditableTypes = array_keys($this->getOrder()->getResource()->aggregateProductsByTypes(
- $order->getId(), array_keys(Mage::getConfig()->getNode('adminhtml/sales/order/create/available_product_types')->asArray()), false
+ $order->getId(),
+ array_keys(Mage::getConfig()
+ ->getNode('adminhtml/sales/order/create/available_product_types')
+ ->asArray()
+ ),
+ false
));
if ($nonEditableTypes) {
$this->_updateButton('order_edit', 'onclick',
@@ -161,7 +166,10 @@ public function __construct()
));
}
- if ($this->_isAllowedAction('reorder') && $this->helper('sales/reorder')->canReorder($order)) {
+ if ($this->_isAllowedAction('reorder')
+ && $this->helper('sales/reorder')->isAllowed($order->getStore())
+ && $order->canReorder()
+ ) {
$this->_addButton('order_reorder', array(
'label' => Mage::helper('sales')->__('Reorder'),
'onclick' => 'setLocation(\'' . $this->getReorderUrl() . '\')',
diff --git a/app/code/core/Mage/Adminhtml/Block/Sales/Order/View/Tab/History.php b/app/code/core/Mage/Adminhtml/Block/Sales/Order/View/Tab/History.php
index 17475ec70d..2d62888132 100644
--- a/app/code/core/Mage/Adminhtml/Block/Sales/Order/View/Tab/History.php
+++ b/app/code/core/Mage/Adminhtml/Block/Sales/Order/View/Tab/History.php
@@ -220,4 +220,15 @@ public function isHidden()
{
return false;
}
+
+ /**
+ * Customer Notification Applicable check method
+ *
+ * @param array $history
+ * @return boolean
+ */
+ public function isCustomerNotificationNotApplicable($historyItem)
+ {
+ return $historyItem['notified'] == Mage_Sales_Model_Order_Status_History::CUSTOMER_NOTIFICATION_NOT_APPLICABLE;
+ }
}
diff --git a/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Preview.php b/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Preview.php
index 9497ad88e2..7048b3d6f2 100644
--- a/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Preview.php
+++ b/app/code/core/Mage/Adminhtml/Block/System/Email/Template/Preview.php
@@ -44,6 +44,9 @@ protected function _toHtml()
$template->setTemplateText($this->getRequest()->getParam('text'));
$template->setTemplateStyles($this->getRequest()->getParam('styles'));
}
+ $template->setTemplateText(
+ $this->escapeHtml($template->getTemplateText())
+ );
Varien_Profiler::start("email_template_proccessing");
$vars = array();
diff --git a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Renderer/Options.php b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Renderer/Options.php
index 24c9952b57..1a1d984c0b 100644
--- a/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Renderer/Options.php
+++ b/app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Renderer/Options.php
@@ -56,9 +56,10 @@ public function render(Varien_Object $row)
}
}
return implode(', ', $res);
- }
- elseif (isset($options[$value])) {
+ } elseif (isset($options[$value])) {
return $options[$value];
+ } elseif (in_array($value, $options)) {
+ return $value;
}
return '';
}
diff --git a/app/code/core/Mage/Adminhtml/Controller/Sales/Creditmemo.php b/app/code/core/Mage/Adminhtml/Controller/Sales/Creditmemo.php
index 85a7bd6365..1f0fb53b67 100644
--- a/app/code/core/Mage/Adminhtml/Controller/Sales/Creditmemo.php
+++ b/app/code/core/Mage/Adminhtml/Controller/Sales/Creditmemo.php
@@ -122,7 +122,7 @@ public function pdfcreditmemosAction(){
public function printAction()
{
/** @see Mage_Adminhtml_Sales_Order_InvoiceController */
- if ($creditmemoId = $this->getRequest()->getParam('invoice_id')) { // invoice_id?!
+ if ($creditmemoId = $this->getRequest()->getParam('creditmemo_id')) {
if ($creditmemo = Mage::getModel('sales/order_creditmemo')->load($creditmemoId)) {
$pdf = Mage::getModel('sales/order_pdf_creditmemo')->getPdf(array($creditmemo));
$this->_prepareDownloadResponse('creditmemo'.Mage::getSingleton('core/date')->date('Y-m-d_H-i-s').
diff --git a/app/code/core/Mage/Adminhtml/Helper/Data.php b/app/code/core/Mage/Adminhtml/Helper/Data.php
index 7116343c7a..0db41a94c6 100644
--- a/app/code/core/Mage/Adminhtml/Helper/Data.php
+++ b/app/code/core/Mage/Adminhtml/Helper/Data.php
@@ -35,7 +35,8 @@ class Mage_Adminhtml_Helper_Data extends Mage_Core_Helper_Abstract
{
const XML_PATH_ADMINHTML_ROUTER_FRONTNAME = 'admin/routers/adminhtml/args/frontName';
const XML_PATH_USE_CUSTOM_ADMIN_URL = 'default/admin/url/use_custom';
- const XML_PATH_CUSTOM_ADMIN_URL = 'default/admin/url/custom';
+ const XML_PATH_USE_CUSTOM_ADMIN_PATH = 'default/admin/url/use_custom_path';
+ const XML_PATH_CUSTOM_ADMIN_PATH = 'default/admin/url/custom_path';
protected $_pageHelpUrl;
diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custom.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custom.php
index 0ca65bdd10..57a4a5fee5 100644
--- a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custom.php
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custom.php
@@ -26,7 +26,7 @@
/**
- * Adminhtml backend model for "Use Secure URLs in Admin" option
+ * Adminhtml backend model for "Custom Admin URL" option
*
* @category Mage
* @package Mage_Adminhtml
@@ -34,22 +34,71 @@
*/
class Mage_Adminhtml_Model_System_Config_Backend_Admin_Custom extends Mage_Core_Model_Config_Data
{
- const CONFIG_SCOPE = 'default';
+ const CONFIG_SCOPE = 'stores';
const CONFIG_SCOPE_ID = 0;
- const XML_PATH_UNSECURE_BASE_LINK_URL = 'web/unsecure/base_link_url';
- const XML_PATH_SECURE_BASE_LINK_URL = 'web/secure/base_link_url';
+ const XML_PATH_UNSECURE_BASE_URL = 'web/unsecure/base_url';
+ const XML_PATH_SECURE_BASE_URL = 'web/secure/base_url';
+ const XML_PATH_UNSECURE_BASE_LINK_URL = 'web/unsecure/base_link_url';
+ const XML_PATH_SECURE_BASE_LINK_URL = 'web/secure/base_link_url';
/**
- * Check whether redirect should be set
+ * Validate value before save
*
* @return Mage_Adminhtml_Model_System_Config_Backend_Admin_Custom
*/
protected function _beforeSave()
{
- if ($this->getOldValue() != $this->getValue()) {
- Mage::register('custom_admin_url_redirect', true, true);
+ $value = $this->getValue();
+
+ if (!empty($value) && substr($value, -2) !== '}}') {
+ $value = rtrim($value, '/').'/';
}
+
+ $this->setValue($value);
+ return $this;
+ }
+
+ /**
+ * Change secure/unsecure base_url after use_custom_url was modified
+ *
+ * @return Mage_Adminhtml_Model_System_Config_Backend_Admin_Custom
+ */
+ public function _afterSave()
+ {
+ $useCustomUrl = $this->getData('groups/url/fields/use_custom/value');
+ $value = $this->getValue();
+
+ if ($useCustomUrl == 1 && empty($value)) {
+ return $this;
+ }
+
+ if ($useCustomUrl == 1) {
+ Mage::getConfig()->saveConfig(
+ self::XML_PATH_SECURE_BASE_URL,
+ $value,
+ self::CONFIG_SCOPE,
+ self::CONFIG_SCOPE_ID
+ );
+ Mage::getConfig()->saveConfig(
+ self::XML_PATH_UNSECURE_BASE_URL,
+ $value,
+ self::CONFIG_SCOPE,
+ self::CONFIG_SCOPE_ID
+ );
+ } else {
+ Mage::getConfig()->deleteConfig(
+ self::XML_PATH_SECURE_BASE_URL,
+ self::CONFIG_SCOPE,
+ self::CONFIG_SCOPE_ID
+ );
+ Mage::getConfig()->deleteConfig(
+ self::XML_PATH_UNSECURE_BASE_URL,
+ self::CONFIG_SCOPE,
+ self::CONFIG_SCOPE_ID
+ );
+ }
+
return $this;
}
}
diff --git a/app/code/core/Mage/GoogleOptimizer/controllers/IndexController.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custompath.php
similarity index 64%
rename from app/code/core/Mage/GoogleOptimizer/controllers/IndexController.php
rename to app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custompath.php
index 4367077769..5c02fa82b4 100644
--- a/app/code/core/Mage/GoogleOptimizer/controllers/IndexController.php
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Custompath.php
@@ -19,23 +19,31 @@
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Adminhtml
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-require_once 'Mage/GoogleOptimizer/controllers/Adminhtml/Googleoptimizer/IndexController.php';
/**
- * GoogleOptimizer Front Controller
+ * Adminhtml backend model for "Custom Admin Path" option
*
* @category Mage
- * @package Mage_GoogleOptimizer
- * @name Mage_GoogleOptimizer_IndexController
+ * @package Mage_Adminhtml
* @author Magento Core Team
- * @deprecated after 1.4.2.0 Mage_GoogleOptimizer_Adminhtml_Googleoptimizer_IndexController is used
-*/
-class Mage_GoogleOptimizer_IndexController extends Mage_GoogleOptimizer_Adminhtml_Googleoptimizer_IndexController
+ */
+class Mage_Adminhtml_Model_System_Config_Backend_Admin_Custompath extends Mage_Core_Model_Config_Data
{
-
+ /**
+ * Check whether redirect should be set
+ *
+ * @return Mage_Adminhtml_Model_System_Config_Backend_Admin_Custom
+ */
+ protected function _beforeSave()
+ {
+ if ($this->getOldValue() != $this->getValue()) {
+ Mage::register('custom_admin_path_redirect', true, true);
+ }
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Observer.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Observer.php
index 0afcb934c8..e1d497bc27 100644
--- a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Observer.php
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Observer.php
@@ -33,7 +33,7 @@ class Mage_Adminhtml_Model_System_Config_Backend_Admin_Observer
*/
public function afterCustomUrlChanged($observer)
{
- if (is_null(Mage::registry('custom_admin_url_redirect'))) {
+ if (is_null(Mage::registry('custom_admin_path_redirect'))) {
return;
}
@@ -42,8 +42,8 @@ public function afterCustomUrlChanged($observer)
$adminSession->unsetAll();
$adminSession->getCookie()->delete($adminSession->getSessionName());
- $route = ((bool)(string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_USE_CUSTOM_ADMIN_URL))
- ? Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_CUSTOM_ADMIN_URL)
+ $route = ((bool)(string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_USE_CUSTOM_ADMIN_PATH))
+ ? Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_CUSTOM_ADMIN_PATH)
: Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_ADMINHTML_ROUTER_FRONTNAME);
Mage::app()->getResponse()
diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Googleoptimizer/Import.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Password/Link/Expirationperiod.php
similarity index 61%
rename from app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Googleoptimizer/Import.php
rename to app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Password/Link/Expirationperiod.php
index de9353aa16..28ccc7562b 100644
--- a/app/code/core/Mage/Adminhtml/Block/Catalog/Form/Renderer/Googleoptimizer/Import.php
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Password/Link/Expirationperiod.php
@@ -25,37 +25,28 @@
*/
/**
- * GoogleOptimizer import controls renderer
+ * Admin Reset Password Link Expiration period backend model
*
* @category Mage
* @package Mage_Adminhtml
* @author Magento Core Team
*/
-class Mage_Adminhtml_Block_Catalog_Form_Renderer_Googleoptimizer_Import extends Mage_Adminhtml_Block_Widget_Form_Renderer_Fieldset_Element
+class Mage_Adminhtml_Model_System_Config_Backend_Admin_Password_Link_Expirationperiod
+ extends Mage_Core_Model_Config_Data
{
- public function __construct()
+ /**
+ * Validate expiration period value before saving
+ *
+ * @return Mage_Adminhtml_Model_System_Config_Backend_Admin_Password_Link_Expirationperiod
+ */
+ protected function _beforeSave()
{
- $this->setTemplate('catalog/form/renderer/googleoptimizer/import.phtml');
- }
-
- public function render(Varien_Data_Form_Element_Abstract $element)
- {
- $this->setElement($element);
- return $this->toHtml();
- }
-
- public function setElement(Varien_Data_Form_Element_Abstract $element)
- {
- $this->_element = $element;
+ parent::_beforeSave();
+ $resetPasswordLinkExpirationPeriod = (int) $this->getValue();
+ if ($resetPasswordLinkExpirationPeriod < 0) {
+ $resetPasswordLinkExpirationPeriod = (int) $this->getOldValue();
+ }
+ $this->setValue((string) $resetPasswordLinkExpirationPeriod);
return $this;
}
-
- public function getElement()
- {
- return $this->_element;
- }
-
- protected function _prepareLayout()
- {
- }
}
diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustom.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustom.php
index 2c482a4d22..5650064ce1 100644
--- a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustom.php
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustom.php
@@ -26,7 +26,7 @@
/**
- * Adminhtml backend model for "Use Secure URLs in Admin" option
+ * Adminhtml backend model for "Use Custom Admin URL" option
*
* @category Mage
* @package Mage_Adminhtml
@@ -35,7 +35,7 @@
class Mage_Adminhtml_Model_System_Config_Backend_Admin_Usecustom extends Mage_Core_Model_Config_Data
{
/**
- * Validate custom url and check whether redirect should be set
+ * Validate custom url
*
* @return Mage_Adminhtml_Model_System_Config_Backend_Admin_Usecustom
*/
@@ -49,10 +49,6 @@ protected function _beforeSave()
}
}
- if ($this->getOldValue() != $value) {
- Mage::register('custom_admin_url_redirect', true, true);
- }
-
return $this;
}
}
diff --git a/app/code/core/Mage/GoogleOptimizer/Block/Code/Product.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustompath.php
similarity index 64%
rename from app/code/core/Mage/GoogleOptimizer/Block/Code/Product.php
rename to app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustompath.php
index 5ba6892fa3..5b5040bd18 100644
--- a/app/code/core/Mage/GoogleOptimizer/Block/Code/Product.php
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Admin/Usecustompath.php
@@ -19,34 +19,32 @@
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Adminhtml
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
- * Google Optmizer Product Block
+ * Adminhtml backend model for "Use Custom Admin Path" option
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Adminhtml
* @author Magento Core Team
*/
-class Mage_GoogleOptimizer_Block_Code_Product extends Mage_GoogleOptimizer_Block_Code
+class Mage_Adminhtml_Model_System_Config_Backend_Admin_Usecustompath extends Mage_Core_Model_Config_Data
{
- protected function _initGoogleOptimizerModel()
+ /**
+ * Check whether redirect should be set
+ *
+ * @return Mage_Adminhtml_Model_System_Config_Backend_Admin_Usecustompath
+ */
+ protected function _beforeSave()
{
- $this->_setGoogleOptimizerModel($this->getGoogleOptimizer());
- return parent::_initGoogleOptimizerModel();
- }
+ if ($this->getOldValue() != $this->getValue()) {
+ Mage::register('custom_admin_path_redirect', true, true);
+ }
- public function getProduct()
- {
- return Mage::registry('current_product');
- }
-
- public function getGoogleOptimizer()
- {
- return $this->getProduct()->getGoogleOptimizerScripts();
+ return $this;
}
}
diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Customer/Password/Link/Expirationperiod.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Customer/Password/Link/Expirationperiod.php
new file mode 100644
index 0000000000..90dbb07a12
--- /dev/null
+++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Customer/Password/Link/Expirationperiod.php
@@ -0,0 +1,53 @@
+
+ */
+class Mage_Adminhtml_Model_System_Config_Backend_Customer_Password_Link_Expirationperiod
+ extends Mage_Core_Model_Config_Data
+{
+ /**
+ * Validate expiration period value before saving
+ *
+ * @return Mage_Adminhtml_Model_System_Config_Backend_Customer_Password_Link_Expirationperiod
+ */
+ protected function _beforeSave()
+ {
+ parent::_beforeSave();
+ $resetPasswordLinkExpirationPeriod = (int) $this->getValue();
+ if ($resetPasswordLinkExpirationPeriod < 0) {
+ $resetPasswordLinkExpirationPeriod = (int) $this->getOldValue();
+ }
+ $this->setValue((string) $resetPasswordLinkExpirationPeriod);
+ return $this;
+ }
+}
diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/GalleryController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/GalleryController.php
index 56808bd599..75e8838062 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/GalleryController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/GalleryController.php
@@ -46,6 +46,12 @@ public function uploadAction()
Mage::getSingleton('catalog/product_media_config')->getBaseTmpMediaPath()
);
+ /**
+ * Workaround for prototype 1.7 methods "isJSON", "evalJSON" on Windows OS
+ */
+ $result['tmp_name'] = str_replace(DS, "/", $result['tmp_name']);
+ $result['path'] = str_replace(DS, "/", $result['path']);
+
$result['url'] = Mage::getSingleton('catalog/product_media_config')->getTmpMediaUrl($result['file']);
$result['file'] = $result['file'] . '.tmp';
$result['cookie'] = array(
diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/ReviewController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/ReviewController.php
index bd205549b1..c09c0eab86 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/ReviewController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/ReviewController.php
@@ -122,9 +122,9 @@ public function saveAction()
{
if (($data = $this->getRequest()->getPost()) && ($reviewId = $this->getRequest()->getParam('id'))) {
$review = Mage::getModel('review/review')->load($reviewId);
-
+ $session = Mage::getSingleton('adminhtml/session');
if (! $review->getId()) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('catalog')->__('The review was removed by another user or does not exist.'));
+ $session->addError(Mage::helper('catalog')->__('The review was removed by another user or does not exist.'));
} else {
try {
$review->addData($data)->save();
@@ -152,45 +152,52 @@ public function saveAction()
$review->aggregate();
- Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('catalog')->__('The review has been saved.'));
+ $session->addSuccess(Mage::helper('catalog')->__('The review has been saved.'));
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
} catch (Exception $e){
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
+ $session->addException($e, Mage::helper('catalog')->__('An error occurred while saving this review.'));
}
}
return $this->getResponse()->setRedirect($this->getUrl($this->getRequest()->getParam('ret') == 'pending' ? '*/*/pending' : '*/*/'));
}
- $this->_redirectReferer();
+ $this->_redirect('*/*/');
}
public function deleteAction()
{
- $reviewId = $this->getRequest()->getParam('id', false);
+ $reviewId = $this->getRequest()->getParam('id', false);
+ $session = Mage::getSingleton('adminhtml/session');
try {
Mage::getModel('review/review')->setId($reviewId)
->aggregate()
->delete();
- Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('catalog')->__('The review has been deleted'));
+ $session->addSuccess(Mage::helper('catalog')->__('The review has been deleted'));
if( $this->getRequest()->getParam('ret') == 'pending' ) {
$this->getResponse()->setRedirect($this->getUrl('*/*/pending'));
} else {
$this->getResponse()->setRedirect($this->getUrl('*/*/'));
}
return;
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
} catch (Exception $e){
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
+ $session->addException($e, Mage::helper('catalog')->__('An error occurred while deleting this review.'));
}
- $this->_redirectReferer();
+ $this->_redirect('*/*/edit/',array('id'=>$reviewId));
}
public function massDeleteAction()
{
$reviewsIds = $this->getRequest()->getParam('reviews');
+ $session = Mage::getSingleton('adminhtml/session');
+
if(!is_array($reviewsIds)) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select review(s).'));
+ $session->addError(Mage::helper('adminhtml')->__('Please select review(s).'));
} else {
try {
foreach ($reviewsIds as $reviewId) {
@@ -200,8 +207,10 @@ public function massDeleteAction()
Mage::getSingleton('adminhtml/session')->addSuccess(
Mage::helper('adminhtml')->__('Total of %d record(s) have been deleted.', count($reviewsIds))
);
- } catch (Exception $e) {
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e){
+ $session->addException($e, Mage::helper('adminhtml')->__('An error occurred while deleting record(s).'));
}
}
@@ -211,10 +220,11 @@ public function massDeleteAction()
public function massUpdateStatusAction()
{
$reviewsIds = $this->getRequest()->getParam('reviews');
+ $session = Mage::getSingleton('adminhtml/session');
+
if(!is_array($reviewsIds)) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select review(s).'));
+ $session->addError(Mage::helper('adminhtml')->__('Please select review(s).'));
} else {
- $session = Mage::getSingleton('adminhtml/session');
/* @var $session Mage_Adminhtml_Model_Session */
try {
$status = $this->getRequest()->getParam('status');
@@ -227,12 +237,10 @@ public function massUpdateStatusAction()
$session->addSuccess(
Mage::helper('adminhtml')->__('Total of %d record(s) have been updated.', count($reviewsIds))
);
- }
- catch (Mage_Core_Exception $e) {
- $session->addException($e->getMessage());
- }
- catch (Exception $e) {
- $session->addError(Mage::helper('adminhtml')->__('An error occurred while updating the selected review(s).'));
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e) {
+ $session->addException($e, Mage::helper('adminhtml')->__('An error occurred while updating the selected review(s).'));
}
}
@@ -242,8 +250,10 @@ public function massUpdateStatusAction()
public function massVisibleInAction()
{
$reviewsIds = $this->getRequest()->getParam('reviews');
+ $session = Mage::getSingleton('adminhtml/session');
+
if(!is_array($reviewsIds)) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select review(s).'));
+ $session->addError(Mage::helper('adminhtml')->__('Please select review(s).'));
} else {
$session = Mage::getSingleton('adminhtml/session');
/* @var $session Mage_Adminhtml_Model_Session */
@@ -257,12 +267,10 @@ public function massVisibleInAction()
$session->addSuccess(
Mage::helper('adminhtml')->__('Total of %d record(s) have been updated.', count($reviewsIds))
);
- }
- catch (Mage_Core_Exception $e) {
- $session->addException($e->getMessage());
- }
- catch (Exception $e) {
- $session->addError(Mage::helper('adminhtml')->__('An error occurred while updating the selected review(s).'));
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e) {
+ $session->addException($e, Mage::helper('adminhtml')->__('An error occurred while updating the selected review(s).'));
}
}
@@ -299,7 +307,9 @@ public function jsonProductInfoAction()
public function postAction()
{
- $productId = $this->getRequest()->getParam('product_id', false);
+ $productId = $this->getRequest()->getParam('product_id', false);
+ $session = Mage::getSingleton('adminhtml/session');
+
if ($data = $this->getRequest()->getPost()) {
if(isset($data['select_stores'])) {
$data['stores'] = $data['select_stores'];
@@ -328,7 +338,7 @@ public function postAction()
$review->aggregate();
- Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('catalog')->__('The review has been saved.'));
+ $session->addSuccess(Mage::helper('catalog')->__('The review has been saved.'));
if( $this->getRequest()->getParam('ret') == 'pending' ) {
$this->getResponse()->setRedirect($this->getUrl('*/*/pending'));
} else {
@@ -336,9 +346,10 @@ public function postAction()
}
return;
- } catch (Exception $e){
- die($e->getMessage());
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e) {
+ $session->addException($e, Mage::helper('adminhtml')->__('An error occurred while saving review.'));
}
}
$this->getResponse()->setRedirect($this->getUrl('*/*/'));
@@ -347,7 +358,9 @@ public function postAction()
public function ratingItemsAction()
{
- $this->getResponse()->setBody($this->getLayout()->createBlock('adminhtml/review_rating_detailed')->setIndependentMode()->toHtml());
+ $this->getResponse()->setBody(
+ $this->getLayout()->createBlock('adminhtml/review_rating_detailed')->setIndependentMode()->toHtml()
+ );
}
protected function _isAllowed()
diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php
index 7512df45ef..c1882abe82 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/SetController.php
@@ -123,7 +123,7 @@ public function saveAction()
if ($isNewSet) {
//filter html tags
$name = $helper->stripTags($this->getRequest()->getParam('attribute_set_name'));
- $model->setAttributeSetName($name);
+ $model->setAttributeSetName(trim($name));
} else {
if ($attributeSetId) {
$model->load($attributeSetId);
diff --git a/app/code/core/Mage/Adminhtml/controllers/IndexController.php b/app/code/core/Mage/Adminhtml/controllers/IndexController.php
index 70cc2344a4..20960f7537 100644
--- a/app/code/core/Mage/Adminhtml/controllers/IndexController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/IndexController.php
@@ -24,14 +24,26 @@
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-
+/**
+ * Index admin controller
+ *
+ * @category Mage
+ * @package Mage_Adminhtml
+ * @author Magento Core Team
+ */
class Mage_Adminhtml_IndexController extends Mage_Adminhtml_Controller_Action
{
- protected function _outTemplate($tplName, $data=array())
+ /**
+ * Render specified template
+ *
+ * @param string $tplName
+ * @param array $data parameters required by template
+ */
+ protected function _outTemplate($tplName, $data = array())
{
$this->_initLayoutMessages('adminhtml/session');
$block = $this->getLayout()->createBlock('adminhtml/template')->setTemplate("$tplName.phtml");
- foreach ($data as $index=>$value) {
+ foreach ($data as $index => $value) {
$block->assign($index, $value);
}
$html = $block->toHtml();
@@ -54,6 +66,9 @@ public function indexAction()
$this->_redirect($url);
}
+ /**
+ * Administrator login action
+ */
public function loginAction()
{
if (Mage::getSingleton('admin/session')->isLoggedIn()) {
@@ -63,7 +78,7 @@ public function loginAction()
$loginData = $this->getRequest()->getParam('login');
$data = array();
- if( is_array($loginData) && array_key_exists('username', $loginData) ) {
+ if(is_array($loginData) && array_key_exists('username', $loginData)) {
$data['username'] = $loginData['username'];
} else {
$data['username'] = null;
@@ -72,6 +87,9 @@ public function loginAction()
$this->_outTemplate('login', $data);
}
+ /**
+ * Administrator logout action
+ */
public function logoutAction()
{
/** @var $adminSession Mage_Admin_Model_Session */
@@ -85,28 +103,27 @@ public function logoutAction()
/**
* Global Search Action
- *
*/
public function globalSearchAction()
{
$searchModules = Mage::getConfig()->getNode("adminhtml/global_search");
$items = array();
- if ( !Mage::getSingleton('admin/session')->isAllowed('admin/global_search') ) {
+ if (!Mage::getSingleton('admin/session')->isAllowed('admin/global_search')) {
$items[] = array(
- 'id' => 'error',
- 'type' => Mage::helper('adminhtml')->__('Error'),
- 'name' => Mage::helper('adminhtml')->__('Access Denied'),
- 'description' => Mage::helper('adminhtml')->__('You have not enough permissions to use this functionality.')
+ 'id' => 'error',
+ 'type' => Mage::helper('adminhtml')->__('Error'),
+ 'name' => Mage::helper('adminhtml')->__('Access Denied'),
+ 'description' => Mage::helper('adminhtml')->__('You have not enough permissions to use this functionality.')
);
$totalCount = 1;
} else {
if (empty($searchModules)) {
$items[] = array(
- 'id' => 'error',
- 'type' => Mage::helper('adminhtml')->__('Error'),
- 'name' => Mage::helper('adminhtml')->__('No search modules were registered'),
- 'description' => Mage::helper('adminhtml')->__('Please make sure that all global admin search modules are installed and activated.')
+ 'id' => 'error',
+ 'type' => Mage::helper('adminhtml')->__('Error'),
+ 'name' => Mage::helper('adminhtml')->__('No search modules were registered'),
+ 'description' => Mage::helper('adminhtml')->__('Please make sure that all global admin search modules are installed and activated.')
);
$totalCount = 1;
} else {
@@ -126,10 +143,10 @@ public function globalSearchAction()
}
$searchInstance = new $className();
$results = $searchInstance->setStart($start)
- ->setLimit($limit)
- ->setQuery($query)
- ->load()
- ->getResults();
+ ->setLimit($limit)
+ ->setQuery($query)
+ ->load()
+ ->getResults();
$items = array_merge_recursive($items, $results);
}
$totalCount = sizeof($items);
@@ -143,16 +160,25 @@ public function globalSearchAction()
$this->getResponse()->setBody($block->toHtml());
}
+ /**
+ * Example action
+ */
public function exampleAction()
{
$this->_outTemplate('example');
}
+ /**
+ * Test action
+ */
public function testAction()
{
echo $this->getLayout()->createBlock('core/profiler')->toHtml();
}
+ /**
+ * Change locale action
+ */
public function changeLocaleAction()
{
$locale = $this->getRequest()->getParam('locale');
@@ -162,38 +188,52 @@ public function changeLocaleAction()
$this->_redirectReferer();
}
+ /**
+ * Denied JSON action
+ */
public function deniedJsonAction()
{
$this->getResponse()->setBody($this->_getDeniedJson());
}
+ /**
+ * Retrieve response for deniedJsonAction()
+ */
protected function _getDeniedJson()
{
- return Mage::helper('core')->jsonEncode(
- array(
- 'ajaxExpired' => 1,
- 'ajaxRedirect' => $this->getUrl('*/index/login')
- )
- );
+ return Mage::helper('core')->jsonEncode(array(
+ 'ajaxExpired' => 1,
+ 'ajaxRedirect' => $this->getUrl('*/index/login')
+ ));
}
+ /**
+ * Denied IFrame action
+ */
public function deniedIframeAction()
{
$this->getResponse()->setBody($this->_getDeniedIframe());
}
+ /**
+ * Retrieve response for deniedIframeAction()
+ */
protected function _getDeniedIframe()
{
- return '';
+ return '';
}
+ /**
+ * Forgot administrator password action
+ */
public function forgotpasswordAction()
{
$email = $this->getRequest()->getParam('email');
$params = $this->getRequest()->getParams();
if (!empty($email) && !empty($params)) {
$collection = Mage::getResourceModel('admin/user_collection');
- /* @var $collection Mage_Admin_Model_Mysql4_User_Collection */
+ /** @var $collection Mage_Admin_Model_Mysql4_User_Collection */
$collection->addFieldToFilter('email', $email);
$collection->load(false);
@@ -201,31 +241,150 @@ public function forgotpasswordAction()
foreach ($collection as $item) {
$user = Mage::getModel('admin/user')->load($item->getId());
if ($user->getId()) {
- $pass = Mage::helper('core')->getRandomString(7);
- $user->setPassword($pass);
+ $newResetPasswordLinkToken = Mage::helper('admin')->generateResetPasswordLinkToken();
+ $user->changeResetPasswordLinkToken($newResetPasswordLinkToken);
$user->save();
- $user->setPlainPassword($pass);
- $user->sendNewPasswordEmail();
- Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('A new password was sent to your email address. Please check your email and click Back to Login.'));
- $email = '';
+ $user->sendPasswordResetConfirmationEmail();
}
break;
}
- } else {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Cannot find the email address.'));
}
+ $this->_getSession()
+ ->addSuccess(Mage::helper('adminhtml')->__('If there is an account associated with %s you will receive an email with a link to reset your password.', Mage::helper('adminhtml')->htmlEscape($email)));
} elseif (!empty($params)) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('The email address is empty.'));
+ $this->_getSession()->addError(Mage::helper('adminhtml')->__('The email address is empty.'));
}
-
$data = array(
'email' => $email
);
$this->_outTemplate('forgotpassword', $data);
}
+ /**
+ * Display reset forgotten password form
+ *
+ * User is redirected on this action when he clicks on the corresponding link in password reset confirmation email
+ */
+ public function resetPasswordAction()
+ {
+ $resetPasswordLinkToken = (string) $this->getRequest()->getQuery('token');
+ $userId = (int) $this->getRequest()->getQuery('id');
+ try {
+ $this->_validateResetPasswordLinkToken($userId, $resetPasswordLinkToken);
+ $data = array(
+ 'userId' => $userId,
+ 'resetPasswordLinkToken' => $resetPasswordLinkToken
+ );
+ $this->_outTemplate('resetforgottenpassword', $data);
+ } catch (Exception $exception) {
+ $this->_getSession()->addError(Mage::helper('adminhtml')->__('Your password reset link has expired.'));
+ $this->_redirect('*/*/');
+ }
+ }
+
+ /**
+ * Reset forgotten password
+ *
+ * Used to handle data recieved from reset forgotten password form
+ */
+ public function resetPasswordPostAction()
+ {
+ $resetPasswordLinkToken = (string) $this->getRequest()->getQuery('token');
+ $userId = (int) $this->getRequest()->getQuery('id');
+ $password = (string) $this->getRequest()->getPost('password');
+ $passwordConfirmation = (string) $this->getRequest()->getPost('confirmation');
+
+ try {
+ $this->_validateResetPasswordLinkToken($userId, $resetPasswordLinkToken);
+ } catch (Exception $exception) {
+ $this->_getSession()->addError(Mage::helper('adminhtml')->__('Your password reset link has expired.'));
+ $this->_redirect('*/*/');
+ return;
+ }
+
+ $errorMessages = array();
+ if (iconv_strlen($password) <= 0) {
+ array_push($errorMessages, Mage::helper('adminhtml')->__('New password field cannot be empty.'));
+ }
+ /** @var $user Mage_Admin_Model_User */
+ $user = Mage::getModel('admin/user')->load($userId);
+
+ $user->setNewPassword($password);
+ $user->setPasswordConfirmation($passwordConfirmation);
+ $validationErrorMessages = $user->validate();
+ if (is_array($validationErrorMessages)) {
+ $errorMessages = array_merge($errorMessages, $validationErrorMessages);
+ }
+
+ if (!empty($errorMessages)) {
+ foreach ($errorMessages as $errorMessage) {
+ $this->_getSession()->addError($errorMessage);
+ }
+ $data = array(
+ 'userId' => $userId,
+ 'resetPasswordLinkToken' => $resetPasswordLinkToken
+ );
+ $this->_outTemplate('resetforgottenpassword', $data);
+ return;
+ }
+
+ try {
+ // Empty current reset password token i.e. invalidate it
+ $user->setRpToken(null);
+ $user->setRpTokenCreatedAt(null);
+ $user->setPasswordConfirmation(null);
+ // Force password change
+ $user->setForceNewPassword(true);
+ $user->save();
+ $this->_getSession()->addSuccess(Mage::helper('adminhtml')->__('Your password has been updated.'));
+ $this->_redirect('*/*/login');
+ } catch (Exception $exception) {
+ $this->_getSession()->addException($exception, $this->__('Cannot save a new password.'));
+ $data = array(
+ 'userId' => $userId,
+ 'resetPasswordLinkToken' => $resetPasswordLinkToken
+ );
+ $this->_outTemplate('resetforgottenpassword', $data);
+ return;
+ }
+ }
+
+ /**
+ * Check if password reset token is valid
+ *
+ * @param int $userId
+ * @param string $resetPasswordLinkToken
+ * @throws Mage_Core_Exception
+ */
+ protected function _validateResetPasswordLinkToken($userId, $resetPasswordLinkToken)
+ {
+ if (!is_int($userId)
+ || !is_string($resetPasswordLinkToken)
+ || empty($resetPasswordLinkToken)
+ || empty($userId)
+ || $userId < 0
+ ) {
+ throw Mage::exception('Mage_Core', Mage::helper('adminhtml')->__('Invalid password reset token.'));
+ }
+
+ /** @var $user Mage_Admin_Model_User */
+ $user = Mage::getModel('admin/user')->load($userId);
+ if (!$user || !$user->getId()) {
+ throw Mage::exception('Mage_Core', Mage::helper('adminhtml')->__('Wrong account specified.'));
+ }
+ $userToken = $user->getRpToken();
+ if (strcmp($userToken, $resetPasswordLinkToken) != 0 || $user->isResetPasswordLinkTokenExpired()) {
+ throw Mage::exception('Mage_Core', Mage::helper('adminhtml')->__('Your password reset link has expired.'));
+ }
+ }
+
+ /**
+ * Check if user has permissions to access this controller
+ *
+ * @return boolean
+ */
protected function _isAllowed()
{
return true;
diff --git a/app/code/core/Mage/Adminhtml/controllers/NotificationController.php b/app/code/core/Mage/Adminhtml/controllers/NotificationController.php
index 2431e0046c..2f8c5d41e6 100644
--- a/app/code/core/Mage/Adminhtml/controllers/NotificationController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/NotificationController.php
@@ -62,11 +62,9 @@ public function markAsReadAction()
$model->setIsRead(1)
->save();
$session->addSuccess(Mage::helper('adminnotification')->__('The message has been marked as read.'));
- }
- catch (Mage_Core_Exception $e) {
+ } catch (Mage_Core_Exception $e) {
$session->addError($e->getMessage());
- }
- catch (Exception $e) {
+ } catch (Exception $e) {
$session->addException($e, Mage::helper('adminnotification')->__('An error occurred while marking notification as read.'));
}
@@ -82,8 +80,7 @@ public function massMarkAsReadAction()
$ids = $this->getRequest()->getParam('notification');
if (!is_array($ids)) {
$session->addError(Mage::helper('adminnotification')->__('Please select messages.'));
- }
- else {
+ } else {
try {
foreach ($ids as $id) {
$model = Mage::getModel('adminnotification/inbox')
@@ -98,8 +95,7 @@ public function massMarkAsReadAction()
);
} catch (Mage_Core_Exception $e) {
$session->addError($e->getMessage());
- }
- catch (Exception $e) {
+ } catch (Exception $e) {
$session->addException($e, Mage::helper('adminnotification')->__('An error occurred while marking the messages as read.'));
}
}
@@ -122,15 +118,13 @@ public function removeAction()
$model->setIsRemove(1)
->save();
$session->addSuccess(Mage::helper('adminnotification')->__('The message has been removed.'));
- }
- catch (Mage_Core_Exception $e) {
+ } catch (Mage_Core_Exception $e) {
$session->addError($e->getMessage());
- }
- catch (Exception $e) {
+ } catch (Exception $e) {
$session->addException($e, Mage::helper('adminnotification')->__('An error occurred while removing the message.'));
}
- $this->_redirectReferer();
+ $this->_redirect('*/*/');
return;
}
$this->_redirect('*/*/');
@@ -142,8 +136,7 @@ public function massRemoveAction()
$ids = $this->getRequest()->getParam('notification');
if (!is_array($ids)) {
$session->addError(Mage::helper('adminnotification')->__('Please select messages.'));
- }
- else {
+ } else {
try {
foreach ($ids as $id) {
$model = Mage::getModel('adminnotification/inbox')
@@ -158,8 +151,7 @@ public function massRemoveAction()
);
} catch (Mage_Core_Exception $e) {
$session->addError($e->getMessage());
- }
- catch (Exception $e) {
+ } catch (Exception $e) {
$session->addException($e, Mage::helper('adminnotification')->__('An error occurred while removing messages.'));
}
}
diff --git a/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php b/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php
index c621024ea8..8a5b56332a 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Report/SalesController.php
@@ -458,7 +458,7 @@ protected function _isAllowed()
return $this->_getSession()->isAllowed('report/salesroot/shipping');
break;
case 'bestsellers':
- return $this->_getSession()->isAllowed('report/products/ordered');
+ return $this->_getSession()->isAllowed('report/products/bestsellers');
break;
default:
return $this->_getSession()->isAllowed('report/salesroot');
diff --git a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php
index 260d798075..34c5955838 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/CreditmemoController.php
@@ -333,7 +333,8 @@ public function saveAction()
*/
public function cancelAction()
{
- if ($creditmemo = $this->_initCreditmemo()) {
+ $creditmemo = $this->_initCreditmemo();
+ if ($creditmemo) {
try {
$creditmemo->cancel();
$this->_saveCreditmemo($creditmemo);
@@ -354,7 +355,8 @@ public function cancelAction()
*/
public function voidAction()
{
- if ($invoice = $this->_initCreditmemo()) {
+ $creditmemo = $this->_initCreditmemo();
+ if ($creditmemo) {
try {
$creditmemo->void();
$this->_saveCreditmemo($creditmemo);
@@ -442,4 +444,13 @@ protected function _needToAddDummy($item, $qtys) {
return false;
}
}
+
+ /**
+ * Create pdf for current creditmemo
+ */
+ public function printAction()
+ {
+ $this->_initCreditmemo();
+ parent::printAction();
+ }
}
diff --git a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/InvoiceController.php b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/InvoiceController.php
index 4529ac6a8a..5296e92272 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/InvoiceController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/InvoiceController.php
@@ -480,4 +480,13 @@ protected function _needToAddDummyForShipment($item, $qtys) {
}
}
+ /**
+ * Create pdf for current invoice
+ */
+ public function printAction()
+ {
+ $this->_initInvoice();
+ parent::printAction();
+ }
+
}
diff --git a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/StatusController.php b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/StatusController.php
index 26d5d47872..4e24919bc3 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Sales/Order/StatusController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Sales/Order/StatusController.php
@@ -64,8 +64,7 @@ protected function _initStatus()
public function indexAction()
{
$this->_title($this->__('Sales'))->_title($this->__('Order Statuses'));
- $this->loadLayout()
- ->renderLayout();
+ $this->loadLayout()->_setActiveMenu('system')->renderLayout();
}
/**
diff --git a/app/code/core/Mage/Adminhtml/controllers/Sales/Recurring/ProfileController.php b/app/code/core/Mage/Adminhtml/controllers/Sales/Recurring/ProfileController.php
index d3b34ddc89..9a34591f47 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Sales/Recurring/ProfileController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Sales/Recurring/ProfileController.php
@@ -159,6 +159,35 @@ public function updateProfileAction()
}
}
+ /**
+ * Cutomer billing agreements ajax action
+ *
+ */
+ public function customerGridAction()
+ {
+ $this->_initCustomer();
+ $this->loadLayout(false)
+ ->renderLayout();
+ }
+
+ /**
+ * Initialize customer by ID specified in request
+ *
+ * @return Mage_Adminhtml_Sales_Billing_AgreementController
+ */
+ protected function _initCustomer()
+ {
+ $customerId = (int) $this->getRequest()->getParam('id');
+ $customer = Mage::getModel('customer/customer');
+
+ if ($customerId) {
+ $customer->load($customerId);
+ }
+
+ Mage::register('current_customer', $customer);
+ return $this;
+ }
+
/**
* Load/set profile
*
diff --git a/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php b/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php
index b34beba4cc..5068421254 100644
--- a/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/System/ConfigController.php
@@ -24,9 +24,8 @@
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-
/**
- * config controller
+ * Configuration controller
*
* @category Mage
* @package Mage_Adminhtml
@@ -59,7 +58,7 @@ public function preDispatch()
}
/**
- * Enter description here...
+ * Index action
*
*/
public function indexAction()
@@ -68,7 +67,7 @@ public function indexAction()
}
/**
- * Enter description here...
+ * Edit configuration section
*
*/
public function editAction()
@@ -91,8 +90,10 @@ public function editAction()
$this->loadLayout();
$this->_setActiveMenu('system/config');
+ $this->getLayout()->getBlock('menu')->setAdditionalCacheKeyInfo(array($current));
- $this->_addBreadcrumb(Mage::helper('adminhtml')->__('System'), Mage::helper('adminhtml')->__('System'), $this->getUrl('*/system'));
+ $this->_addBreadcrumb(Mage::helper('adminhtml')->__('System'), Mage::helper('adminhtml')->__('System'),
+ $this->getUrl('*/system'));
$this->getLayout()->getBlock('left')
->append($this->getLayout()->createBlock('adminhtml/system_config_tabs')->initTabs());
@@ -100,16 +101,22 @@ public function editAction()
if ($this->_isSectionAllowedFlag) {
$this->_addContent($this->getLayout()->createBlock('adminhtml/system_config_edit')->initForm());
- $this->_addJs($this->getLayout()->createBlock('adminhtml/template')->setTemplate('system/shipping/ups.phtml'));
- $this->_addJs($this->getLayout()->createBlock('adminhtml/template')->setTemplate('system/config/js.phtml'));
- $this->_addJs($this->getLayout()->createBlock('adminhtml/template')->setTemplate('system/shipping/applicable_country.phtml'));
+ $this->_addJs($this->getLayout()
+ ->createBlock('adminhtml/template')
+ ->setTemplate('system/shipping/ups.phtml'));
+ $this->_addJs($this->getLayout()
+ ->createBlock('adminhtml/template')
+ ->setTemplate('system/config/js.phtml'));
+ $this->_addJs($this->getLayout()
+ ->createBlock('adminhtml/template')
+ ->setTemplate('system/shipping/applicable_country.phtml'));
$this->renderLayout();
}
}
/**
- * Enter description here...
+ * Save configuration
*
*/
public function saveAction()
@@ -168,7 +175,9 @@ public function saveAction()
}
}
catch (Exception $e) {
- $session->addException($e, Mage::helper('adminhtml')->__('An error occurred while saving this configuration:').' '.$e->getMessage());
+ $session->addException($e,
+ Mage::helper('adminhtml')->__('An error occurred while saving this configuration:') . ' '
+ . $e->getMessage());
}
$this->_saveState($this->getRequest()->getPost('config_state'));
@@ -188,20 +197,19 @@ protected function _saveSection ()
}
/**
- * Description goes here...
+ * Advanced save procedure
*/
- protected function _saveAdvanced ()
+ protected function _saveAdvanced()
{
Mage::app()->cleanCache(
array(
'layout',
Mage_Core_Model_Layout_Update::LAYOUT_GENERAL_CACHE_TAG
- )
- );
+ ));
}
/**
- * action for ajax saving of fieldset state
+ * Save fieldset state through AJAX
*
*/
public function stateAction()
@@ -282,7 +290,7 @@ protected function _isSectionAllowed($section)
}
/**
- * saving state of config field sets
+ * Save state of configuration field sets
*
* @param array $configState
* @return bool
diff --git a/app/code/core/Mage/Adminhtml/controllers/Tax/Class/CustomerController.php b/app/code/core/Mage/Adminhtml/controllers/Tax/Class/CustomerController.php
index 13d2317560..6ea3ff3f67 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Tax/Class/CustomerController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Tax/Class/CustomerController.php
@@ -45,7 +45,11 @@ public function indexAction()
->_title($this->__('Customer Tax Classes'));
$this->_initAction()
- ->_addContent($this->getLayout()->createBlock('adminhtml/tax_class')->setClassType(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER))
+ ->_addContent(
+ $this->getLayout()
+ ->createBlock('adminhtml/tax_class')
+ ->setClassType(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER)
+ )
->renderLayout();
}
@@ -89,8 +93,16 @@ public function editAction()
Mage::register('tax_class', $model);
$this->_initAction()
- ->_addBreadcrumb($classId ? Mage::helper('tax')->__('Edit Class') : Mage::helper('tax')->__('New Class'), $classId ? Mage::helper('tax')->__('Edit Class') : Mage::helper('tax')->__('New Class'))
- ->_addContent($this->getLayout()->createBlock('adminhtml/tax_class_edit')->setData('action', $this->getUrl('*/tax_class/save'))->setClassType(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER))
+ ->_addBreadcrumb(
+ $classId ? Mage::helper('tax')->__('Edit Class') : Mage::helper('tax')->__('New Class'),
+ $classId ? Mage::helper('tax')->__('Edit Class') : Mage::helper('tax')->__('New Class')
+ )
+ ->_addContent(
+ $this->getLayout()
+ ->createBlock('adminhtml/tax_class_edit')
+ ->setData('action', $this->getUrl('*/tax_class/save'))
+ ->setClassType(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER)
+ )
->renderLayout();
}
@@ -101,6 +113,7 @@ public function editAction()
public function deleteAction()
{
$classId = $this->getRequest()->getParam('id');
+ $session = Mage::getSingleton('adminhtml/session');
$classModel = Mage::getModel('tax/class')
->load($classId);
@@ -115,8 +128,8 @@ public function deleteAction()
->setClassTypeFilter(Mage_Tax_Model_Class::TAX_CLASS_TYPE_CUSTOMER, $classId);
if ($ruleCollection->getSize() > 0) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used in Tax Rules. You have to delete the rules it is used in first.'));
- $this->_redirectReferer();
+ $session->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used in Tax Rules. You have to delete the rules it is used in first.'));
+ $this->_redirect('*/*/edit/',array('id'=>$classId));
return;
}
@@ -126,26 +139,24 @@ public function deleteAction()
$groupCount = $customerGroupCollection->getSize();
if ($groupCount > 0) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used for %d customer groups.', $groupCount));
- $this->_redirectReferer();
+ $session->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used for %d customer groups.', $groupCount));
+ $this->_redirect('*/*/edit/',array('id'=>$classId));
return;
}
try {
$classModel->delete();
- Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('tax')->__('The tax class has been deleted.'));
+ $session->addSuccess(Mage::helper('tax')->__('The tax class has been deleted.'));
$this->getResponse()->setRedirect($this->getUrl("*/*/"));
return ;
- }
- catch (Mage_Core_Exception $e) {
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
- }
- catch (Exception $e) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('An error occurred while deleting this tax class.'));
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e) {
+ $session->addException($e, Mage::helper('tax')->__('An error occurred while deleting this tax class.'));
}
- $this->_redirectReferer();
+ $this->_redirect('*/*/edit/',array('id'=>$classId));
}
/**
diff --git a/app/code/core/Mage/Adminhtml/controllers/Tax/Class/ProductController.php b/app/code/core/Mage/Adminhtml/controllers/Tax/Class/ProductController.php
index 8825c8c6f4..3e54230c77 100644
--- a/app/code/core/Mage/Adminhtml/controllers/Tax/Class/ProductController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/Tax/Class/ProductController.php
@@ -112,11 +112,12 @@ public function editAction()
public function deleteAction()
{
$classId = $this->getRequest()->getParam('id');
+ $session = Mage::getSingleton('adminhtml/session');
$classModel = Mage::getModel('tax/class')
->load($classId);
if (!$classModel->getId() || $classModel->getClassType() != Mage_Tax_Model_Class::TAX_CLASS_TYPE_PRODUCT) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('This class no longer exists'));
+ $session->addError(Mage::helper('tax')->__('This class no longer exists'));
$this->_redirect('*/*/');
return;
}
@@ -126,8 +127,8 @@ public function deleteAction()
->setClassTypeFilter(Mage_Tax_Model_Class::TAX_CLASS_TYPE_PRODUCT, $classId);
if ($ruleCollection->getSize() > 0) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used in Tax Rules. You have to delete the rules it is used in first.'));
- $this->_redirectReferer();
+ $session->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used in Tax Rules. You have to delete the rules it is used in first.'));
+ $this->_redirect('*/*/edit/', array('id' => $classId));
return;
}
@@ -137,26 +138,24 @@ public function deleteAction()
$productCount = $productCollection->getSize();
if ($productCount > 0) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used for %d products.', $productCount));
- $this->_redirectReferer();
+ $session->addError(Mage::helper('tax')->__('You cannot delete this tax class as it is used for %d products.', $productCount));
+ $this->_redirect('*/*/edit/', array('id' => $classId));
return;
}
try {
$classModel->delete();
- Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('tax')->__('The tax class has been deleted.'));
+ $session->addSuccess(Mage::helper('tax')->__('The tax class has been deleted.'));
$this->getResponse()->setRedirect($this->getUrl("*/*/"));
return;
- }
- catch (Mage_Core_Exception $e) {
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
- }
- catch (Exception $e) {
- Mage::getSingleton('adminhtml/session')->addError(Mage::helper('tax')->__('An error occurred while deleting this tax class.'));
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage());
+ } catch (Exception $e) {
+ $session->addException($e, Mage::helper('tax')->__('An error occurred while deleting this tax class.'));
}
- $this->_redirectReferer();
+ $this->_redirect('*/*/edit/', array('id' => $classId));
}
/**
diff --git a/app/code/core/Mage/Adminhtml/controllers/UrlrewriteController.php b/app/code/core/Mage/Adminhtml/controllers/UrlrewriteController.php
index 7ce26034e6..cd4714c918 100644
--- a/app/code/core/Mage/Adminhtml/controllers/UrlrewriteController.php
+++ b/app/code/core/Mage/Adminhtml/controllers/UrlrewriteController.php
@@ -121,6 +121,7 @@ public function saveAction()
$this->_initRegistry();
if ($data = $this->getRequest()->getPost()) {
+ $session = Mage::getSingleton('adminhtml/session');
try {
// set basic urlrewrite data
$model = Mage::registry('current_urlrewrite');
@@ -162,7 +163,8 @@ public function saveAction()
$rewrite = Mage::getResourceModel('catalog/url')
->getRewriteByIdPath($idPath, $model->getStoreId());
if (!$rewrite) {
- Mage::throwException('Chosen product does not associated with the chosen store or category.');
+ $exceptionTxt = 'Chosen product does not associated with the chosen store or category.';
+ Mage::throwException($exceptionTxt);
}
if($rewrite->getId() && $rewrite->getId() != $model->getId()) {
$model->setIdPath($idPath);
@@ -179,17 +181,15 @@ public function saveAction()
// save and redirect
$model->save();
- Mage::getSingleton('adminhtml/session')->addSuccess(
- Mage::helper('adminhtml')->__('The URL Rewrite has been saved.')
- );
+ $session->addSuccess(Mage::helper('adminhtml')->__('The URL Rewrite has been saved.'));
$this->_redirect('*/*/');
return;
- }
- catch (Exception $e) {
- Mage::getSingleton('adminhtml/session')
- ->addError($e->getMessage())
- ->setUrlrewriteData($data)
- ;
+ } catch (Mage_Core_Exception $e) {
+ $session->addError($e->getMessage())
+ ->setUrlrewriteData($data);
+ } catch (Exception $e) {
+ $session->addException($e, Mage::helper('adminhtml')->__('An error occurred while saving URL Rewrite.'))
+ ->setUrlrewriteData($data);
// return intentionally omitted
}
}
@@ -210,10 +210,10 @@ public function deleteAction()
Mage::getSingleton('adminhtml/session')->addSuccess(
Mage::helper('adminhtml')->__('The URL Rewrite has been deleted.')
);
- }
- catch (Exception $e) {
- Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
- $this->_redirectReferer();
+ } catch (Exception $e) {
+ Mage::getSingleton('adminhtml/session')
+ ->addException($e, Mage::helper('adminhtml')->__('An error occurred while deleting URL Rewrite.'));
+ $this->_redirect('*/*/edit/', array('id'=>Mage::registry('current_urlrewrite')->getId()));
return;
}
}
diff --git a/app/code/core/Mage/Adminhtml/etc/config.xml b/app/code/core/Mage/Adminhtml/etc/config.xml
index 7e4806dbfa..569b189ee5 100644
--- a/app/code/core/Mage/Adminhtml/etc/config.xml
+++ b/app/code/core/Mage/Adminhtml/etc/config.xml
@@ -50,8 +50,8 @@
-
- admin_password_new.html
+
+ admin_password_reset_confirmation.htmlhtml
diff --git a/app/code/core/Mage/Api/Helper/Data.php b/app/code/core/Mage/Api/Helper/Data.php
index ddf394c8a6..0ededf8474 100644
--- a/app/code/core/Mage/Api/Helper/Data.php
+++ b/app/code/core/Mage/Api/Helper/Data.php
@@ -49,28 +49,71 @@ public function isComplianceWSI()
* @param Object $obj - Link to Object
* @return Object
*/
- public function wsiArrayUnpacker(&$obj){
- if(is_object($obj)){
+ public function wsiArrayUnpacker(&$obj)
+ {
+ if (is_object($obj)) {
$modifiedKeys = $this->clearWsiFootprints($obj);
- foreach( $obj as $key => $value ){
- if(is_object($value)){
+ foreach ($obj as $key => $value) {
+ if (is_object($value)) {
$this->wsiArrayUnpacker($value);
}
- if(is_array($value)){
- foreach($value as &$val){
- if(is_object($val)){
+ if (is_array($value)) {
+ foreach ($value as &$val) {
+ if (is_object($val)) {
$this->wsiArrayUnpacker($val);
}
}
}
}
+
+ foreach ($modifiedKeys as $arrKey) {
+ $this->associativeArrayUnpack($obj->$arrKey);
+ }
}
+ }
- foreach($modifiedKeys as $arrKey){
- $this->assocativArrayUnpacker($obj->$arrKey);
+ /**
+ * Go thru an object parameters and unpak associative object to array.
+ *
+ * @param Object $obj - Link to Object
+ * @return Object
+ */
+ public function v2AssociativeArrayUnpacker(&$obj)
+ {
+ if (is_object($obj)
+ && property_exists($obj, 'key')
+ && property_exists($obj, 'value')
+ ) {
+ if (count(array_keys(get_object_vars($obj))) == 2) {
+ $obj = array($obj->key => $obj->value);
+ return true;
+ }
+ } elseif (is_array($obj)) {
+ $arr = array();
+ $needReplacement = true;
+ foreach ($obj as $key => &$value) {
+ $isAssoc = $this->v2AssociativeArrayUnpacker($value);
+ if ($isAssoc) {
+ foreach ($value as $aKey => $aVal) {
+ $arr[$aKey] = $aVal;
+ }
+ } else {
+ $needReplacement = false;
+ }
+ }
+ if ($needReplacement) {
+ $obj = $arr;
+ }
+ } elseif (is_object($obj)) {
+ $objectKeys = array_keys(get_object_vars($obj));
+
+ foreach ($objectKeys as $key) {
+ $this->v2AssociativeArrayUnpacker($obj->$key);
+ }
}
+ return false;
}
/**
@@ -78,34 +121,34 @@ public function wsiArrayUnpacker(&$obj){
*
* @param Mixed $mixed A link to variable that may contain associative array.
*/
- public function assocativArrayUnpacker(&$mixed){
-
- if(is_array($mixed)){
- $tmpArr = array();
- foreach($mixed as $key => $value){
- if(is_object($value)){
- $value = get_object_vars($value);
- if(count($value) == 2 && isset($value['key']) && isset($value['value'])){
- $tmpArr[$value['key']] = $value['value'];
- }
+ public function associativeArrayUnpack(&$mixed)
+ {
+ if (is_array($mixed)) {
+ $tmpArr = array();
+ foreach ($mixed as $key => $value) {
+ if (is_object($value)) {
+ $value = get_object_vars($value);
+ if (count($value) == 2 && isset($value['key']) && isset($value['value'])) {
+ $tmpArr[$value['key']] = $value['value'];
}
}
- if(count($tmpArr)){
- $mixed = $tmpArr;
- }
}
+ if (count($tmpArr)) {
+ $mixed = $tmpArr;
+ }
+ }
- if(is_object($mixed)){
- $numOfVals = count(get_object_vars($mixed));
- if($numOfVals == 2 && isset($mixed->key) && isset($mixed->value)){
- $mixed = get_object_vars($mixed);
- /*
- * Processing an associative arrays.
- * $mixed->key = '2'; $mixed->value = '3'; turns to array(2 => '3');
- */
- $mixed = array($mixed['key'] => $mixed['value']);
- }
+ if (is_object($mixed)) {
+ $numOfVals = count(get_object_vars($mixed));
+ if ($numOfVals == 2 && isset($mixed->key) && isset($mixed->value)) {
+ $mixed = get_object_vars($mixed);
+ /*
+ * Processing an associative arrays.
+ * $mixed->key = '2'; $mixed->value = '3'; turns to array(2 => '3');
+ */
+ $mixed = array($mixed['key'] => $mixed['value']);
}
+ }
}
/**
@@ -114,13 +157,14 @@ public function assocativArrayUnpacker(&$mixed){
* @param Object $obj - Link to Object
* @return Object
*/
- public function clearWsiFootprints(&$obj){
+ public function clearWsiFootprints(&$obj)
+ {
$modifiedKeys = array();
$objectKeys = array_keys(get_object_vars($obj));
- foreach( $objectKeys as $key ){
- if(is_object($obj->$key) && isset($obj->$key->complexObjectArray) ){
+ foreach ($objectKeys as $key) {
+ if (is_object($obj->$key) && isset($obj->$key->complexObjectArray)) {
$obj->$key = $obj->$key->complexObjectArray;
$modifiedKeys[] = $key;
}
@@ -131,28 +175,29 @@ public function clearWsiFootprints(&$obj){
/**
* For the WSI, generates an response object.
*
- * @param Object $arr - Link to Object
- * @return Object
+ * @param mixed $mixed - Link to Object
+ * @return mixed
*/
- public function wsiArrayPacker($mixed){
- if(is_array($mixed)){
+ public function wsiArrayPacker($mixed)
+ {
+ if (is_array($mixed)) {
$arrKeys = array_keys($mixed);
$isDigit = false;
$isString = false;
- foreach($arrKeys as $key){
- if(is_int($key)){
+ foreach ($arrKeys as $key) {
+ if (is_int($key)) {
$isDigit = true;
break;
}
}
- if($isDigit){
+ if ($isDigit) {
$mixed = $this->packArrayToObjec($mixed);
} else {
- $mixed = (object)$mixed;
+ $mixed = (object) $mixed;
}
}
- if(is_object($mixed) && isset($mixed->complexObjectArray)){
- foreach($mixed->complexObjectArray as $k => $v){
+ if (is_object($mixed) && isset($mixed->complexObjectArray)) {
+ foreach ($mixed->complexObjectArray as $k => $v) {
$mixed->complexObjectArray[$k] = $this->wsiArrayPacker($v);
}
}
@@ -165,9 +210,30 @@ public function wsiArrayPacker($mixed){
* @param Array $arr - Link to Object
* @return Object
*/
- public function packArrayToObjec(Array $arr){
+ public function packArrayToObjec(Array $arr)
+ {
$obj = new stdClass();
$obj->complexObjectArray = $arr;
return $obj;
}
+
+ /**
+ * Convert objects and arrays to array recursively
+ *
+ * @param array|object $data
+ * @return void
+ */
+ public function toArray(&$data)
+ {
+ if (is_object($data)) {
+ $data = get_object_vars($data);
+ }
+ if (is_array($data)) {
+ foreach ($data as &$value) {
+ if (is_array($value) or is_object($value)) {
+ $this->toArray($value);
+ }
+ }
+ }
+ }
} // Class Mage_Api_Helper_Data End
diff --git a/app/code/core/Mage/Api/Model/Acl.php b/app/code/core/Mage/Api/Model/Acl.php
index 9f78a51ae4..1628ac3626 100644
--- a/app/code/core/Mage/Api/Model/Acl.php
+++ b/app/code/core/Mage/Api/Model/Acl.php
@@ -46,6 +46,17 @@ class Mage_Api_Model_Acl extends Zend_Acl
*/
const ROLE_TYPE_USER = 'U';
+ /**
+ * User types for store access
+ * G - Guest customer (anonymous)
+ * C - Authenticated customer
+ * A - Authenticated admin user
+ *
+ */
+ const USER_TYPE_GUEST = 'G';
+ const USER_TYPE_CUSTOMER = 'C';
+ const USER_TYPE_ADMIN = 'A';
+
/**
* Permission level to deny access
*
diff --git a/app/code/core/Mage/Api/Model/Server.php b/app/code/core/Mage/Api/Model/Server.php
index 19e0c966d4..2f77af4e7d 100644
--- a/app/code/core/Mage/Api/Model/Server.php
+++ b/app/code/core/Mage/Api/Model/Server.php
@@ -33,6 +33,13 @@
*/
class Mage_Api_Model_Server
{
+
+ /**
+ * Api Name by Adapter
+ * @var string
+ */
+ protected $_api = "";
+
/**
* Web service adapter
*
@@ -44,6 +51,7 @@ public function init(Mage_Api_Controller_Action $controller, $adapter='default',
{
$adapters = Mage::getSingleton('api/config')->getActiveAdapters();
$handlers = Mage::getSingleton('api/config')->getHandlers();
+ $this->_api = $adapter;
if (isset($adapters[$adapter])) {
$adapterModel = Mage::getModel((string) $adapters[$adapter]->model);
/* @var $adapterModel Mage_Api_Model_Server_Adapter_Interface */
@@ -76,6 +84,15 @@ public function run()
$this->getAdapter()->run();
}
+ /**
+ * Get Api name by Adapter
+ * @return string
+ */
+ public function getApiName()
+ {
+ return $this->_api;
+ }
+
/**
* Retrieve web service adapter
*
diff --git a/app/code/core/Mage/Api/etc/wsi.xml b/app/code/core/Mage/Api/etc/wsi.xml
index ded00510c1..0db28ab286 100644
--- a/app/code/core/Mage/Api/etc/wsi.xml
+++ b/app/code/core/Mage/Api/etc/wsi.xml
@@ -19,6 +19,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/Api/sql/api_setup/mysql4-modify-columns.php b/app/code/core/Mage/Api/sql/api_setup/mysql4-modify-columns.php
deleted file mode 100644
index 88a3b15b6e..0000000000
--- a/app/code/core/Mage/Api/sql/api_setup/mysql4-modify-columns.php
+++ /dev/null
@@ -1,232 +0,0 @@
-
-$tables = array(
-
- 'api_assert' => array(
- 'columns' => array(
-
- 'assert_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'identity' => true,
- 'unsigned' => true,
- 'nullable' => false,
- 'primary' => true,
- 'comment' => 'Assert id'
- ),
- 'assert_type' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 20,
- 'comment' => 'Assert type'
- ),
- 'assert_data' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => '64K',
- 'comment' => 'Assert additional data'
- )
- ),
- 'comment' => 'Api ACL Asserts'
- ),
-
- 'api_role' => array(
- 'columns' => array(
-
- 'role_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'identity' => true,
- 'unsigned' => true,
- 'nullable' => false,
- 'primary' => true,
- 'comment' => 'Role id'
- ),
- 'parent_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Parent role id'
- ),
- 'tree_level' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_SMALLINT,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Role level in tree'
- ),
- 'sort_order' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_SMALLINT,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Sort order to display on admin area'
- ),
- 'role_type' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 1,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Role type'
- ),
- 'user_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'User id'
- ),
- 'role_name' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 50,
- 'comment' => 'Role name'
- )
- ),
- 'comment' => 'Api ACL Roles'
- ),
-
- 'api_rule' => array(
- 'columns' => array(
-
- 'rule_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'identity' => true,
- 'unsigned' => true,
- 'nullable' => false,
- 'primary' => true,
- 'comment' => 'Api rule Id'
- ),
- 'role_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Api role Id'
- ),
- 'resource_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 255,
- 'comment' => 'Module code'
- ),
- 'api_privileges' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 20,
- 'comment' => 'Privileges'
- ),
- 'assert_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Assert id'
- ),
- 'role_type' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 1,
- 'comment' => 'Role type'
- ),
- 'api_permission' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 10,
- 'comment' => 'Permission'
- )
- ),
- 'comment' => 'Api ACL Rules'
- ),
-
- 'api_user' => array(
- 'columns' => array(
-
- 'user_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'identity' => true,
- 'unsigned' => true,
- 'nullable' => false,
- 'primary' => true,
- 'comment' => 'User id'
- ),
- 'firstname' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 32,
- 'comment' => 'First name'
- ),
- 'lastname' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 32,
- 'comment' => 'Last name'
- ),
- 'email' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 128,
- 'comment' => 'Email'
- ),
- 'username' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 40,
- 'comment' => 'Nickname'
- ),
- 'api_key' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 100,
- 'comment' => 'Api key'
- ),
- 'created' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
- 'default' => 'CURRENT_TIMESTAMP',
- 'comment' => 'User record create date'
- ),
- 'modified' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
-,
- 'comment' => 'User record modify date'
- ),
- 'lognum' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_SMALLINT,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Quantity of log ins'
- ),
- 'reload_acl_flag' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_SMALLINT,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'Refresh ACL flag'
- ),
- 'is_active' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_SMALLINT,
- 'nullable' => false,
- 'default' => '1',
- 'comment' => 'Account status'
- )
- ),
- 'comment' => 'Api Users'
- ),
-
- 'api_session' => array(
- 'columns' => array(
-
- 'user_id' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
- 'unsigned' => true,
- 'nullable' => false,
- 'default' => '0',
- 'comment' => 'User id'
- ),
- 'logdate' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TIMESTAMP,
- 'default' => 'CURRENT_TIMESTAMP',
- 'comment' => 'Login date'
- ),
- 'sessid' => array(
- 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
- 'length' => 40,
- 'comment' => 'Sessioin id'
- )
- ),
- 'comment' => 'Api Sessions'
- )
-);
-
-foreach ($tables as $table => $tableData) {
- foreach ($tableData['columns'] as $column =>$columnDefinition) {
- $installer->getConnection()->modifyColumn($installer->getTable($table), $column, $columnDefinition);
- }
- $installer->getConnection()->changeTableComment($installer->getTable($table), $tableData['comment']);
-}
diff --git a/app/code/core/Mage/Bundle/Block/Catalog/Product/Price.php b/app/code/core/Mage/Bundle/Block/Catalog/Product/Price.php
index c0c30dd0c8..571e6a8817 100644
--- a/app/code/core/Mage/Bundle/Block/Catalog/Product/Price.php
+++ b/app/code/core/Mage/Bundle/Block/Catalog/Product/Price.php
@@ -74,6 +74,7 @@ protected function _toHtml()
if ($this->getMAPTemplate() && Mage::helper('catalog')->canApplyMsrp($product)
&& $product->getPriceType() != Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC
) {
+ $hiddenPriceHtml = parent::_toHtml();
if (Mage::helper('catalog')->isShowPriceOnGesture($product)) {
$this->setWithoutPrice(true);
}
@@ -84,8 +85,9 @@ protected function _toHtml()
$html = $this->getLayout()
->createBlock('catalog/product_price')
->setTemplate($this->getMAPTemplate())
- ->setRealPriceHtml($realPriceHtml)
- ->setIdSuffix('_clone')
+ ->setRealPriceHtml($hiddenPriceHtml)
+ ->setPriceElementIdPrefix('bundle-price-')
+ ->setIdSuffix($this->getIdSuffix())
->setProduct($product)
->toHtml();
diff --git a/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php b/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php
index f5106d17c7..d8e5daef87 100644
--- a/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php
+++ b/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php
@@ -81,6 +81,7 @@ public function getJsonConfig()
$selected = array();
$currentProduct = $this->getProduct();
$coreHelper = Mage::helper('core');
+ $bundlePriceModel = Mage::getModel('bundle/product_price');
if ($preconfiguredFlag = $currentProduct->hasPreconfiguredValues()) {
$preconfiguredValues = $currentProduct->getPreconfiguredValues();
@@ -120,14 +121,8 @@ public function getJsonConfig()
);
}
- $itemPrice = $_selection->getFinalPrice();
- if ($_selection->getSelectionPriceValue() != 0) {
- if ($_selection->getSelectionPriceType()) { // percent
- $itemPrice = $currentProduct->getFinalPrice() * $_selection->getSelectionPriceValue() / 100;
- } else { // fixed
- $itemPrice = $_selection->getSelectionPriceValue();
- }
- }
+ $itemPrice = $bundlePriceModel->getSelectionFinalTotalPrice($currentProduct, $_selection,
+ $currentProduct->getQty(), $_selection->getQty());
$canApplyMAP = false;
diff --git a/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php b/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php
index 0ad068fd12..3541ac0e89 100644
--- a/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php
+++ b/app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php
@@ -248,12 +248,12 @@ public function formatPriceString($price, $includeContainer = true)
$taxHelper = Mage::helper('tax');
$coreHelper = $this->helper('core');
$currentProduct = $this->getProduct();
- if (!$currentProduct->getPriceType() == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED
+ if ($currentProduct->getPriceType() == Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC
&& $this->getFormatProduct()
) {
$product = $this->getFormatProduct();
} else {
- $product = $this->getProduct();
+ $product = $currentProduct;
}
$priceTax = $taxHelper->getPrice($product, $price);
diff --git a/app/code/core/Mage/Bundle/Model/Observer.php b/app/code/core/Mage/Bundle/Model/Observer.php
index 72c95bd163..61943827ca 100644
--- a/app/code/core/Mage/Bundle/Model/Observer.php
+++ b/app/code/core/Mage/Bundle/Model/Observer.php
@@ -62,7 +62,9 @@ public function prepareProductSave($observer)
}
}
- $product->setCanSaveBundleSelections((bool)$request->getPost('affect_bundle_product_selections') && !$product->getCompositeReadonly());
+ $product->setCanSaveBundleSelections(
+ (bool)$request->getPost('affect_bundle_product_selections') && !$product->getCompositeReadonly()
+ );
return $this;
}
@@ -100,7 +102,7 @@ public function appendUpsellProducts($observer)
$resource = Mage::getResourceSingleton('bundle/selection');
$productIds = array_keys($collection->getItems());
- if ($limit <= count($productIds)) {
+ if (!is_null($limit) && $limit <= count($productIds)) {
return $this;
}
@@ -124,12 +126,22 @@ public function appendUpsellProducts($observer)
Mage::getSingleton('catalog/product_visibility')
->addVisibleInCatalogFilterToCollection($bundleCollection);
- $bundleCollection->setPageSize($limit - count($productIds))
- ->addFieldToFilter('entity_id', array('in' => $bundleIds))
+ if (!is_null($limit)) {
+ $bundleCollection->setPageSize($limit);
+ }
+ $bundleCollection->addFieldToFilter('entity_id', array('in' => $bundleIds))
->setFlag('do_not_use_category_id', true);
- foreach ($bundleCollection as $item) {
- $collection->addItem($item);
+ if ($collection instanceof Varien_Data_Collection) {
+ foreach ($bundleCollection as $item) {
+ $collection->addItem($item);
+ }
+ } elseif ($collection instanceof Varien_Object) {
+ $items = $collection->getItems();
+ foreach ($bundleCollection as $item) {
+ $items[$item->getEntityId()] = $item;
+ }
+ $collection->setItems($items);
}
return $this;
diff --git a/app/code/core/Mage/Bundle/Model/Product/Price.php b/app/code/core/Mage/Bundle/Model/Product/Price.php
index 43fc5a9869..748e771322 100644
--- a/app/code/core/Mage/Bundle/Model/Product/Price.php
+++ b/app/code/core/Mage/Bundle/Model/Product/Price.php
@@ -215,14 +215,12 @@ public function getTotalPrices($product, $which = null, $includeTax = null, $tak
$selectionMinimalPrices[] = Mage::helper('tax')->getPrice(
$item,
$this->getSelectionFinalTotalPrice($product, $selection, 1, $qty, true, $takeTierPrice),
- $includeTax,
- $takeTierPrice
+ $includeTax
);
$selectionMaximalPrices[] = Mage::helper('tax')->getPrice(
$item,
$this->getSelectionFinalTotalPrice($product, $selection, 1, null, true, $takeTierPrice),
- $includeTax,
- $takeTierPrice
+ $includeTax
);
}
@@ -373,7 +371,7 @@ public function getSelectionPrice($bundleProduct, $selectionProduct, $selectionQ
} else {
if ($selectionProduct->getSelectionPriceType()) { // percent
return $bundleProduct->getPrice() * ($selectionProduct->getSelectionPriceValue() / 100) * $selectionQty;
- } else {
+ } else { // fixed
return $selectionProduct->getSelectionPriceValue() * $selectionQty;
}
}
diff --git a/app/code/core/Mage/Bundle/Model/Product/Type.php b/app/code/core/Mage/Bundle/Model/Product/Type.php
index 4b5e42885c..a63111940d 100644
--- a/app/code/core/Mage/Bundle/Model/Product/Type.php
+++ b/app/code/core/Mage/Bundle/Model/Product/Type.php
@@ -552,7 +552,6 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
return Mage::helper('bundle')->__('Please select options for product.');
}
- //$optionsCollection = $this->getOptionsByIds($optionIds, $product);
$product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
$optionsCollection = $this->getOptionsCollection($product);
if (!$this->getProduct($product)->getSkipCheckRequiredOption() && $isStrictProcessMode) {
@@ -577,31 +576,33 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
}
}
}
+ // If product has not been configured yet then $selections array should be empty
+ if (!empty($selectionIds)) {
+ $selections = $this->getSelectionsByIds($selectionIds, $product);
- $selections = $this->getSelectionsByIds($selectionIds, $product);
-
- /**
- * checking if selections that where added are still on sale
- */
- foreach ($selections->getItems() as $key => $selection) {
- if (!$selection->isSalable()) {
- $_option = $optionsCollection->getItemById($selection->getOptionId());
- if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1){
- $moreSelections = true;
- } else {
- $moreSelections = false;
- }
- if ($_option->getRequired() &&
- (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))
- ) {
- return Mage::helper('bundle')->__('Selected required options are not available.');
+ // Check if added selections are still on sale
+ foreach ($selections->getItems() as $key => $selection) {
+ if (!$selection->isSalable()) {
+ $_option = $optionsCollection->getItemById($selection->getOptionId());
+ if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1) {
+ $moreSelections = true;
+ } else {
+ $moreSelections = false;
+ }
+ if ($_option->getRequired()
+ && (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))
+ ) {
+ return Mage::helper('bundle')->__('Selected required options are not available.');
+ }
}
}
- }
- $optionsCollection->appendSelections($selections, false, $_appendAllSelections);
+ $optionsCollection->appendSelections($selections, false, $_appendAllSelections);
- $selections = $selections->getItems();
+ $selections = $selections->getItems();
+ } else {
+ $selections = array();
+ }
} else {
$product->setOptionsValidationFail(true);
$product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
@@ -632,9 +633,7 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
$uniqueKey = array($product->getId());
$selectionIds = array();
- /*
- * shaking selection array :) by option position
- */
+ // Shuffle selection array by option position
usort($selections, array($this, 'shakeSelections'));
foreach ($selections as $selection) {
@@ -649,14 +648,14 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
$selection->addCustomOption('selection_id', $selection->getSelectionId());
$beforeQty = 0;
- if ($customOption = $product->getCustomOption('product_qty_' . $selection->getId())) {
+ $customOption = $product->getCustomOption('product_qty_' . $selection->getId());
+ if ($customOption) {
$beforeQty = (float)$customOption->getValue();
}
$product->addCustomOption('product_qty_' . $selection->getId(), $qty + $beforeQty, $selection);
/*
- * creating extra attributes that will be converted
- * to product options in order item
+ * Create extra attributes that will be converted to product options in order item
* for selection (not for all bundle)
*/
$price = $product->getPriceModel()->getSelectionPrice($product, $selection, $qty);
@@ -667,7 +666,6 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
'option_id' => $selection->getOption()->getId()
);
- //if (!$product->getPriceType()) {
$_result = $selection->getTypeInstance(true)->prepareForCart($buyRequest, $selection);
if (is_string($_result) && !is_array($_result)) {
return $_result;
@@ -680,7 +678,6 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
$result[] = $_result[0]->setParentProductId($product->getId())
->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)))
->addCustomOption('bundle_selection_attributes', serialize($attributes));
- //}
if ($isStrictProcessMode) {
$_result[0]->setCartQty($qty);
@@ -690,14 +687,13 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
$uniqueKey[] = $_result[0]->getSelectionId();
$uniqueKey[] = $qty;
}
- /**
- * "unique" key for bundle selection and add it to selections and bundle for selections
- */
+
+ // "unique" key for bundle selection and add it to selections and bundle for selections
$uniqueKey = implode('_', $uniqueKey);
foreach ($result as $item) {
$item->addCustomOption('bundle_identity', $uniqueKey);
}
- $product->addCustomOption('bundle_option_ids', serialize(array_map('intval',$optionIds)));
+ $product->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)));
$product->addCustomOption('bundle_selection_ids', serialize($selectionIds));
return $result;
@@ -845,17 +841,33 @@ public function getOrderOptions($product = null)
return $optionArr;
}
+ /**
+ * Sort selections method for usort function
+ * Sort selections by option position, selection position and selection id
+ *
+ * @param Mage_Catalog_Model_Product $a
+ * @param Mage_Catalog_Model_Product $b
+ * @return int
+ */
public function shakeSelections($a, $b)
{
- $aPosition = ($a->getOption()->getPosition()+1)*($a->getPosition()+1);
- $bPosition = ($b->getOption()->getPosition()+1)*($b->getPosition()+1);
+ $aPosition = array(
+ $a->getOption()->getPosition(),
+ $a->getOptionId(),
+ $a->getPosition(),
+ $a->getSelectionId()
+ );
+ $bPosition = array(
+ $b->getOption()->getPosition(),
+ $b->getOptionId(),
+ $b->getPosition(),
+ $b->getSelectionId()
+ );
if ($aPosition == $bPosition) {
- if ($a->getSelectionId() == $b->getSelectionId()) {
- return 0;
- }
- return ($a->getSelectionId() < $b->getSelectionId()) ? -1 : 1;
+ return 0;
+ } else {
+ return $aPosition < $bPosition ? -1 : 1;
}
- return ($aPosition < $bPosition) ? -1 : 1;
}
/**
diff --git a/app/code/core/Mage/Bundle/Model/Resource/Indexer/Price.php b/app/code/core/Mage/Bundle/Model/Resource/Indexer/Price.php
index 119764b61f..96a97e2512 100755
--- a/app/code/core/Mage/Bundle/Model/Resource/Indexer/Price.php
+++ b/app/code/core/Mage/Bundle/Model/Resource/Indexer/Price.php
@@ -211,7 +211,7 @@ protected function _prepareBundlePriceByType($priceType, $entityIds = null)
'0'
)
)
- . " > 0 AND {$specialPrice} > 0 ",
+ . " > 0 AND {$specialPrice} > 0 AND {$specialPrice} < 100 ",
$specialPrice,
'0'
);
diff --git a/app/code/core/Mage/Catalog/Block/Product/Abstract.php b/app/code/core/Mage/Catalog/Block/Product/Abstract.php
index e0263c04dd..e573a5163e 100644
--- a/app/code/core/Mage/Catalog/Block/Product/Abstract.php
+++ b/app/code/core/Mage/Catalog/Block/Product/Abstract.php
@@ -280,13 +280,14 @@ public function addReviewSummaryTemplate($type, $template)
protected function _initReviewsHelperBlock()
{
if (!$this->_reviewsHelperBlock) {
- if (Mage::helper('catalog')->isModuleEnabled('Mage_Review')) {
+ if (!Mage::helper('catalog')->isModuleEnabled('Mage_Review')) {
+ return false;
+ } else {
$this->_reviewsHelperBlock = $this->getLayout()->createBlock('review/helper');
- return true;
}
}
- return false;
+ return true;
}
/**
diff --git a/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php b/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php
index be0a278775..eb0ff63514 100644
--- a/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php
+++ b/app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php
@@ -154,6 +154,7 @@ public function getJsonConfig()
$currentProduct->setConfigurablePrice(
$this->_preparePrice($value['pricing_value'], $value['is_percent'])
);
+ $currentProduct->setParentId(true);
Mage::dispatchEvent(
'catalog_product_type_configurable_price',
array('product' => $currentProduct)
diff --git a/app/code/core/Mage/Catalog/Helper/Product.php b/app/code/core/Mage/Catalog/Helper/Product.php
index 2d62c75c28..bf9b7c26c1 100644
--- a/app/code/core/Mage/Catalog/Helper/Product.php
+++ b/app/code/core/Mage/Catalog/Helper/Product.php
@@ -280,7 +280,10 @@ public function initProduct($productId, $controller, $params = null)
}
// Init and load product
- Mage::dispatchEvent('catalog_controller_product_init_before', array('controller_action' => $controller));
+ Mage::dispatchEvent('catalog_controller_product_init_before', array(
+ 'controller_action' => $controller,
+ 'params' => $params,
+ ));
if (!$productId) {
return false;
diff --git a/app/code/core/Mage/Catalog/Helper/Product/Configuration.php b/app/code/core/Mage/Catalog/Helper/Product/Configuration.php
index e9084308f1..ce9e98360a 100644
--- a/app/code/core/Mage/Catalog/Helper/Product/Configuration.php
+++ b/app/code/core/Mage/Catalog/Helper/Product/Configuration.php
@@ -143,7 +143,15 @@ public function getGroupedOptions(Mage_Catalog_Model_Product_Configuration_Item_
}
}
- return array_merge($options, $this->getCustomOptions($item));
+ $options = array_merge($options, $this->getCustomOptions($item));
+ $isUnConfigured = true;
+ foreach ($options as &$option) {
+ if ($option['value']) {
+ $isUnConfigured = false;
+ break;
+ }
+ }
+ return $isUnConfigured ? array() : $options;
}
/**
diff --git a/app/code/core/Mage/Catalog/Model/Api/Resource.php b/app/code/core/Mage/Catalog/Model/Api/Resource.php
index 9cd461db80..bfe7e715ff 100644
--- a/app/code/core/Mage/Catalog/Model/Api/Resource.php
+++ b/app/code/core/Mage/Catalog/Model/Api/Resource.php
@@ -53,6 +53,12 @@ class Mage_Catalog_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract
*/
protected $_storeIdSessionField = 'store_id';
+ /**
+ * Name of resource model in ACL list
+ * @var string
+ */
+ protected $_resourceAttributeAclName = 'catalog/category/attributes/field_';
+
/**
* Check is attribute allowed
*
@@ -62,6 +68,13 @@ class Mage_Catalog_Model_Api_Resource extends Mage_Api_Model_Resource_Abstract
*/
protected function _isAllowedAttribute($attribute, $attributes = null)
{
+
+ if (Mage::getSingleton('api/server')->getApiName() == 'rest') {
+ if (!$this->_checkAttributeAcl($attribute)) {
+ return false;
+ }
+ }
+
if (is_array($attributes)
&& !( in_array($attribute->getAttributeCode(), $attributes)
|| in_array($attribute->getAttributeId(), $attributes))) {
@@ -106,6 +119,9 @@ protected function _getStoreId($store = null)
protected function _getProduct($productId, $store = null, $identifierType = null)
{
$product = Mage::helper('catalog/product')->getProduct($productId, $this->_getStoreId($store), $identifierType);
+ if (is_null($product->getId())) {
+ $this->_fault('product_not_exists');
+ }
return $product;
}
diff --git a/app/code/core/Mage/Catalog/Model/Category/Api.php b/app/code/core/Mage/Catalog/Model/Category/Api.php
index 091e6e3a59..3b51f812f4 100644
--- a/app/code/core/Mage/Catalog/Model/Category/Api.php
+++ b/app/code/core/Mage/Catalog/Model/Category/Api.php
@@ -39,10 +39,11 @@ public function __construct()
}
/**
- * Retrive level of categories for category/store view/website
+ * Retrieve level of categories for category/store view/website
*
- * @param string|int $website
- * @param string|int $store
+ * @param string|int|null $website
+ * @param string|int|null $store
+ * @param int|null $categoryId
* @return array
*/
public function level($website = null, $store = null, $categoryId = null)
@@ -240,39 +241,57 @@ public function info($categoryId, $store = null, $attributes = null)
*
* @param int $parentId
* @param array $categoryData
+ * @param int|null|string $store
* @return int
*/
public function create($parentId, $categoryData, $store = null)
{
$parent_category = $this->_initCategory($parentId, $store);
+
+ /** @var $category Mage_Catalog_Model_Category */
$category = Mage::getModel('catalog/category')
->setStoreId($this->_getStoreId($store));
- $category->addData(array('path'=>implode('/',$parent_category->getPathIds())));
-
- $category ->setAttributeSetId($category->getDefaultAttributeSetId());
- /* @var $category Mage_Catalog_Model_Category */
+ $category->addData(array('path'=>implode('/', $parent_category->getPathIds())));
+ $category->setAttributeSetId($category->getDefaultAttributeSetId());
+ $useConfig = array();
foreach ($category->getAttributes() as $attribute) {
if ($this->_isAllowedAttribute($attribute)
- && isset($categoryData[$attribute->getAttributeCode()])) {
- $category->setData(
- $attribute->getAttributeCode(),
- $categoryData[$attribute->getAttributeCode()]
- );
+ && isset($categoryData[$attribute->getAttributeCode()])
+ ) {
+ // check whether value is 'use_config'
+ $attrCode = $attribute->getAttributeCode();
+ $categoryDataValue = $categoryData[$attrCode];
+ if ('use_config' === $categoryDataValue ||
+ (is_array($categoryDataValue) &&
+ count($categoryDataValue) == 1 &&
+ 'use_config' === $categoryDataValue[0])
+ ) {
+ $useConfig[] = $attrCode;
+ $category->setData($attrCode, null);
+ } else {
+ $category->setData($attrCode, $categoryDataValue);
+ }
}
}
$category->setParentId($parent_category->getId());
+ /**
+ * Proceed with $useConfig set into category model for processing through validation
+ */
+ if (count($useConfig) > 0) {
+ $category->setData("use_post_data_config", $useConfig);
+ }
+
try {
$validate = $category->validate();
if ($validate !== true) {
foreach ($validate as $code => $error) {
if ($error === true) {
Mage::throwException(Mage::helper('catalog')->__('Attribute "%s" is required.', $code));
- }
- else {
+ } else {
Mage::throwException($error);
}
}
@@ -283,6 +302,9 @@ public function create($parentId, $categoryData, $store = null)
catch (Mage_Core_Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
}
+ catch (Exception $e) {
+ $this->_fault('data_invalid', $e->getMessage());
+ }
return $category->getId();
}
diff --git a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php b/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php
index 1977a6e045..04058ec294 100644
--- a/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php
+++ b/app/code/core/Mage/Catalog/Model/Category/Attribute/Api.php
@@ -72,7 +72,7 @@ public function items()
return $result;
}
- /**
+ /**
* Retrieve category attribute options
*
* @param int|string $attributeId
@@ -92,7 +92,7 @@ public function options($attributeId, $store = null)
$result = array();
if ($attribute->usesSource()) {
- foreach ($attribute->getSource()->getAllOptions() as $optionId=>$optionValue) {
+ foreach ($attribute->getSource()->getAllOptions(false) as $optionId=>$optionValue) {
if (is_array($optionValue)) {
$result[] = $optionValue;
} else {
diff --git a/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php b/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php
index de628da596..4d55942957 100644
--- a/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php
+++ b/app/code/core/Mage/Catalog/Model/Convert/Adapter/Product.php
@@ -742,7 +742,13 @@ public function saveRow(array $importData)
} else {
$setValue = false;
foreach ($options as $item) {
- if ($item['label'] == $value) {
+ if (is_array($item['value'])) {
+ foreach ($item['value'] as $subValue) {
+ if (isset($subValue['value']) && $subValue['value'] == $value) {
+ $setValue = $value;
+ }
+ }
+ } else if ($item['label'] == $value) {
$setValue = $item['value'];
}
}
diff --git a/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php b/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php
index ba03020f87..969184a993 100644
--- a/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php
+++ b/app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php
@@ -91,8 +91,7 @@ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
}
$this->_categoryId = $filter;
- $category = $this->getCategory();
- Mage::register('current_category_filter', $category);
+ Mage::register('current_category_filter', $this->getCategory(), true);
$this->_appliedCategory = Mage::getModel('catalog/category')
->setStoreId(Mage::app()->getStore()->getId())
diff --git a/app/code/core/Mage/Catalog/Model/Product.php b/app/code/core/Mage/Catalog/Model/Product.php
index 5f4987bef6..1470ccbfdf 100644
--- a/app/code/core/Mage/Catalog/Model/Product.php
+++ b/app/code/core/Mage/Catalog/Model/Product.php
@@ -242,6 +242,9 @@ public function getTypeId()
*/
public function getStatus()
{
+ if (is_null($this->_getData('status'))) {
+ $this->setData('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
+ }
return $this->_getData('status');
}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Api.php b/app/code/core/Mage/Catalog/Model/Product/Api.php
index dd7a853e09..b23698f02f 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Api.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Api.php
@@ -39,6 +39,40 @@ class Mage_Catalog_Model_Product_Api extends Mage_Catalog_Model_Api_Resource
'type' => 'type_id'
);
+ protected $_defaultProductAttributeList = array(
+ 'type_id',
+ 'category_ids',
+ 'website_ids',
+ 'name',
+ 'description',
+ 'short_description',
+ 'sku',
+ 'weight',
+ 'status',
+ 'url_key',
+ 'url_path',
+ 'visibility',
+ 'has_options',
+ 'gift_message_available',
+ 'price',
+ 'special_price',
+ 'special_from_date',
+ 'special_to_date',
+ 'tax_class_id',
+ 'tier_price',
+ 'meta_title',
+ 'meta_keyword',
+ 'meta_description',
+ 'custom_design',
+ 'custom_layout_update',
+ 'options_container',
+ 'image_label',
+ 'small_image_label',
+ 'thumbnail_label',
+ 'created_at',
+ 'updated_at'
+ );
+
public function __construct()
{
$this->_storeIdSessionField = 'product_store_id';
@@ -102,9 +136,6 @@ public function info($productId, $store = null, $attributes = null, $identifierT
{
$product = $this->_getProduct($productId, $store, $identifierType);
- if (!$product->getId()) {
- $this->_fault('not_exists');
- }
$result = array( // Basic product data
'product_id' => $product->getId(),
@@ -141,6 +172,9 @@ public function create($type, $set, $sku, $productData, $store = null)
$this->_fault('data_invalid');
}
+ $this->_checkProductTypeExists($type);
+ $this->_checkProductAttributeSet($set);
+
/** @var $product Mage_Catalog_Model_Product */
$product = Mage::getModel('catalog/product');
$product->setStoreId($this->_getStoreId($store))
@@ -148,20 +182,6 @@ public function create($type, $set, $sku, $productData, $store = null)
->setTypeId($type)
->setSku($sku);
- if (isset($productData['website_ids']) && is_array($productData['website_ids'])) {
- $product->setWebsiteIds($productData['website_ids']);
- }
-
- foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
- if ($this->_isAllowedAttribute($attribute)
- && isset($productData[$attribute->getAttributeCode()])) {
- $product->setData(
- $attribute->getAttributeCode(),
- $productData[$attribute->getAttributeCode()]
- );
- }
- }
-
$this->_prepareDataForSave($product, $productData);
try {
@@ -171,8 +191,11 @@ public function create($type, $set, $sku, $productData, $store = null)
*/
if (is_array($errors = $product->validate())) {
$strErrors = array();
- foreach($errors as $code=>$error) {
- $strErrors[] = ($error === true)? Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code) : $error;
+ foreach($errors as $code => $error) {
+ if ($error === true) {
+ $error = Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code);
+ }
+ $strErrors[] = $error;
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
@@ -197,27 +220,8 @@ public function update($productId, $productData, $store = null, $identifierType
{
$product = $this->_getProduct($productId, $store, $identifierType);
- if (!$product->getId()) {
- $this->_fault('not_exists');
- }
-
- if (isset($productData['website_ids']) && is_array($productData['website_ids'])) {
- $product->setWebsiteIds($productData['website_ids']);
- }
-
- foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
- if ($this->_isAllowedAttribute($attribute)
- && isset($productData[$attribute->getAttributeCode()])) {
- $product->setData(
- $attribute->getAttributeCode(),
- $productData[$attribute->getAttributeCode()]
- );
- }
- }
-
$this->_prepareDataForSave($product, $productData);
-
try {
/**
* @todo implement full validation process with errors returning which are ignoring now
@@ -225,8 +229,13 @@ public function update($productId, $productData, $store = null, $identifierType
*/
if (is_array($errors = $product->validate())) {
$strErrors = array();
- foreach($errors as $code=>$error) {
- $strErrors[] = ($error === true)? Mage::helper('catalog')->__('Value for "%s" is invalid.', $code) : Mage::helper('catalog')->__('Value for "%s" is invalid: %s', $code, $error);
+ foreach($errors as $code => $error) {
+ if ($error === true) {
+ $error = Mage::helper('catalog')->__('Value for "%s" is invalid.', $code);
+ } else {
+ $error = Mage::helper('catalog')->__('Value for "%s" is invalid: %s', $code, $error);
+ }
+ $strErrors[] = $error;
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
@@ -244,10 +253,35 @@ public function update($productId, $productData, $store = null, $identifierType
*
* @param Mage_Catalog_Model_Product $product
* @param array $productData
- * @return object
+ * @return object
*/
- protected function _prepareDataForSave ($product, $productData)
+ protected function _prepareDataForSave($product, $productData)
{
+ if (isset($productData['website_ids']) && is_array($productData['website_ids'])) {
+ $product->setWebsiteIds($productData['website_ids']);
+ }
+
+ foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
+ if ($this->_isAllowedAttribute($attribute)) {
+ if (isset($productData[$attribute->getAttributeCode()])) {
+ $product->setData(
+ $attribute->getAttributeCode(),
+ $productData[$attribute->getAttributeCode()]
+ );
+ } elseif (isset($productData['additional_attributes']['single_data'][$attribute->getAttributeCode()])) {
+ $product->setData(
+ $attribute->getAttributeCode(),
+ $productData['additional_attributes']['single_data'][$attribute->getAttributeCode()]
+ );
+ } elseif (isset($productData['additional_attributes']['multi_data'][$attribute->getAttributeCode()])) {
+ $product->setData(
+ $attribute->getAttributeCode(),
+ $productData['additional_attributes']['multi_data'][$attribute->getAttributeCode()]
+ );
+ }
+ }
+ }
+
if (isset($productData['categories']) && is_array($productData['categories'])) {
$product->setCategoryIds($productData['categories']);
}
@@ -274,7 +308,8 @@ protected function _prepareDataForSave ($product, $productData)
}
if (isset($productData['tier_price']) && is_array($productData['tier_price'])) {
- $tierPrices = Mage::getModel('catalog/product_attribute_tierprice_api')->prepareTierPrices($product, $productData['tier_price']);
+ $tierPrices = Mage::getModel('catalog/product_attribute_tierprice_api')
+ ->prepareTierPrices($product, $productData['tier_price']);
$product->setData(Mage_Catalog_Model_Product_Attribute_Tierprice_Api::ATTRIBUTE_CODE, $tierPrices);
}
}
@@ -320,10 +355,6 @@ public function delete($productId, $identifierType = null)
{
$product = $this->_getProduct($productId, null, $identifierType);
- if (!$product->getId()) {
- $this->_fault('not_exists');
- }
-
try {
$product->delete();
} catch (Mage_Core_Exception $e) {
@@ -332,4 +363,82 @@ public function delete($productId, $identifierType = null)
return true;
}
+
+ /**
+ * Get list of additional attributes which are not in default create/update list
+ *
+ * @param $productType
+ * @param $attributeSetId
+ * @return array
+ */
+ public function getAdditionalAttributes($productType, $attributeSetId)
+ {
+ $this->_checkProductTypeExists($productType);
+ $this->_checkProductAttributeSet($attributeSetId);
+
+ /** @var $product Mage_Catalog_Model_Product */
+ $productAttributes = Mage::getModel('catalog/product')
+ ->setAttributeSetId($attributeSetId)
+ ->setTypeId($productType)
+ ->getTypeInstance(false)
+ ->getEditableAttributes();
+
+ $result = array();
+ foreach ($productAttributes as $attribute) {
+ /* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
+ if ($attribute->isInSet($attributeSetId) && $this->_isAllowedAttribute($attribute)
+ && !in_array($attribute->getAttributeCode(), $this->_defaultProductAttributeList)) {
+
+ if ($attribute->isScopeGlobal()) {
+ $scope = 'global';
+ } elseif ($attribute->isScopeWebsite()) {
+ $scope = 'website';
+ } else {
+ $scope = 'store';
+ }
+
+ $result[] = array(
+ 'attribute_id' => $attribute->getId(),
+ 'code' => $attribute->getAttributeCode(),
+ 'type' => $attribute->getFrontendInput(),
+ 'required' => $attribute->getIsRequired(),
+ 'scope' => $scope
+ );
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Check if product type exists
+ *
+ * @param $productType
+ * @throw Mage_Api_Exception
+ * @return void
+ */
+ protected function _checkProductTypeExists($productType)
+ {
+ if (!in_array($productType, array_keys(Mage::getModel('catalog/product_type')->getOptionArray()))) {
+ $this->_fault('product_type_not_exists');
+ }
+ }
+
+ /**
+ * Check if attributeSet is exits and in catalog_product entity group type
+ *
+ * @param $attributeSetId
+ * @throw Mage_Api_Exception
+ * @return void
+ */
+ protected function _checkProductAttributeSet($attributeSetId)
+ {
+ $attributeSet = Mage::getModel('eav/entity_attribute_set')->load($attributeSetId);
+ if (is_null($attributeSet->getId())) {
+ $this->_fault('product_attribute_set_not_exists');
+ }
+ if (Mage::getModel('catalog/product')->getResource()->getTypeId() != $attributeSet->getEntityTypeId()) {
+ $this->_fault('product_attribute_set_not_valid');
+ }
+ }
} // Class Mage_Catalog_Model_Product_Api End
diff --git a/app/code/core/Mage/Catalog/Model/Product/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Api/V2.php
index e1afaa7dd8..3395546044 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Api/V2.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Api/V2.php
@@ -105,10 +105,6 @@ public function info($productId, $store = null, $attributes = null, $identifierT
{
$product = $this->_getProduct($productId, $store, $identifierType);
- if (!$product->getId()) {
- $this->_fault('not_exists');
- }
-
$result = array( // Basic product data
'product_id' => $product->getId(),
'sku' => $product->getSku(),
@@ -142,7 +138,8 @@ public function info($productId, $store = null, $attributes = null, $identifierT
if ($this->_isAllowedAttribute($attribute, $allAttributes)) {
if (in_array($attribute->getAttributeCode(), $_additionalAttributeCodes)) {
$result['additional_attributes'][$_additionalAttribute]['key'] = $attribute->getAttributeCode();
- $result['additional_attributes'][$_additionalAttribute]['value'] = $product->getData($attribute->getAttributeCode());
+ $result['additional_attributes'][$_additionalAttribute]['value'] = $product
+ ->getData($attribute->getAttributeCode());
$_additionalAttribute++;
} else {
$result[$attribute->getAttributeCode()] = $product->getData($attribute->getAttributeCode());
@@ -169,6 +166,9 @@ public function create($type, $set, $sku, $productData, $store = null)
$this->_fault('data_invalid');
}
+ $this->_checkProductTypeExists($type);
+ $this->_checkProductAttributeSet($set);
+
/** @var $product Mage_Catalog_Model_Product */
$product = Mage::getModel('catalog/product');
$product->setStoreId($this->_getStoreId($store))
@@ -176,29 +176,6 @@ public function create($type, $set, $sku, $productData, $store = null)
->setTypeId($type)
->setSku($sku);
- if (property_exists($productData, 'website_ids') && is_array($productData->website_ids)) {
- $product->setWebsiteIds($productData->website_ids);
- }
-
- if (property_exists($productData, 'additional_attributes')) {
- foreach ($productData->additional_attributes as $_attribute) {
- $_attrCode = $_attribute->key;
- $productData->$_attrCode = $_attribute->value;
- }
- unset($productData->additional_attributes);
- }
-
- foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
- $_attrCode = $attribute->getAttributeCode();
- if ($this->_isAllowedAttribute($attribute)
- && isset($productData->$_attrCode)) {
- $product->setData(
- $attribute->getAttributeCode(),
- $productData->$_attrCode
- );
- }
- }
-
$this->_prepareDataForSave($product, $productData);
try {
@@ -208,8 +185,11 @@ public function create($type, $set, $sku, $productData, $store = null)
*/
if (is_array($errors = $product->validate())) {
$strErrors = array();
- foreach($errors as $code=>$error) {
- $strErrors[] = ($error === true)? Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code) : $error;
+ foreach($errors as $code => $error) {
+ if ($error === true) {
+ $error = Mage::helper('catalog')->__('Attribute "%s" is invalid.', $code);
+ }
+ $strErrors[] = $error;
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
@@ -234,33 +214,6 @@ public function update($productId, $productData, $store = null, $identifierType
{
$product = $this->_getProduct($productId, $store, $identifierType);
- if (!$product->getId()) {
- $this->_fault('not_exists');
- }
-
- if (property_exists($productData, 'website_ids') && is_array($productData->website_ids)) {
- $product->setWebsiteIds($productData->website_ids);
- }
-
- if (property_exists($productData, 'additional_attributes')) {
- foreach ($productData->additional_attributes as $_attribute) {
- $_attrCode = $_attribute->key;
- $productData->$_attrCode = $_attribute->value;
- }
- unset($productData->additional_attributes);
- }
-
- foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
- $_attrCode = $attribute->getAttributeCode();
- if ($this->_isAllowedAttribute($attribute)
- && isset($productData->$_attrCode)) {
- $product->setData(
- $attribute->getAttributeCode(),
- $productData->$_attrCode
- );
- }
- }
-
$this->_prepareDataForSave($product, $productData);
try {
@@ -270,8 +223,13 @@ public function update($productId, $productData, $store = null, $identifierType
*/
if (is_array($errors = $product->validate())) {
$strErrors = array();
- foreach($errors as $code=>$error) {
- $strErrors[] = ($error === true)? Mage::helper('catalog')->__('Value for "%s" is invalid.', $code) : Mage::helper('catalog')->__('Value for "%s" is invalid: %s', $code, $error);
+ foreach($errors as $code => $error) {
+ if ($error === true) {
+ $error = Mage::helper('catalog')->__('Value for "%s" is invalid.', $code);
+ } else {
+ $error = Mage::helper('catalog')->__('Value for "%s" is invalid: %s', $code, $error);
+ }
+ $strErrors[] = $error;
}
$this->_fault('data_invalid', implode("\n", $strErrors));
}
@@ -289,10 +247,40 @@ public function update($productId, $productData, $store = null, $identifierType
*
* @param Mage_Catalog_Model_Product $product
* @param array $productData
- * @return object
+ * @return object
*/
protected function _prepareDataForSave ($product, $productData)
{
+ if (property_exists($productData, 'website_ids') && is_array($productData->website_ids)) {
+ $product->setWebsiteIds($productData->website_ids);
+ }
+
+ if (property_exists($productData, 'additional_attributes')) {
+ if (property_exists($productData->additional_attributes, 'single_data')) {
+ foreach ($productData->additional_attributes->single_data as $_attribute) {
+ $_attrCode = $_attribute->key;
+ $productData->$_attrCode = $_attribute->value;
+ }
+ }
+ if (property_exists($productData->additional_attributes, 'multi_data')) {
+ foreach ($productData->additional_attributes->multi_data as $_attribute) {
+ $_attrCode = $_attribute->key;
+ $productData->$_attrCode = $_attribute->value;
+ }
+ }
+ unset($productData->additional_attributes);
+ }
+
+ foreach ($product->getTypeInstance(true)->getEditableAttributes($product) as $attribute) {
+ $_attrCode = $attribute->getAttributeCode();
+ if ($this->_isAllowedAttribute($attribute) && (isset($productData->$_attrCode))) {
+ $product->setData(
+ $attribute->getAttributeCode(),
+ $productData->$_attrCode
+ );
+ }
+ }
+
if (property_exists($productData, 'categories') && is_array($productData->categories)) {
$product->setCategoryIds($productData->categories);
}
@@ -323,7 +311,8 @@ protected function _prepareDataForSave ($product, $productData)
$product->setStockData($_stockData);
if (property_exists($productData, 'tier_price')) {
- $tierPrices = Mage::getModel('catalog/product_attribute_tierprice_api_V2')->prepareTierPrices($product, $productData->tier_price);
+ $tierPrices = Mage::getModel('catalog/product_attribute_tierprice_api_V2')
+ ->prepareTierPrices($product, $productData->tier_price);
$product->setData(Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2::ATTRIBUTE_CODE, $tierPrices);
}
}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php
index c01c66a31a..0357dc3d3f 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php
@@ -33,12 +33,23 @@
*/
class Mage_Catalog_Model_Product_Attribute_Api extends Mage_Catalog_Model_Api_Resource
{
+ /**
+ * Product entity type id
+ *
+ * @var int
+ */
+ protected $_entityTypeId;
+
+ /**
+ * Constructor. Initializes default values.
+ */
public function __construct()
{
$this->_storeIdSessionField = 'product_store_id';
$this->_ignoredAttributeCodes[] = 'type_id';
$this->_ignoredAttributeTypes[] = 'gallery';
$this->_ignoredAttributeTypes[] = 'media_image';
+ $this->_entityTypeId = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId();
}
/**
@@ -56,8 +67,8 @@ public function items($setId)
foreach ($attributes as $attribute) {
/* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
- if ( (!$attribute->getId() || $attribute->isInSet($setId))
- && $this->_isAllowedAttribute($attribute)) {
+ if ((!$attribute->getId() || $attribute->isInSet($setId))
+ && $this->_isAllowedAttribute($attribute)) {
if (!$attribute->getId() || $attribute->isScopeGlobal()) {
$scope = 'global';
@@ -69,10 +80,10 @@ public function items($setId)
$result[] = array(
'attribute_id' => $attribute->getId(),
- 'code' => $attribute->getAttributeCode(),
- 'type' => $attribute->getFrontendInput(),
- 'required' => $attribute->getIsRequired(),
- 'scope' => $scope
+ 'code' => $attribute->getAttributeCode(),
+ 'type' => $attribute->getFrontendInput(),
+ 'required' => $attribute->getIsRequired(),
+ 'scope' => $scope
);
}
}
@@ -91,10 +102,9 @@ public function options($attributeId, $store = null)
{
$storeId = $this->_getStoreId($store);
$attribute = Mage::getModel('catalog/product')
- ->setStoreId($storeId)
- ->getResource()
- ->getAttribute($attributeId)
- ->setStoreId($storeId);
+ ->setStoreId($storeId)
+ ->getResource()
+ ->getAttribute($attributeId);
/* @var $attribute Mage_Catalog_Model_Entity_Attribute */
if (!$attribute) {
@@ -102,7 +112,7 @@ public function options($attributeId, $store = null)
}
$options = array();
if ($attribute->usesSource()) {
- foreach ($attribute->getSource()->getAllOptions() as $optionId=>$optionValue) {
+ foreach ($attribute->getSource()->getAllOptions() as $optionId => $optionValue) {
if (is_array($optionValue)) {
$options[] = $optionValue;
} else {
@@ -113,6 +123,404 @@ public function options($attributeId, $store = null)
}
}
}
+
return $options;
}
+
+ /**
+ * Retrieve list of possible attribute types
+ *
+ * @return array
+ */
+ public function types()
+ {
+ return Mage::getModel('catalog/product_attribute_source_inputtype')->toOptionArray();
+ }
+
+ /**
+ * Create new product attribute
+ *
+ * @param array $data input data
+ * @return integer
+ */
+ public function create($data)
+ {
+ /** @var $model Mage_Catalog_Model_Resource_Eav_Attribute */
+ $model = Mage::getModel('catalog/resource_eav_attribute');
+ /** @var $helper Mage_Catalog_Helper_Product */
+ $helper = Mage::helper('catalog/product');
+
+ if (empty($data['attribute_code']) || !is_array($data['frontend_label'])) {
+ $this->_fault('invalid_parameters');
+ }
+
+ //validate attribute_code
+ if (!preg_match('/^[a-z][a-z_0-9]{0,254}$/', $data['attribute_code'])) {
+ $this->_fault('invalid_code');
+ }
+
+ //validate frontend_input
+ $allowedTypes = array();
+ foreach ($this->types() as $type) {
+ $allowedTypes[] = $type['value'];
+ }
+ if (!in_array($data['frontend_input'], $allowedTypes)) {
+ $this->_fault('invalid_frontend_input');
+ }
+
+ $data['source_model'] = $helper->getAttributeSourceModelByInputType($data['frontend_input']);
+ $data['backend_model'] = $helper->getAttributeBackendModelByInputType($data['frontend_input']);
+ if (is_null($model->getIsUserDefined()) || $model->getIsUserDefined() != 0) {
+ $data['backend_type'] = $model->getBackendTypeByInput($data['frontend_input']);
+ }
+
+ $this->_prepareDataForSave($data);
+
+ $model->addData($data);
+ $model->setEntityTypeId($this->_entityTypeId);
+ $model->setIsUserDefined(1);
+
+ try {
+ $model->save();
+ // clear translation cache because attribute labels are stored in translation
+ Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG));
+ } catch (Exception $e) {
+ $this->_fault('unable_to_save', $e->getMessage());
+ }
+
+ return (int) $model->getId();
+ }
+
+ /**
+ * Update product attribute
+ *
+ * @param string|integer $attribute attribute code or ID
+ * @param array $data
+ * @return boolean
+ */
+ public function update($attribute, $data)
+ {
+ $model = $this->_getAttribute($attribute);
+
+ if ($model->getEntityTypeId() != $this->_entityTypeId) {
+ $this->_fault('can_not_edit');
+ }
+
+ $data['attribute_code'] = $model->getAttributeCode();
+ $data['is_user_defined'] = $model->getIsUserDefined();
+ $data['frontend_input'] = $model->getFrontendInput();
+
+ $this->_prepareDataForSave($data);
+
+ $model->addData($data);
+ try {
+ $model->save();
+ // clear translation cache because attribute labels are stored in translation
+ Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG));
+ return true;
+ } catch (Exception $e) {
+ $this->_fault('unable_to_save', $e->getMessage());
+ }
+ }
+
+ /**
+ * Remove attribute
+ *
+ * @param integer|string $attribute attribute ID or code
+ * @return boolean
+ */
+ public function remove($attribute)
+ {
+ $model = $this->_getAttribute($attribute);
+
+ if ($model->getEntityTypeId() != $this->_entityTypeId) {
+ $this->_fault('can_not_delete');
+ }
+
+ try {
+ $model->delete();
+ return true;
+ } catch (Exception $e) {
+ $this->_fault('can_not_delete', $e->getMessage());
+ }
+ }
+
+ /**
+ * Get full information about attribute with list of options
+ *
+ * @param integer|string $attribute attribute ID or code
+ * @return array
+ */
+ public function info($attribute)
+ {
+ $model = $this->_getAttribute($attribute);
+
+ if ($model->isScopeGlobal()) {
+ $scope = 'global';
+ } elseif ($model->isScopeWebsite()) {
+ $scope = 'website';
+ } else {
+ $scope = 'store';
+ }
+
+ $frontendLabels = array(
+ array(
+ 'store_id' => 0,
+ 'label' => $model->getFrontendLabel()
+ )
+ );
+ foreach ($model->getStoreLabels() as $store_id => $label) {
+ $frontendLabels[] = array(
+ 'store_id' => $store_id,
+ 'label' => $label
+ );
+ }
+
+ $result = array(
+ 'attribute_id' => $model->getId(),
+ 'attribute_code' => $model->getAttributeCode(),
+ 'frontend_input' => $model->getFrontendInput(),
+ 'default_value' => $model->getDefaultValue(),
+ 'is_unique' => $model->getIsUnique(),
+ 'is_required' => $model->getIsRequired(),
+ 'apply_to' => $model->getApplyTo(),
+ 'is_configurable' => $model->getIsConfigurable(),
+ 'is_searchable' => $model->getIsSearchable(),
+ 'is_visible_in_advanced_search' => $model->getIsVisibleInAdvancedSearch(),
+ 'is_comparable' => $model->getIsComparable(),
+ 'is_used_for_promo_rules' => $model->getIsUsedForPromoRules(),
+ 'is_visible_on_front' => $model->getIsVisibleOnFront(),
+ 'used_in_product_listing' => $model->getUsedInProductListing(),
+ 'frontend_label' => $frontendLabels
+ );
+ if ($model->getFrontendInput() != 'price') {
+ $result['scope'] = $scope;
+ }
+
+ // set additional fields to different types
+ switch ($model->getFrontendInput()) {
+ case 'text':
+ $result['additional_fields'] = array(
+ 'frontend_class' => $model->getFrontendClass(),
+ 'is_html_allowed_on_front' => $model->getIsHtmlAllowedOnFront(),
+ 'used_for_sort_by' => $model->getUsedForSortBy()
+ );
+ break;
+ case 'textarea':
+ $result['additional_fields'] = array(
+ 'is_wysiwyg_enabled' => $model->getIsWysiwygEnabled(),
+ 'is_html_allowed_on_front' => $model->getIsHtmlAllowedOnFront(),
+ );
+ break;
+ case 'date':
+ case 'boolean':
+ $result['additional_fields'] = array(
+ 'used_for_sort_by' => $model->getUsedForSortBy()
+ );
+ break;
+ case 'multiselect':
+ $result['additional_fields'] = array(
+ 'is_filterable' => $model->getIsFilterable(),
+ 'is_filterable_in_search' => $model->getIsFilterableInSearch(),
+ 'position' => $model->getPosition()
+ );
+ break;
+ case 'select':
+ case 'price':
+ $result['additional_fields'] = array(
+ 'is_filterable' => $model->getIsFilterable(),
+ 'is_filterable_in_search' => $model->getIsFilterableInSearch(),
+ 'position' => $model->getPosition(),
+ 'used_for_sort_by' => $model->getUsedForSortBy()
+ );
+ break;
+ default:
+ $result['additional_fields'] = array();
+ break;
+ }
+
+ // set options
+ $options = $this->options($model->getId());
+ // remove empty first element
+ if ($model->getFrontendInput() != 'boolean') {
+ array_shift($options);
+ }
+
+ if (count($options) > 0) {
+ $result['options'] = $options;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Add option to select or multiselect attribute
+ *
+ * @param integer|string $attribute attribute ID or code
+ * @param array $data
+ * @return bool
+ */
+ public function addOption($attribute, $data)
+ {
+ $model = $this->_getAttribute($attribute);
+
+ if (!$model->usesSource()) {
+ $this->_fault('invalid_frontend_input');
+ }
+
+ /** @var $helperCatalog Mage_Catalog_Helper_Data */
+ $helperCatalog = Mage::helper('catalog');
+
+ $optionLabels = array();
+ foreach ($data['label'] as $label) {
+ $storeId = $label['store_id'];
+ $labelText = $helperCatalog->stripTags($label['value']);
+ if (is_array($storeId)) {
+ foreach ($storeId as $multiStoreId) {
+ $optionLabels[$multiStoreId] = $labelText;
+ }
+ } else {
+ $optionLabels[$storeId] = $labelText;
+ }
+ }
+ // data in the following format is accepted by the model
+ // it simulates parameters of the request made to
+ // Mage_Adminhtml_Catalog_Product_AttributeController::saveAction()
+ $modelData = array(
+ 'option' => array(
+ 'value' => array(
+ 'option_1' => $optionLabels
+ ),
+ 'order' => array(
+ 'option_1' => (int) $data['order']
+ )
+ )
+ );
+ if ($data['is_default']) {
+ $modelData['default'][] = 'option_1';
+ }
+
+ $model->addData($modelData);
+ try {
+ $model->save();
+ } catch (Exception $e) {
+ $this->_fault('unable_to_add_option', $e->getMessage());
+ }
+
+ return true;
+ }
+
+ /**
+ * Remove option from select or multiselect attribute
+ *
+ * @param integer|string $attribute attribute ID or code
+ * @param integer $optionId option to remove ID
+ * @return bool
+ */
+ public function removeOption($attribute, $optionId)
+ {
+ $model = $this->_getAttribute($attribute);
+
+ if (!$model->usesSource()) {
+ $this->_fault('invalid_frontend_input');
+ }
+
+ // data in the following format is accepted by the model
+ // it simulates parameters of the request made to
+ // Mage_Adminhtml_Catalog_Product_AttributeController::saveAction()
+ $modelData = array(
+ 'option' => array(
+ 'value' => array(
+ $optionId => array()
+ ),
+ 'delete' => array(
+ $optionId => '1'
+ )
+ )
+ );
+ $model->addData($modelData);
+ try {
+ $model->save();
+ } catch (Exception $e) {
+ $this->_fault('unable_to_remove_option', $e->getMessage());
+ }
+
+ return true;
+ }
+
+ /**
+ * Prepare request input data for saving
+ *
+ * @param array $data input data
+ * @return void
+ */
+ protected function _prepareDataForSave(&$data)
+ {
+ /** @var $helperCatalog Mage_Catalog_Helper_Data */
+ $helperCatalog = Mage::helper('catalog');
+
+ if ($data['scope'] == 'global') {
+ $data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL;
+ } else if ($data['scope'] == 'website') {
+ $data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE;
+ } else {
+ $data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE;
+ }
+ if (!isset($data['is_configurable'])) {
+ $data['is_configurable'] = 0;
+ }
+ if (!isset($data['is_filterable'])) {
+ $data['is_filterable'] = 0;
+ }
+ if (!isset($data['is_filterable_in_search'])) {
+ $data['is_filterable_in_search'] = 0;
+ }
+ if (!isset($data['apply_to'])) {
+ $data['apply_to'] = array();
+ }
+ // set frontend labels array with store_id as keys
+ if (isset($data['frontend_label']) && is_array($data['frontend_label'])) {
+ $labels = array();
+ foreach ($data['frontend_label'] as $label) {
+ $storeId = $label['store_id'];
+ $labelText = $helperCatalog->stripTags($label['label']);
+ $labels[$storeId] = $labelText;
+ }
+ $data['frontend_label'] = $labels;
+ }
+ // set additional fields
+ if (isset($data['additional_fields']) && is_array($data['additional_fields'])) {
+ $data = array_merge($data, $data['additional_fields']);
+ unset($data['additional_fields']);
+ }
+ //default value
+ if (!empty($data['default_value'])) {
+ $data['default_value'] = $helperCatalog->stripTags($data['default_value']);
+ }
+ }
+
+ /**
+ * Load model by attribute ID or code
+ *
+ * @param integer|string $attribute
+ * @return Mage_Catalog_Model_Resource_Eav_Attribute
+ */
+ protected function _getAttribute($attribute)
+ {
+ $model = Mage::getResourceModel('catalog/eav_attribute')
+ ->setEntityTypeId($this->_entityTypeId);
+
+ if (is_numeric($attribute)) {
+ $model->load(intval($attribute));
+ } else {
+ $model->load($attribute, 'attribute_code');
+ }
+
+ if (!$model->getId()) {
+ $this->_fault('not_exists');
+ }
+
+ return $model;
+ }
+
} // Class Mage_Catalog_Model_Product_Attribute_Api End
diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php
index d577f73458..6a0dbba1c9 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Api/V2.php
@@ -33,4 +33,67 @@
*/
class Mage_Catalog_Model_Product_Attribute_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Api
{
+ /**
+ * Create new product attribute
+ *
+ * @param array $data input data
+ * @return integer
+ */
+ public function create($data)
+ {
+ $helper = Mage::helper('api');
+ $helper->v2AssociativeArrayUnpacker($data);
+ Mage::helper('api')->toArray($data);
+ return parent::create($data);
+ }
+
+ /**
+ * Update product attribute
+ *
+ * @param string|integer $attribute attribute code or ID
+ * @param array $data
+ * @return boolean
+ */
+ public function update($attribute, $data)
+ {
+ $helper = Mage::helper('api');
+ $helper->v2AssociativeArrayUnpacker($data);
+ Mage::helper('api')->toArray($data);
+ return parent::update($attribute, $data);
+ }
+
+ /**
+ * Add option to select or multiselect attribute
+ *
+ * @param integer|string $attribute attribute ID or code
+ * @param array $data
+ * @return bool
+ */
+ public function addOption($attribute, $data)
+ {
+ Mage::helper('api')->toArray($data);
+ return parent::addOption($attribute, $data);
+ }
+
+ /**
+ * Get full information about attribute with list of options
+ *
+ * @param integer|string $attribute attribute ID or code
+ * @return array
+ */
+ public function info($attribute)
+ {
+ $result = parent::info($attribute);
+ if (!empty($result['additional_fields'])){
+ $keys = array_keys($result['additional_fields']);
+ foreach ($keys as $key ) {
+ $result['additional_fields'][] = array(
+ 'key' => $key,
+ 'value' => $result['additional_fields'][$key]
+ );
+ unset($result['additional_fields'][$key]);
+ }
+ }
+ return $result;
+ }
}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Group.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Group.php
new file mode 100644
index 0000000000..cf2dd5ef39
--- /dev/null
+++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Group.php
@@ -0,0 +1,69 @@
+setAttributeGroupFilter($this->getId());
+ foreach ($attributesCollection as $attribute) {
+ if (!$attribute->getIsUserDefined()) {
+ $result = true;
+ break;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Check if contains attributes used in the configurable products
+ *
+ * @return bool
+ */
+ public function hasConfigurableAttributes()
+ {
+ $result = false;
+ /** @var $attributesCollection Mage_Catalog_Model_Resource_Product_Attribute_Collection */
+ $attributesCollection = Mage::getResourceModel('catalog/product_attribute_collection');
+ $attributesCollection->setAttributeGroupFilter($this->getId());
+ foreach ($attributesCollection as $attribute) {
+ if ($attribute->getIsConfigurable()) {
+ $result = true;
+ break;
+ }
+ }
+ return $result;
+ }
+}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php
index c466fb2a71..c37e659a39 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php
@@ -55,4 +55,233 @@ public function items()
return $result;
}
+
+ /**
+ * Create new attribute set based on another set
+ *
+ * @param string $attributeSetName
+ * @param string $skeletonSetId
+ * @return integer
+ */
+ public function create($attributeSetName, $skeletonSetId)
+ {
+ // check if set with requested $skeletonSetId exists
+ if (!Mage::getModel('eav/entity_attribute_set')->load($skeletonSetId)->getId()){
+ $this->_fault('invalid_skeleton_set_id');
+ }
+ // get catalog product entity type id
+ $entityTypeId = Mage::getModel('catalog/product')->getResource()->getTypeId();
+ /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */
+ $attributeSet = Mage::getModel('eav/entity_attribute_set')
+ ->setEntityTypeId($entityTypeId)
+ ->setAttributeSetName($attributeSetName);
+ try {
+ // check if name is valid
+ $attributeSet->validate();
+ // copy parameters to new set from skeleton set
+ $attributeSet->save();
+ $attributeSet->initFromSkeleton($skeletonSetId)->save();
+ } catch (Mage_Eav_Exception $e) {
+ $this->_fault('invalid_data', $e->getMessage());
+ } catch (Exception $e) {
+ $this->_fault('create_attribute_set_error', $e->getMessage());
+ }
+ return (int)$attributeSet->getId();
+ }
+
+ /**
+ * Remove attribute set
+ *
+ * @param string $attributeSetId
+ * @param bool $forceProductsRemove
+ * @return bool
+ */
+ public function remove($attributeSetId, $forceProductsRemove = false)
+ {
+ // if attribute set has related goods and $forceProductsRemove is not set throw exception
+ if (!$forceProductsRemove) {
+ /** @var $catalogProductsCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */
+ $catalogProductsCollection = Mage::getModel('catalog/product')->getCollection()
+ ->addFieldToFilter('attribute_set_id', $attributeSetId);
+ if (count($catalogProductsCollection)) {
+ $this->_fault('attribute_set_has_related_products');
+ }
+ }
+ $attributeSet = Mage::getModel('eav/entity_attribute_set')->load($attributeSetId);
+ // check if set with requested id exists
+ if (!$attributeSet->getId()){
+ $this->_fault('invalid_attribute_set_id');
+ }
+ try {
+ $attributeSet->delete();
+ } catch (Exception $e) {
+ $this->_fault('remove_attribute_set_error', $e->getMessage());
+ }
+ return true;
+ }
+
+ /**
+ * Add attribute to attribute set
+ *
+ * @param string $attributeId
+ * @param string $attributeSetId
+ * @param string|null $attributeGroupId
+ * @param string $sortOrder
+ * @return bool
+ */
+ public function attributeAdd($attributeId, $attributeSetId, $attributeGroupId = null, $sortOrder = '0')
+ {
+ // check if attribute with requested id exists
+ /** @var $attribute Mage_Eav_Model_Entity_Attribute */
+ $attribute = Mage::getModel('eav/entity_attribute')->load($attributeId);
+ if (!$attribute->getId()) {
+ $this->_fault('invalid_attribute_id');
+ }
+ // check if attribute set with requested id exists
+ /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */
+ $attributeSet = Mage::getModel('eav/entity_attribute_set')->load($attributeSetId);
+ if (!$attributeSet->getId()) {
+ $this->_fault('invalid_attribute_set_id');
+ }
+ if (!empty($attributeGroupId)) {
+ // check if attribute group with requested id exists
+ if (!Mage::getModel('eav/entity_attribute_group')->load($attributeGroupId)->getId()) {
+ $this->_fault('invalid_attribute_group_id');
+ }
+ } else {
+ // define default attribute group id for current attribute set
+ $attributeGroupId = $attributeSet->getDefaultGroupId();
+ }
+ $attribute->setAttributeSetId($attributeSet->getId())->loadEntityAttributeIdBySet();
+ if ($attribute->getEntityAttributeId()) {
+ $this->_fault('attribute_is_already_in_set');
+ }
+ try {
+ $attribute->setEntityTypeId($attributeSet->getEntityTypeId())
+ ->setAttributeSetId($attributeSetId)
+ ->setAttributeGroupId($attributeGroupId)
+ ->setSortOrder($sortOrder)
+ ->save();
+ } catch (Exception $e) {
+ $this->_fault('add_attribute_error', $e->getMessage());
+ }
+ return true;
+ }
+
+ /**
+ * Remove attribute from attribute set
+ *
+ * @param string $attributeId
+ * @param string $attributeSetId
+ * @return bool
+ */
+ public function attributeRemove($attributeId, $attributeSetId)
+ {
+ // check if attribute with requested id exists
+ /** @var $attribute Mage_Eav_Model_Entity_Attribute */
+ $attribute = Mage::getModel('eav/entity_attribute')->load($attributeId);
+ if (!$attribute->getId()) {
+ $this->_fault('invalid_attribute_id');
+ }
+ // check if attribute set with requested id exists
+ /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */
+ $attributeSet = Mage::getModel('eav/entity_attribute_set')->load($attributeSetId);
+ if (!$attributeSet->getId()) {
+ $this->_fault('invalid_attribute_set_id');
+ }
+ // check if attribute is in set
+ $attribute->setAttributeSetId($attributeSet->getId())->loadEntityAttributeIdBySet();
+ if (!$attribute->getEntityAttributeId()) {
+ $this->_fault('attribute_is_not_in_set');
+ }
+ try {
+ // delete record from eav_entity_attribute
+ // using entity_attribute_id loaded by loadEntityAttributeIdBySet()
+ $attribute->deleteEntity();
+ } catch (Exception $e) {
+ $this->_fault('remove_attribute_error', $e->getMessage());
+ }
+
+ return true;
+ }
+
+ /**
+ * Create group within existing attribute set
+ *
+ * @param string|int $attributeSetId
+ * @param string $groupName
+ * @return int
+ */
+ public function groupAdd($attributeSetId, $groupName)
+ {
+ /** @var $group Mage_Eav_Model_Entity_Attribute_Group */
+ $group = Mage::getModel('eav/entity_attribute_group');
+ $group->setAttributeSetId($attributeSetId)
+ ->setAttributeGroupName(
+ Mage::helper('catalog')->stripTags($groupName)
+ );
+ if ($group->itemExists()) {
+ $this->_fault('group_already_exists');
+ }
+ try {
+ $group->save();
+ } catch (Exception $e) {
+ $this->_fault('group_add_error', $e->getMessage());
+ }
+ return (int)$group->getId();
+ }
+
+ /**
+ * Rename existing group
+ *
+ * @param string|int $groupId
+ * @param string $groupName
+ * @return boolean
+ */
+ public function groupRename($groupId, $groupName)
+ {
+ $model = Mage::getModel('eav/entity_attribute_group')->load($groupId);
+
+ if (!$model->getAttributeGroupName()) {
+ $this->_fault('invalid_attribute_group_id');
+ }
+
+ $model->setAttributeGroupName(
+ Mage::helper('catalog')->stripTags($groupName)
+ );
+ try {
+ $model->save();
+ } catch (Exception $e) {
+ $this->_fault('group_rename_error', $e->getMessage());
+ }
+ return true;
+ }
+
+ /**
+ * Remove group from existing attribute set
+ *
+ * @param string|int $attributeGroupId
+ * @return bool
+ */
+ public function groupRemove($attributeGroupId)
+ {
+ /** @var $group Mage_Catalog_Model_Product_Attribute_Group */
+ $group = Mage::getModel('catalog/product_attribute_group')->load($attributeGroupId);
+ if (!$group->getId()) {
+ $this->_fault('invalid_attribute_group_id');
+ }
+ if ($group->hasConfigurableAttributes()) {
+ $this->_fault('group_has_configurable_attributes');
+ }
+ if ($group->hasSystemAttributes()) {
+ $this->_fault('group_has_system_attributes');
+ }
+ try {
+ $group->delete();
+ } catch (Exception $e) {
+ $this->_fault('group_remove_error', $e->getMessage());
+ }
+ return true;
+ }
+
} // Class Mage_Catalog_Model_Product_Attribute_Set_Api End
diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Source/Inputtype.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Source/Inputtype.php
new file mode 100644
index 0000000000..ca058436ac
--- /dev/null
+++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Source/Inputtype.php
@@ -0,0 +1,77 @@
+
+ */class Mage_Catalog_Model_Product_Attribute_Source_Inputtype extends Mage_Eav_Model_Adminhtml_System_Config_Source_Inputtype
+{
+ /**
+ * Get product input types as option array
+ *
+ * @return array
+ */
+ public function toOptionArray()
+ {
+ $inputTypes = array(
+ array(
+ 'value' => 'price',
+ 'label' => Mage::helper('catalog')->__('Price')
+ ),
+ array(
+ 'value' => 'media_image',
+ 'label' => Mage::helper('catalog')->__('Media Image')
+ )
+ );
+
+ $response = new Varien_Object();
+ $response->setTypes(array());
+ Mage::dispatchEvent('adminhtml_product_attribute_types', array('response'=>$response));
+ $_disabledTypes = array();
+ $_hiddenFields = array();
+ foreach ($response->getTypes() as $type) {
+ $inputTypes[] = $type;
+ if (isset($type['hide_fields'])) {
+ $_hiddenFields[$type['value']] = $type['hide_fields'];
+ }
+ if (isset($type['disabled_types'])) {
+ $_disabledTypes[$type['value']] = $type['disabled_types'];
+ }
+ }
+
+ if (Mage::registry('attribute_type_hidden_fields') === null) {
+ Mage::register('attribute_type_hidden_fields', $_hiddenFields);
+ }
+ if (Mage::registry('attribute_type_disabled_types') === null) {
+ Mage::register('attribute_type_disabled_types', $_disabledTypes);
+ }
+
+ return array_merge(parent::toOptionArray(), $inputTypes);
+ }
+}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Link/Api.php b/app/code/core/Mage/Catalog/Model/Product/Link/Api.php
index d8006bc6ff..d49fc4e25d 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Link/Api.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Link/Api.php
@@ -33,6 +33,11 @@
*/
class Mage_Catalog_Model_Product_Link_Api extends Mage_Catalog_Model_Api_Resource
{
+ /**
+ * Product link type mapping, used for references and validation
+ *
+ * @var array
+ */
protected $_typeMap = array(
'related' => Mage_Catalog_Model_Product_Link::LINK_TYPE_RELATED,
'up_sell' => Mage_Catalog_Model_Product_Link::LINK_TYPE_UPSELL,
@@ -50,6 +55,7 @@ public function __construct()
*
* @param string $type
* @param int|sku $productId
+ * @param string $identifierType
* @return array
*/
public function items($type, $productId, $identifierType = null)
@@ -90,6 +96,7 @@ public function items($type, $productId, $identifierType = null)
* @param int|string $productId
* @param int|string $linkedProductId
* @param array $data
+ * @param string $identifierType
* @return boolean
*/
public function assign($type, $productId, $linkedProductId, $data = array(), $identifierType = null)
@@ -118,7 +125,20 @@ public function assign($type, $productId, $linkedProductId, $data = array(), $id
}
try {
- $link->getResource()->saveProductLinks($product, $links, $typeId);
+ if ($type == 'grouped') {
+ $link->getResource()->saveGroupedLinks($product, $links, $typeId);
+ } else {
+ $link->getResource()->saveProductLinks($product, $links, $typeId);
+ }
+
+ $_linkInstance = Mage::getSingleton('catalog/product_link');
+ $_linkInstance->saveProductRelations($product);
+
+ $indexerStock = Mage::getModel('cataloginventory/stock_status');
+ $indexerStock->updateStatus($productId);
+
+ $indexerPrice = Mage::getResourceModel('catalog/product_indexer_price');
+ $indexerPrice->reindexProductIds($productId);
} catch (Exception $e) {
$this->_fault('data_invalid', Mage::helper('catalog')->__('Link product does not exist.'));
}
@@ -133,6 +153,7 @@ public function assign($type, $productId, $linkedProductId, $data = array(), $id
* @param int|string $productId
* @param int|string $linkedProductId
* @param array $data
+ * @param string $identifierType
* @return boolean
*/
public function update($type, $productId, $linkedProductId, $data = array(), $identifierType = null)
@@ -160,7 +181,20 @@ public function update($type, $productId, $linkedProductId, $data = array(), $id
}
try {
- $link->getResource()->saveProductLinks($product, $links, $typeId);
+ if ($type == 'grouped') {
+ $link->getResource()->saveGroupedLinks($product, $links, $typeId);
+ } else {
+ $link->getResource()->saveProductLinks($product, $links, $typeId);
+ }
+
+ $_linkInstance = Mage::getSingleton('catalog/product_link');
+ $_linkInstance->saveProductRelations($product);
+
+ $indexerStock = Mage::getModel('cataloginventory/stock_status');
+ $indexerStock->updateStatus($productId);
+
+ $indexerPrice = Mage::getResourceModel('catalog/product_indexer_price');
+ $indexerPrice->reindexProductIds($productId);
} catch (Exception $e) {
$this->_fault('data_invalid', Mage::helper('catalog')->__('Link product does not exist.'));
}
@@ -174,6 +208,7 @@ public function update($type, $productId, $linkedProductId, $data = array(), $id
* @param string $type
* @param int|string $productId
* @param int|string $linkedProductId
+ * @param string $identifierType
* @return boolean
*/
public function remove($type, $productId, $linkedProductId, $identifierType = null)
@@ -258,7 +293,7 @@ protected function _getTypeId($type)
}
/**
- * Initilize and return product model
+ * Initialize and return product model
*
* @param int $productId
* @param string $identifierType
diff --git a/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php
index 53d35d27c7..1f0aa83ae7 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Link/Api/V2.php
@@ -67,9 +67,24 @@ public function assign($type, $productId, $linkedProductId, $data = array(), $id
}
try {
- $link->getResource()->saveProductLinks($product, $links, $typeId);
+ if ($type == 'grouped') {
+ $link->getResource()->saveGroupedLinks($product, $links, $typeId);
+ } else {
+ $link->getResource()->saveProductLinks($product, $links, $typeId);
+ }
+
+ $_linkInstance = Mage::getSingleton('catalog/product_link');
+ $_linkInstance->saveProductRelations($product);
+
+ $indexerStock = Mage::getModel('cataloginventory/stock_status');
+ $indexerStock->updateStatus($productId);
+
+ $indexerPrice = Mage::getResourceModel('catalog/product_indexer_price');
+ $indexerPrice->reindexProductIds($productId);
+
} catch (Exception $e) {
- $this->_fault('data_invalid', Mage::helper('catalog')->__('Link product does not exist.'));
+ $this->_fault('data_invalid', $e->getMessage());
+ //$this->_fault('data_invalid', Mage::helper('catalog')->__('Link product does not exist.'));
}
return true;
@@ -109,7 +124,21 @@ public function update($type, $productId, $linkedProductId, $data = array(), $id
}
try {
- $link->getResource()->saveProductLinks($product, $links, $typeId);
+ if ($type == 'grouped') {
+ $link->getResource()->saveGroupedLinks($product, $links, $typeId);
+ } else {
+ $link->getResource()->saveProductLinks($product, $links, $typeId);
+ }
+
+ $_linkInstance = Mage::getSingleton('catalog/product_link');
+ $_linkInstance->saveProductRelations($product);
+
+ $indexerStock = Mage::getModel('cataloginventory/stock_status');
+ $indexerStock->updateStatus($productId);
+
+ $indexerPrice = Mage::getResourceModel('catalog/product_indexer_price');
+ $indexerPrice->reindexProductIds($productId);
+
} catch (Exception $e) {
$this->_fault('data_invalid', Mage::helper('catalog')->__('Link product does not exist.'));
}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Api.php b/app/code/core/Mage/Catalog/Model/Product/Option/Api.php
new file mode 100644
index 0000000000..6718827bed
--- /dev/null
+++ b/app/code/core/Mage/Catalog/Model/Product/Option/Api.php
@@ -0,0 +1,327 @@
+
+ */
+class Mage_Catalog_Model_Product_Option_Api extends Mage_Catalog_Model_Api_Resource
+{
+
+ /**
+ * Add custom option to product
+ *
+ * @param string $productId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool $isAdded
+ */
+ public function add($productId, $data, $store = null)
+ {
+ $product = $this->_getProduct($productId, $store, null);
+ if (!(is_array($data['additional_fields']) and count($data['additional_fields']))) {
+ $this->_fault('invalid_data');
+ }
+ if (!$this->_isTypeAllowed($data['type'])) {
+ $this->_fault('invalid_type');
+ }
+ $this->_prepareAdditionalFields(
+ $data,
+ $product->getOptionInstance()->getGroupByType($data['type'])
+ );
+ $this->_saveProductCustomOption($product, $data);
+ return true;
+ }
+
+ /**
+ * Update product custom option data
+ *
+ * @param string $optionId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function update($optionId, $data, $store = null)
+ {
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = Mage::getModel('catalog/product_option')->load($optionId);
+ if (!$option->getId()) {
+ $this->_fault('option_not_exists');
+ }
+ $product = $this->_getProduct($option->getProductId(), $store, null);
+ $option = $product->getOptionById($optionId);
+ if (isset($data['type']) and !$this->_isTypeAllowed($data['type'])) {
+ $this->_fault('invalid_type');
+ }
+ if (isset($data['additional_fields'])) {
+ $this->_prepareAdditionalFields(
+ $data,
+ $option->getGroupByType()
+ );
+ }
+ foreach ($option->getValues() as $valueId => $value) {
+ if(isset($data['values'][$valueId])) {
+ $data['values'][$valueId] = array_merge($value->getData(), $data['values'][$valueId]);
+ }
+ }
+ $data = array_merge($option->getData(), $data);
+ $this->_saveProductCustomOption($product, $data);
+ return true;
+ }
+
+ /**
+ * Prepare custom option data for saving by model. Used for custom option add and update
+ *
+ * @param array $data
+ * @param string $groupType
+ * @return void
+ */
+ protected function _prepareAdditionalFields(&$data, $groupType)
+ {
+ if (is_array($data['additional_fields'])) {
+ if ($groupType != Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) {
+ // reset can be used as there should be the only
+ // element in 'additional_fields' for options of all types except those from Select group
+ $field = reset($data['additional_fields']);
+ if (!(is_array($field) and count($field))) {
+ $this->_fault('invalid_data');
+ } else {
+ foreach ($field as $key => $value) {
+ $data[$key] = $value;
+ }
+ }
+ } else {
+ // convert Select rows array to appropriate format for saving in the model
+ foreach ($data['additional_fields'] as $row) {
+ if (!(is_array($row) and count($row))) {
+ $this->_fault('invalid_data');
+ } else {
+ foreach ($row as $key => $value) {
+ $row[$key] = Mage::helper('catalog')->stripTags($value);
+ }
+ if (!empty($row['value_id'])) {
+ // map 'value_id' to 'option_type_id'
+ $row['option_type_id'] = $row['value_id'];
+ unset($row['value_id']);
+ $data['values'][$row['option_type_id']] = $row;
+ } else {
+ $data['values'][] = $row;
+ }
+ }
+ }
+ }
+ }
+ unset($data['additional_fields']);
+ }
+
+ /**
+ * Save product custom option data. Used for custom option add and update.
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param array $data
+ * @return void
+ */
+ protected function _saveProductCustomOption($product, $data)
+ {
+ foreach ($data as $key => $value) {
+ if (is_string($value)) {
+ $data[$key] = Mage::helper('catalog')->stripTags($value);
+ }
+ }
+ // setProductOptions expects data to be an array of options arrays
+ $data = array($data);
+ if (!$product->getOptionsReadonly()) {
+ $product->setProductOptions($data);
+ }
+ $product->setCanSaveCustomOptions(!$product->getOptionsReadonly());
+ try {
+ // an empty request can be set as event parameter
+ // because it is not used for options changing in observers
+ Mage::dispatchEvent(
+ 'catalog_product_prepare_save',
+ array('product' => $product, 'request' => new Mage_Core_Controller_Request_Http())
+ );
+ $product->save();
+ } catch (Exception $e) {
+ $this->_fault('save_option_error', $e->getMessage());
+ }
+ }
+
+ /**
+ * Read list of possible custom option types from module config
+ *
+ * @return array
+ */
+ public function types()
+ {
+ $path = Mage_Adminhtml_Model_System_Config_Source_Product_Options_Type::PRODUCT_OPTIONS_GROUPS_PATH;
+ $types = array();
+ foreach (Mage::getConfig()->getNode($path)->children() as $group) {
+ $groupTypes = Mage::getConfig()->getNode($path . '/' . $group->getName() . '/types')->children();
+ /** @var $type Mage_Core_Model_Config_Element */
+ foreach($groupTypes as $type){
+ $labelPath = $path . '/' . $group->getName() . '/types/' . $type->getName() . '/label';
+ $types[] = array(
+ 'label' => (string) Mage::getConfig()->getNode($labelPath),
+ 'value' => $type->getName()
+ );
+ }
+ }
+ return $types;
+ }
+
+ /**
+ * Get full information about custom option in product
+ *
+ * @param int|string $optionId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function info($optionId, $store = null)
+ {
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = Mage::getModel('catalog/product_option')->load($optionId);
+ if (!$option->getId()) {
+ $this->_fault('option_not_exists');
+ }
+ /** @var $product Mage_Catalog_Model_Product */
+ $product = $this->_getProduct($option->getProductId(), $store, null);
+ $option = $product->getOptionById($optionId);
+ $result = array(
+ 'title' => $option->getTitle(),
+ 'type' => $option->getType(),
+ 'is_require' => $option->getIsRequire(),
+ 'sort_order' => $option->getSortOrder(),
+ // additional_fields should be two-dimensional array for all option types
+ 'additional_fields' => array(
+ array(
+ 'price' => $option->getPrice(),
+ 'price_type' => $option->getPriceType(),
+ 'sku' => $option->getSku()
+ )
+ )
+ );
+ // Set additional fields to each type group
+ switch ($option->getGroupByType()) {
+ case Mage_Catalog_Model_Product_Option::OPTION_GROUP_TEXT:
+ $result['additional_fields'][0]['max_characters'] = $option->getMaxCharacters();
+ break;
+ case Mage_Catalog_Model_Product_Option::OPTION_GROUP_FILE:
+ $result['additional_fields'][0]['file_extension'] = $option->getFileExtension();
+ $result['additional_fields'][0]['image_size_x'] = $option->getImageSizeX();
+ $result['additional_fields'][0]['image_size_y'] = $option->getImageSizeY();
+ break;
+ case Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT:
+ $result['additional_fields'] = array();
+ foreach ($option->getValuesCollection() as $value) {
+ $result['additional_fields'][] = array(
+ 'value_id' => $value->getId(),
+ 'title' => $value->getTitle(),
+ 'price' => $value->getPrice(),
+ 'price_type' => $value->getPriceType(),
+ 'sku' => $value->getSku(),
+ 'sort_order' => $value->getSortOrder()
+ );
+ }
+ break;
+ default:
+ break;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Retrieve list of product custom options
+ *
+ * @param string $productId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function items($productId, $store = null)
+ {
+ $result = array();
+ $product = $this->_getProduct($productId, $store, null);
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ foreach ($product->getProductOptionsCollection() as $option) {
+ $result[] = array(
+ 'option_id' => $option->getId(),
+ 'title' => $option->getTitle(),
+ 'type' => $option->getType(),
+ 'is_require' => $option->getIsRequire(),
+ 'sort_order' => $option->getSortOrder()
+ );
+ }
+ return $result;
+ }
+
+ /**
+ * Remove product custom option
+ *
+ * @param string $optionId
+ * @return boolean
+ */
+ public function remove($optionId)
+ {
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = Mage::getModel('catalog/product_option')->load($optionId);
+ if (!$option->getId()) {
+ $this->_fault('option_not_exists');
+ }
+ try {
+ $option->getValueInstance()->deleteValue($optionId);
+ $option->deletePrices($optionId);
+ $option->deleteTitles($optionId);
+ $option->delete();
+ } catch (Exception $e){
+ $this->fault('delete_option_error');
+ }
+ return true;
+ }
+
+ /**
+ * Check is type in allowed set
+ *
+ * @param string $type
+ * @return bool
+ */
+ protected function _isTypeAllowed($type)
+ {
+ $allowedTypes = array();
+ foreach($this->types() as $optionType){
+ $allowedTypes[] = $optionType['value'];
+ }
+
+ if (!in_array($type, $allowedTypes)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Option/Api/V2.php
new file mode 100644
index 0000000000..d0e1c323ea
--- /dev/null
+++ b/app/code/core/Mage/Catalog/Model/Product/Option/Api/V2.php
@@ -0,0 +1,81 @@
+
+ */
+class Mage_Catalog_Model_Product_Option_Api_V2 extends Mage_Catalog_Model_Product_Option_Api
+{
+
+ /**
+ * Add custom option to product
+ *
+ * @param string $productId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function add($productId, $data, $store = null)
+ {
+ Mage::helper('api')->toArray($data);
+ return parent::add($productId, $data, $store);
+ }
+
+ /**
+ * Update product custom option data
+ *
+ * @param string $optionId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function update($optionId, $data, $store = null)
+ {
+ Mage::helper('api')->toArray($data);
+ return parent::update($optionId, $data, $store);
+ }
+
+ /**
+ * Retrieve list of product custom options
+ *
+ * @param string $productId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function items($productId, $store)
+ {
+ $result = parent::items($productId, $store);
+ foreach ($result as $key => $option) {
+ $result[$key] = Mage::helper('api')->wsiArrayPacker($option);
+ }
+ return $result;
+ }
+
+}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api.php b/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api.php
new file mode 100644
index 0000000000..669fa8aa2e
--- /dev/null
+++ b/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api.php
@@ -0,0 +1,226 @@
+
+ */
+class Mage_Catalog_Model_Product_Option_Value_Api extends Mage_Catalog_Model_Api_Resource
+{
+ /**
+ * Retrieve values from specified option
+ *
+ * @param string $optionId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function items($optionId, $store = null)
+ {
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = $this->_prepareOption($optionId, $store);
+ $productOptionValues = $option->getValuesCollection();
+ $result = array();
+ foreach($productOptionValues as $value){
+ $result[] = array(
+ 'value_id' => $value->getId(),
+ 'title' => $value->getTitle(),
+ 'price' => $value->getPrice(),
+ 'price_type' => $value->getPriceType(),
+ 'sku' => $value->getSku(),
+ 'sort_order' => $value->getSortOrder()
+ );
+ }
+ return $result;
+ }
+
+ /**
+ * Retrieve specified option value info
+ *
+ * @param string $valueId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function info($valueId, $store = null)
+ {
+ /** @var $productOptionValue Mage_Catalog_Model_Product_Option_Value */
+ $productOptionValue = Mage::getModel('catalog/product_option_value')->load($valueId);
+ if (!$productOptionValue->getId()) {
+ $this->_fault('value_not_exists');
+ }
+ $storeId = $this->_getStoreId($store);
+ $productOptionValues = $productOptionValue
+ ->getValuesByOption(
+ array($valueId),
+ $productOptionValue->getOptionId(),
+ $storeId
+ )
+ ->addTitleToResult($storeId)
+ ->addPriceToResult($storeId);
+
+ $result = $productOptionValues->toArray();
+ // reset can be used as the only item is expected
+ $result = reset($result['items']);
+ if (empty($result)) {
+ $this->_fault('value_not_exists');
+ }
+ // map option_type_id to value_id
+ $result['value_id'] = $result['option_type_id'];
+ unset($result['option_type_id']);
+ return $result;
+ }
+
+ /**
+ * Add new values to select option
+ *
+ * @param string $optionId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function add($optionId, $data, $store = null)
+ {
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = $this->_prepareOption($optionId, $store);
+ /** @var $optionValueModel Mage_Catalog_Model_Product_Option_Value */
+ $optionValueModel = Mage::getModel('catalog/product_option_value');
+ $optionValueModel->setOption($option);
+ foreach ($data as &$optionValue) {
+ foreach ($optionValue as &$value) {
+ $value = Mage::helper('catalog')->stripTags($value);
+ }
+ }
+ $optionValueModel->setValues($data);
+ try {
+ $optionValueModel->saveValues();
+ } catch (Exception $e) {
+ $this->_fault('add_option_value_error', $e->getMessage());
+ }
+ return true;
+ }
+
+ /**
+ * Update value to select option
+ *
+ * @param string $valueId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function update($valueId, $data, $store = null)
+ {
+ /** @var $productOptionValue Mage_Catalog_Model_Product_Option_Value */
+ $productOptionValue = Mage::getModel('catalog/product_option_value')->load($valueId);
+ if (!$productOptionValue->getId()) {
+ $this->_fault('value_not_exists');
+ }
+
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = $this->_prepareOption($productOptionValue->getOptionId(), $store);
+ if (!$option->getId()) {
+ $this->_fault('option_not_exists');
+ }
+ $productOptionValue->setOption($option);
+ // Sanitize data
+ foreach ($data as $key => $value) {
+ $data[$key] = Mage::helper('catalog')->stripTags($value);
+ }
+ if (!isset($data['title']) OR empty($data['title'])) {
+ $this->_fault('option_value_title_required');
+ }
+ $data['option_type_id'] = $valueId;
+ $data['store_id'] = $this->_getStoreId($store);
+ $productOptionValue->addValue($data);
+ $productOptionValue->setData($data);
+
+ try {
+ $productOptionValue->save()->saveValues();
+ } catch (Exception $e) {
+ $this->_fault('update_option_value_error', $e->getMessage());
+ }
+
+ return true;
+ }
+
+ /**
+ * Delete value from select option
+ *
+ * @param int $valueId
+ * @return boolean
+ */
+ public function remove($valueId)
+ {
+ /** @var $optionValue Mage_Catalog_Model_Product_Option_Value */
+ $optionValue = Mage::getModel('catalog/product_option_value')->load($valueId);
+ if (!$optionValue->getId()) {
+ $this->_fault('value_not_exists');
+ }
+
+ // check values count
+ if(count($this->items($optionValue->getOptionId())) <= 1){
+ $this->_fault('cant_delete_last_value');
+ }
+
+ try {
+ $optionValue->deleteValues($valueId);
+ } catch (Mage_Core_Exception $e) {
+ $this->_fault('not_deleted', $e->getMessage());
+ }
+
+ return true;
+ }
+
+ /**
+ * Load option by id and store
+ *
+ * @param string $optionId
+ * @param int|string|null $store
+ * @return Mage_Catalog_Model_Product_Option
+ */
+ protected function _prepareOption($optionId, $store = null)
+ {
+ /** @var $option Mage_Catalog_Model_Product_Option */
+ $option = Mage::getModel('catalog/product_option');
+ if (is_string($store) || is_integer($store)) {
+ $storeId = $this->_getStoreId($store);
+ $option->setStoreId($storeId);
+ }
+ $option->load($optionId);
+ if (isset($storeId)) {
+ $option->setData('store_id', $storeId);
+ }
+ if (!$option->getId()) {
+ $this->_fault('option_not_exists');
+ }
+ if ($option->getGroupByType() != Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) {
+ $this->_fault('invalid_option_type');
+ }
+ return $option;
+ }
+
+}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api/V2.php b/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api/V2.php
new file mode 100644
index 0000000000..3d0c0d4f43
--- /dev/null
+++ b/app/code/core/Mage/Catalog/Model/Product/Option/Value/Api/V2.php
@@ -0,0 +1,104 @@
+
+ */
+class Mage_Catalog_Model_Product_Option_Value_Api_V2 extends Mage_Catalog_Model_Product_Option_Value_Api
+{
+ /**
+ * Retrieve values from specified option
+ *
+ * @param string $optionId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function items($optionId, $store = null)
+ {
+ $result = parent::items($optionId, $store);
+ foreach ($result as $key => $optionValue) {
+ $result[$key] = Mage::helper('api')->wsiArrayPacker($optionValue);
+ }
+ return $result;
+ }
+
+ /**
+ * Retrieve specified option value info
+ *
+ * @param string $valueId
+ * @param int|string|null $store
+ * @return array
+ */
+ public function info($valueId, $store = null)
+ {
+ return Mage::helper('api')->wsiArrayPacker(
+ parent::info($valueId, $store)
+ );
+ }
+
+ /**
+ * Add new values to select option
+ *
+ * @param string $optionId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function add($optionId, $data, $store = null)
+ {
+ Mage::helper('api')->toArray($data);
+ return parent::add($optionId, $data, $store);
+ }
+
+ /**
+ * Update value to select option
+ *
+ * @param string $valueId
+ * @param array $data
+ * @param int|string|null $store
+ * @return bool
+ */
+ public function update($valueId, $data, $store = null)
+ {
+ Mage::helper('api')->toArray($data);
+ return parent::update($valueId, $data, $store);
+ }
+
+ /**
+ * Delete value from select option
+ *
+ * @param int $valueId
+ * @return boolean
+ */
+ public function remove($valueId)
+ {
+ return parent::remove($valueId);
+ }
+}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php b/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php
index 26dfa56dc1..25839fba41 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Type/Abstract.php
@@ -122,6 +122,11 @@ abstract class Mage_Catalog_Model_Product_Type_Abstract
*/
const PROCESS_MODE_LITE = 'lite';
+ /**
+ * Item options prefix
+ */
+ const OPTION_PREFIX = 'option_';
+
/**
* Specify type instance product
*
@@ -357,7 +362,7 @@ protected function _prepareProduct(Varien_Object $buyRequest, $product, $process
$optionIds = array_keys($options);
$product->addCustomOption('option_ids', implode(',', $optionIds));
foreach ($options as $optionId => $optionValue) {
- $product->addCustomOption('option_'.$optionId, $optionValue);
+ $product->addCustomOption(self::OPTION_PREFIX . $optionId, $optionValue);
}
}
@@ -569,7 +574,8 @@ public function checkProductBuyState($product = null)
if (!$this->getProduct($product)->getSkipCheckRequiredOption()) {
foreach ($this->getProduct($product)->getOptions() as $option) {
if ($option->getIsRequire()) {
- $customOption = $this->getProduct($product)->getCustomOption('option_' . $option->getId());
+ $customOption = $this->getProduct($product)
+ ->getCustomOption(self::OPTION_PREFIX . $option->getId());
if (!$customOption || strlen($customOption->getValue()) == 0) {
$this->getProduct($product)->setSkipCheckRequiredOption(true);
Mage::throwException(
@@ -601,7 +607,8 @@ public function getOrderOptions($product = null)
foreach (explode(',', $optionIds->getValue()) as $optionId) {
if ($option = $this->getProduct($product)->getOptionById($optionId)) {
- $confItemOption = $this->getProduct($product)->getCustomOption('option_'.$option->getId());
+ $confItemOption = $this->getProduct($product)
+ ->getCustomOption(self::OPTION_PREFIX . $option->getId());
$group = $option->groupFactory($option->getType())
->setOption($option)
@@ -740,7 +747,7 @@ public function getOptionSku($product = null, $sku='')
foreach (explode(',', $optionIds->getValue()) as $optionId) {
if ($option = $this->getProduct($product)->getOptionById($optionId)) {
- $confItemOption = $this->getProduct($product)->getCustomOption('option_'.$optionId);
+ $confItemOption = $this->getProduct($product)->getCustomOption(self::OPTION_PREFIX . $optionId);
$group = $option->groupFactory($option->getType())
->setOption($option)->setListener(new Varien_Object());
diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php
index bf7e72d233..c45a79cb9a 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable.php
@@ -452,6 +452,9 @@ public function isSalable($product = null)
if ($salable !== false) {
$salable = false;
+ if (!is_null($product)) {
+ $this->setStoreFilter($product->getStoreId(), $product);
+ }
foreach ($this->getUsedProducts(null, $product) as $child) {
if ($child->isSalable()) {
$salable = true;
@@ -851,4 +854,16 @@ public function isMapEnabledInOptions($product, $visibility = null)
{
return null;
}
+
+ /**
+ * Prepare and retrieve options values with product data
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @return array
+ */
+ public function getConfigurableOptions($product)
+ {
+ return Mage::getResourceSingleton('catalog/product_type_configurable')
+ ->getConfigurableOptions($product, $this->getUsedProductAttributes($product));
+ }
}
diff --git a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php
index 7303bcb8e9..e9adb8ee82 100644
--- a/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php
+++ b/app/code/core/Mage/Catalog/Model/Product/Type/Configurable/Price.php
@@ -64,6 +64,7 @@ public function getFinalPrice($qty=null, $product)
$attribute->getPrices() ? $attribute->getPrices() : array(),
isset($selectedAttributes[$attributeId]) ? $selectedAttributes[$attributeId] : null
);
+ $product->setParentId(true);
if($value) {
if($value['pricing_value'] != 0) {
$product->setConfigurablePrice($this->_calcSelectionPrice($value, $basePrice));
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Category.php b/app/code/core/Mage/Catalog/Model/Resource/Category.php
index c2061b329f..159d2a1351 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Category.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Category.php
@@ -369,11 +369,6 @@ protected function _saveCategoryProducts($category)
if (!empty($insert) || !empty($update) || !empty($delete)) {
$category->setIsChangedProductList(true);
- /**
- * Moved to index
- */
- //$categoryIds = explode('/', $category->getPath());
- //$this->refreshProductIndex($categoryIds);
/**
* Setting affected products to category for third party engine index refresh
@@ -886,7 +881,7 @@ protected function _processPositions($category, $newParent, $afterCategoryId)
$select = $adapter->select()
->from($table,array('position' => new Zend_Db_Expr('MIN(' . $positionField. ')')))
->where('parent_id = :parent_id');
- $position = $adapter->fetchOne($select, array('patent_id' => $newParent->getId()));
+ $position = $adapter->fetchOne($select, array('parent_id' => $newParent->getId()));
}
$position += 1;
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Category/Indexer/Product.php b/app/code/core/Mage/Catalog/Model/Resource/Category/Indexer/Product.php
index db52624a31..5f7a5df146 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Category/Indexer/Product.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Category/Indexer/Product.php
@@ -512,7 +512,7 @@ protected function _refreshDirectRelations($categoryIds = null, $productIds = nu
}
/**
- * Rebuild index for anchor categories and associated t child categories products
+ * Rebuild index for anchor categories and associated to child categories products
*
* @param null | array $categoryIds
* @param null | array $productIds
@@ -533,24 +533,27 @@ protected function _refreshAnchorRelations($categoryIds = null, $productIds = nu
*/
$adapter = $this->_getReadAdapter();
$isParent = $adapter->getCheckSql('MIN(cp.category_id)=ce.entity_id', 1, 0);
- $position = $adapter->getCheckSql(
- 'MIN(cp.category_id)=ce.entity_id',
- 'MIN(cp.position)',
- 'ROUND((MIN(cc.position) + 1) * (MIN(' . $adapter->quoteIdentifier('cc.level') . ') + 1) * 10000, 0)'.
- ' + MIN(cp.position)'
- );
+ $position = 'MIN('.
+ $adapter->getCheckSql(
+ 'cp.category_id = ce.entity_id',
+ 'cp.position',
+ '(cc.position + 1) * ('.$adapter->quoteIdentifier('cc.level').' + 1) * 10000 + cp.position'
+ )
+ .')';
+
$select = $adapter->select()
->distinct(true)
->from(array('ce' => $this->_categoryTable), array('entity_id'))
- ->joinLeft(
+ ->joinInner(
array('cc' => $this->_categoryTable),
$adapter->quoteIdentifier('cc.path') .
' LIKE ('.$adapter->getConcatSql(array($adapter->quoteIdentifier('ce.path'),$adapter->quote('/%'))).')'
+ . ' OR cc.entity_id=ce.entity_id'
, array()
)
->joinInner(
array('cp' => $this->_categoryProductTable),
- 'cp.category_id=cc.entity_id OR cp.category_id=ce.entity_id',
+ 'cp.category_id=cc.entity_id',
array('cp.product_id', 'position' => $position, 'is_parent' => $isParent)
)
->joinInner(array('pw' => $this->_productWebsiteTable), 'pw.product_id=cp.product_id', array())
@@ -837,12 +840,16 @@ public function reindexAll()
$anchorProductsTable = $this->_getAnchorCategoriesProductsTemporaryTable();
$idxAdapter->delete($anchorProductsTable);
- $position = $idxAdapter->getCheckSql('ca.category_id=MIN(ce.entity_id)',
- 'MIN(' . $idxAdapter->quoteIdentifier('cp.position') . ')',
- 'ROUND((MIN(' . $idxAdapter->quoteIdentifier('ce.position') . ') + 1) * ' .
- '(MIN(' . $idxAdapter->quoteIdentifier('ce.level') . ') + 1) * 10000, 0) + ' .
- 'MIN(' . $idxAdapter->quoteIdentifier('cp.position') . ')'
- );
+ $position = 'MIN('.
+ $idxAdapter->getCheckSql(
+ 'ca.category_id = ce.entity_id',
+ $idxAdapter->quoteIdentifier('cp.position'),
+ '('.$idxAdapter->quoteIdentifier('ce.position').' + 1) * '
+ .'('.$idxAdapter->quoteIdentifier('ce.level').' + 1 * 10000)'
+ .' + '.$idxAdapter->quoteIdentifier('cp.position')
+ )
+ .')';
+
$select = $idxAdapter->select()
->useStraightJoin(true)
@@ -917,7 +924,7 @@ public function reindexAll()
);
$idxAdapter->query($query, array('store_id' => $storeId, 'category_id' => $rootId));
- }
+ }
$this->syncData();
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product.php b/app/code/core/Mage/Catalog/Model/Resource/Product.php
index bec4a8ab06..526bc37b5c 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Product.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Product.php
@@ -518,9 +518,11 @@ public function getCategoryCollection($product)
*/
public function getAvailableInCategories($object)
{
- $select = $this->_getReadAdapter()->select()
+ // is_parent=1 ensures that we'll get only category IDs those are direct parents of the product, instead of
+ // fetching all parent IDs, including those are higher on the tree
+ $select = $this->_getReadAdapter()->select()->distinct()
->from($this->getTable('catalog/category_product_index'), array('category_id'))
- ->where('product_id = ?', (int)$object->getEntityId());
+ ->where('product_id = ? AND is_parent = 1', (int)$object->getEntityId());
return $this->_getReadAdapter()->fetchCol($select);
}
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price.php
index 4c112ddf6d..099a1a1393 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price.php
@@ -376,7 +376,13 @@ public function reindexAll()
$indexers = $this->getTypeIndexers();
foreach ($indexers as $indexer) {
/** @var $indexer Mage_Catalog_Model_Resource_Product_Indexer_Price_Interface */
+ if (!$this->_allowTableChanges && is_callable(array($indexer, 'setAllowTableChanges'))) {
+ $indexer->setAllowTableChanges(false);
+ }
$indexer->reindexAll();
+ if (!$this->_allowTableChanges && is_callable(array($indexer, 'setAllowTableChanges'))) {
+ $indexer->setAllowTableChanges(true);
+ }
}
$this->syncData();
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Configurable.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Configurable.php
index 25c69dfd03..b3f8208617 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Configurable.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Configurable.php
@@ -208,7 +208,7 @@ protected function _applyConfigurableOption()
$query = $select->crossUpdateFromSelect($table);
$write->query($query);
- if ($this->useIdxTable()) {
+ if ($this->useIdxTable() && $this->_allowTableChanges) {
$write->truncateTable($coaTable);
$write->truncateTable($copTable);
} else {
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Default.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Default.php
index 43e732f756..542b0fa6b8 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Default.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Price/Default.php
@@ -496,7 +496,7 @@ protected function _applyCustomOption()
$query = $select->crossUpdateFromSelect($table);
$write->query($query);
- if ($this->useIdxTable()) {
+ if ($this->useIdxTable() && $this->_allowTableChanges) {
$write->truncateTable($coaTable);
$write->truncateTable($copTable);
} else {
@@ -534,7 +534,7 @@ protected function _movePriceDataToIndexTable()
$query = $select->insertFromSelect($this->getIdxTable(), array(), false);
$write->query($query);
- if ($this->useIdxTable()) {
+ if ($this->useIdxTable() && $this->_allowTableChanges) {
$write->truncateTable($table);
} else {
$write->delete($table);
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable.php
index 458e2a84ea..5e041a3387 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable.php
@@ -145,4 +145,86 @@ public function getParentIdsByChild($childId)
return $parentIds;
}
+
+ /**
+ * Collect product options with values according to the product instance and attributes, that were received
+ *
+ * @param Mage_Catalog_Model_Product $product
+ * @param array $attributes
+ * @return array
+ */
+ public function getConfigurableOptions($product, $attributes)
+ {
+ $attributesOptionsData = array();
+ foreach ($attributes as $superAttribute) {
+ $select = $this->_getReadAdapter()->select()
+ ->from(
+ array(
+ 'super_attribute' => $this->getTable('catalog/product_super_attribute')
+ ),
+ array(
+ 'sku' => 'entity.sku',
+ 'product_id' => 'super_attribute.product_id',
+ 'attribute_code' => 'attribute.attribute_code',
+ 'option_title' => 'option_value.value',
+ 'pricing_value' => 'attribute_pricing.pricing_value',
+ 'pricing_is_percent' => 'attribute_pricing.is_percent'
+ )
+ )->joinInner(
+ array(
+ 'product_link' => $this->getTable('catalog/product_super_link')
+ ),
+ 'product_link.parent_id = super_attribute.product_id',
+ array()
+ )->joinInner(
+ array(
+ 'attribute' => $this->getTable('eav/attribute')
+ ),
+ 'attribute.attribute_id = super_attribute.attribute_id',
+ array()
+ )->joinInner(
+ array(
+ 'entity' => $this->getTable('catalog/product')
+ ),
+ 'entity.entity_id = product_link.product_id',
+ array()
+ )->joinInner(
+ array(
+ 'entity_value' => $superAttribute->getBackendTable()
+ ),
+ implode(
+ ' AND ',
+ array(
+ $this->_getReadAdapter()
+ ->quoteInto('entity_value.entity_type_id = ?', $product->getEntityTypeId()),
+ 'entity_value.attribute_id = super_attribute.attribute_id',
+ 'entity_value.store_id = 0',
+ 'entity_value.entity_id = product_link.product_id'
+ )
+ ),
+ array()
+ )->joinLeft(
+ array(
+ 'option_value' => $this->getTable('eav/attribute_option_value')
+ ),
+ implode(' AND ', array(
+ 'option_value.option_id = entity_value.value',
+ 'option_value.store_id = ' . Mage_Core_Model_App::ADMIN_STORE_ID,
+ )),
+ array()
+ )->joinLeft(
+ array(
+ 'attribute_pricing' => $this->getTable('catalog/product_super_attribute_pricing')
+ ),
+ implode(' AND ', array(
+ 'super_attribute.product_super_attribute_id = attribute_pricing.product_super_attribute_id',
+ 'entity_value.value = attribute_pricing.value_index'
+ )),
+ array()
+ )->where('super_attribute.product_id = ?', $product->getId());
+
+ $attributesOptionsData[$superAttribute->getAttributeId()] = $this->_getReadAdapter()->fetchAssoc($select);
+ }
+ return $attributesOptionsData;
+ }
}
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Setup.php b/app/code/core/Mage/Catalog/Model/Resource/Setup.php
index 33f2a8223e..450f8a2198 100755
--- a/app/code/core/Mage/Catalog/Model/Resource/Setup.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Setup.php
@@ -45,7 +45,11 @@ protected function _prepareValues($attr)
$data = parent::_prepareValues($attr);
$data = array_merge($data, array(
'frontend_input_renderer' => $this->_getValue($attr, 'input_renderer'),
- 'is_global' => $this->_getValue($attr, 'global', Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL),
+ 'is_global' => $this->_getValue(
+ $attr,
+ 'global',
+ Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL
+ ),
'is_visible' => $this->_getValue($attr, 'visible', 1),
'is_searchable' => $this->_getValue($attr, 'searchable', 0),
'is_filterable' => $this->_getValue($attr, 'filterable', 0),
@@ -100,7 +104,7 @@ public function getDefaultEntities()
),
'url_key' => array(
'type' => 'varchar',
- 'label' => 'URL key',
+ 'label' => 'URL Key',
'input' => 'text',
'backend' => 'catalog/category_attribute_backend_urlkey',
'required' => false,
@@ -635,7 +639,7 @@ public function getDefaultEntities()
),
'url_key' => array(
'type' => 'varchar',
- 'label' => 'URL key',
+ 'label' => 'URL Key',
'input' => 'text',
'backend' => 'catalog/product_attribute_backend_urlkey',
'required' => false,
@@ -667,7 +671,8 @@ public function getDefaultEntities()
'input' => 'select',
'source' => 'eav/entity_attribute_source_boolean',
'required' => false,
- 'note' => 'Products with recurring profile participate in catalog as nominal items.',
+ 'note' =>
+ 'Products with recurring profile participate in catalog as nominal items.',
'sort_order' => 1,
'apply_to' => 'simple,virtual',
'is_configurable' => false,
@@ -752,7 +757,7 @@ public function getDefaultEntities()
),
'options_container' => array(
'type' => 'varchar',
- 'label' => 'Display product options in',
+ 'label' => 'Display Product Options In',
'input' => 'select',
'source' => 'catalog/entity_product_attribute_design_options_container',
'required' => false,
diff --git a/app/code/core/Mage/Catalog/etc/api.xml b/app/code/core/Mage/Catalog/etc/api.xml
index b90b159f7e..07044afebb 100644
--- a/app/code/core/Mage/Catalog/etc/api.xml
+++ b/app/code/core/Mage/Catalog/etc/api.xml
@@ -174,16 +174,21 @@
Set special pricecatalog/product/update
+
+ Get list of non-default attributes by product type and attributes set
+ getAdditionalAttributes
+ catalog/product/listOfAdditionalAttributes
+ 100Requested store view not found.
-
+ 101Product not exists.
-
+
102Invalid data given. Details in error message.
@@ -192,6 +197,18 @@
103Product not deleted. Details in error message.
+
+ 104
+ Product type is not in allowed types.
+
+
+ 105
+ Product attribute set is not existed
+
+
+ 106
+ Product attribute set is not belong catalog product entity type
+
@@ -212,6 +229,34 @@
Retrieve attribute optionscatalog/product/attribute/read
+
+ Get list of possible attribute types
+ catalog/product/attribute/types
+
+
+ Create new attribute
+ catalog/product/attribute/create
+
+
+ Update attribute
+ catalog/product/attribute/update
+
+
+ Delete attribute
+ catalog/product/attribute/remove
+
+
+ Get full information about attribute with list of options
+ catalog/product/attribute/info
+
+
+ Add option
+ catalog/product/attribute/option/add
+
+
+ Remove option
+ catalog/product/attribute/option/remove
+
@@ -222,19 +267,152 @@
101Requested attribute not found.
+
+ 102
+ Invalid request parameters.
+
+
+ 103
+ Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.
+
+
+ 104
+ Incorrect attribute type.
+
+
+ 105
+ Unable to save attribute.
+
+
+ 106
+ This attribute cannot be deleted.
+
+
+ 107
+ This attribute cannot be edited.
+
+
+ 108
+ Unable to add option.
+
+
+ 109
+ Unable to remove option.
+ Product attribute sets APIcatalog/product_attribute_set_api
- catalog/product
+ catalog/product/attribute/set
+
+ Create attribute set based on another set
+ catalog/product/attribute/set/create
+
+
+ Remove attribute set
+ catalog/product/attribute/set/remove
+ Retrieve product attribute setsitems
+ catalog/product/attribute/set/list
+
+ Add attribute into attribute set
+ catalog/product/attribute/set/attribute_add
+
+
+ Remove attribute from attribute set
+ catalog/product/attribute/set/attribute_remove
+
+
+ Add group into attribute set
+ catalog/product/attribute/set/group_add
+
+
+ Rename existing group
+ catalog/product/attribute/set/group_rename
+
+
+ Remove group from attribute set
+ catalog/product/attribute/set/group_remove
+
+
+ 100
+ Attribute set with requested id does not exist.
+
+
+ 101
+ Invalid data given.
+
+
+ 102
+ Error while creating attribute set. Details in error message.
+
+
+ 103
+ Error while removing attribute set. Details in error message.
+
+
+ 104
+ Attribute set with requested id does not exist.
+
+
+ 105
+ Unable to remove attribute set as it has related goods. Use forceProductsRemove parameter to remove attribute set with all goods.
+
+
+ 106
+ Attribute with requested id does not exist.
+
+
+ 107
+ Error while adding attribute to attribute set. Details in error message.
+
+
+ 108
+ Attribute group with requested id does not exist.
+
+
+ 109
+ Requested attribute is already in requested attribute set.
+
+
+ 110
+ Error while removing attribute from attribute set. Details in error message.
+
+
+ 111
+ Requested attribute is not in requested attribute set.
+
+
+ 112
+ Requested group exist already in requested attribute set.
+
+
+ 113
+ Error while adding group to attribute set. Details in error message.
+
+
+ 114
+ Error while renaming group. Details in error message.
+
+
+ 115
+ Error while removing group from attribute set. Details in error message.
+
+
+ 116
+ Group can not be removed as it contains system attributes.
+
+
+ 117
+ Group can not be removed as it contains attributes, used in configurable products.
+
@@ -391,6 +569,134 @@
+
+ Catalog product custom options API
+ catalog/product_option_api
+ catalog/product/option
+
+
+ Add new custom option into product
+ catalog/product/option/add
+
+
+ Update custom option of product
+ catalog/product/option/update
+
+
+ Get list of available custom option types
+ catalog/product/option/types
+
+
+ Get full information about custom option in product
+ catalog/product/option/info
+
+
+ Retrieve list of product custom options
+ catalog/product/option/list
+ items
+
+
+ Remove custom option
+ catalog/product/option/remove
+
+
+
+
+ 101
+ Product with requested id does not exist.
+
+
+ 102
+ Provided data is invalid.
+
+
+ 103
+ Error while saving an option. Details are in the error message.
+
+
+ 104
+ Store with requested code/id does not exist.
+
+
+ 105
+ Option with requested id does not exist.
+
+
+ 106
+ Invalid option type provided. Call 'types' to get list of allowed option types.
+
+
+ 107
+ Error while deleting an option. Details are in the error message.
+
+
+
+
+ Catalog product custom option values API
+ catalog/product_option_value_api
+ catalog/product/option/value
+
+
+ Retrieve list of option values
+ items
+ catalog/product/option/value/list
+
+
+ Retrieve option value info
+ catalog/product/option/value/info
+
+
+ Add new values into custom option
+ catalog/product/option/value/add
+
+
+ Update value of custom option
+ catalog/product/option/value/update
+
+
+ Remove value from custom option
+ catalog/product/option/value/remove
+
+
+
+
+ 101
+ Option value with requested id does not exist.
+
+
+ 102
+ Error while adding an option value. Details are in the error message.
+
+
+ 103
+ Option with requested id does not exist.
+
+
+ 104
+ Invalid option type.
+
+
+ 105
+ Store with requested code/id does not exist.
+
+
+ 106
+ Can not delete option.
+
+
+ 107
+ Error while updating an option value. Details are in the error message.
+
+
+ 108
+ Title field is required.
+
+
+ 109
+ Option should have at least one value. Can not delete last value.
+
+
+ catalog_category
@@ -404,6 +710,8 @@
catalog_product_attribute_mediacatalog_product_attribute_tier_pricecatalog_product_attribute_tier_price
+ catalog_product_custom_option
+ catalog_product_custom_option_value
@@ -416,8 +724,32 @@
catalogProductAttributeTierPricecatalogProductAttributeMediacatalogProductLink
+ catalogProductCustomOption
+ catalogProductCustomOptionValue
+
+
+
+
+ tree
+
+
+
+
+ remove
+
+
+
+
+ assign
+
+
+ remove
+
+
+
+
@@ -443,6 +775,10 @@
Retrieve category data
+
+ Allowed Attributes (REST Only)
+ 0
+ Assigned Products100
@@ -474,6 +810,13 @@
Retrieve products data
+
+ Get list of non-default attributes by product type and attributes set
+
+
+ Allowed Attributes (REST Only)
+ 0
+ Product Attributes100
@@ -483,6 +826,57 @@
Change or Retrieve attribute store view
+
+ Get list of possible attribute types
+
+
+ Create
+
+
+ Update
+
+
+ Remove
+
+
+ Get full information about attribute with list of options
+
+
+
+ Attribute Sets
+
+ List
+
+
+ Create
+
+
+ Remove
+
+
+ Attribute add
+
+
+ Attribute remove
+
+
+ Group add
+
+
+ Rename group
+
+
+ Group remove
+
+ Link (Related, Up sell, Cross sell)
@@ -510,6 +904,47 @@
Remove
+
diff --git a/app/code/core/Mage/Catalog/etc/config.xml b/app/code/core/Mage/Catalog/etc/config.xml
index f0fe875ee7..a14d2b2c02 100644
--- a/app/code/core/Mage/Catalog/etc/config.xml
+++ b/app/code/core/Mage/Catalog/etc/config.xml
@@ -28,7 +28,7 @@
- 1.6.0.0.5
+ 1.6.0.0.6
diff --git a/app/code/core/Mage/Catalog/etc/system.xml b/app/code/core/Mage/Catalog/etc/system.xml
index 07110b786f..4cbacb4a7d 100644
--- a/app/code/core/Mage/Catalog/etc/system.xml
+++ b/app/code/core/Mage/Catalog/etc/system.xml
@@ -243,7 +243,7 @@
1
-
+
selectadminhtml/system_config_source_yesno5
diff --git a/app/code/core/Mage/Catalog/etc/wsdl.xml b/app/code/core/Mage/Catalog/etc/wsdl.xml
index a324953c9e..21a67e0cbc 100644
--- a/app/code/core/Mage/Catalog/etc/wsdl.xml
+++ b/app/code/core/Mage/Catalog/etc/wsdl.xml
@@ -15,6 +15,12 @@
+
+
+
+
+
+
@@ -98,7 +104,7 @@
-
+
@@ -367,6 +373,235 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -451,6 +686,14 @@
+
+
+
+
+
+
+
+
@@ -466,12 +709,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -547,7 +898,7 @@
-
+
@@ -556,7 +907,7 @@
-
+
@@ -576,7 +927,7 @@
-
+
@@ -587,7 +938,7 @@
-
+
@@ -597,7 +948,7 @@
-
+
@@ -619,6 +970,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -652,7 +1091,7 @@
-
+
@@ -857,6 +1296,11 @@
+
+ Get list of additional attributes which are not in default create/update list
+
+
+ Retrieve attribute list
@@ -867,11 +1311,81 @@
+
+ Create product attribute set based on another set
+
+
+
+
+ Remove product attribute set
+
+
+ Retrieve product attribute sets
+
+ Add attribute into attribute set
+
+
+
+
+ Remove attribute from attribute set
+
+
+
+
+ Create group within existing attribute set
+
+
+
+
+ Rename existing group
+
+
+
+
+ Remove group from attribute set
+
+
+
+
+ Get list of possible attribute types
+
+
+
+
+ Create new attribute
+
+
+
+
+ Delete attribute
+
+
+
+
+ Get full information about attribute with list of options
+
+
+
+
+ Update attribute
+
+
+
+
+ Add option to attribute
+
+
+
+
+ Remove option from attribute
+
+
+ Retrieve product types
@@ -952,6 +1466,61 @@
+
+ Add new custom option into product
+
+
+
+
+ Update product custom option
+
+
+
+
+ Get list of available custom option types
+
+
+
+
+ Get full information about custom option in product
+
+
+
+
+ Retrieve list of product custom options
+
+
+
+
+ Remove custom option
+
+
+
+
+ Retrieve custom option value info
+
+
+
+
+ Retrieve custom option values list
+
+
+
+
+ Add new custom option values
+
+
+
+
+ Update custom option value
+
+
+
+
+ Remove value from custom option
+
+
+
@@ -1098,6 +1667,17 @@
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+
+
+
+
+
+
+
@@ -1186,6 +1766,17 @@
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+
+
+
+
+
+
+
@@ -1208,6 +1799,17 @@
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+
+
+
+
+
+
+
@@ -1219,7 +1821,7 @@
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1428,6 +2162,127 @@
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/Catalog/sql/catalog_setup/mysql4-upgrade-0.7.40-0.7.41.php b/app/code/core/Mage/Catalog/sql/catalog_setup/mysql4-upgrade-0.7.40-0.7.41.php
index fa4ab4206c..d1cf0d4c52 100644
--- a/app/code/core/Mage/Catalog/sql/catalog_setup/mysql4-upgrade-0.7.40-0.7.41.php
+++ b/app/code/core/Mage/Catalog/sql/catalog_setup/mysql4-upgrade-0.7.40-0.7.41.php
@@ -36,7 +36,7 @@
'type' => 'varchar',
'backend' => '',
'frontend' => '',
- 'label' => 'Display product options in',
+ 'label' => 'Display Product Options In',
'input' => 'select',
'class' => '',
'source' => 'catalog/entity_product_attribute_design_options_container',
@@ -59,7 +59,8 @@
$installer->run("
INSERT INTO {$this->getTable('catalog_product_entity_varchar')}
(entity_id, entity_type_id, attribute_id, value)
- SELECT entity_id, entity_type_id, {$newAttributeId}, '{$defaultValue}' FROM {$this->getTable('catalog_product_entity')}
+ SELECT entity_id, entity_type_id, {$newAttributeId}, '{$defaultValue}'
+ FROM {$this->getTable('catalog_product_entity')}
");
$installer->endSetup();
diff --git a/app/code/core/Mage/Catalog/sql/catalog_setup/upgrade-1.6.0.0.5-1.6.0.0.6.php b/app/code/core/Mage/Catalog/sql/catalog_setup/upgrade-1.6.0.0.5-1.6.0.0.6.php
new file mode 100644
index 0000000000..fd578cc350
--- /dev/null
+++ b/app/code/core/Mage/Catalog/sql/catalog_setup/upgrade-1.6.0.0.5-1.6.0.0.6.php
@@ -0,0 +1,49 @@
+updateAttribute(
+ Mage_Catalog_Model_Product::ENTITY,
+ 'url_key',
+ 'frontend_label',
+ 'URL Key'
+);
+
+$installer->updateAttribute(
+ Mage_Catalog_Model_Category::ENTITY,
+ 'url_key',
+ 'frontend_label',
+ 'URL Key'
+);
+
+$installer->updateAttribute(
+ Mage_Catalog_Model_Product::ENTITY,
+ 'options_container',
+ 'frontend_label',
+ 'Display Product Options In'
+);
diff --git a/app/code/core/Mage/CatalogInventory/Block/Qtyincrements.php b/app/code/core/Mage/CatalogInventory/Block/Qtyincrements.php
index 41b19aeb4d..30ae4b9ba8 100644
--- a/app/code/core/Mage/CatalogInventory/Block/Qtyincrements.php
+++ b/app/code/core/Mage/CatalogInventory/Block/Qtyincrements.php
@@ -70,6 +70,9 @@ public function getProductQtyIncrements()
{
if ($this->_qtyIncrements === null) {
$this->_qtyIncrements = $this->_getProduct()->getStockItem()->getQtyIncrements();
+ if (!$this->_qtyIncrements) {
+ $this->_qtyIncrements = $this->_getProduct()->getStockItem()->getDefaultQtyIncrements();
+ }
if (!$this->_getProduct()->isSaleable()) {
$this->_qtyIncrements = false;
}
diff --git a/app/code/core/Mage/CatalogInventory/Model/Stock/Item.php b/app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
index e746cbe96f..8088314f3a 100644
--- a/app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
+++ b/app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
@@ -393,6 +393,19 @@ public function getQtyIncrements()
return $this->_qtyIncrements;
}
+ /**
+ * Retrieve Default Quantity Increments data wraper
+ *
+ * @return int|false
+ */
+ public function getDefaultQtyIncrements()
+ {
+ if (Mage::getStoreConfigFlag(self::XML_PATH_ENABLE_QTY_INCREMENTS)) {
+ return (int) Mage::getStoreConfig(self::XML_PATH_QTY_INCREMENTS);
+ }
+ return false;
+ }
+
/**
* Retrieve backorders status
*
@@ -564,6 +577,12 @@ public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0)
return $result;
}
+ $result->addData($this->checkQtyIncrements($qty)->getData());
+
+ if ($result->getHasError()) {
+ return $result;
+ }
+
if (!$this->getManageStock()) {
return $result;
}
@@ -577,12 +596,6 @@ public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0)
return $result;
}
- $result->addData($this->checkQtyIncrements($qty)->getData());
-
- if ($result->getHasError()) {
- return $result;
- }
-
if (!$this->checkQty($summaryQty) || !$this->checkQty($qty)) {
$message = $_helper->__('The requested quantity for "%s" is not available.', $this->getProductName());
$result->setHasError(true)
@@ -647,11 +660,15 @@ public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0)
public function checkQtyIncrements($qty)
{
$result = new Varien_Object();
- if (!$this->getManageStock() || $this->getSuppressCheckQtyIncrements()) {
+ if ($this->getSuppressCheckQtyIncrements()) {
return $result;
}
$qtyIncrements = $this->getQtyIncrements();
+ if (!$qtyIncrements){
+ $qtyIncrements = $this->getDefaultQtyIncrements();
+ }
+
if ($qtyIncrements && ($qty % $qtyIncrements != 0)) {
$result->setHasError(true)
->setQuoteMessage(
@@ -823,6 +840,16 @@ public function setProduct($product)
return $this;
}
+ /**
+ * Returns product instance
+ *
+ * @return Mage_Catalog_Model_Product|null
+ */
+ public function getProduct()
+ {
+ return $this->_productInstance ? $this->_productInstance : $this->_getData('product');
+ }
+
/**
* Retrieve stock qty whether product is composite or no
*
diff --git a/app/code/core/Mage/CatalogInventory/etc/system.xml b/app/code/core/Mage/CatalogInventory/etc/system.xml
index f5c9142b61..80e11f659a 100644
--- a/app/code/core/Mage/CatalogInventory/etc/system.xml
+++ b/app/code/core/Mage/CatalogInventory/etc/system.xml
@@ -118,7 +118,7 @@
0
-
+
text51
diff --git a/app/code/core/Mage/CatalogRule/Helper/Data.php b/app/code/core/Mage/CatalogRule/Helper/Data.php
index 0df625f894..f3237e51eb 100644
--- a/app/code/core/Mage/CatalogRule/Helper/Data.php
+++ b/app/code/core/Mage/CatalogRule/Helper/Data.php
@@ -49,6 +49,8 @@ public function calcPriceRule ($actionOperator, $ruleAmount, $price)
break;
case 'by_fixed':
$priceRule = $price - $ruleAmount;
+ // Price can not be negative
+ $priceRule = ($priceRule < 0) ? 0 : $priceRule;
break;
case 'by_percent':
$priceRule = $price * (1 - $ruleAmount / 100);
diff --git a/app/code/core/Mage/CatalogRule/Model/Rule.php b/app/code/core/Mage/CatalogRule/Model/Rule.php
index d2bacb676c..0301f02702 100644
--- a/app/code/core/Mage/CatalogRule/Model/Rule.php
+++ b/app/code/core/Mage/CatalogRule/Model/Rule.php
@@ -316,6 +316,7 @@ public function getCustomerGroupIds()
*/
public function applyAll()
{
+ $this->getResourceCollection()->walk(array($this->_getResource(), 'updateRuleProductData'));
$this->_getResource()->applyAllRulesForDateRange();
$this->_invalidateCache();
$indexProcess = Mage::getSingleton('index/indexer')->getProcessByCode('catalog_product_price');
@@ -371,12 +372,28 @@ public function calcProductPriceRule(Mage_Catalog_Model_Product $product, $price
$rulesData = $this->_getResource()->getRulesFromProduct($dateTs, $websiteId, $customerGroupId, $productId);
if ($rulesData) {
foreach ($rulesData as $ruleData) {
- $priceRules = Mage::helper('catalogrule')->calcPriceRule(
- $ruleData['simple_action'],
- $ruleData['discount_amount'],
- $priceRules ? $priceRules :$price);
- if ($ruleData['stop_rules_processing']) {
- break;
+ if ($product->getParentId()) {
+ if ($ruleData['sub_is_enable']) {
+ $priceRules = Mage::helper('catalogrule')->calcPriceRule(
+ $ruleData['sub_simple_action'],
+ $ruleData['sub_discount_amount'],
+ $priceRules ? $priceRules : $price
+ );
+ } else {
+ $priceRules = $price;
+ }
+ if ($ruleData['stop_rules_processing']) {
+ break;
+ }
+ } else {
+ $priceRules = Mage::helper('catalogrule')->calcPriceRule(
+ $ruleData['simple_action'],
+ $ruleData['discount_amount'],
+ $priceRules ? $priceRules :$price
+ );
+ if ($ruleData['stop_rules_processing']) {
+ break;
+ }
}
}
return self::$_priceRulesData[$cacheKey] = $priceRules;
diff --git a/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php b/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php
index dd2ed65957..80c8cb4314 100644
--- a/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php
+++ b/app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php
@@ -52,6 +52,24 @@ class Mage_CatalogRule_Model_Rule_Condition_Product extends Mage_Rule_Model_Cond
*/
protected $_isUsedForRuleProperty = 'is_used_for_promo_rules';
+ /**
+ * Customize default operator input by type mapper for some types
+ *
+ * @return array
+ */
+ public function getDefaultOperatorInputByType()
+ {
+ if (null === $this->_defaultOperatorInputByType) {
+ parent::getDefaultOperatorInputByType();
+ /*
+ * '{}' and '!{}' are left for back-compatibility and equal to '==' and '!='
+ */
+ $this->_defaultOperatorInputByType['category'] = array('==', '!=', '{}', '!{}', '()', '!()');
+ $this->_arrayInputTypes[] = 'category';
+ }
+ return $this->_defaultOperatorInputByType;
+ }
+
/**
* Retrieve attribute object
*
@@ -96,7 +114,9 @@ public function loadAttributeOptions()
$attributes = array();
foreach ($productAttributes as $attribute) {
/* @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
- if (!$attribute->isAllowedForRuleCondition() || !$attribute->getDataUsingMethod($this->_isUsedForRuleProperty)) {
+ if (!$attribute->isAllowedForRuleCondition()
+ || !$attribute->getDataUsingMethod($this->_isUsedForRuleProperty)
+ ) {
continue;
}
$attributes[$attribute->getAttributeCode()] = $attribute->getFrontendLabel();
@@ -261,6 +281,9 @@ public function getInputType()
if (!is_object($this->getAttributeObject())) {
return 'string';
}
+ if ($this->getAttributeObject()->getAttributeCode() == 'category_ids') {
+ return 'category';
+ }
switch ($this->getAttributeObject()->getFrontendInput()) {
case 'select':
return 'select';
@@ -433,7 +456,8 @@ public function validate(Varien_Object $object)
return parent::validate($object);
} else {
$result = false; // any valid value will set it to TRUE
- $oldAttrValue = $object->hasData($attrCode) ? $object->getData($attrCode) : null; // remember old attribute state
+ // remember old attribute state
+ $oldAttrValue = $object->hasData($attrCode) ? $object->getData($attrCode) : null;
foreach ($this->_entityAttributeValues[$object->getId()] as $storeId => $value) {
$attr = $object->getResource()->getAttribute($attrCode);
@@ -460,4 +484,24 @@ public function validate(Varien_Object $object)
return (bool) $result;
}
}
+
+ /**
+ * Correct '==' and '!=' operators
+ * Categories can't be equal because product is included categories selected by administrator and in their parents
+ *
+ * @return string
+ */
+ public function getOperatorForValidate()
+ {
+ $op = $this->getOperator();
+ if ($this->getInputType() == 'category') {
+ if ($op == '==') {
+ $op = '{}';
+ } elseif ($op == '!=') {
+ $op = '!{}';
+ }
+ }
+
+ return $op;
+ }
}
diff --git a/app/code/core/Mage/CatalogRule/etc/config.xml b/app/code/core/Mage/CatalogRule/etc/config.xml
index ddb08bbeee..918026fc76 100644
--- a/app/code/core/Mage/CatalogRule/etc/config.xml
+++ b/app/code/core/Mage/CatalogRule/etc/config.xml
@@ -28,7 +28,7 @@
- 1.6.0.0
+ 1.6.0.1
diff --git a/app/code/core/Mage/CatalogRule/sql/catalogrule_setup/upgrade-1.6.0.0-1.6.0.1.php b/app/code/core/Mage/CatalogRule/sql/catalogrule_setup/upgrade-1.6.0.0-1.6.0.1.php
new file mode 100644
index 0000000000..2b97372452
--- /dev/null
+++ b/app/code/core/Mage/CatalogRule/sql/catalogrule_setup/upgrade-1.6.0.0-1.6.0.1.php
@@ -0,0 +1,55 @@
+getTable('catalogrule/rule');
+$columnOptions = array(
+ 'TYPE' => Varien_Db_Ddl_Table::TYPE_SMALLINT,
+ 'UNSIGNED' => true,
+ 'NULLABLE' => false,
+ 'DEFAULT' => 0,
+ 'COMMENT' => 'Is Rule Enable For Subitems',
+);
+$installer->getConnection()->addColumn($tableName, 'sub_is_enable', $columnOptions);
+
+$columnOptions = array(
+ 'TYPE' => Varien_Db_Ddl_Table::TYPE_TEXT,
+ 'LENGTH' => 32,
+ 'COMMENT' => 'Simple Action For Subitems',
+);
+$installer->getConnection()->addColumn($tableName, 'sub_simple_action', $columnOptions);
+
+$columnOptions = array(
+ 'TYPE' => Varien_Db_Ddl_Table::TYPE_DECIMAL,
+ 'SCALE' => 4,
+ 'PRECISION' => 12,
+ 'NULLABLE' => false,
+ 'DEFAULT' => '0.0000',
+ 'COMMENT' => 'Discount Amount For Subitems',
+);
+$installer->getConnection()->addColumn($tableName, 'sub_discount_amount', $columnOptions);
diff --git a/app/code/core/Mage/CatalogSearch/Model/Advanced.php b/app/code/core/Mage/CatalogSearch/Model/Advanced.php
index b74baef11e..71306af5b2 100644
--- a/app/code/core/Mage/CatalogSearch/Model/Advanced.php
+++ b/app/code/core/Mage/CatalogSearch/Model/Advanced.php
@@ -158,21 +158,25 @@ public function addFilters($values)
$value = $values[$attribute->getAttributeCode()];
if ($attribute->getAttributeCode() == 'price') {
- if ((isset($value['from']) && strlen(trim($value['from']))) ||
- (isset($value['to']) && strlen(trim($value['to'])))) {
- if (isset($value['currency']) && !empty($value['currency'])) {
+ $value['from'] = isset($value['from']) ? trim($value['from']) : '';
+ $value['to'] = isset($value['to']) ? trim($value['to']) : '';
+ if (is_numeric($value['from']) || is_numeric($value['to'])) {
+ if (!empty($value['currency'])) {
$rate = Mage::app()->getStore()->getBaseCurrency()->getRate($value['currency']);
} else {
$rate = 1;
}
- if ($this->_getResource()->addRatedPriceFilter($this->getProductCollection(), $attribute, $value, $rate)) {
+ if ($this->_getResource()->addRatedPriceFilter(
+ $this->getProductCollection(), $attribute, $value, $rate)
+ ) {
$hasConditions = true;
$this->_addSearchCriteria($attribute, $value);
}
}
} else if ($attribute->isIndexable()) {
if (!is_string($value) || strlen($value) != 0) {
- if ($this->_getResource()->addIndexableAttributeModifiedFilter($this->getProductCollection(), $attribute, $value)) {
+ if ($this->_getResource()->addIndexableAttributeModifiedFilter(
+ $this->getProductCollection(), $attribute, $value)) {
$hasConditions = true;
$this->_addSearchCriteria($attribute, $value);
}
@@ -227,7 +231,8 @@ protected function _addSearchCriteria($attribute, $value)
if (strlen($value['from']) > 0 && strlen($value['to']) > 0) {
// -
- $value = sprintf('%s - %s', ($currencyModel ? $from : $value['from']), ($currencyModel ? $to : $value['to']));
+ $value = sprintf('%s - %s',
+ ($currencyModel ? $from : $value['from']), ($currencyModel ? $to : $value['to']));
} elseif (strlen($value['from']) > 0) {
// and more
$value = Mage::helper('catalogsearch')->__('%s and greater', ($currencyModel ? $from : $value['from']));
@@ -241,7 +246,9 @@ protected function _addSearchCriteria($attribute, $value)
}
}
- if (($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect') && is_array($value)) {
+ if (($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect')
+ && is_array($value)
+ ) {
foreach ($value as $key => $val){
$value[$key] = $attribute->getSource()->getOptionText($val);
diff --git a/app/code/core/Mage/CatalogSearch/Model/Fulltext.php b/app/code/core/Mage/CatalogSearch/Model/Fulltext.php
index dd48bfab8a..12e3d7370c 100644
--- a/app/code/core/Mage/CatalogSearch/Model/Fulltext.php
+++ b/app/code/core/Mage/CatalogSearch/Model/Fulltext.php
@@ -47,6 +47,13 @@ class Mage_CatalogSearch_Model_Fulltext extends Mage_Core_Model_Abstract
const SEARCH_TYPE_COMBINE = 3;
const XML_PATH_CATALOG_SEARCH_TYPE = 'catalog/search/search_type';
+ /**
+ * Whether table changes are allowed
+ *
+ * @var bool
+ */
+ protected $_allowTableChanges = true;
+
protected function _construct()
{
$this->_init('catalogsearch/fulltext');
@@ -67,7 +74,22 @@ protected function _construct()
*/
public function rebuildIndex($storeId = null, $productIds = null)
{
- $this->getResource()->rebuildIndex($storeId, $productIds);
+ Mage::dispatchEvent('catalogsearch_index_process_start', array(
+ 'store_id' => $storeId,
+ 'product_ids' => $productIds
+ ));
+
+ $resourceModel = $this->getResource();
+ if (!$this->_allowTableChanges && is_callable(array($resourceModel, 'setAllowTableChanges'))) {
+ $resourceModel->setAllowTableChanges(false);
+ }
+ $resourceModel->rebuildIndex($storeId, $productIds);
+ if (!$this->_allowTableChanges && is_callable(array($resourceModel, 'setAllowTableChanges'))) {
+ $resourceModel->setAllowTableChanges(true);
+ }
+
+ Mage::dispatchEvent('catalogsearch_index_process_complete', array());
+
return $this;
}
@@ -97,7 +119,15 @@ public function cleanIndex($storeId = null, $productId = null)
*/
public function resetSearchResults()
{
- $this->getResource()->resetSearchResults();
+ $resourceModel = $this->getResource();
+ if (!$this->_allowTableChanges && is_callable(array($resourceModel, 'setAllowTableChanges'))) {
+ $resourceModel->setAllowTableChanges(false);
+ }
+ $resourceModel->resetSearchResults();
+ if (!$this->_allowTableChanges && is_callable(array($resourceModel, 'setAllowTableChanges'))) {
+ $resourceModel->setAllowTableChanges(true);
+ }
+
return $this;
}
@@ -143,4 +173,16 @@ public function updateCategoryIndex($productIds, $categoryIds)
$this->getResource()->updateCategoryIndex($productIds, $categoryIds);
return $this;
}
+
+ /**
+ * Set whether table changes are allowed
+ *
+ * @param bool $value
+ * @return Mage_CatalogSearch_Model_Fulltext
+ */
+ public function setAllowTableChanges($value = true)
+ {
+ $this->_allowTableChanges = $value;
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/CatalogSearch/Model/Indexer/Fulltext.php b/app/code/core/Mage/CatalogSearch/Model/Indexer/Fulltext.php
index dd0232df4a..f7c813257d 100644
--- a/app/code/core/Mage/CatalogSearch/Model/Indexer/Fulltext.php
+++ b/app/code/core/Mage/CatalogSearch/Model/Indexer/Fulltext.php
@@ -314,6 +314,9 @@ protected function _isProductComposite($productId)
*/
protected function _processEvent(Mage_Index_Model_Event $event)
{
+ if (!$this->_allowTableChanges && is_callable(array($this->_getIndexer(), 'setAllowTableChanges'))) {
+ $this->_getIndexer()->setAllowTableChanges(false);
+ }
$data = $event->getNewData();
if (!empty($data['catalogsearch_fulltext_reindex_all'])) {
@@ -384,6 +387,9 @@ protected function _processEvent(Mage_Index_Model_Event $event)
$this->_getIndexer()
->updateCategoryIndex($productIds, $categoryIds);
}
+ if (!$this->_allowTableChanges && is_callable(array($this->_getIndexer(), 'setAllowTableChanges'))) {
+ $this->_getIndexer()->setAllowTableChanges(true);
+ }
}
/**
diff --git a/app/code/core/Mage/CatalogSearch/Model/Resource/Advanced.php b/app/code/core/Mage/CatalogSearch/Model/Resource/Advanced.php
index 6346123bda..5e5f79a58c 100755
--- a/app/code/core/Mage/CatalogSearch/Model/Resource/Advanced.php
+++ b/app/code/core/Mage/CatalogSearch/Model/Resource/Advanced.php
@@ -117,10 +117,12 @@ public function addRatedPriceFilter($collection, $attribute, $value, $rate = 1)
$conditions = array();
if (strlen($value['from']) > 0) {
- $conditions[] = $adapter->quoteInto('price_index.min_price %s * %s >= ?', $value['from']);
+ $conditions[] = $adapter->quoteInto(
+ 'price_index.min_price %s * %s >= ?', $value['from'], Zend_Db::FLOAT_TYPE);
}
if (strlen($value['to']) > 0) {
- $conditions[] = $adapter->quoteInto('price_index.min_price %s * %s <= ?', $value['to']);
+ $conditions[] = $adapter->quoteInto(
+ 'price_index.min_price %s * %s <= ?', $value['to'], Zend_Db::FLOAT_TYPE);
}
if (!$conditions) {
diff --git a/app/code/core/Mage/CatalogSearch/Model/Resource/Fulltext.php b/app/code/core/Mage/CatalogSearch/Model/Resource/Fulltext.php
index 3749caa26e..01f27a0c6d 100755
--- a/app/code/core/Mage/CatalogSearch/Model/Resource/Fulltext.php
+++ b/app/code/core/Mage/CatalogSearch/Model/Resource/Fulltext.php
@@ -69,6 +69,13 @@ class Mage_CatalogSearch_Model_Resource_Fulltext extends Mage_Core_Model_Resourc
*/
protected $_engine = null;
+ /**
+ * Whether table changes are allowed
+ *
+ * @var bool
+ */
+ protected $_allowTableChanges = true;
+
/**
* Init resource model
*
@@ -108,8 +115,8 @@ public function updateCategoryIndex($productIds, $categoryIds)
/**
* Regenerate search index for store(s)
*
- * @param int $storeId Store View Id
- * @param int|array $productIds Product Entity Id(s)
+ * @param int|null $storeId
+ * @param int|array|null $productIds
* @return Mage_CatalogSearch_Model_Mysql4_Fulltext
*/
public function rebuildIndex($storeId = null, $productIds = null)
@@ -184,31 +191,33 @@ protected function _rebuildStoreIndex($storeId, $productIds = null)
* If using advanced index and there is no required fields - do not add to index.
* Skipping out of stock products if there are no prices for them in catalog_product_index_price table
*/
- if ($this->_engine->allowAdvancedIndex() &&
- (!isset($productData[$this->_engine->getFieldsPrefix() . 'categories']))) {
+ if ($this->_engine->allowAdvancedIndex()
+ && (!isset($productData[$this->_engine->getFieldsPrefix() . 'categories']))
+ ) {
continue;
}
if (!isset($productAttributes[$productData['entity_id']])) {
continue;
}
- $protductAttr = $productAttributes[$productData['entity_id']];
- if (!isset($protductAttr[$visibility->getId()])
- || (!in_array($protductAttr[$visibility->getId()], $visibilityVals)
+ $productAttr = $productAttributes[$productData['entity_id']];
+ if (!isset($productAttr[$visibility->getId()])
+ || (!in_array($productAttr[$visibility->getId()], $visibilityVals)
&& !$this->_engine->allowAdvancedIndex()
)
) {
continue;
}
- if (!isset($protductAttr[$status->getId()])
- || !in_array($protductAttr[$status->getId()], $statusVals)
+ if (!isset($productAttr[$status->getId()])
+ || !in_array($productAttr[$status->getId()], $statusVals)
) {
continue;
}
$productIndex = array(
- $productData['entity_id'] => $protductAttr
+ $productData['entity_id'] => $productAttr
);
+
if ($productChilds = $productRelations[$productData['entity_id']]) {
foreach ($productChilds as $productChildId) {
if (isset($productAttributes[$productChildId])) {
@@ -220,8 +229,8 @@ protected function _rebuildStoreIndex($storeId, $productIds = null)
$index = $this->_prepareProductIndex($productIndex, $productData, $storeId);
$productIndexes[$productData['entity_id']] = $index;
- //$this->_saveProductIndex($productData['entity_id'], $storeId, $index);
}
+
$this->_saveProductIndexes($storeId, $productIndexes);
}
@@ -248,7 +257,8 @@ protected function _getSearchableProducts($storeId, array $staticFields, $produc
->useStraightJoin(true)
->from(
array('e' => $this->getTable('catalog/product')),
- array_merge(array('entity_id', 'type_id'), $staticFields))
+ array_merge(array('entity_id', 'type_id'), $staticFields)
+ )
->join(
array('website' => $this->getTable('catalog/product_website')),
$this->_getWriteAdapter()->quoteInto(
@@ -289,10 +299,13 @@ protected function _getSearchableProducts($storeId, array $staticFields, $produc
*/
public function resetSearchResults()
{
-
$adapter = $this->_getWriteAdapter();
$adapter->update($this->getTable('catalogsearch/search_query'), array('is_processed' => 0));
- $adapter->truncateTable($this->getTable('catalogsearch/result'));
+ if ($this->_allowTableChanges) {
+ $adapter->truncateTable($this->getTable('catalogsearch/result'));
+ } else {
+ $adapter->delete($this->getTable('catalogsearch/result'));
+ }
Mage::dispatchEvent('catalogsearch_reset_search_result');
@@ -335,7 +348,8 @@ public function prepareResult($object, $queryText, $query)
$like = array();
$likeCond = '';
if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE
- || $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
+ || $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE
+ ) {
$helper = Mage::getResourceHelper('core');
$words = Mage::helper('core/string')->splitWords($queryText, true, $query->getMaxQueryWords());
foreach ($words as $word) {
@@ -363,11 +377,10 @@ public function prepareResult($object, $queryText, $query)
$where = Mage::getResourceHelper('catalogsearch')
->chooseFulltext($this->getMainTable(), $mainTableAlias, $select);
}
- if ($likeCond!=''
- && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
+ if ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
$where .= ($where ? ' OR ' : '') . $likeCond;
}
- if ($likeCond!='' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE) {
+ if ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE) {
$select->columns(array('relevance' => new Zend_Db_Expr(0)));
$where = $likeCond;
}
@@ -762,4 +775,16 @@ protected function _getStoreDate($storeId, $date = null)
return null;
}
+
+ /**
+ * Set whether table changes are allowed
+ *
+ * @param bool $value
+ * @return Mage_CatalogSearch_Model_Resource_Fulltext
+ */
+ public function setAllowTableChanges($value = true)
+ {
+ $this->_allowTableChanges = $value;
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/CatalogSearch/Model/Resource/Query/Collection.php b/app/code/core/Mage/CatalogSearch/Model/Resource/Query/Collection.php
index 930ee07529..9f35cfcfe2 100755
--- a/app/code/core/Mage/CatalogSearch/Model/Resource/Query/Collection.php
+++ b/app/code/core/Mage/CatalogSearch/Model/Resource/Query/Collection.php
@@ -109,17 +109,15 @@ public function setQueryFilter($query)
public function setPopularQueryFilter($storeIds = null)
{
$ifSynonymFor = new Zend_Db_Expr($this->getConnection()
- ->getIfNullSql('synonym_for', 'query_text'));
+ ->getCheckSql("synonym_for IS NOT NULL AND synonym_for != ''", 'synonym_for', 'query_text'));
+
$this->getSelect()
->reset(Zend_Db_Select::FROM)
->reset(Zend_Db_Select::COLUMNS)
->distinct(true)
->from(
- array('main_table'=>$this->getTable('catalogsearch/search_query')),
- array('name'=>$ifSynonymFor,
- 'num_results',
- 'popularity',
- )
+ array('main_table' => $this->getTable('catalogsearch/search_query')),
+ array('name' => $ifSynonymFor, 'num_results', 'popularity')
);
if ($storeIds) {
$this->addStoreFilter($storeIds);
diff --git a/app/code/core/Mage/Centinel/Model/State/Visa.php b/app/code/core/Mage/Centinel/Model/State/Visa.php
index 2126ff4138..e4f2b51a0d 100644
--- a/app/code/core/Mage/Centinel/Model/State/Visa.php
+++ b/app/code/core/Mage/Centinel/Model/State/Visa.php
@@ -95,7 +95,7 @@ public function isAuthenticateSuccessful()
}
//Test case 11
- if ($paResStatus == '' && $signatureVerification == '' && $eciFlag == '07' &&
+ if ($paResStatus == 'U' && $signatureVerification == '' && $eciFlag == '07' &&
$xid == '' && $cavv == '' && $errorNo == '1050') {
if ($this->getIsModeStrict()) {
return false;
diff --git a/app/code/core/Mage/Centinel/controllers/Adminhtml/Centinel/IndexController.php b/app/code/core/Mage/Centinel/controllers/Adminhtml/Centinel/IndexController.php
index fcc5769d85..f75f2d2542 100644
--- a/app/code/core/Mage/Centinel/controllers/Adminhtml/Centinel/IndexController.php
+++ b/app/code/core/Mage/Centinel/controllers/Adminhtml/Centinel/IndexController.php
@@ -27,6 +27,9 @@
/**
* Centinel Index Controller
*
+ * @category Mage
+ * @package Mage_Centinel
+ * @author Magento Core Team
*/
class Mage_Centinel_Adminhtml_Centinel_IndexController extends Mage_Adminhtml_Controller_Action
{
@@ -43,12 +46,9 @@ public function validatePaymentDataAction()
if (!$validator) {
throw new Exception('This payment method does not have centinel validation.');
}
+ $validator->reset();
$this->_getPayment()->importData($paymentData);
- if ($validator->shouldAuthenticate()) {
- $result['authenticationUrl'] = $validator->getAuthenticationStartUrl();
- } else {
- Mage::throwException(Mage::helper('centinel')->__('This card has failed validation, but it is possible to place the order.'));
- }
+ $result['authenticationUrl'] = $validator->getAuthenticationStartUrl();
} catch (Mage_Core_Exception $e) {
$result['message'] = $e->getMessage();
} catch (Exception $e) {
diff --git a/app/code/core/Mage/Checkout/Block/Cart/Sidebar.php b/app/code/core/Mage/Checkout/Block/Cart/Sidebar.php
index 7eb59441d5..7aefd6d07f 100644
--- a/app/code/core/Mage/Checkout/Block/Cart/Sidebar.php
+++ b/app/code/core/Mage/Checkout/Block/Cart/Sidebar.php
@@ -258,4 +258,56 @@ public function getTotalsCache()
}
return $this->_totals;
}
+
+ /**
+ * Get cache key informative items
+ *
+ * @return array
+ */
+ public function getCacheKeyInfo()
+ {
+ $cacheKeyInfo = parent::getCacheKeyInfo();
+ $cacheKeyInfo['item_renders'] = $this->_serializeRenders();
+ return $cacheKeyInfo;
+ }
+
+ /**
+ * Serialize renders
+ *
+ * @return string
+ */
+ protected function _serializeRenders()
+ {
+ $result = array();
+ foreach ($this->_itemRenders as $type => $renderer) {
+ $result[] = implode('|', array($type, $renderer['block'], $renderer['template']));
+ }
+ return implode('|', $result);
+ }
+
+ /**
+ * Deserialize renders from string
+ *
+ * @param string $renders
+ * @return Mage_Checkout_Block_Cart_Sidebar
+ */
+ public function deserializeRenders($renders)
+ {
+ if (!is_string($renders)) {
+ return $this;
+ }
+
+ $renders = explode('|', $renders);
+ while (!empty($renders)) {
+ $template = array_pop($renders);
+ $block = array_pop($renders);
+ $type = array_pop($renders);
+ if (!$template || !$block || !$type) {
+ continue;
+ }
+ $this->addItemRender($type, $block, $template);
+ }
+
+ return $this;
+ }
}
diff --git a/app/code/core/Mage/Checkout/Model/Api/Resource.php b/app/code/core/Mage/Checkout/Model/Api/Resource.php
index de11ecde38..2d55f060c9 100644
--- a/app/code/core/Mage/Checkout/Model/Api/Resource.php
+++ b/app/code/core/Mage/Checkout/Model/Api/Resource.php
@@ -119,7 +119,7 @@ protected function _getQuote($quoteId, $store = null)
/** @var $quote Mage_Sales_Model_Quote */
$quote = Mage::getModel("sales/quote");
- if (!(is_string($store) && is_integer($store))) {
+ if (!(is_string($store) || is_integer($store))) {
$quote->loadByIdWithoutStore($quoteId);
} else {
$storeId = $this->_getStoreId($store);
diff --git a/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php b/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php
index b446a0fbc0..670b188d4d 100644
--- a/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php
+++ b/app/code/core/Mage/Checkout/Model/Api/Resource/Customer.php
@@ -203,9 +203,9 @@ public function involveNewCustomer(Mage_Sales_Model_Quote $quote)
{
$customer = $quote->getCustomer();
if ($customer->isConfirmationRequired()) {
- $customer->sendNewAccountEmail('confirmation', '', $quote->getStoreId());
+ $customer->sendNewAccountEmail('confirmation');
} else {
- $customer->sendNewAccountEmail('registered' , '', $quote->getStoreId());
+ $customer->sendNewAccountEmail();
}
return $this;
diff --git a/app/code/core/Mage/Checkout/Model/Resource/Agreement/Collection.php b/app/code/core/Mage/Checkout/Model/Resource/Agreement/Collection.php
index fb555b78f8..6dbc11fe7b 100755
--- a/app/code/core/Mage/Checkout/Model/Resource/Agreement/Collection.php
+++ b/app/code/core/Mage/Checkout/Model/Resource/Agreement/Collection.php
@@ -34,6 +34,10 @@
*/
class Mage_Checkout_Model_Resource_Agreement_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
{
+ protected $_map = array('fields' => array(
+ 'agreement_id' => 'main_table.agreement_id',
+ ));
+
/**
* Is store filter with admin store
*
diff --git a/app/code/core/Mage/Checkout/Model/Type/Multishipping.php b/app/code/core/Mage/Checkout/Model/Type/Multishipping.php
index eabe75b163..93edf95e48 100644
--- a/app/code/core/Mage/Checkout/Model/Type/Multishipping.php
+++ b/app/code/core/Mage/Checkout/Model/Type/Multishipping.php
@@ -241,7 +241,10 @@ public function setShippingItemsInformation($info)
* MultishippingQty should be defined for each quote item when it processed with _addShippingItem
*/
foreach ($quote->getAllItems() as $_item) {
- if (!$_item->getProduct()->getIsVirtual() && !$_item->getParentItem() && !$_item->getMultishippingQty()) {
+ if (!$_item->getProduct()->getIsVirtual() &&
+ !$_item->getParentItem() &&
+ !$_item->getMultishippingQty()
+ ) {
$_item->delete();
}
}
@@ -419,6 +422,7 @@ protected function _prepareOrder(Mage_Sales_Model_Quote_Address $address)
$convertQuote = Mage::getSingleton('sales/convert_quote');
$order = $convertQuote->addressToOrder($address);
+ $order->setQuote($quote);
$order->setBillingAddress(
$convertQuote->addressToOrderAddress($quote->getBillingAddress())
);
@@ -435,11 +439,14 @@ protected function _prepareOrder(Mage_Sales_Model_Quote_Address $address)
}
foreach ($address->getAllItems() as $item) {
- if (! $item->getQuoteItem()) {
+ $_quoteItem = $item->getQuoteItem();
+ if (!$_quoteItem) {
throw new Mage_Checkout_Exception(Mage::helper('checkout')->__('Item not found or already ordered'));
}
- $item->setProductType($item->getQuoteItem()->getProductType())
- ->setProductOptions($item->getQuoteItem()->getProduct()->getTypeInstance(true)->getOrderOptions($item->getQuoteItem()->getProduct()));
+ $item->setProductType($_quoteItem->getProductType())
+ ->setProductOptions(
+ $_quoteItem->getProduct()->getTypeInstance(true)->getOrderOptions($_quoteItem->getProduct())
+ );
$orderItem = $convertQuote->itemToOrderItem($item);
if ($item->getParentItem()) {
$orderItem->setParentItem($order->getItemByQuoteItemId($item->getParentItem()->getId()));
@@ -463,6 +470,12 @@ protected function _validate()
Mage::throwException($helper->__('Invalid checkout type.'));
}
+ /** @var $paymentMethod Mage_Payment_Model_Method_Abstract */
+ $paymentMethod = $quote->getPayment()->getMethodInstance();
+ if (!empty($paymentMethod) && !$paymentMethod->isAvailable($quote)) {
+ Mage::throwException($helper->__('Please specify payment method.'));
+ }
+
$addresses = $quote->getAllShippingAddresses();
foreach ($addresses as $address) {
$addressValidation = $address->validate();
diff --git a/app/code/core/Mage/Checkout/Model/Type/Onepage.php b/app/code/core/Mage/Checkout/Model/Type/Onepage.php
index 7b9de19035..7ad0cca693 100644
--- a/app/code/core/Mage/Checkout/Model/Type/Onepage.php
+++ b/app/code/core/Mage/Checkout/Model/Type/Onepage.php
@@ -332,6 +332,11 @@ public function saveBilling($data, $customerAddressId)
$this->getQuote()->collectTotals();
$this->getQuote()->save();
+ if (!$this->getQuote()->isVirtual() && $this->getCheckout()->getStepData('shipping', 'complete') == true) {
+ //Recollect Shipping rates for shipping methods
+ $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
+ }
+
$this->getCheckout()
->setStepData('billing', 'allow', true)
->setStepData('billing', 'complete', true)
@@ -572,8 +577,6 @@ public function saveShippingMethod($shippingMethod)
}
$this->getQuote()->getShippingAddress()
->setShippingMethod($shippingMethod);
- $this->getQuote()->collectTotals()
- ->save();
$this->getCheckout()
->setStepData('shipping_method', 'complete', true)
diff --git a/app/code/core/Mage/Checkout/controllers/CartController.php b/app/code/core/Mage/Checkout/controllers/CartController.php
index 33970d101e..35903de569 100644
--- a/app/code/core/Mage/Checkout/controllers/CartController.php
+++ b/app/code/core/Mage/Checkout/controllers/CartController.php
@@ -272,7 +272,7 @@ public function configureAction()
if (!$quoteItem) {
$this->_getSession()->addError($this->__('Quote item is not found.'));
- $this->_goBack();
+ $this->_redirect('checkout/cart');
return;
}
diff --git a/app/code/core/Mage/Checkout/controllers/MultishippingController.php b/app/code/core/Mage/Checkout/controllers/MultishippingController.php
index 43163e8da5..8af1443a57 100644
--- a/app/code/core/Mage/Checkout/controllers/MultishippingController.php
+++ b/app/code/core/Mage/Checkout/controllers/MultishippingController.php
@@ -553,7 +553,7 @@ public function successAction()
public function redirectLogin()
{
$this->setFlag('', 'no-dispatch', true);
- Mage::getSingleton('customer/session')->setBeforeAuthUrl($this->_getRefererUrl());
+ Mage::getSingleton('customer/session')->setBeforeAuthUrl(Mage::getUrl('*/*', array('_secure'=>true)));
$this->getResponse()->setRedirect(
Mage::helper('core/url')->addRequestParam(
diff --git a/app/code/core/Mage/Checkout/controllers/OnepageController.php b/app/code/core/Mage/Checkout/controllers/OnepageController.php
index c1ea4a56b8..536530122f 100644
--- a/app/code/core/Mage/Checkout/controllers/OnepageController.php
+++ b/app/code/core/Mage/Checkout/controllers/OnepageController.php
@@ -374,6 +374,7 @@ public function saveShippingMethodAction()
Mage::dispatchEvent('checkout_controller_onepage_save_shipping_method',
array('request'=>$this->getRequest(),
'quote'=>$this->getOnepage()->getQuote()));
+ $this->getOnepage()->getQuote()->collectTotals();
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
$result['goto_section'] = 'payment';
@@ -382,6 +383,7 @@ public function saveShippingMethodAction()
'html' => $this->_getPaymentMethodsHtml()
);
}
+ $this->getOnepage()->getQuote()->collectTotals()->save();
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
}
}
@@ -461,12 +463,12 @@ protected function _getOrder()
protected function _initInvoice()
{
$items = array();
- foreach ($this->getOnepage()->getQuote()->getAllItems() as $item) {
- $items[$item->getId()] = $item->getQty();
+ foreach ($this->_getOrder()->getAllItems() as $item) {
+ $items[$item->getId()] = $item->getQtyOrdered();
}
/* @var $invoice Mage_Sales_Model_Service_Order */
$invoice = Mage::getModel('sales/service_order', $this->_getOrder())->prepareInvoice($items);
- $invoice->setEmailSent(true);
+ $invoice->setEmailSent(true)->register();
Mage::register('current_invoice', $invoice);
return $invoice;
@@ -507,7 +509,10 @@ public function saveOrderAction()
&& $paymentHelper->getZeroSubTotalOrderStatus($storeId) == 'pending') {
$invoice = $this->_initInvoice();
$invoice->getOrder()->setIsInProcess(true);
- $invoice->save();
+ $transactionSave = Mage::getModel('core/resource_transaction')
+ ->addObject($invoice)
+ ->addObject($invoice->getOrder());
+ $transactionSave->save();
}
$redirectUrl = $this->getOnepage()->getCheckout()->getRedirectUrl();
diff --git a/app/code/core/Mage/Checkout/etc/api.xml b/app/code/core/Mage/Checkout/etc/api.xml
index 0c582315a3..b22730f7ed 100644
--- a/app/code/core/Mage/Checkout/etc/api.xml
+++ b/app/code/core/Mage/Checkout/etc/api.xml
@@ -381,6 +381,46 @@
+
+ cart_customer
+
+
+
+
+
+ add
+
+
+ remove
+
+
+
+
+ method
+
+
+
+
+ method
+
+
+
+
+ set
+
+
+
+
+ addresses
+
+
+
+
+ method
+
+
+
+
diff --git a/app/code/core/Mage/Core/Controller/Front/Action.php b/app/code/core/Mage/Core/Controller/Front/Action.php
index c9f0ecfb98..50dcdfedbb 100644
--- a/app/code/core/Mage/Core/Controller/Front/Action.php
+++ b/app/code/core/Mage/Core/Controller/Front/Action.php
@@ -134,6 +134,9 @@ protected function _prepareDownloadResponse($fileName, $content, $contentType =
$this->getResponse()->sendHeaders();
$ioAdapter = new Varien_Io_File();
+ if (!$ioAdapter->fileExists($file)) {
+ Mage::throwException(Mage::helper('core')->__('File not found'));
+ }
$ioAdapter->open(array('path' => $ioAdapter->dirname($file)));
$ioAdapter->streamOpen($file, 'r');
while ($buffer = $ioAdapter->streamRead()) {
diff --git a/app/code/core/Mage/Core/Controller/Response/Http.php b/app/code/core/Mage/Core/Controller/Response/Http.php
index ab2596ebc6..0add065959 100644
--- a/app/code/core/Mage/Core/Controller/Response/Http.php
+++ b/app/code/core/Mage/Core/Controller/Response/Http.php
@@ -32,6 +32,13 @@
*/
class Mage_Core_Controller_Response_Http extends Zend_Controller_Response_Http
{
+ /**
+ * Transport object for observers to perform
+ *
+ * @var Varien_Object
+ */
+ protected static $_transportObject = null;
+
/**
* Fixes CGI only one Status header allowed bug
*
@@ -74,4 +81,27 @@ public function sendResponse()
Mage::dispatchEvent('http_response_send_before', array('response'=>$this));
return parent::sendResponse();
}
+
+ /**
+ * Additionally check for session messages in several domains case
+ *
+ * @param string $url
+ * @param int $code
+ * @return Mage_Core_Controller_Response_Http
+ */
+ public function setRedirect($url, $code = 302)
+ {
+ /**
+ * Use single transport object instance
+ */
+ if (self::$_transportObject === null) {
+ self::$_transportObject = new Varien_Object;
+ }
+ self::$_transportObject->setUrl($url);
+ self::$_transportObject->setCode($code);
+ Mage::dispatchEvent('controller_response_redirect',
+ array('response' => $this, 'transport' => self::$_transportObject));
+
+ return parent::setRedirect(self::$_transportObject->getUrl(), self::$_transportObject->getCode());
+ }
}
diff --git a/app/code/core/Mage/Core/Controller/Varien/Front.php b/app/code/core/Mage/Core/Controller/Varien/Front.php
index 1335b67932..0d3b8ad5f9 100644
--- a/app/code/core/Mage/Core/Controller/Varien/Front.php
+++ b/app/code/core/Mage/Core/Controller/Varien/Front.php
@@ -300,6 +300,16 @@ protected function _checkBaseUrl($request)
return;
}
+ $adminPath = (string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_CUSTOM_ADMIN_PATH);
+ if (!$adminPath) {
+ $adminPath = (string)Mage::getConfig()
+ ->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_ADMINHTML_ROUTER_FRONTNAME);
+ }
+ if (preg_match('#^' . $adminPath . '(\/.*)?$#', ltrim($request->getPathInfo(), '/'))
+ && (string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_USE_CUSTOM_ADMIN_URL)) {
+ return;
+ }
+
$baseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB, Mage::app()->getStore()->isCurrentlySecure());
if (!$baseUrl) {
@@ -307,17 +317,16 @@ protected function _checkBaseUrl($request)
}
$redirectCode = 302;
- if (Mage::getStoreConfig('web/url/redirect_to_base')==301) {
+ if (Mage::getStoreConfig('web/url/redirect_to_base') == 301) {
$redirectCode = 301;
}
- $uri = @parse_url($baseUrl);
+ $uri = @parse_url($baseUrl);
$host = isset($uri['host']) ? $uri['host'] : '';
$path = isset($uri['path']) ? $uri['path'] : '';
$requestUri = $request->getRequestUri() ? $request->getRequestUri() : '/';
- if ($host && $host != $request->getHttpHost() || $path && strpos($requestUri, $path) === false)
- {
+ if ($host && $host != $request->getHttpHost() || $path && strpos($requestUri, $path) === false) {
Mage::app()->getFrontController()->getResponse()
->setRedirect($baseUrl, $redirectCode)
->sendResponse();
diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php b/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php
index 7ed882d7b2..b052fd835f 100644
--- a/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php
+++ b/app/code/core/Mage/Core/Controller/Varien/Router/Admin.php
@@ -120,8 +120,8 @@ protected function _getCurrentSecureUrl($request)
*/
public function collectRoutes($configArea, $useRouterName)
{
- if ((string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_USE_CUSTOM_ADMIN_URL)) {
- $customUrl = (string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_CUSTOM_ADMIN_URL);
+ if ((string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_USE_CUSTOM_ADMIN_PATH)) {
+ $customUrl = (string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_CUSTOM_ADMIN_PATH);
$xmlPath = Mage_Adminhtml_Helper_Data::XML_PATH_ADMINHTML_ROUTER_FRONTNAME;
if ((string)Mage::getConfig()->getNode($xmlPath) != $customUrl) {
Mage::getConfig()->setNode($xmlPath, $customUrl, true);
diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php b/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php
index e0a6ac4eb9..c3bcd1c6a4 100644
--- a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php
+++ b/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php
@@ -416,19 +416,28 @@ public function rewrite(array $p)
return $p;
}
- protected function _checkShouldBeSecure($request, $path='')
+ /**
+ * Check if request URL should be secure
+ *
+ * Function redirects user to correct URL if needed
+ *
+ * @param Mage_Core_Controller_Request_Http $request
+ * @param string $path
+ * @return null
+ */
+ protected function _checkShouldBeSecure($request, $path = '')
{
if (!Mage::isInstalled() || $request->getPost()) {
return;
}
- if ($this->_shouldBeSecure($path) && !Mage::app()->getStore()->isCurrentlySecure()) {
+ if ($this->_shouldBeSecure($path) && !$request->isSecure()) {
$url = $this->_getCurrentSecureUrl($request);
Mage::app()->getFrontController()->getResponse()
->setRedirect($url)
->sendResponse();
- exit;
+ exit();
}
}
diff --git a/app/code/core/Mage/Core/Helper/Url.php b/app/code/core/Mage/Core/Helper/Url.php
index 2f8e421173..811b5c49cb 100644
--- a/app/code/core/Mage/Core/Helper/Url.php
+++ b/app/code/core/Mage/Core/Helper/Url.php
@@ -112,6 +112,8 @@ public function addRequestParam($url, $param)
if (is_array($value)) {
// $key[]=$value1&$key[]=$value2 ...
$arrQueryParams[] = $key . '[]=' . implode('&' . $key . '[]=', $value);
+ } elseif (is_null($value)) {
+ $arrQueryParams[] = $key;
} else {
$arrQueryParams[] = $key . '=' . $value;
}
diff --git a/app/code/core/Mage/Core/Model/App.php b/app/code/core/Mage/Core/Model/App.php
index ffd9a848ff..0c8556c68f 100644
--- a/app/code/core/Mage/Core/Model/App.php
+++ b/app/code/core/Mage/Core/Model/App.php
@@ -286,7 +286,8 @@ public function baseInit($options)
$this->_config->setOptions($options);
$this->_initBaseConfig();
- $this->_initCache();
+ $cacheInitOptions = is_array($options) && array_key_exists('cache', $options) ? $options['cache'] : array();
+ $this->_initCache($cacheInitOptions);
return $this;
}
@@ -329,6 +330,7 @@ public function run($params)
{
$options = isset($params['options']) ? $params['options'] : array();
$this->baseInit($options);
+ Mage::register('application_params', $params);
if ($this->_cache->processRequest()) {
$this->getResponse()->sendResponse();
@@ -378,9 +380,10 @@ protected function _initBaseConfig()
/**
* Initialize application cache instance
*
+ * @param array $cacheInitOptions
* @return Mage_Core_Model_App
*/
- protected function _initCache()
+ protected function _initCache(array $cacheInitOptions = array())
{
$this->_isCacheLocked = true;
$options = $this->_config->getNode('global/cache');
@@ -389,6 +392,7 @@ protected function _initCache()
} else {
$options = array();
}
+ $options = array_merge($options, $cacheInitOptions);
$this->_cache = Mage::getModel('core/cache', $options);
$this->_isCacheLocked = false;
return $this;
diff --git a/app/code/core/Mage/Core/Model/Cache.php b/app/code/core/Mage/Core/Model/Cache.php
index 9bb3eb643a..f2a9cc8e8b 100644
--- a/app/code/core/Mage/Core/Model/Cache.php
+++ b/app/code/core/Mage/Core/Model/Cache.php
@@ -83,6 +83,13 @@ class Mage_Core_Model_Cache
*/
protected $_requestProcessors = array();
+ /**
+ * Disallow cache saving
+ *
+ * @var bool
+ */
+ protected $_disallowSave = false;
+
/**
* List of allowed cache options
*
@@ -119,6 +126,10 @@ public function __construct(array $options = array())
if (isset($options['request_processors'])) {
$this->_requestProcessors = $options['request_processors'];
}
+
+ if (isset($options['disallow_save'])) {
+ $this->_disallowSave = $options['disallow_save'];
+ }
}
/**
@@ -150,7 +161,7 @@ protected function _getBackendOptions(array $cacheOptions)
$options = $cacheOptions['memcached'];
}
$enable2levels = true;
- $backendType = 'Memcached';
+ $backendType = 'Varien_Cache_Backend_Memcached';
}
break;
case 'apc':
@@ -281,7 +292,8 @@ protected function _getFrontendOptions(array $cacheOptions)
$options['caching'] = true;
}
if (!array_key_exists('lifetime', $options)) {
- $options['lifetime'] = isset($cacheOptions['lifetime']) ? $cacheOptions['lifetime'] : self::DEFAULT_LIFETIME;
+ $options['lifetime'] = isset($cacheOptions['lifetime']) ? $cacheOptions['lifetime']
+ : self::DEFAULT_LIFETIME;
}
if (!array_key_exists('automatic_cleaning_factor', $options)) {
$options['automatic_cleaning_factor'] = 0;
@@ -356,6 +368,9 @@ public function save($data, $id, $tags=array(), $lifeTime=null)
if (!in_array(Mage_Core_Model_Config::CACHE_TAG, $tags)) {
$tags[] = Mage_Core_Model_App::CACHE_TAG;
}
+ if ($this->_disallowSave) {
+ return true;
+ }
return $this->_frontend->save((string)$data, $this->_id($id), $this->_tags($tags), $lifeTime);
}
diff --git a/app/code/core/Mage/Core/Model/Resource.php b/app/code/core/Mage/Core/Model/Resource.php
index c4ce790f78..1e286060d7 100644
--- a/app/code/core/Mage/Core/Model/Resource.php
+++ b/app/code/core/Mage/Core/Model/Resource.php
@@ -332,9 +332,10 @@ public function getMappedTableName($tableName)
*/
public function cleanDbRow(&$row)
{
+ $zeroDate = $this->getConnection(self::DEFAULT_READ_RESOURCE)->getSuggestedZeroDate();
if (!empty($row) && is_array($row)) {
foreach ($row as $key=>&$value) {
- if (is_string($value) && $value === '0000-00-00 00:00:00') {
+ if (is_string($value) && $value === $zeroDate) {
$value = '';
}
}
diff --git a/app/code/core/Mage/Core/Model/Resource/Db/Abstract.php b/app/code/core/Mage/Core/Model/Resource/Db/Abstract.php
index fd76ed8b04..3a08d1db28 100644
--- a/app/code/core/Mage/Core/Model/Resource/Db/Abstract.php
+++ b/app/code/core/Mage/Core/Model/Resource/Db/Abstract.php
@@ -618,7 +618,7 @@ protected function _prepareValueForSave($value, $type)
/**
* Check for unique values existence
-
+ *
* @param Varien_Object $object
* @return Mage_Core_Model_Resource_Db_Abstract
* @throws Mage_Core_Exception
@@ -645,17 +645,18 @@ protected function _checkUnique(Mage_Core_Model_Abstract $object)
if (is_array($unique['field'])) {
foreach ($unique['field'] as $field) {
- $select->where($field.'=?', $data->getData($field));
+ $select->where($field . '=?', trim($data->getData($field)));
}
} else {
- $select->where( $unique['field'] . ' = ?', $data->getData($unique['field']) );
+ $select->where($unique['field'] . '=?', trim($data->getData($unique['field'])));
}
if ($object->getId()) {
- $select->where($this->getIdFieldName().' != ?', $object->getId());
+ $select->where($this->getIdFieldName() . '!=?', $object->getId());
}
- if ( $test = $this->_getWriteAdapter()->fetchRow($select) ) {
+ $test = $this->_getWriteAdapter()->fetchRow($select);
+ if ($test) {
$existent[] = $unique['title'];
}
}
diff --git a/app/code/core/Mage/Core/Model/Resource/Email/Template.php b/app/code/core/Mage/Core/Model/Resource/Email/Template.php
index a431a53aac..e8f504c23b 100644
--- a/app/code/core/Mage/Core/Model/Resource/Email/Template.php
+++ b/app/code/core/Mage/Core/Model/Resource/Email/Template.php
@@ -73,13 +73,17 @@ public function checkCodeUsage(Mage_Core_Model_Email_Template $template)
if ($template->getTemplateActual() != 0 || is_null($template->getTemplateActual())) {
$select = $this->_getReadAdapter()->select()
->from($this->getMainTable(), 'COUNT(*)')
- ->where('template_id != :template_id')
->where('template_code = :template_code');
-
$bind = array(
- 'template_id' => $template->getId(),
'template_code' => $template->getTemplateCode()
);
+
+ $templateId = $template->getId();
+ if ($templateId) {
+ $select->where('template_id != :template_id');
+ $bind['template_id'] = $templateId;
+ }
+
$result = $this->_getReadAdapter()->fetchOne($select, $bind);
if ($result) {
return true;
diff --git a/app/code/core/Mage/Core/Model/Resource/Store/Group/Collection.php b/app/code/core/Mage/Core/Model/Resource/Store/Group/Collection.php
index 8d76c4672d..d046909fc8 100644
--- a/app/code/core/Mage/Core/Model/Resource/Store/Group/Collection.php
+++ b/app/code/core/Mage/Core/Model/Resource/Store/Group/Collection.php
@@ -98,7 +98,7 @@ public function _beforeLoad()
$this->setWithoutDefaultFilter();
}
$this->addOrder('main_table.name', self::SORT_ORDER_ASC);
- return $this;
+ return parent::_beforeLoad();
}
/**
diff --git a/app/code/core/Mage/Core/Model/Session/Abstract.php b/app/code/core/Mage/Core/Model/Session/Abstract.php
index a0797a9801..d705cb1aae 100644
--- a/app/code/core/Mage/Core/Model/Session/Abstract.php
+++ b/app/code/core/Mage/Core/Model/Session/Abstract.php
@@ -539,7 +539,7 @@ public function getSessionSaveMethod()
}
/**
- * Get sesssion save path
+ * Get session save path
*
* @return string
*/
diff --git a/app/code/core/Mage/Core/Model/Source/Email/Variables.php b/app/code/core/Mage/Core/Model/Source/Email/Variables.php
index 64d81777d2..de9b35cb59 100644
--- a/app/code/core/Mage/Core/Model/Source/Email/Variables.php
+++ b/app/code/core/Mage/Core/Model/Source/Email/Variables.php
@@ -34,6 +34,11 @@
*/
class Mage_Core_Model_Source_Email_Variables
{
+ /**
+ * Assoc array of configuration variables
+ *
+ * @var array
+ */
protected $_configVariables = array();
/**
@@ -42,20 +47,61 @@ class Mage_Core_Model_Source_Email_Variables
*/
public function __construct()
{
+ $helper = Mage::helper('core');
$this->_configVariables = array(
- array('value' => Mage_Core_Model_Url::XML_PATH_UNSECURE_URL, 'label' => 'Base Unsecure URL'),
- array('value' => Mage_Core_Model_Url::XML_PATH_SECURE_URL, 'label' => 'Base Secure URL'),
- array('value' => 'trans_email/ident_general/name', 'label' => 'General Contact Name'),
- array('value' => 'trans_email/ident_general/email', 'label' => 'General Contact Email'),
- array('value' => 'trans_email/ident_sales/name', 'label' => 'Sales Representative Contact Name'),
- array('value' => 'trans_email/ident_sales/email', 'label' => 'Sales Representative Contact Email'),
- array('value' => 'trans_email/ident_custom1/name', 'label' => 'Custom1 Contact Name'),
- array('value' => 'trans_email/ident_custom1/email', 'label' => 'Custom1 Contact Email'),
- array('value' => 'trans_email/ident_custom2/name', 'label' => 'Custom2 Contact Name'),
- array('value' => 'trans_email/ident_custom2/email', 'label' => 'Custom2 Contact Email'),
- array('value' => 'general/store_information/name', 'label' => 'Store Name'),
- array('value' => 'general/store_information/phone', 'label' => 'Store Contact Telephone'),
- array('value' => 'general/store_information/address', 'label' => 'Store Contact Address'));
+ array(
+ 'value' => Mage_Core_Model_Url::XML_PATH_UNSECURE_URL,
+ 'label' => $helper->__('Base Unsecure URL')
+ ),
+ array(
+ 'value' => Mage_Core_Model_Url::XML_PATH_SECURE_URL,
+ 'label' => $helper->__('Base Secure URL')
+ ),
+ array(
+ 'value' => 'trans_email/ident_general/name',
+ 'label' => $helper->__('General Contact Name')
+ ),
+ array(
+ 'value' => 'trans_email/ident_general/email',
+ 'label' => $helper->__('General Contact Email')
+ ),
+ array(
+ 'value' => 'trans_email/ident_sales/name',
+ 'label' => $helper->__('Sales Representative Contact Name')
+ ),
+ array(
+ 'value' => 'trans_email/ident_sales/email',
+ 'label' => $helper->__('Sales Representative Contact Email')
+ ),
+ array(
+ 'value' => 'trans_email/ident_custom1/name',
+ 'label' => $helper->__('Custom1 Contact Name')
+ ),
+ array(
+ 'value' => 'trans_email/ident_custom1/email',
+ 'label' => $helper->__('Custom1 Contact Email')
+ ),
+ array(
+ 'value' => 'trans_email/ident_custom2/name',
+ 'label' => $helper->__('Custom2 Contact Name')
+ ),
+ array(
+ 'value' => 'trans_email/ident_custom2/email',
+ 'label' => $helper->__('Custom2 Contact Email')
+ ),
+ array(
+ 'value' => 'general/store_information/name',
+ 'label' => $helper->__('Store Name')
+ ),
+ array(
+ 'value' => 'general/store_information/phone',
+ 'label' => $helper->__('Store Contact Telephone')
+ ),
+ array(
+ 'value' => 'general/store_information/address',
+ 'label' => $helper->__('Store Contact Address')
+ )
+ );
}
/**
diff --git a/app/code/core/Mage/Core/Model/Store.php b/app/code/core/Mage/Core/Model/Store.php
index 06fc61f507..4c1279123b 100644
--- a/app/code/core/Mage/Core/Model/Store.php
+++ b/app/code/core/Mage/Core/Model/Store.php
@@ -24,7 +24,6 @@
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-
/**
* Store model
*
@@ -44,11 +43,16 @@
*/
class Mage_Core_Model_Store extends Mage_Core_Model_Abstract
{
+ /**
+ * Entity name
+ */
const ENTITY = 'core_store';
+ /**
+ * Configuration pathes
+ */
const XML_PATH_STORE_STORE_NAME = 'general/store_information/name';
const XML_PATH_STORE_STORE_PHONE = 'general/store_information/phone';
-
const XML_PATH_STORE_IN_URL = 'web/url/use_store';
const XML_PATH_USE_REWRITES = 'web/seo/use_rewrites';
const XML_PATH_UNSECURE_BASE_URL = 'web/unsecure/base_url';
@@ -57,11 +61,18 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract
const XML_PATH_SECURE_IN_ADMINHTML = 'web/secure/use_in_adminhtml';
const XML_PATH_SECURE_BASE_LINK_URL = 'web/secure/base_link_url';
const XML_PATH_UNSECURE_BASE_LINK_URL = 'web/unsecure/base_link_url';
-
+ const XML_PATH_OFFLOADER_HEADER = 'web/secure/offloader_header';
const XML_PATH_PRICE_SCOPE = 'catalog/price/scope';
+
+ /**
+ * Price scope constants
+ */
const PRICE_SCOPE_GLOBAL = 0;
const PRICE_SCOPE_WEBSITE = 1;
+ /**
+ * Possible URL types
+ */
const URL_TYPE_LINK = 'link';
const URL_TYPE_DIRECT_LINK = 'direct_link';
const URL_TYPE_WEB = 'web';
@@ -69,11 +80,20 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract
const URL_TYPE_JS = 'js';
const URL_TYPE_MEDIA = 'media';
+ /**
+ * Code constants
+ */
const DEFAULT_CODE = 'default';
const ADMIN_CODE = 'admin';
+ /**
+ * Cache tag
+ */
const CACHE_TAG = 'store';
+ /**
+ * Cookie name
+ */
const COOKIE_NAME = 'store';
/**
@@ -81,18 +101,32 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract
*/
const MEDIA_REWRITE_SCRIPT = 'get.php/';
+ /**
+ * Cache flag
+ *
+ * @var boolean
+ */
protected $_cacheTag = true;
/**
+ * Event prefix for model events
+ *
* @var string
*/
protected $_eventPrefix = 'store';
/**
+ * Event object name
+ *
* @var string
*/
protected $_eventObject = 'store';
+ /**
+ * Price filter
+ *
+ * @var Mage_Directory_Model_Currency_Filter
+ */
protected $_priceFilter;
/**
@@ -109,27 +143,79 @@ class Mage_Core_Model_Store extends Mage_Core_Model_Abstract
*/
protected $_group;
+ /**
+ * Store configuration cache
+ *
+ * @var array|null
+ */
protected $_configCache = null;
+
+ /**
+ * Base nodes of store configuration cache
+ *
+ * @var array
+ */
protected $_configCacheBaseNodes = array();
+ /**
+ * Directory cache
+ *
+ * @var array
+ */
protected $_dirCache = array();
+ /**
+ * URL cache
+ *
+ * @var array
+ */
protected $_urlCache = array();
+ /**
+ * Base URL cache
+ *
+ * @var array
+ */
protected $_baseUrlCache = array();
+ /**
+ * Session entity
+ *
+ * @var Mage_Core_Model_Session_Abstract
+ */
protected $_session;
+ /**
+ * Flag that shows that backend URLs are secure
+ *
+ * @var boolean|null
+ */
protected $_isAdminSecure = null;
+
+ /**
+ * Flag that shows that frontend URLs are secure
+ *
+ * @var boolean|null
+ */
protected $_isFrontSecure = null;
+ /**
+ * Store frontend name
+ *
+ * @var string|null
+ */
protected $_frontendName = null;
/**
+ * Readonly flag
+ *
* @var bool
*/
private $_isReadOnly = false;
+ /**
+ * Initialize object
+ */
protected function _construct()
{
$this->_init('core/store');
@@ -186,8 +272,8 @@ public function load($id, $field=null)
public function loadConfig($code)
{
if (is_numeric($code)) {
- foreach (Mage::getConfig()->getNode()->stores->children() as $storeCode=>$store) {
- if ((int)$store->system->store->id==$code) {
+ foreach (Mage::getConfig()->getNode()->stores->children() as $storeCode => $store) {
+ if ((int) $store->system->store->id == $code) {
$code = $storeCode;
break;
}
@@ -197,9 +283,9 @@ public function loadConfig($code)
}
if (!empty($store)) {
$this->setCode($code);
- $id = (int)$store->system->store->id;
+ $id = (int) $store->system->store->id;
$this->setId($id)->setStoreId($id);
- $this->setWebsiteId((int)$store->system->website->id);
+ $this->setWebsiteId((int) $store->system->website->id);
}
return $this;
}
@@ -241,13 +327,13 @@ public function getConfig($path)
/**
* Initialize base store configuration data
+ *
* Method provide cache configuration data without loading store config XML
*
* @return Mage_Core_Model_Config
*/
public function initConfigCache()
{
-// return $this;
/**
* Funtionality related with config separation
*/
@@ -264,11 +350,10 @@ public function initConfigCache()
foreach ($this->_configCacheBaseNodes as $node) {
$data[$node] = $this->getConfig($node);
}
- Mage::app()->saveCache(
- serialize($data),
- $cacheId,
- array(self::CACHE_TAG, Mage_Core_Model_Config::CACHE_TAG)
- );
+ Mage::app()->saveCache(serialize($data), $cacheId, array(
+ self::CACHE_TAG,
+ Mage_Core_Model_Config::CACHE_TAG
+ ));
}
$this->_configCache = $data;
}
@@ -279,6 +364,7 @@ public function initConfigCache()
/**
* Set config value for CURRENT model
+ *
* This value don't save in config
*
* @param string $path
@@ -290,7 +376,7 @@ public function setConfig($path, $value)
if (isset($this->_configCache[$path])) {
$this->_configCache[$path] = $value;
}
- $fullPath = 'stores/'.$this->getCode().'/'.$path;
+ $fullPath = 'stores/' . $this->getCode() . '/' . $path;
Mage::getConfig()->setNode($fullPath, $value);
return $this;
@@ -323,7 +409,7 @@ public function getWebsite()
}
/**
- * Enter description here...
+ * Process config value
*
* @param string $fullPath
* @param string $path
@@ -338,26 +424,26 @@ protected function _processConfigValue($fullPath, $path, $node)
if ($node->hasChildren()) {
$aValue = array();
- foreach ($node->children() as $k=>$v) {
- $aValue[$k] = $this->_processConfigValue($fullPath.'/'.$k, $path.'/'.$k, $v);
+ foreach ($node->children() as $k => $v) {
+ $aValue[$k] = $this->_processConfigValue($fullPath . '/' . $k, $path . '/' . $k, $v);
}
$this->_configCache[$path] = $aValue;
return $aValue;
}
- $sValue = (string)$node;
+ $sValue = (string) $node;
if (!empty($node['backend_model']) && !empty($sValue)) {
- $backend = Mage::getModel((string)$node['backend_model']);
+ $backend = Mage::getModel((string) $node['backend_model']);
$backend->setPath($path)->setValue($sValue)->afterLoad();
$sValue = $backend->getValue();
}
- if (is_string($sValue) && strpos($sValue, '{{')!==false) {
- if (strpos($sValue, '{{unsecure_base_url}}')!==false) {
- $unsecureBaseUrl = $this->getConfig('web/unsecure/base_url');
+ if (is_string($sValue) && strpos($sValue, '{{') !== false) {
+ if (strpos($sValue, '{{unsecure_base_url}}') !== false) {
+ $unsecureBaseUrl = $this->getConfig(self::XML_PATH_UNSECURE_BASE_URL);
$sValue = str_replace('{{unsecure_base_url}}', $unsecureBaseUrl, $sValue);
- } elseif (strpos($sValue, '{{secure_base_url}}')!==false) {
- $secureBaseUrl = $this->getConfig('web/secure/base_url');
+ } elseif (strpos($sValue, '{{secure_base_url}}') !== false) {
+ $secureBaseUrl = $this->getConfig(self::XML_PATH_SECURE_BASE_URL);
$sValue = str_replace('{{secure_base_url}}', $secureBaseUrl, $sValue);
} elseif (strpos($sValue, '{{base_url}}') === false) {
$sValue = Mage::getConfig()->substDistroServerVars($sValue);
@@ -383,11 +469,11 @@ public function processSubst($value)
}
if (strpos($value, '{{unsecure_base_url}}') !== false) {
- $unsecureBaseUrl = $this->getConfig('web/unsecure/base_url');
+ $unsecureBaseUrl = $this->getConfig(self::XML_PATH_UNSECURE_BASE_URL);
$value = str_replace('{{unsecure_base_url}}', $unsecureBaseUrl, $value);
} elseif (strpos($value, '{{secure_base_url}}') !== false) {
- $secureBaseUrl = $this->getConfig('web/secure/base_url');
+ $secureBaseUrl = $this->getConfig(self::XML_PATH_SECURE_BASE_URL);
$value = str_replace('{{secure_base_url}}', $secureBaseUrl, $value);
} elseif (strpos($value, '{{') !== false && strpos($value, '{{base_url}}') === false) {
$value = Mage::getConfig()->substDistroServerVars($value);
@@ -395,12 +481,17 @@ public function processSubst($value)
return $value;
}
+ /**
+ * Retrieve default base path
+ *
+ * @return string
+ */
public function getDefaultBasePath()
{
if (!isset($_SERVER['SCRIPT_NAME'])) {
return '/';
}
- return rtrim(Mage::app()->getRequest()->getBasePath().'/').'/';
+ return rtrim(Mage::app()->getRequest()->getBasePath() . '/') . '/';
}
/**
@@ -412,7 +503,7 @@ public function getDefaultBasePath()
*/
public function getUrl($route = '', $params = array())
{
- /* @var $url Mage_Core_Model_Url */
+ /** @var $url Mage_Core_Model_Url */
$url = Mage::getModel('core/url')
->setStore($this);
if (Mage::app()->getStore()->getId() != $this->getId()) {
@@ -422,33 +513,40 @@ public function getUrl($route = '', $params = array())
return $url->getUrl($route, $params);
}
+ /**
+ * Retrieve base URL
+ *
+ * @param string $type
+ * @param boolean|null $secure
+ * @return string
+ */
public function getBaseUrl($type = self::URL_TYPE_LINK, $secure = null)
{
- $cacheKey = $type.'/'.(is_null($secure) ? 'null' : ($secure ? 'true' : 'false'));
+ $cacheKey = $type . '/' . (is_null($secure) ? 'null' : ($secure ? 'true' : 'false'));
if (!isset($this->_baseUrlCache[$cacheKey])) {
switch ($type) {
case self::URL_TYPE_WEB:
$secure = is_null($secure) ? $this->isCurrentlySecure() : (bool)$secure;
- $url = $this->getConfig('web/'.($secure ? 'secure' : 'unsecure').'/base_url');
+ $url = $this->getConfig('web/' . ($secure ? 'secure' : 'unsecure') . '/base_url');
break;
case self::URL_TYPE_LINK:
- $secure = (bool)$secure;
- $url = $this->getConfig('web/'.($secure ? 'secure' : 'unsecure').'/base_link_url');
+ $secure = (bool) $secure;
+ $url = $this->getConfig('web/' . ($secure ? 'secure' : 'unsecure') . '/base_link_url');
$url = $this->_updatePathUseRewrites($url);
$url = $this->_updatePathUseStoreView($url);
break;
case self::URL_TYPE_DIRECT_LINK:
- $secure = (bool)$secure;
- $url = $this->getConfig('web/'.($secure ? 'secure' : 'unsecure').'/base_link_url');
+ $secure = (bool) $secure;
+ $url = $this->getConfig('web/' . ($secure ? 'secure' : 'unsecure') . '/base_link_url');
$url = $this->_updatePathUseRewrites($url);
break;
case self::URL_TYPE_SKIN:
case self::URL_TYPE_JS:
- $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool)$secure;
- $url = $this->getConfig('web/'.($secure ? 'secure' : 'unsecure').'/base_'.$type.'_url');
+ $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool) $secure;
+ $url = $this->getConfig('web/' . ($secure ? 'secure' : 'unsecure') . '/base_' . $type . '_url');
break;
case self::URL_TYPE_MEDIA:
@@ -480,14 +578,16 @@ protected function _updatePathUseRewrites($url)
{
if ($this->isAdmin()
|| !$this->getConfig(self::XML_PATH_USE_REWRITES)
- || !Mage::isInstalled()) {
- $url .= basename($_SERVER['SCRIPT_FILENAME']).'/';
+ || !Mage::isInstalled()
+ ) {
+ $url .= basename($_SERVER['SCRIPT_FILENAME']) . '/';
}
return $url;
}
/**
- * Gets URL for media catalog.
+ * Retrieve URL for media catalog
+ *
* If we use Database file storage and server doesn't support rewrites (.htaccess in media folder)
* we have to put name of fetching media script exactly into URL
*
@@ -495,15 +595,15 @@ protected function _updatePathUseRewrites($url)
* @param string $type
* @return string
*/
- protected function _updateMediaPathUseRewrites($secure=null, $type = self::URL_TYPE_MEDIA)
+ protected function _updateMediaPathUseRewrites($secure = null, $type = self::URL_TYPE_MEDIA)
{
- $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool)$secure;
+ $secure = is_null($secure) ? $this->isCurrentlySecure() : (bool) $secure;
$secureStringFlag = $secure ? 'secure' : 'unsecure';
- $url = $this->getConfig('web/' . $secureStringFlag . '/base_' . $type . '_url');
+ $url = $this->getConfig('web/' . $secureStringFlag . '/base_' . $type . '_url');
if (!$this->getConfig(self::XML_PATH_USE_REWRITES)
- && Mage::helper('core/file_storage_database')->checkDbUsage()) {
-
- $urlStart = $this->getConfig('web/' . $secureStringFlag . '/base_url');
+ && Mage::helper('core/file_storage_database')->checkDbUsage()
+ ) {
+ $urlStart = $this->getConfig('web/' . $secureStringFlag . '/base_url');
$url = str_replace($urlStart, $urlStart . self::MEDIA_REWRITE_SCRIPT, $url);
}
return $url;
@@ -554,46 +654,66 @@ public function isAdmin()
}
+ /**
+ * Check if backend URLs should be secure
+ *
+ * @return boolean
+ */
public function isAdminUrlSecure()
{
if ($this->_isAdminSecure === null) {
- $this->_isAdminSecure = Mage::getStoreConfigFlag(
- Mage_Core_Model_Url::XML_PATH_SECURE_IN_ADMIN,
- $this->getId()
- );
+ $this->_isAdminSecure = (boolean) (int) (string) Mage::getConfig()
+ ->getNode(Mage_Core_Model_Url::XML_PATH_SECURE_IN_ADMIN);
}
return $this->_isAdminSecure;
}
+ /**
+ * Check if forntend URLs should be secure
+ *
+ * @return boolean
+ */
public function isFrontUrlSecure()
{
if ($this->_isFrontSecure === null) {
- $this->_isFrontSecure = Mage::getStoreConfigFlag(
- Mage_Core_Model_Url::XML_PATH_SECURE_IN_FRONT,
- $this->getId()
- );
+ $this->_isFrontSecure = Mage::getStoreConfigFlag(Mage_Core_Model_Url::XML_PATH_SECURE_IN_FRONT,
+ $this->getId());
}
return $this->_isFrontSecure;
}
+ /**
+ * Check if request was secure
+ *
+ * @return boolean
+ */
public function isCurrentlySecure()
{
- $standardRule = !empty($_SERVER['HTTPS']) && 'off' != $_SERVER['HTTPS'];
- $offloaderHeader = trim(Mage::getStoreConfig('web/secure/offloader_header'));
+ $standardRule = !empty($_SERVER['HTTPS']) && ('off' != $_SERVER['HTTPS']);
+ $offloaderHeader = trim((string) Mage::getConfig()->getNode(self::XML_PATH_OFFLOADER_HEADER, 'default'));
if ((!empty($offloaderHeader) && !empty($_SERVER[$offloaderHeader])) || $standardRule) {
return true;
}
if (Mage::isInstalled()) {
- $secureBaseUrl = Mage::getStoreConfig('web/secure/base_route_url');
+ $secureBaseUrl = '';
+ if (!$this->isAdmin()) {
+ $secureBaseUrl = Mage::getStoreConfig(Mage_Core_Model_Url::XML_PATH_SECURE_URL);
+ } else {
+ $secureBaseUrl = (string) Mage::getConfig()
+ ->getNode(Mage_Core_Model_Url::XML_PATH_SECURE_URL, 'default');
+ }
+
if (!$secureBaseUrl) {
return false;
}
+
$uri = Zend_Uri::factory($secureBaseUrl);
- $isSecure = ($uri->getScheme() == 'https' )
+ $port = $uri->getPort();
+ $isSecure = ($uri->getScheme() == 'https')
&& isset($_SERVER['SERVER_PORT'])
- && ($uri->getPort() == $_SERVER['SERVER_PORT']);
+ && ($port == $_SERVER['SERVER_PORT']);
return $isSecure;
} else {
$isSecure = isset($_SERVER['SERVER_PORT']) && (443 == $_SERVER['SERVER_PORT']);
@@ -767,6 +887,11 @@ public function getCurrentCurrency()
return $currency;
}
+ /**
+ * Retrieve current currency rate
+ *
+ * @return float
+ */
public function getCurrentCurrencyRate()
{
return $this->getBaseCurrency()->getRate($this->getCurrentCurrency());
@@ -780,7 +905,7 @@ public function getCurrentCurrencyRate()
* @param boolean $includeContainer Enclose into
* @return double
*/
- public function convertPrice($price, $format=false, $includeContainer = true)
+ public function convertPrice($price, $format = false, $includeContainer = true)
{
if ($this->getCurrentCurrency() && $this->getBaseCurrency()) {
$value = $this->getBaseCurrency()->convert($price, $this->getCurrentCurrency());
@@ -843,7 +968,7 @@ public function getPriceFilter()
}
/**
- * Enter description here...
+ * Retrieve root category identifier
*
* @return int
*/
@@ -881,21 +1006,41 @@ public function getGroup()
return $this->_group;
}
+ /**
+ * Retrieve website identifier
+ *
+ * @return string|int|null
+ */
public function getWebsiteId()
{
return $this->_getData('website_id');
}
+ /**
+ * Retrieve group identifier
+ *
+ * @return string|int|null
+ */
public function getGroupId()
{
return $this->_getData('group_id');
}
+ /**
+ * Retrieve default group identifier
+ *
+ * @return string|int|null
+ */
public function getDefaultGroupId()
{
return $this->_getData('default_group_id');
}
+ /**
+ * Check if store can be deleted
+ *
+ * @return boolean
+ */
public function isCanDelete()
{
if (!$this->getId()) {
@@ -918,8 +1063,8 @@ public function getCurrentUrl($fromStore = true)
ltrim(Mage::app()->getRequest()->getRequestString(), '/'));
$storeUrl = Mage::app()->getStore()->isCurrentlySecure()
- ? $this->getUrl('', array('_secure' => true))
- : $this->getUrl('');
+ ? $this->getUrl('', array('_secure' => true))
+ : $this->getUrl('');
$storeParsedUrl = parse_url($storeUrl);
$storeParsedQuery = array();
@@ -951,11 +1096,21 @@ public function getCurrentUrl($fromStore = true)
. ($storeParsedQuery ? '?'.http_build_query($storeParsedQuery, '', '&') : '');
}
+ /**
+ * Check if store is active
+ *
+ * @return boolean|null
+ */
public function getIsActive()
{
return $this->_getData('is_active');
}
+ /**
+ * Retrieve store name
+ *
+ * @return string|null
+ */
public function getName()
{
return $this->_getData('name');
@@ -963,6 +1118,7 @@ public function getName()
/**
* Protect delete from non admin area
+ *
* Register indexing event before delete store
*
* @return Mage_Core_Model_Store
@@ -970,9 +1126,7 @@ public function getName()
protected function _beforeDelete()
{
$this->_protectFromNonAdmin();
- Mage::getSingleton('index/indexer')->logEvent(
- $this, self::ENTITY, Mage_Index_Model_Event::TYPE_DELETE
- );
+ Mage::getSingleton('index/indexer')->logEvent($this, self::ENTITY, Mage_Index_Model_Event::TYPE_DELETE);
return parent::_beforeDelete();
}
@@ -996,9 +1150,8 @@ protected function _afterDelete()
protected function _afterDeleteCommit()
{
parent::_afterDeleteCommit();
- Mage::getSingleton('index/indexer')->indexEvents(
- self::ENTITY, Mage_Index_Model_Event::TYPE_DELETE
- );
+ Mage::getSingleton('index/indexer')->indexEvents(self::ENTITY, Mage_Index_Model_Event::TYPE_DELETE);
+ return $this;
}
/**
@@ -1026,7 +1179,7 @@ public function resetConfig()
public function isReadOnly($value = null)
{
if (null !== $value) {
- $this->_isReadOnly = (bool)$value;
+ $this->_isReadOnly = (bool) $value;
}
return $this->_isReadOnly;
}
@@ -1039,7 +1192,7 @@ public function isReadOnly($value = null)
public function getFrontendName()
{
if (is_null($this->_frontendName)) {
- $storeGroupName = (string)Mage::getStoreConfig('general/store_information/name', $this);
+ $storeGroupName = (string) Mage::getStoreConfig('general/store_information/name', $this);
$this->_frontendName = (!empty($storeGroupName)) ? $storeGroupName : $this->getGroup()->getName();
}
return $this->_frontendName;
diff --git a/app/code/core/Mage/Core/Model/Store/Api.php b/app/code/core/Mage/Core/Model/Store/Api.php
new file mode 100644
index 0000000000..3271c070ad
--- /dev/null
+++ b/app/code/core/Mage/Core/Model/Store/Api.php
@@ -0,0 +1,96 @@
+
+ */
+
+class Mage_Core_Model_Store_Api extends Mage_Api_Model_Resource_Abstract
+{
+ /**
+ * Retrieve stores list
+ *
+ * @return array
+ */
+ public function items()
+ {
+ // Retrieve stores
+ $stores = Mage::app()->getStores();
+
+ // Make result array
+ $result = array();
+ foreach ($stores as $store) {
+ $result[] = array(
+ 'store_id' => $store->getId(),
+ 'code' => $store->getCode(),
+ 'website_id' => $store->getWebsiteId(),
+ 'group_id' => $store->getGroupId(),
+ 'name' => $store->getName(),
+ 'sort_order' => $store->getSortOrder(),
+ 'is_active' => $store->getIsActive()
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * Retrieve store data
+ *
+ * @param string|int $storeId
+ * @return array
+ */
+ public function info($storeId)
+ {
+ // Retrieve store info
+ try {
+ $store = Mage::app()->getStore($storeId);
+ } catch (Mage_Core_Model_Store_Exception $e) {
+ $this->_fault('store_not_exists');
+ }
+
+ if (!$store->getId()) {
+ $this->_fault('store_not_exists');
+ }
+
+ // Basic store data
+ $result = array();
+ $result['store_id'] = $store->getId();
+ $result['code'] = $store->getCode();
+ $result['website_id'] = $store->getWebsiteId();
+ $result['group_id'] = $store->getGroupId();
+ $result['name'] = $store->getName();
+ $result['sort_order'] = $store->getSortOrder();
+ $result['is_active'] = $store->getIsActive();
+
+ return $result;
+ }
+
+}
diff --git a/app/code/community/Find/Feed/Model/Mysql4/Setup.php b/app/code/core/Mage/Core/Model/Store/Api/V2.php
old mode 100755
new mode 100644
similarity index 78%
rename from app/code/community/Find/Feed/Model/Mysql4/Setup.php
rename to app/code/core/Mage/Core/Model/Store/Api/V2.php
index 4d79d56f16..1e08e5ca00
--- a/app/code/community/Find/Feed/Model/Mysql4/Setup.php
+++ b/app/code/core/Mage/Core/Model/Store/Api/V2.php
@@ -18,19 +18,19 @@
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
- * @category
- * @package _storage
+ * @category Mage
+ * @package Mage_Core
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
/**
- * Thefind feed module setup
+ * Directory Country Api V2
*
- * @category Find
- * @package Find_Feed
+ * @category Mage
+ * @package Mage_Core
+ * @author Magento Core Team
*/
-class Find_Feed_Model_Mysql4_Setup extends Mage_Catalog_Model_Resource_Eav_Mysql4_Setup
+class Mage_Core_Model_Store_Api_V2 extends Mage_Core_Model_Store_Api
{
}
-
diff --git a/app/code/core/Mage/Core/Model/Url.php b/app/code/core/Mage/Core/Model/Url.php
index 5414afcdc3..63bd855343 100644
--- a/app/code/core/Mage/Core/Model/Url.php
+++ b/app/code/core/Mage/Core/Model/Url.php
@@ -78,16 +78,36 @@
*/
class Mage_Core_Model_Url extends Varien_Object
{
+ /**
+ * Default controller name
+ */
const DEFAULT_CONTROLLER_NAME = 'index';
+
+ /**
+ * Default action name
+ */
const DEFAULT_ACTION_NAME = 'index';
+ /**
+ * Configuration pathes
+ */
const XML_PATH_UNSECURE_URL = 'web/unsecure/base_url';
const XML_PATH_SECURE_URL = 'web/secure/base_url';
-
- const XML_PATH_SECURE_IN_ADMIN = 'web/secure/use_in_adminhtml';
+ const XML_PATH_SECURE_IN_ADMIN = 'default/web/secure/use_in_adminhtml';
const XML_PATH_SECURE_IN_FRONT = 'web/secure/use_in_frontend';
+ /**
+ * Configuration data cache
+ *
+ * @var array
+ */
static protected $_configDataCache;
+
+ /**
+ * Encrypted session identifier
+ *
+ * @var string|null
+ */
static protected $_encryptedSessionId;
/**
@@ -115,6 +135,9 @@ class Mage_Core_Model_Url extends Varien_Object
*/
protected $_useSession;
+ /**
+ * Initailize object
+ */
protected function _construct()
{
$this->setStore(null);
@@ -128,18 +151,18 @@ protected function _construct()
*/
public function parseUrl($url)
{
- $data = parse_url($url);
- $parts = array(
- 'scheme'=>'setScheme',
- 'host' =>'setHost',
- 'port' =>'setPort',
- 'user' =>'setUser',
- 'pass' =>'setPassword',
- 'path' =>'setPath',
- 'query' =>'setQuery',
- 'fragment'=>'setFragment');
-
- foreach ($parts as $component=>$method) {
+ $data = parse_url($url);
+ $parts = array(
+ 'scheme' => 'setScheme',
+ 'host' => 'setHost',
+ 'port' => 'setPort',
+ 'user' => 'setUser',
+ 'pass' => 'setPassword',
+ 'path' => 'setPath',
+ 'query' => 'setQuery',
+ 'fragment' => 'setFragment');
+
+ foreach ($parts as $component => $method) {
if (isset($data[$component])) {
$this->$method($data[$component]);
}
@@ -157,6 +180,12 @@ public function getDefaultControllerName()
return self::DEFAULT_CONTROLLER_NAME;
}
+ /**
+ * Set use_url_cache flag
+ *
+ * @param boolean $flag
+ * @return Mage_Core_Model_Url
+ */
public function setUseUrlCache($flag)
{
$this->setData('use_url_cache', $flag);
@@ -171,10 +200,16 @@ public function setUseUrlCache($flag)
*/
public function setUseSession($useSession)
{
- $this->_useSession = (bool)$useSession;
+ $this->_useSession = (bool) $useSession;
return $this;
}
+ /**
+ * Set route front name
+ *
+ * @param string $name
+ * @return Mage_Core_Model_Url
+ */
public function setRouteFrontName($name)
{
$this->setData('route_front_name', $name);
@@ -204,14 +239,21 @@ public function getDefaultActionName()
return self::DEFAULT_ACTION_NAME;
}
- public function getConfigData($key, $prefix=null)
+ /**
+ * Retrieve configuration data
+ *
+ * @param string $key
+ * @param string|null $prefix
+ * @return string
+ */
+ public function getConfigData($key, $prefix = null)
{
if (is_null($prefix)) {
- $prefix = 'web/'.($this->getSecure() ? 'secure' : 'unsecure').'/';
+ $prefix = 'web/' . ($this->getSecure() ? 'secure' : 'unsecure').'/';
}
- $path = $prefix.$key;
+ $path = $prefix . $key;
- $cacheId = $this->getStore()->getCode().'/'.$path;
+ $cacheId = $this->getStore()->getCode() . '/' . $path;
if (!isset(self::$_configDataCache[$cacheId])) {
$data = $this->getStore()->getConfig($path);
self::$_configDataCache[$cacheId] = $data;
@@ -220,6 +262,12 @@ public function getConfigData($key, $prefix=null)
return self::$_configDataCache[$cacheId];
}
+ /**
+ * Set request
+ *
+ * @param Zend_Controller_Request_Http $request
+ * @return Mage_Core_Model_Url
+ */
public function setRequest(Zend_Controller_Request_Http $request)
{
$this->_request = $request;
@@ -239,6 +287,11 @@ public function getRequest()
return $this->_request;
}
+ /**
+ * Retrieve URL type
+ *
+ * @return string
+ */
public function getType()
{
if (!$this->hasData('type')) {
@@ -268,16 +321,22 @@ public function getSecure()
}
if (!$this->hasData('secure')) {
- if ($this->getType() == Mage_Core_Model_Store::URL_TYPE_LINK) {
- $pathSecure = Mage::getConfig()->shouldUrlBeSecure('/'.$this->getActionPath());
+ if ($this->getType() == Mage_Core_Model_Store::URL_TYPE_LINK && !$store->isAdmin()) {
+ $pathSecure = Mage::getConfig()->shouldUrlBeSecure('/' . $this->getActionPath());
$this->setData('secure', $pathSecure);
} else {
- $this->setData('secure', $store->isCurrentlySecure());
+ $this->setData('secure', true);
}
}
return $this->getData('secure');
}
+ /**
+ * Set store entity
+ *
+ * @param mixed $data
+ * @return Mage_Core_Model_Url
+ */
public function setStore($data)
{
$this->setData('store', Mage::app()->getStore($data));
@@ -334,35 +393,35 @@ public function getBaseUrl($params = array())
*/
public function setRoutePath($data)
{
- if ($this->_getData('route_path')==$data) {
+ if ($this->_getData('route_path') == $data) {
return $this;
}
$a = explode('/', $data);
$route = array_shift($a);
- if ('*'===$route) {
+ if ('*' === $route) {
$route = $this->getRequest()->getRequestedRouteName();
}
$this->setRouteName($route);
- $routePath = $route.'/';
+ $routePath = $route . '/';
if (!empty($a)) {
$controller = array_shift($a);
- if ('*'===$controller) {
+ if ('*' === $controller) {
$controller = $this->getRequest()->getRequestedControllerName();
}
$this->setControllerName($controller);
- $routePath .= $controller.'/';
+ $routePath .= $controller . '/';
}
if (!empty($a)) {
$action = array_shift($a);
- if ('*'===$action) {
+ if ('*' === $action) {
$action = $this->getRequest()->getRequestedActionName();
}
$this->setActionName($action);
- $routePath .= $action.'/';
+ $routePath .= $action . '/';
}
if (!empty($a)) {
@@ -372,24 +431,26 @@ public function setRoutePath($data)
if (!empty($a)) {
$value = array_shift($a);
$this->setRouteParam($key, $value);
- #$routePath .= $key.'/'.urlencode($value).'/';
- $routePath .= $key.'/'.$value.'/';
+ $routePath .= $key . '/' . $value . '/';
}
}
}
- #$this->setData('route_path', $routePath);
-
return $this;
}
+ /**
+ * Retrieve action path
+ *
+ * @return string
+ */
public function getActionPath()
{
if (!$this->getRouteName()) {
return '';
}
- $hasParams = (bool)$this->getRouteParams();
+ $hasParams = (bool) $this->getRouteParams();
$path = $this->getRouteFrontName() . '/';
if ($this->getControllerName()) {
@@ -406,35 +467,46 @@ public function getActionPath()
return $path;
}
- public function getRoutePath($routeParams=array())
+ /**
+ * Retrieve route path
+ *
+ * @param array $routParams
+ * @return string
+ */
+ public function getRoutePath($routeParams = array())
{
if (!$this->hasData('route_path')) {
$routePath = $this->getRequest()->getAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS);
- if (!empty($routeParams['_use_rewrite'])
- && ($routePath !== null)) {
+ if (!empty($routeParams['_use_rewrite']) && ($routePath !== null)) {
$this->setData('route_path', $routePath);
return $routePath;
}
$routePath = $this->getActionPath();
if ($this->getRouteParams()) {
foreach ($this->getRouteParams() as $key=>$value) {
- if (is_null($value) || false===$value || ''===$value || !is_scalar($value)) {
+ if (is_null($value) || false === $value || '' === $value || !is_scalar($value)) {
continue;
}
- $routePath .= $key.'/'.$value.'/';
+ $routePath .= $key . '/' . $value . '/';
}
}
if ($routePath != '' && substr($routePath, -1, 1) !== '/') {
- $routePath.= '/';
+ $routePath .= '/';
}
$this->setData('route_path', $routePath);
}
return $this->_getData('route_path');
}
+ /**
+ * Set route name
+ *
+ * @param string $data
+ * @return Mage_Core_Model_Url
+ */
public function setRouteName($data)
{
- if ($this->_getData('route_name')==$data) {
+ if ($this->_getData('route_name') == $data) {
return $this;
}
$this->unsetData('route_front_name')
@@ -445,6 +517,11 @@ public function setRouteName($data)
return $this->setData('route_name', $data);
}
+ /**
+ * Retrieve route front name
+ *
+ * @return string
+ */
public function getRouteFrontName()
{
if (!$this->hasData('route_front_name')) {
@@ -458,6 +535,11 @@ public function getRouteFrontName()
return $this->_getData('route_front_name');
}
+ /**
+ * Retrieve route name
+ *
+ * @return string|null
+ */
public function getRouteName()
{
return $this->_getData('route_name');
@@ -465,6 +547,7 @@ public function getRouteName()
/**
* Set Controller Name
+ *
* Reset action name and route path if has change
*
* @param string $data
@@ -472,13 +555,18 @@ public function getRouteName()
*/
public function setControllerName($data)
{
- if ($this->_getData('controller_name')==$data) {
+ if ($this->_getData('controller_name') == $data) {
return $this;
}
$this->unsetData('route_path')->unsetData('action_name')->unsetData('secure');
return $this->setData('controller_name', $data);
}
+ /**
+ * Retrieve controller name
+ *
+ * @return string|null
+ */
public function getControllerName()
{
return $this->_getData('controller_name');
@@ -500,12 +588,24 @@ public function setActionName($data)
return $this->setData('action_name', $data)->unsetData('secure');
}
+ /**
+ * Retrieve action name
+ *
+ * @return string|null
+ */
public function getActionName()
{
return $this->_getData('action_name');
}
- public function setRouteParams(array $data, $unsetOldParams=true)
+ /**
+ * Set route params
+ *
+ * @param array $data
+ * @param boolean $unsetOldParams
+ * @return Mage_Core_Model_Url
+ */
+ public function setRouteParams(array $data, $unsetOldParams = true)
{
if (isset($data['_type'])) {
$this->setType($data['_type']);
@@ -521,11 +621,9 @@ public function setRouteParams(array $data, $unsetOldParams=true)
$this->setSecure((bool)$data['_forced_secure']);
$this->setSecureIsForced(true);
unset($data['_forced_secure']);
- } else {
- if (isset($data['_secure'])) {
- $this->setSecure((bool)$data['_secure']);
- unset($data['_secure']);
- }
+ } elseif (isset($data['_secure'])) {
+ $this->setSecure((bool)$data['_secure']);
+ unset($data['_secure']);
}
if (isset($data['_absolute'])) {
@@ -546,13 +644,13 @@ public function setRouteParams(array $data, $unsetOldParams=true)
$data[$key] = $this->getRequest()->getUserParam($key);
}
} elseif ($data['_current']) {
- foreach ($this->getRequest()->getUserParams() as $key=>$value) {
+ foreach ($this->getRequest()->getUserParams() as $key => $value) {
if (array_key_exists($key, $data) || $this->getRouteParam($key)) {
continue;
}
$data[$key] = $value;
}
- foreach ($this->getRequest()->getQuery() as $key=>$value) {
+ foreach ($this->getRequest()->getQuery() as $key => $value) {
$this->setQueryParam($key, $value);
}
$this->setUseUrlCache(false);
@@ -573,22 +671,34 @@ public function setRouteParams(array $data, $unsetOldParams=true)
}
unset($data['_store_to_url']);
- foreach ($data as $k=>$v) {
+ foreach ($data as $k => $v) {
$this->setRouteParam($k, $v);
}
return $this;
}
+ /**
+ * Retrieve route params
+ *
+ * @return array
+ */
public function getRouteParams()
{
return $this->_getData('route_params');
}
+ /**
+ * Set route param
+ *
+ * @param string $key
+ * @param mixed $data
+ * @return Mage_Core_Model_Url
+ */
public function setRouteParam($key, $data)
{
$params = $this->_getData('route_params');
- if (isset($params[$key]) && $params[$key]==$data) {
+ if (isset($params[$key]) && $params[$key] == $data) {
return $this;
}
$params[$key] = $data;
@@ -596,12 +706,26 @@ public function setRouteParam($key, $data)
return $this->setData('route_params', $params);
}
+ /**
+ * Retrieve route params
+ *
+ * @param string $key
+ * @return mixed
+ */
public function getRouteParam($key)
{
return $this->_getData('route_params', $key);
}
- public function getRouteUrl($routePath=null, $routeParams=null)
+ /**
+ * Retrieve route URL
+ *
+ * @param string $routePath
+ * @param array $routeParams
+ *
+ * @return string
+ */
+ public function getRouteUrl($routePath = null, $routeParams = null)
{
$this->unsetData('route_params');
@@ -609,7 +733,7 @@ public function getRouteUrl($routePath=null, $routeParams=null)
if (is_array($routeParams)) {
$this->setRouteParams($routeParams, false);
}
- return $this->getBaseUrl().$routeParams['_direct'];
+ return $this->getBaseUrl() . $routeParams['_direct'];
}
if (!is_null($routePath)) {
@@ -619,19 +743,19 @@ public function getRouteUrl($routePath=null, $routeParams=null)
$this->setRouteParams($routeParams, false);
}
- $url = $this->getBaseUrl().$this->getRoutePath($routeParams);
+ $url = $this->getBaseUrl() . $this->getRoutePath($routeParams);
return $url;
}
/**
* If the host was switched but session cookie won't recognize it - add session id to query
*
- * @return unknown
+ * @return Mage_Core_Model_Url
*/
public function checkCookieDomains()
{
$hostArr = explode(':', $this->getRequest()->getServer('HTTP_HOST'));
- if ($hostArr[0]!==$this->getHost()) {
+ if ($hostArr[0] !== $this->getHost()) {
$session = Mage::getSingleton('core/session');
if (!$session->isValidForHost($this->getHost())) {
if (!self::$_encryptedSessionId) {
@@ -641,15 +765,17 @@ public function checkCookieDomains()
}
self::$_encryptedSessionId = $session->getEncryptedSessionId();
}
- $this->setQueryParam(
- $session->getSessionIdQueryParam(),
- self::$_encryptedSessionId
- );
+ $this->setQueryParam($session->getSessionIdQueryParam(), self::$_encryptedSessionId);
}
}
return $this;
}
+ /**
+ * Add session param
+ *
+ * @return Mage_Core_Model_Url
+ */
public function addSessionParam()
{
$session = Mage::getSingleton('core/session');
@@ -661,10 +787,7 @@ public function addSessionParam()
}
self::$_encryptedSessionId = $session->getEncryptedSessionId();
}
- $this->setQueryParam(
- $session->getSessionIdQueryParam(),
- self::$_encryptedSessionId
- );
+ $this->setQueryParam($session->getSessionIdQueryParam(), self::$_encryptedSessionId);
return $this;
}
@@ -760,10 +883,17 @@ public function getQueryParams()
return $this->_getData('query_params');
}
+ /**
+ * Set query param
+ *
+ * @param string $key
+ * @param mixed $data
+ * @return Mage_Core_Model_Url
+ */
public function setQueryParam($key, $data)
{
$params = $this->getQueryParams();
- if (isset($params[$key]) && $params[$key]==$data) {
+ if (isset($params[$key]) && $params[$key] == $data) {
return $this;
}
$params[$key] = $data;
@@ -771,6 +901,12 @@ public function setQueryParam($key, $data)
return $this->setData('query_params', $params);
}
+ /**
+ * Retrieve query param
+ *
+ * @param string $key
+ * @return mixed
+ */
public function getQueryParam($key)
{
if (!$this->hasData('query_params')) {
@@ -790,6 +926,11 @@ public function setFragment($data)
return $this->setData('fragment', $data);
}
+ /**
+ * Retrieve URL fragment
+ *
+ * @return string|null
+ */
public function getFragment()
{
return $this->_getData('fragment');
@@ -798,11 +939,11 @@ public function getFragment()
/**
* Build url by requested path and parameters
*
- * @param string $routePath
- * @param array $routeParams
+ * @param string|null $routePath
+ * @param array|null $routeParams
* @return string
*/
- public function getUrl($routePath=null, $routeParams=null)
+ public function getUrl($routePath = null, $routeParams = null)
{
$escapeQuery = false;
@@ -830,7 +971,7 @@ public function getUrl($routePath=null, $routeParams=null)
$noSid = null;
if (isset($routeParams['_nosid'])) {
- $noSid = (bool)$routeParams['_nosid'];
+ $noSid = (bool) $routeParams['_nosid'];
unset($routeParams['_nosid']);
}
$url = $this->getRouteUrl($routePath, $routeParams);
@@ -852,12 +993,14 @@ public function getUrl($routePath=null, $routeParams=null)
$this->_prepareSessionUrl($url);
}
- if ($query = $this->getQuery($escapeQuery)) {
- $url .= '?'.$query;
+ $query = $this->getQuery($escapeQuery);
+ if ($query) {
+ $mark = (strpos($url, '?') === false) ? '?' : ($escapeQuery ? '&' : '&');
+ $url .= $mark . $query;
}
if ($this->getFragment()) {
- $url .= '#'.$this->getFragment();
+ $url .= '#' . $this->getFragment();
}
return $this->escape($url);
@@ -875,18 +1018,17 @@ protected function _prepareSessionUrl($url)
return $this;
}
$session = Mage::getSingleton('core/session');
- /* @var $session Mage_Core_Model_Session */
+ /** @var $session Mage_Core_Model_Session */
if (Mage::app()->getUseSessionVar() && !$session->getSessionIdForHost($url)) {
// secure URL
if ($this->getSecure()) {
$this->setQueryParam('___SID', 'S');
- }
- else {
+ } else {
$this->setQueryParam('___SID', 'U');
}
- }
- else {
- if ($sessionId = $session->getSessionIdForHost($url)) {
+ } else {
+ $sessionId = $session->getSessionIdForHost($url);
+ if ($sessionId) {
$this->setQueryParam($session->getSessionIdQueryParam(), $sessionId);
}
}
@@ -928,7 +1070,8 @@ public function getDirectUrl($url, $params = array()) {
*/
public function sessionUrlVar($html)
{
- return preg_replace_callback('#(\?|&|&)___SID=([SU])(&|&)?#', array($this, "sessionVarCallback"), $html);
+ return preg_replace_callback('#(\?|&|&)___SID=([SU])(&|&)?#',
+ array($this, "sessionVarCallback"), $html);
}
/**
@@ -939,18 +1082,15 @@ public function sessionUrlVar($html)
*/
public function useSessionIdForUrl($secure = false)
{
- $key = 'use_session_id_for_url_' . (int)$secure;
+ $key = 'use_session_id_for_url_' . (int) $secure;
if (is_null($this->getData($key))) {
$httpHost = Mage::app()->getFrontController()->getRequest()->getHttpHost();
- $urlHost = parse_url(
- Mage::app()->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, $secure),
- PHP_URL_HOST
- );
+ $urlHost = parse_url(Mage::app()->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK, $secure),
+ PHP_URL_HOST);
if ($httpHost != $urlHost) {
$this->setData($key, true);
- }
- else {
+ } else {
$this->setData($key, false);
}
}
@@ -972,18 +1112,14 @@ public function sessionVarCallback($match)
. $session->getSessionIdQueryParam()
. '=' . $session->getEncryptedSessionId()
. (isset($match[3]) ? $match[3] : '');
- }
- else {
+ } else {
if ($match[1] == '?' && isset($match[3])) {
return '?';
- }
- elseif ($match[1] == '?' && !isset($match[3])) {
+ } elseif ($match[1] == '?' && !isset($match[3])) {
return '';
- }
- elseif (($match[1] == '&' || $match[1] == '&') && !isset($match[3])) {
+ } elseif (($match[1] == '&' || $match[1] == '&') && !isset($match[3])) {
return '';
- }
- elseif (($match[1] == '&' || $match[1] == '&') && isset($match[3])) {
+ } elseif (($match[1] == '&' || $match[1] == '&') && isset($match[3])) {
return $match[3];
}
}
diff --git a/app/code/core/Mage/Core/Model/Url/Rewrite.php b/app/code/core/Mage/Core/Model/Url/Rewrite.php
index cfa03c4173..07cd5d3209 100644
--- a/app/code/core/Mage/Core/Model/Url/Rewrite.php
+++ b/app/code/core/Mage/Core/Model/Url/Rewrite.php
@@ -217,7 +217,9 @@ public function rewrite(Zend_Controller_Request_Http $request=null, Zend_Control
$origSlash = (substr($pathInfo, -1) == '/') ? '/' : '';
$requestPath = trim($pathInfo, '/');
- $altSlash = $origSlash ? '' : '/'; // If there were final slash - add nothing to less priority paths. And vice versa.
+ // If there were final slash - add nothing to less priority paths. And vice versa.
+ $altSlash = $origSlash ? '' : '/';
+
$queryString = $this->_getQueryString(); // Query params in request, matching "path + query" has more priority
if ($queryString) {
$requestCases[] = $requestPath . $origSlash . '?' . $queryString;
@@ -243,7 +245,13 @@ public function rewrite(Zend_Controller_Request_Http $request=null, Zend_Control
if (!$this->getId()) {
return false;
}
- $this->setStoreId(Mage::app()->getStore()->getId())->loadByIdPath($this->getIdPath());
+ $currentStore = Mage::app()->getStore();
+ $this->setStoreId($currentStore->getId())->loadByIdPath($this->getIdPath());
+
+ Mage::app()->getCookie()->set(Mage_Core_Model_Store::COOKIE_NAME, $currentStore->getCode(), true);
+ $targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
+
+ $this->_sendRedirectHeaders($targetUrl, true);
}
if (!$this->getId()) {
@@ -255,11 +263,10 @@ public function rewrite(Zend_Controller_Request_Http $request=null, Zend_Control
$external = substr($this->getTargetPath(), 0, 6);
$isPermanentRedirectOption = $this->hasOption('RP');
if ($external === 'http:/' || $external === 'https:') {
- if ($isPermanentRedirectOption) {
- header('HTTP/1.1 301 Moved Permanently');
- }
- header("Location: ".$this->getTargetPath());
- exit;
+ $destinationStoreCode = Mage::app()->getStore($this->getStoreId())->getCode();
+ Mage::app()->getCookie()->set(Mage_Core_Model_Store::COOKIE_NAME, $destinationStoreCode, true);
+
+ $this->_sendRedirectHeaders($this->getTargetPath(), $isPermanentRedirectOption);
} else {
$targetUrl = $request->getBaseUrl(). '/' . $this->getTargetPath();
}
@@ -268,11 +275,8 @@ public function rewrite(Zend_Controller_Request_Http $request=null, Zend_Control
if (Mage::getStoreConfig('web/url/use_store') && $storeCode = Mage::app()->getStore()->getCode()) {
$targetUrl = $request->getBaseUrl(). '/' . $storeCode . '/' .$this->getTargetPath();
}
- if ($isPermanentRedirectOption) {
- header('HTTP/1.1 301 Moved Permanently');
- }
- header('Location: '.$targetUrl);
- exit;
+
+ $this->_sendRedirectHeaders($targetUrl, $isPermanentRedirectOption);
}
if (Mage::getStoreConfig('web/url/use_store') && $storeCode = Mage::app()->getStore()->getCode()) {
@@ -317,4 +321,21 @@ public function getStoreId()
return $this->_getData('store_id');
}
+ /**
+ * Add location header and disable browser page caching
+ *
+ * @param string $url
+ * @param bool $isPermanent
+ */
+ protected function _sendRedirectHeaders($url, $isPermanent = false)
+ {
+ if ($isPermanent) {
+ header('HTTP/1.1 301 Moved Permanently');
+ }
+
+ header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
+ header('Pragma: no-cache');
+ header('Location: ' . $url);
+ exit;
+ }
}
diff --git a/app/code/core/Mage/Core/etc/api.xml b/app/code/core/Mage/Core/etc/api.xml
new file mode 100644
index 0000000000..4e728d23d7
--- /dev/null
+++ b/app/code/core/Mage/Core/etc/api.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+ core/store_api
+ Store API
+ core/store
+
+
+ Retrieve store list
+ items
+ core/store/list
+
+
+ Retrieve store data
+ core/store/info
+
+
+
+
+ 100
+ Requested store view not found.
+
+
+
+
+
+ core_store
+
+
+
+ store
+
+
+
+
+
+
+
+
+
+ Core
+ 1
+
+ Store
+
+ Retrieve store data
+
+
+ List of stores
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/Core/etc/config.xml b/app/code/core/Mage/Core/etc/config.xml
index 782a0b8ae9..68e241fb98 100644
--- a/app/code/core/Mage/Core/etc/config.xml
+++ b/app/code/core/Mage/Core/etc/config.xml
@@ -28,7 +28,7 @@
- 1.6.0.1
+ 1.6.0.2
diff --git a/app/code/core/Mage/Core/etc/system.xml b/app/code/core/Mage/Core/etc/system.xml
index ea16205dff..685194aab3 100644
--- a/app/code/core/Mage/Core/etc/system.xml
+++ b/app/code/core/Mage/Core/etc/system.xml
@@ -916,7 +916,7 @@
selectadminhtml/system_config_source_email_template
- 1
+ 10111
@@ -925,11 +925,20 @@
selectadminhtml/system_config_source_email_identity
- 2
+ 20111
+
+
+ text
+ adminhtml/system_config_backend_admin_password_link_expirationperiod
+ 30
+ 1
+ 0
+ 0
+
@@ -960,7 +969,7 @@
0
-
+
selectadminhtml/system_config_source_yesnoadminhtml/system_config_backend_admin_usecustom
@@ -970,17 +979,38 @@
0
-
+
text
- required-entry validate-alphanumadminhtml/system_config_backend_admin_custom12100
- You will have to log in after you save your custom admin path.
+ Make sure that base URL ends with '/' (slash), e.g. http://yourdomain/magento/
+
+
+ select
+ adminhtml/system_config_source_yesno
+ adminhtml/system_config_backend_admin_usecustompath
+ 3
+ 1
+ 0
+ 0
+
+
+
+ text
+ required-entry validate-alphanum
+ adminhtml/system_config_backend_admin_custompath
+ 1
+ 4
+ 1
+ 0
+ 0
+ You will have to log in after you save your custom admin path.
+
diff --git a/app/code/core/Mage/Core/etc/wsdl.xml b/app/code/core/Mage/Core/etc/wsdl.xml
new file mode 100644
index 0000000000..0689e69f79
--- /dev/null
+++ b/app/code/core/Mage/Core/etc/wsdl.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ List of stores
+
+
+
+
+ Store view info
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/Core/etc/wsi.xml b/app/code/core/Mage/Core/etc/wsi.xml
new file mode 100644
index 0000000000..8877c0fbdb
--- /dev/null
+++ b/app/code/core/Mage/Core/etc/wsi.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ List of stores
+
+
+
+
+ Store view info
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/Core/sql/core_setup/install-1.6.0.0.php b/app/code/core/Mage/Core/sql/core_setup/install-1.6.0.0.php
index 6673649717..c616047472 100644
--- a/app/code/core/Mage/Core/sql/core_setup/install-1.6.0.0.php
+++ b/app/code/core/Mage/Core/sql/core_setup/install-1.6.0.0.php
@@ -199,9 +199,9 @@
'nullable' => false,
'default' => 'general',
), 'Config Path')
- ->addColumn('value', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array(
- ), 'Config Value')
- ->addIndex($installer->getIdxName('core/config_data', array('scope', 'scope_id', 'path'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ ->addColumn('value', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array(), 'Config Value')
+ ->addIndex($installer->getIdxName('core/config_data', array('scope', 'scope_id', 'path'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
array('scope', 'scope_id', 'path'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->setComment('Config Data');
$installer->getConnection()->createTable($table);
@@ -243,7 +243,8 @@
), 'Original Template Code')
->addColumn('orig_template_variables', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array(
), 'Original Template Variables')
- ->addIndex($installer->getIdxName('core/email_template', array('template_code'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ ->addIndex($installer->getIdxName('core/email_template', array('template_code'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
array('template_code'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->addIndex($installer->getIdxName('core/email_template', array('added_at')),
array('added_at'))
@@ -303,16 +304,20 @@
'nullable' => false,
'default' => '0',
), 'Layout Update Id')
- ->addIndex($installer->getIdxName('core/layout_link', array('store_id', 'package', 'theme', 'layout_update_id'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
- array('store_id', 'package', 'theme', 'layout_update_id'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
+ ->addIndex($installer->getIdxName('core/layout_link', array('store_id', 'package', 'theme', 'layout_update_id'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ array('store_id', 'package', 'theme', 'layout_update_id'),
+ array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->addIndex($installer->getIdxName('core/layout_link', array('layout_update_id')),
array('layout_update_id'))
->addForeignKey($installer->getFkName('core/layout_link', 'store_id', 'core/store', 'store_id'),
'store_id', $installer->getTable('core/store'), 'store_id',
Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
- ->addForeignKey($installer->getFkName('core/layout_link', 'layout_update_id', 'core/layout_update', 'layout_update_id'),
+ ->addForeignKey(
+ $installer->getFkName('core/layout_link', 'layout_update_id', 'core/layout_update', 'layout_update_id'),
'layout_update_id', $installer->getTable('core/layout_update'), 'layout_update_id',
- Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
+ Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE
+ )
->setComment('Layout Link');
$installer->getConnection()->createTable($table);
@@ -362,7 +367,8 @@
'nullable' => false,
'default' => 'en_US',
), 'Locale')
- ->addIndex($installer->getIdxName('core/translate', array('store_id', 'locale', 'string'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ ->addIndex($installer->getIdxName('core/translate', array('store_id', 'locale', 'string'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
array('store_id', 'locale', 'string'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->addIndex($installer->getIdxName('core/translate', array('store_id')),
array('store_id'))
@@ -403,9 +409,11 @@
), 'Options')
->addColumn('description', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array(
), 'Deascription')
- ->addIndex($installer->getIdxName('core/url_rewrite', array('request_path', 'store_id'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ ->addIndex($installer->getIdxName('core/url_rewrite', array('request_path', 'store_id'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
array('request_path', 'store_id'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
- ->addIndex($installer->getIdxName('core/url_rewrite', array('id_path', 'is_system', 'store_id'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ ->addIndex($installer->getIdxName('core/url_rewrite', array('id_path', 'is_system', 'store_id'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
array('id_path', 'is_system', 'store_id'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->addIndex($installer->getIdxName('core/url_rewrite', array('target_path', 'store_id')),
array('target_path', 'store_id'))
@@ -493,7 +501,8 @@
), 'Plain Text Value')
->addColumn('html_value', Varien_Db_Ddl_Table::TYPE_TEXT, '64k', array(
), 'Html Value')
- ->addIndex($installer->getIdxName('core/variable_value', array('variable_id', 'store_id'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
+ ->addIndex($installer->getIdxName('core/variable_value', array('variable_id', 'store_id'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
array('variable_id', 'store_id'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
->addIndex($installer->getIdxName('core/variable_value', array('variable_id')),
array('variable_id'))
@@ -545,9 +554,6 @@
), 'Cache Id')
->addIndex($installer->getIdxName('core/cache_tag', array('cache_id')),
array('cache_id'))
- ->addForeignKey($installer->getFkName('core/cache_tag', 'cache_id', 'core/cache', 'id'),
- 'cache_id', $installer->getTable('core/cache'), 'id',
- Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
->setComment('Tag Caches');
$installer->getConnection()->createTable($table);
diff --git a/app/code/core/Mage/Core/sql/core_setup/mysql4-upgrade-1.5.9.9-1.6.0.0.php b/app/code/core/Mage/Core/sql/core_setup/mysql4-upgrade-1.5.9.9-1.6.0.0.php
index c06b78175c..8ef11ff8fd 100644
--- a/app/code/core/Mage/Core/sql/core_setup/mysql4-upgrade-1.5.9.9-1.6.0.0.php
+++ b/app/code/core/Mage/Core/sql/core_setup/mysql4-upgrade-1.5.9.9-1.6.0.0.php
@@ -1342,13 +1342,6 @@
/**
* Add foreign keys
*/
-$installer->getConnection()->addForeignKey(
- $installer->getFkName('core/cache_tag', 'cache_id', 'core/cache', 'id'),
- $installer->getTable('core/cache_tag'),
- 'cache_id',
- $installer->getTable('core/cache'),
- 'id'
-);
$installer->getConnection()->addForeignKey(
$installer->getFkName('core/layout_link', 'store_id', 'core/store', 'store_id'),
diff --git a/app/code/core/Mage/GoogleOptimizer/sql/googleoptimizer_setup/mysql4-upgrade-0.1.0-0.1.1.php b/app/code/core/Mage/Core/sql/core_setup/upgrade-1.6.0.1-1.6.0.2.php
similarity index 84%
rename from app/code/core/Mage/GoogleOptimizer/sql/googleoptimizer_setup/mysql4-upgrade-0.1.0-0.1.1.php
rename to app/code/core/Mage/Core/sql/core_setup/upgrade-1.6.0.1-1.6.0.2.php
index 31365974b0..137a8f46f9 100644
--- a/app/code/core/Mage/GoogleOptimizer/sql/googleoptimizer_setup/mysql4-upgrade-0.1.0-0.1.1.php
+++ b/app/code/core/Mage/Core/sql/core_setup/upgrade-1.6.0.1-1.6.0.2.php
@@ -19,16 +19,19 @@
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Core
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-$installer = $this;
/* @var $installer Mage_Core_Model_Resource_Setup */
+$installer = $this;
$installer->startSetup();
-$installer->getConnection()->addColumn($installer->getTable('googleoptimizer/code'), 'conversion_page', "varchar(255) NOT NULL default ''");
+$installer->getConnection()->dropForeignKey(
+ $installer->getTable('core/cache_tag'),
+ $installer->getFkName('core/cache_tag', 'cache_id', 'core/cache', 'id')
+);
$installer->endSetup();
diff --git a/app/code/core/Mage/GoogleOptimizer/Model/Mysql4/Code.php b/app/code/core/Mage/Customer/Block/Account/Resetpassword.php
similarity index 83%
rename from app/code/core/Mage/GoogleOptimizer/Model/Mysql4/Code.php
rename to app/code/core/Mage/Customer/Block/Account/Resetpassword.php
index 5bf7dc87e9..fa36efb1b0 100644
--- a/app/code/core/Mage/GoogleOptimizer/Model/Mysql4/Code.php
+++ b/app/code/core/Mage/Customer/Block/Account/Resetpassword.php
@@ -19,19 +19,20 @@
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Customer
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-
/**
- * Google Optimizer resource model
+ * Customer reset password form
*
* @category Mage
- * @package Mage_GoogleOptimizer
+ * @package Mage_Customer
* @author Magento Core Team
*/
-class Mage_GoogleOptimizer_Model_Mysql4_Code extends Mage_GoogleOptimizer_Model_Resource_Code
+
+class Mage_Customer_Block_Account_Resetpassword extends Mage_Core_Block_Template
{
+
}
diff --git a/app/code/core/Mage/Customer/Block/Widget/Name.php b/app/code/core/Mage/Customer/Block/Widget/Name.php
index d8b965fc89..bd951eeb99 100644
--- a/app/code/core/Mage/Customer/Block/Widget/Name.php
+++ b/app/code/core/Mage/Customer/Block/Widget/Name.php
@@ -182,7 +182,7 @@ public function getStoreLabel($attributeCode)
{
$attribute = $this->_getAttribute($attributeCode);
if ($attribute) {
- return $attribute->getStoreLabel();
+ return $this->__($attribute->getStoreLabel());
}
return '';
}
diff --git a/app/code/core/Mage/Customer/Helper/Data.php b/app/code/core/Mage/Customer/Helper/Data.php
index 15fcbe2090..541e726a60 100644
--- a/app/code/core/Mage/Customer/Helper/Data.php
+++ b/app/code/core/Mage/Customer/Helper/Data.php
@@ -44,6 +44,12 @@ class Mage_Customer_Helper_Data extends Mage_Core_Helper_Abstract
*/
const XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD = 'customer/startup/redirect_dashboard';
+ /**
+ * Configuration path to expiration period of reset password link
+ */
+ const XML_PATH_CUSTOMER_RESET_PASSWORD_LINK_EXPIRATION_PERIOD
+ = 'default/customer/password/reset_link_expiration_period';
+
/**
* Customer groups collection
*
@@ -320,4 +326,24 @@ protected function _prepareNamePrefixSuffixOptions($options)
}
return $result;
}
+
+ /**
+ * Generate unique token for reset password confirmation link
+ *
+ * @return string
+ */
+ public function generateResetPasswordLinkToken()
+ {
+ return Mage::helper('core')->uniqHash();
+ }
+
+ /**
+ * Retrieve customer reset password link expiration period in days
+ *
+ * @return int
+ */
+ public function getResetPasswordLinkExpirationPeriod()
+ {
+ return (int) Mage::getConfig()->getNode(self::XML_PATH_CUSTOMER_RESET_PASSWORD_LINK_EXPIRATION_PERIOD);
+ }
}
diff --git a/app/code/core/Mage/Customer/Model/Customer.php b/app/code/core/Mage/Customer/Model/Customer.php
index df079f90ac..ba2ac0ec1c 100644
--- a/app/code/core/Mage/Customer/Model/Customer.php
+++ b/app/code/core/Mage/Customer/Model/Customer.php
@@ -27,30 +27,64 @@
/**
* Customer model
*
+ * @category Mage
+ * @package Mage_Customer
* @author Magento Core Team
*/
class Mage_Customer_Model_Customer extends Mage_Core_Model_Abstract
{
- const XML_PATH_REGISTER_EMAIL_TEMPLATE = 'customer/create_account/email_template';
- const XML_PATH_REGISTER_EMAIL_IDENTITY = 'customer/create_account/email_identity';
- const XML_PATH_FORGOT_EMAIL_TEMPLATE = 'customer/password/forgot_email_template';
- const XML_PATH_FORGOT_EMAIL_IDENTITY = 'customer/password/forgot_email_identity';
+ /**
+ * Configuration pathes for email templates and identities
+ */
+ const XML_PATH_REGISTER_EMAIL_TEMPLATE = 'customer/create_account/email_template';
+ const XML_PATH_REGISTER_EMAIL_IDENTITY = 'customer/create_account/email_identity';
+ const XML_PATH_REMIND_EMAIL_TEMPLATE = 'customer/password/remind_email_template';
+ const XML_PATH_FORGOT_EMAIL_TEMPLATE = 'customer/password/forgot_email_template';
+ const XML_PATH_FORGOT_EMAIL_IDENTITY = 'customer/password/forgot_email_identity';
+
const XML_PATH_DEFAULT_EMAIL_DOMAIN = 'customer/create_account/email_domain';
const XML_PATH_IS_CONFIRM = 'customer/create_account/confirm';
const XML_PATH_CONFIRM_EMAIL_TEMPLATE = 'customer/create_account/email_confirmation_template';
const XML_PATH_CONFIRMED_EMAIL_TEMPLATE = 'customer/create_account/email_confirmed_template';
const XML_PATH_GENERATE_HUMAN_FRIENDLY_ID = 'customer/create_account/generate_human_friendly_id';
+ /**
+ * Codes of exceptions related to customer model
+ */
const EXCEPTION_EMAIL_NOT_CONFIRMED = 1;
const EXCEPTION_INVALID_EMAIL_OR_PASSWORD = 2;
const EXCEPTION_EMAIL_EXISTS = 3;
+ const EXCEPTION_INVALID_RESET_PASSWORD_LINK_TOKEN = 4;
const SUBSCRIBED_YES = 'yes';
const SUBSCRIBED_NO = 'no';
+ /**
+ * Model event prefix
+ *
+ * @var string
+ */
protected $_eventPrefix = 'customer';
+
+ /**
+ * Name of the event object
+ *
+ * @var string
+ */
protected $_eventObject = 'customer';
- protected $_errors = array();
+
+ /**
+ * List of errors
+ *
+ * @var array
+ */
+ protected $_errors = array();
+
+ /**
+ * Assoc array of customer attributes
+ *
+ * @var array
+ */
protected $_attributes;
/**
@@ -82,8 +116,16 @@ class Mage_Customer_Model_Customer extends Mage_Core_Model_Abstract
*/
protected $_isReadonly = false;
+ /**
+ * Confirmation requirement flag
+ *
+ * @var boolean
+ */
private static $_isConfirmationRequired;
+ /**
+ * Initialize customer model
+ */
function _construct()
{
$this->_init('customer/customer');
@@ -489,6 +531,12 @@ public function getAdditionalAddresses()
return $addresses;
}
+ /**
+ * Check if address is primary
+ *
+ * @param Mage_Customer_Model_Address $address
+ * @return boolean
+ */
public function isAddressPrimary(Mage_Customer_Model_Address $address)
{
if (!$address->getId()) {
@@ -498,8 +546,11 @@ public function isAddressPrimary(Mage_Customer_Model_Address $address)
}
/**
- * Send email with new account specific information
+ * Send email with new account related information
*
+ * @param string $type
+ * @param string $backUrl
+ * @param string $storeId
* @throws Mage_Core_Exception
* @return Mage_Customer_Model_Customer
*/
@@ -514,24 +565,12 @@ public function sendNewAccountEmail($type = 'registered', $backUrl = '', $storeI
Mage::throwException(Mage::helper('customer')->__('Wrong transactional account email type'));
}
- $translate = Mage::getSingleton('core/translate');
- /* @var $translate Mage_Core_Model_Translate */
- $translate->setTranslateInline(false);
-
if (!$storeId) {
$storeId = $this->_getWebsiteStoreId($this->getSendemailStoreId());
}
- Mage::getModel('core/email_template')
- ->setDesignConfig(array('area' => 'frontend', 'store' => $storeId))
- ->sendTransactional(
- Mage::getStoreConfig($types[$type], $storeId),
- Mage::getStoreConfig(self::XML_PATH_REGISTER_EMAIL_IDENTITY, $storeId),
- $this->getEmail(),
- $this->getName(),
- array('customer' => $this, 'back_url' => $backUrl));
-
- $translate->setTranslateInline(true);
+ $this->_sendEmailTemplate($types[$type], self::XML_PATH_REGISTER_EMAIL_IDENTITY,
+ array('customer' => $this, 'back_url' => $backUrl), $storeId);
return $this;
}
@@ -554,6 +593,11 @@ public function isConfirmationRequired()
return self::$_isConfirmationRequired;
}
+ /**
+ * Generate random confirmation key
+ *
+ * @return string
+ */
public function getRandomConfirmationKey()
{
return md5(uniqid());
@@ -566,26 +610,57 @@ public function getRandomConfirmationKey()
*/
public function sendPasswordReminderEmail()
{
- $translate = Mage::getSingleton('core/translate');
- /* @var $translate Mage_Core_Model_Translate */
- $translate->setTranslateInline(false);
-
$storeId = $this->getStoreId();
if (!$storeId) {
$storeId = $this->_getWebsiteStoreId();
}
- Mage::getModel('core/email_template')
- ->setDesignConfig(array('area' => 'frontend', 'store' => $storeId))
- ->sendTransactional(
- Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_TEMPLATE, $storeId),
- Mage::getStoreConfig(self::XML_PATH_FORGOT_EMAIL_IDENTITY, $storeId),
- $this->getEmail(),
- $this->getName(),
- array('customer' => $this)
- );
+ $this->_sendEmailTemplate(self::XML_PATH_REMIND_EMAIL_TEMPLATE, self::XML_PATH_FORGOT_EMAIL_IDENTITY,
+ array('customer' => $this), $storeId);
- $translate->setTranslateInline(true);
+ return $this;
+ }
+
+ /**
+ * Send corresponding email template
+ *
+ * @param string $emailTemplate configuration path of email template
+ * @param string $emailSender configuration path of email identity
+ * @param array $templateParams
+ * @param int|null $storeId
+ * @return Mage_Customer_Model_Customer
+ */
+ protected function _sendEmailTemplate($template, $sender, $templateParams = array(), $storeId = null)
+ {
+ /** @var $mailer Mage_Core_Model_Email_Template_Mailer */
+ $mailer = Mage::getModel('core/email_template_mailer');
+ $emailInfo = Mage::getModel('core/email_info');
+ $emailInfo->addTo($this->getEmail(), $this->getName());
+ $mailer->addEmailInfo($emailInfo);
+
+ // Set all required params and send emails
+ $mailer->setSender(Mage::getStoreConfig($sender, $storeId));
+ $mailer->setStoreId($storeId);
+ $mailer->setTemplateId(Mage::getStoreConfig($template, $storeId));
+ $mailer->setTemplateParams($templateParams);
+ $mailer->send();
+ return $this;
+ }
+
+ /**
+ * Send email with reset password confirmation link
+ *
+ * @return Mage_Customer_Model_Customer
+ */
+ public function sendPasswordResetConfirmationEmail()
+ {
+ $storeId = $this->getStoreId();
+ if (!$storeId) {
+ $storeId = $this->_getWebsiteStoreId();
+ }
+
+ $this->_sendEmailTemplate(self::XML_PATH_FORGOT_EMAIL_TEMPLATE, self::XML_PATH_FORGOT_EMAIL_IDENTITY,
+ array('customer' => $this), $storeId);
return $this;
}
@@ -759,10 +834,10 @@ public function validate()
}
/**
- * Importing customer data from text array
+ * Import customer data from text array
*
* @param array $row
- * @return uMage_Customer_Model_Customer
+ * @return Mage_Customer_Model_Customer
*/
public function importFromTextArray(array $row)
{
@@ -828,7 +903,8 @@ public function importFromTextArray(array $row)
if (!empty($row['password_hash'])) unset($row['password_hash']);
}
- if ($errors = $this->getErrors()) {
+ $errors = $this->getErrors();
+ if ($errors) {
$this->unsetData();
$this->printError(implode(' ', $errors));
return;
@@ -986,21 +1062,22 @@ function resetErrors()
*
* @param $error
* @param $line
+ * @return boolean
*/
function printError($error, $line = null)
{
if ($error == null) {
return false;
}
- $img = 'error_msg_icon.gif';
- $liStyle = 'background-color:#FDD; ';
- echo '
+
diff --git a/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.0-1.6.0.1.php b/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.0-1.6.0.1.php
new file mode 100644
index 0000000000..43ee81dfd4
--- /dev/null
+++ b/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.0-1.6.0.1.php
@@ -0,0 +1,34 @@
+getConnection();
+$connection->createTable($connection->createTableByDdl(
+ $installer->getTable('tax/tax_order_aggregated_created'),
+ $installer->getTable('tax/tax_order_aggregated_updated')
+));
diff --git a/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.1-1.6.0.2.php b/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.1-1.6.0.2.php
new file mode 100644
index 0000000000..01e02eb424
--- /dev/null
+++ b/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.1-1.6.0.2.php
@@ -0,0 +1,87 @@
+getConnection()
+ ->newTable($installer->getTable('tax/sales_order_tax_item'))
+ ->addColumn('tax_item_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
+ 'identity' => true,
+ 'unsigned' => true,
+ 'nullable' => false,
+ 'primary' => true,
+ ), 'Tax Item Id')
+ ->addColumn('tax_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
+ 'unsigned' => true,
+ 'nullable' => false,
+ ), 'Tax Id')
+ ->addColumn('item_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
+ 'unsigned' => true,
+ 'nullable' => false,
+ ), 'Item Id')
+ ->addIndex($installer->getIdxName('tax/sales_order_tax_item', array('tax_id')),
+ array('tax_id'))
+ ->addIndex($installer->getIdxName('tax/sales_order_tax_item', array('item_id')),
+ array('item_id'))
+ ->addIndex(
+ $installer->getIdxName(
+ 'tax/sales_order_tax_item', array('tax_id', 'item_id'),
+ Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
+ ),
+ array('tax_id', 'item_id'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)
+ )
+ ->addForeignKey(
+ $installer->getFkName(
+ 'tax/sales_order_tax_item',
+ 'tax_id',
+ 'tax/sales_order_tax',
+ 'tax_id'
+ ),
+ 'tax_id',
+ $installer->getTable('tax/sales_order_tax'),
+ 'tax_id',
+ Varien_Db_Ddl_Table::ACTION_CASCADE,
+ Varien_Db_Ddl_Table::ACTION_CASCADE
+ )
+ ->addForeignKey(
+ $installer->getFkName(
+ 'tax/sales_order_tax_item',
+ 'item_id',
+ 'sales_flat_order_item',
+ 'item_id'
+ ),
+ 'item_id',
+ $installer->getTable('sales_flat_order_item'),
+ 'item_id',
+ Varien_Db_Ddl_Table::ACTION_CASCADE,
+ Varien_Db_Ddl_Table::ACTION_CASCADE
+ )
+ ->setComment('Sales Order Tax Item');
+$installer->getConnection()->createTable($table);
diff --git a/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.2-1.6.0.3.php b/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.2-1.6.0.3.php
new file mode 100644
index 0000000000..8dcf938873
--- /dev/null
+++ b/app/code/core/Mage/Tax/sql/tax_setup/upgrade-1.6.0.2-1.6.0.3.php
@@ -0,0 +1,44 @@
+getConnection()
+ ->addColumn(
+ $installer->getTable('tax/sales_order_tax_item'),
+ 'tax_percent',
+ array(
+ 'TYPE' => Varien_Db_Ddl_Table::TYPE_DECIMAL,
+ 'SCALE' => 4,
+ 'PRECISION' => 12,
+ 'NULLABLE' => false,
+ 'COMMENT' => 'Real Tax Percent For Item',
+ )
+ );
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 8166cb4f9a..d567b6e3c3 100644
--- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php
+++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php
@@ -85,6 +85,13 @@ class Mage_Usa_Model_Shipping_Carrier_Fedex
*/
protected $_shipServiceWsdl = null;
+ /**
+ * Path to wsdl file of track service
+ *
+ * @var string
+ */
+ protected $_trackServiceWsdl = null;
+
/**
* Container types that could be customized for FedEx carrier
*
@@ -95,27 +102,40 @@ class Mage_Usa_Model_Shipping_Carrier_Fedex
public function __construct()
{
parent::__construct();
- $this->_shipServiceWsdl = Mage::getModuleDir('etc', 'Mage_Usa') . DS . 'wsdl' . DS . 'FedEx'
- . DS . 'ShipService_v9.wsdl';
- $this->_rateServiceWsdl = Mage::getModuleDir('etc', 'Mage_Usa') . DS . 'wsdl' . DS . 'FedEx'
- . DS . 'RateService_v9.wsdl';
+ $wsdlBasePath = Mage::getModuleDir('etc', 'Mage_Usa') . DS . 'wsdl' . DS . 'FedEx' . DS;
+ $this->_shipServiceWsdl = $wsdlBasePath . 'ShipService_v9.wsdl';
+ $this->_rateServiceWsdl = $wsdlBasePath . 'RateService_v9.wsdl';
+ $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v5.wsdl';
}
/**
- * Create rate soap client
+ * Create soap client with selected wsdl
*
+ * @param string $wsdl
+ * @param bool|int $trace
* @return SoapClient
*/
- protected function _createRateSoapClient()
+ protected function _createSoapClient($wsdl, $trace = false)
{
- $client = new SoapClient($this->_rateServiceWsdl);
+ $client = new SoapClient($wsdl, array('trace' => $trace));
$client->__setLocation($this->getConfigFlag('sandbox_mode')
? 'https://wsbeta.fedex.com:443/web-services/rate'
: 'https://ws.fedex.com:443/web-services/rate'
);
+
return $client;
}
+ /**
+ * Create rate soap client
+ *
+ * @return SoapClient
+ */
+ protected function _createRateSoapClient()
+ {
+ return $this->_createSoapClient($this->_rateServiceWsdl);
+ }
+
/**
* Create ship soap client
*
@@ -123,12 +143,17 @@ protected function _createRateSoapClient()
*/
protected function _createShipSoapClient()
{
- $client = new SoapClient($this->_shipServiceWsdl, array('trace' => 1));
- $client->__setLocation($this->getConfigFlag('sandbox_mode')
- ? 'https://wsbeta.fedex.com:443/web-services/ship'
- : 'https://ws.fedex.com:443/web-services/ship'
- );
- return $client;
+ return $this->_createSoapClient($this->_shipServiceWsdl, 1);
+ }
+
+ /**
+ * Create track soap client
+ *
+ * @return SoapClient
+ */
+ protected function _createTrackSoapClient()
+ {
+ return $this->_createSoapClient($this->_trackServiceWsdl, 1);
}
/**
@@ -704,6 +729,11 @@ public function getCode($type, $code='')
'STANDARD_OVERNIGHT',
'PRIORITY_OVERNIGHT',
'FIRST_OVERNIGHT',
+ 'FEDEX_FREIGHT',
+ 'FEDEX_1_DAY_FREIGHT',
+ 'FEDEX_2_DAY_FREIGHT',
+ 'FEDEX_3_DAY_FREIGHT',
+ 'FEDEX_NATIONAL_FREIGHT',
)
),
'from_us' => array(
@@ -712,6 +742,13 @@ public function getCode($type, $code='')
'INTERNATIONAL_ECONOMY',
'INTERNATIONAL_PRIORITY',
'INTERNATIONAL_GROUND',
+ 'FEDEX_FREIGHT',
+ 'FEDEX_1_DAY_FREIGHT',
+ 'FEDEX_2_DAY_FREIGHT',
+ 'FEDEX_3_DAY_FREIGHT',
+ 'FEDEX_NATIONAL_FREIGHT',
+ 'INTERNATIONAL_ECONOMY_FREIGHT',
+ 'INTERNATIONAL_PRIORITY_FREIGHT',
)
)
)
@@ -811,58 +848,165 @@ protected function setTrackingReqeust()
*/
protected function _getXMLTracking($tracking)
{
- $r = $this->_rawTrackingRequest;
-
- $xml = new SimpleXMLElement('');
- $xml->addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
- $xml->addAttribute('xsi:noNamespaceSchemaLocation', 'FDXTrack2Request.xsd');
+ $trackRequest = array(
+ 'WebAuthenticationDetail' => array(
+ 'UserCredential' => array(
+ 'Key' => $this->getConfigData('key'),
+ 'Password' => $this->getConfigData('password')
+ )
+ ),
+ 'ClientDetail' => array(
+ 'AccountNumber' => $this->getConfigData('account'),
+ 'MeterNumber' => $this->getConfigData('meter_number')
+ ),
+ 'Version' => array(
+ 'ServiceId' => 'trck',
+ 'Major' => '5',
+ 'Intermediate' => '0',
+ 'Minor' => '0'
+ ),
+ 'PackageIdentifier' => array(
+ 'Type' => 'TRACKING_NUMBER_OR_DOORTAG',
+ 'Value' => $tracking,
+ ),
+ /*
+ * 0 = summary data, one signle scan structure with the most recent scan
+ * 1 = multiple sacn activity for each package
+ */
+ 'IncludeDetailedScans' => 1,
+ );
+ $requestString = serialize($trackRequest);
+ $response = $this->_getCachedQuotes($requestString);
+ $debugData = array('request' => $trackRequest);
+ if ($response === null) {
+ try {
+ $client = $this->_createTrackSoapClient();
+ $response = $client->track($trackRequest);
+ $this->_setCachedQuotes($requestString, serialize($response));
+ $debugData['result'] = $response;
+ } catch (Exception $e) {
+ $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
+ Mage::logException($e);
+ }
+ } else {
+ $response = unserialize($response);
+ $debugData['result'] = $response;
+ }
+ $this->_debug($debugData);
- $requestHeader = $xml->addChild('RequestHeader');
- $requestHeader->addChild('AccountNumber', $r->getAccount());
+ $this->_parseTrackingResponse($tracking, $response);
+ }
- /*
- * for tracking result, actual meter number is not needed
- */
- $requestHeader->addChild('MeterNumber', '0');
+ /**
+ * Parse tracking response
+ *
+ * @param array $trackingValue
+ * @param stdClass $response
+ */
+ protected function _parseTrackingResponse($trackingValue, $response)
+ {
+ if (is_object($response)) {
+ if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') {
+ $errorTitle = (string)$response->Notifications->Message;
+ } elseif (isset($response->TrackDetails)) {
+ $trackInfo = $response->TrackDetails;
+ $resultArray['status'] = (string)$trackInfo->StatusDescription;
+ $resultArray['service'] = (string)$trackInfo->ServiceInfo;
+ $timestamp = isset($trackInfo->EstimatedDeliveryTimestamp) ?
+ $trackInfo->EstimatedDeliveryTimestamp : $trackInfo->ActualDeliveryTimestamp;
+ $timestamp = strtotime((string)$timestamp);
+ if ($timestamp) {
+ $resultArray['deliverydate'] = date('Y-m-d', $timestamp);
+ $resultArray['deliverytime'] = date('H:i:s', $timestamp);
+ }
- $packageIdentifier = $xml->addChild('PackageIdentifier');
- $packageIdentifier->addChild('Value', $tracking);
+ $deliveryLocation = isset($trackInfo->EstimatedDeliveryAddress) ?
+ $trackInfo->EstimatedDeliveryAddress : $trackInfo->ActualDeliveryAddress;
+ $deliveryLocationArray = array();
+ if (isset($deliveryLocation->City)) {
+ $deliveryLocationArray[] = (string)$deliveryLocation->City;
+ }
+ if (isset($deliveryLocation->StateOrProvinceCode)) {
+ $deliveryLocationArray[] = (string)$deliveryLocation->StateOrProvinceCode;
+ }
+ if (isset($deliveryLocation->CountryCode)) {
+ $deliveryLocationArray[] = (string)$deliveryLocation->CountryCode;
+ }
+ if ($deliveryLocationArray) {
+ $resultArray['deliverylocation'] = implode(', ', $deliveryLocationArray);
+ }
- /*
- * 0 = summary data, one signle scan structure with the most recent scan
- * 1 = multiple sacn activity for each package
- */
- $xml->addChild('DetailScans', '1');
+ $resultArray['signedby'] = (string)$trackInfo->DeliverySignatureName;
+ $resultArray['shippeddate'] = date('Y-m-d', (int)$trackInfo->ShipTimestamp);
+ if (isset($trackInfo->PackageWeight) && isset($trackInfo->Units)) {
+ $weight = (string)$trackInfo->PackageWeight;
+ $unit = (string)$trackInfo->Units;
+ $resultArray['weight'] = "{$weight} {$unit}";
+ }
- $request = $xml->asXML();
- $debugData = array('request' => $request);
+ $packageProgress = array();
+ if (isset($trackInfo->Events)) {
+ $events = $trackInfo->Events;
+ if (isset($events->Address)) {
+ $events = array($events);
+ }
+ foreach ($events as $event) {
+ $tempArray = array();
+ $tempArray['activity'] = (string)$event->EventDescription;
+ $timestamp = strtotime((string)$event->Timestamp);
+ if ($timestamp) {
+ $tempArray['deliverydate'] = date('Y-m-d', $timestamp);
+ $tempArray['deliverytime'] = date('H:i:s', $timestamp);
+ }
+ if (isset($event->Address)) {
+ $addressArray = array();
+ $address = $event->Address;
+ if (isset($address->City)) {
+ $addressArray[] = (string)$address->City;
+ }
+ if (isset($address->StateOrProvinceCode)) {
+ $addressArray[] = (string)$address->StateOrProvinceCode;
+ }
+ if (isset($address->CountryCode)) {
+ $addressArray[] = (string)$address->CountryCode;
+ }
+ if ($addressArray) {
+ $tempArray['deliverylocation'] = implode(', ', $addressArray);
+ }
+ }
+ $packageProgress[] = $tempArray;
+ }
+ }
- try {
- $url = $this->getConfigData('gateway_url');
- if (!$url) {
- $url = $this->_defaultGatewayUrl;
+ $resultArray['progressdetail'] = $packageProgress;
}
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
- $responseBody = curl_exec($ch);
- $debugData['result'] = $responseBody;
- curl_close ($ch);
}
- catch (Exception $e) {
- $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
- $responseBody = '';
+
+ if(!$this->_result){
+ $this->_result = Mage::getModel('shipping/tracking_result');
+ }
+
+ if(isset($resultArray)) {
+ $tracking = Mage::getModel('shipping/tracking_result_status');
+ $tracking->setCarrier('fedex');
+ $tracking->setCarrierTitle($this->getConfigData('title'));
+ $tracking->setTracking($trackingValue);
+ $tracking->addData($resultArray);
+ $this->_result->append($tracking);
+ } else {
+ $error = Mage::getModel('shipping/tracking_result_error');
+ $error->setCarrier('fedex');
+ $error->setCarrierTitle($this->getConfigData('title'));
+ $error->setTracking($trackingValue);
+ $error->setErrorMessage($errorTitle ? $errorTitle : Mage::helper('usa')->__('Unable to retrieve tracking'));
+ $this->_result->append($error);
}
- $this->_debug($debugData);
- $this->_parseXmlTrackingResponse($tracking, $responseBody);
}
/**
* Parse xml tracking response
*
+ * @deprecated after 1.6.0.0 see _parseTrackingResponse()
* @param array $trackingvalue
* @param string $response
* @return void
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 1f884d9a72..3819a2e6c8 100644
--- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php
+++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Ups.php
@@ -739,6 +739,7 @@ public function getCode($type, $code='')
'14', // Next Day Air Early AM
'02', // 2nd Day Air
'59', // 2nd Day Air AM
+ '13', // Next Day Air Saver
)
),
'from_us' => array(
@@ -1696,10 +1697,22 @@ public function getContainerTypes(Varien_Object $params = null)
$containerTypes = $containerTypes + array(
'03' => Mage::helper('usa')->__('UPS Tube'),
'04' => Mage::helper('usa')->__('PAK'),
- '21' => Mage::helper('usa')->__('UPS Express Box'),
+ '2a' => Mage::helper('usa')->__('Small Express Box'),
+ '2b' => Mage::helper('usa')->__('Medium Express Box'),
+ '2c' => Mage::helper('usa')->__('Large Express Box'),
);
}
return array('00' => Mage::helper('usa')->__('Customer Packaging')) + $containerTypes;
+ } elseif ($countryShipper == self::USA_COUNTRY_ID && $countryRecipient == self::PUERTORICO_COUNTRY_ID
+ && ($method == '03' // UPS Ground
+ || $method == '02' // UPS Second Day Air
+ || $method == '01' // UPS Next Day Air
+ )) {
+ // Container types should be the same as for domestic
+ $params->setCountryRecipient(self::USA_COUNTRY_ID);
+ $containerTypes = $this->_getAllowedContainers($params);
+ $params->setCountryRecipient($countryRecipient);
+ return $containerTypes;
}
return $this->_getAllowedContainers($params);
}
diff --git a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php
index 4685c6aa87..810fbfece2 100644
--- a/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php
+++ b/app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php
@@ -1248,16 +1248,8 @@ protected function _formUsExpressShipmentRequest(Varien_Object $request)
));
}
- if (strlen($request->getShipperAddressPostalCode()) == 5) {
- $fromZip5 = $request->getShipperAddressPostalCode();
- } else {
- $fromZip5 = '';
- }
- if (strlen($request->getShipperAddressPostalCode()) == 4) {
- $fromZip4 = $request->getShipperAddressPostalCode();
- } else {
- $fromZip4 = '';
- }
+ list($fromZip5, $fromZip4) = $this->_parseZip($request->getShipperAddressPostalCode());
+ list($toZip5, $toZip4) = $this->_parseZip($request->getRecipientAddressPostalCode(), true);
$rootNode = 'ExpressMailLabelRequest';
// the wrap node needs for remove xml declaration above
@@ -1287,8 +1279,8 @@ protected function _formUsExpressShipmentRequest(Varien_Object $request)
$xml->addChild('ToAddress2', $request->getRecipientAddressStreet1());
$xml->addChild('ToCity', $request->getRecipientAddressCity());
$xml->addChild('ToState', $request->getRecipientAddressStateOrProvinceCode());
- $xml->addChild('ToZip5', $request->getRecipientAddressPostalCode());
- $xml->addChild('ToZip4');
+ $xml->addChild('ToZip5', $toZip5);
+ $xml->addChild('ToZip4', $toZip4);
$xml->addChild('ToPhone', $request->getRecipientContactPhoneNumber());
$xml->addChild('WeightInOunces', $packageWeight);
$xml->addChild('WaiverOfSignature', $packageParams->getDeliveryConfirmation());
@@ -1338,16 +1330,9 @@ protected function _formUsSignatureConfirmationShipmentRequest(Varien_Object $re
Zend_Measure_Weight::OUNCE
));
}
- if (strlen($request->getShipperAddressPostalCode()) == 5) {
- $fromZip5 = $request->getShipperAddressPostalCode();
- } else {
- $fromZip5 = '';
- }
- if (strlen($request->getShipperAddressPostalCode()) == 4) {
- $fromZip4 = $request->getShipperAddressPostalCode();
- } else {
- $fromZip4 = '';
- }
+
+ list($fromZip5, $fromZip4) = $this->_parseZip($request->getShipperAddressPostalCode());
+ list($toZip5, $toZip4) = $this->_parseZip($request->getRecipientAddressPostalCode(), true);
$rootNode = 'SigConfirmCertifyV3.0Request';
// the wrap node needs for remove xml declaration above
@@ -1370,8 +1355,8 @@ protected function _formUsSignatureConfirmationShipmentRequest(Varien_Object $re
$xml->addChild('ToAddress2', $request->getRecipientAddressStreet1());
$xml->addChild('ToCity', $request->getRecipientAddressCity());
$xml->addChild('ToState', $request->getRecipientAddressStateOrProvinceCode());
- $xml->addChild('ToZip5', $request->getRecipientAddressPostalCode());
- $xml->addChild('ToZip4');
+ $xml->addChild('ToZip5', $toZip5);
+ $xml->addChild('ToZip4', $toZip4);
$xml->addChild('WeightInOunces', $packageWeight);
$xml->addChild('ServiceType', $serviceType);
$xml->addChild('WaiverOfSignature', $packageParams->getDeliveryConfirmation());
@@ -1464,16 +1449,8 @@ protected function _formIntlShipmentRequest(Varien_Object $request)
$container = 'VARIABLE';
}
$shippingMethod = $request->getShippingMethod();
- if (strlen($request->getShipperAddressPostalCode()) == 5) {
- $fromZip5 = $request->getShipperAddressPostalCode();
- } else {
- $fromZip5 = '';
- }
- if (strlen($request->getShipperAddressPostalCode()) == 4) {
- $fromZip4 = $request->getShipperAddressPostalCode();
- } else {
- $fromZip4 = '';
- }
+ list($fromZip5, $fromZip4) = $this->_parseZip($request->getShipperAddressPostalCode());
+
// the wrap node needs for remove xml declaration above
$xmlWrap = new SimpleXMLElement('');
$method = '';
@@ -1802,4 +1779,32 @@ public function getContentTypes(Varien_Object $params)
return array();
}
+ /**
+ * Parse zip from string to zip5-zip4
+ *
+ * @param string $zipString
+ * @param bool $returnFull
+ * @return array
+ */
+ protected function _parseZip($zipString, $returnFull = false)
+ {
+ $zip4 = '';
+ $zip5 = '';
+ $zip = array($zipString);
+ if (preg_match('/[\\d\\w]{5}\\-[\\d\\w]{4}/', $zipString) != 0) {
+ $zip = explode('-', $zipString);
+ }
+ for ($i = 0; $i < count($zip); ++$i) {
+ if (strlen($zip[$i]) == 5) {
+ $zip5 = $zip[$i];
+ } elseif (strlen($zip[$i]) == 4) {
+ $zip4 = $zip[$i];
+ }
+ }
+ if (empty($zip5) && empty($zip4) && $returnFull) {
+ $zip5 = $zipString;
+ }
+
+ return array($zip5, $zip4);
+ }
}
diff --git a/app/code/core/Mage/Usa/etc/wsdl/FedEx/TrackService_v5.wsdl b/app/code/core/Mage/Usa/etc/wsdl/FedEx/TrackService_v5.wsdl
new file mode 100644
index 0000000000..1f275b3104
--- /dev/null
+++ b/app/code/core/Mage/Usa/etc/wsdl/FedEx/TrackService_v5.wsdl
@@ -0,0 +1,1510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Descriptive data for a physical location. May be used as an actual physical address (place to which one could go), or as a container of "address parts" which should be handled as a unit (such as a city-state-ZIP combination within the US).
+
+
+
+
+ Combination of number, street name, etc. At least one line is required for a valid physical address; empty lines should not be included.
+
+
+
+
+ Name of city, town, etc.
+
+
+
+
+ Identifying abbreviation for US state, Canada province, etc. Format and presence of this field will vary, depending on country.
+
+
+
+
+ Identification of a region (usually small) for mail/package delivery. Format and presence of this field will vary, depending on country.
+
+
+
+
+ Relevant only to addresses in Puerto Rico.
+
+
+
+
+ The two-letter code used to identify a country.
+
+
+
+
+ Indicates whether this address residential (as opposed to commercial).
+
+
+
+
+
+
+ Identifies where a tracking event occurs.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Identification of a FedEx operating company (transportation).
+
+
+
+
+
+
+
+
+
+
+
+
+ Descriptive data for the client submitting a transaction.
+
+
+
+
+ The FedEx account number associated with this transaction.
+
+
+
+
+ This number is assigned by FedEx and identifies the unique device from which the request is originating
+
+
+
+
+ Only used in transactions which require identification of the Fed Ex Office integrator.
+
+
+
+
+ The language to be used for human-readable Notification.localizedMessages in responses to the request containing this ClientDetail object. Different requests from the same client may contain different Localization data. (Contrast with TransactionDetail.localization, which governs data payload language/translation.)
+
+
+
+
+
+
+ The descriptive data for a point-of-contact person.
+
+
+
+
+ Identifies the contact person's name.
+
+
+
+
+ Identifies the contact person's title.
+
+
+
+
+ Identifies the company this contact is associated with.
+
+
+
+
+ Identifies the phone number associated with this contact.
+
+
+
+
+ Identifies the phone extension associated with this contact.
+
+
+
+
+ Identifies the pager number associated with this contact.
+
+
+
+
+ Identifies the fax number associated with this contact.
+
+
+
+
+ Identifies the email address associated with this contact.
+
+
+
+
+
+
+
+
+
+
+
+
+ The dimensions of this package and the unit type used for the measurements.
+
+
+
+
+
+
+
+
+
+
+ Driving or other transportation distances, distinct from dimension measurements.
+
+
+
+
+ Identifies the distance quantity.
+
+
+
+
+ Identifies the unit of measure for the distance value.
+
+
+
+
+
+
+ Identifies the collection of units of measure that can be associated with a distance value.
+
+
+
+
+
+
+
+
+ Information describing email notifications that will be sent in relation to events that occur during package movement
+
+
+
+
+ A message that will be included in the email notifications
+
+
+
+
+ Information describing the destination of the email, format of the email and events to be notified on
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The format of the email
+
+
+
+
+
+
+
+
+
+
+
+ Identifies the relationship this email recipient has to the shipment.
+
+
+
+
+ The email address to send the notification to
+
+
+
+
+ The types of email notifications being requested for this recipient.
+
+
+
+
+ The format of the email notification.
+
+
+
+
+ The language/locale to be used in this email notification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CM = centimeters, IN = inches
+
+
+
+
+
+
+
+
+ Identifies the representation of human-readable text.
+
+
+
+
+ Two-letter code for language (e.g. EN, FR, etc.)
+
+
+
+
+ Two-letter code for the region (e.g. us, ca, etc..).
+
+
+
+
+
+
+ The descriptive data regarding the result of the submitted transaction.
+
+
+
+
+ The severity of this notification. This can indicate success or failure or some other information about the request. The values that can be returned are SUCCESS - Your transaction succeeded with no other applicable information. NOTE - Additional information that may be of interest to you about your transaction. WARNING - Additional information that you need to know about your transaction that you may need to take action on. ERROR - Information about an error that occurred while processing your transaction. FAILURE - FedEx was unable to process your transaction at this time due to a system failure. Please try again later
+
+
+
+
+ Indicates the source of this notification. Combined with the Code it uniquely identifies this notification
+
+
+
+
+ A code that represents this notification. Combined with the Source it uniquely identifies this notification.
+
+
+
+
+ Human-readable text that explains this notification.
+
+
+
+
+ The translated message. The language and locale specified in the ClientDetail. Localization are used to determine the representation. Currently only supported in a TrackReply.
+
+
+
+
+ A collection of name/value pairs that provide specific data to help the client determine the nature of an error (or warning, etc.) witout having to parse the message string.
+
+
+
+
+
+
+
+
+ Identifies the type of data contained in Value (e.g. SERVICE_TYPE, PACKAGE_SEQUENCE, etc..).
+
+
+
+
+ The value of the parameter (e.g. PRIORITY_OVERNIGHT, 2, etc..).
+
+
+
+
+
+
+ Identifies the set of severity values for a Notification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Identification for a FedEx operating company (transportation and non-transportation).
+
+
+
+
+
+
+
+ The enumerated packaging type used for this package.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tracking number and additional shipment data used to identify a unique shipment for proof of delivery.
+
+
+
+
+ FedEx assigned identifier for a package/shipment.
+
+
+
+
+ The date the package was shipped.
+
+
+
+
+ If the account number used to ship the package is provided in the request the shipper and recipient information is included on the letter or fax.
+
+
+
+
+ FedEx operating company that delivered the package.
+
+
+
+
+ Only country is used for elimination of duplicate tracking numbers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The service type of the package/shipment.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FedEx Signature Proof Of Delivery Fax reply.
+
+
+
+
+ This contains the severity type of the most severe Notification in the Notifications array.
+
+
+
+
+ Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply.
+
+
+
+
+ Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data.
+
+
+
+
+ Contains the version of the reply being used.
+
+
+
+
+ Confirmation of fax transmission.
+
+
+
+
+
+
+ FedEx Signature Proof Of Delivery Fax request.
+
+
+
+
+ Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services).
+
+
+
+
+ Descriptive data identifying the client submitting the transaction.
+
+
+
+
+ Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations.
+
+
+
+
+ The version of the request being used.
+
+
+
+
+ Tracking number and additional shipment data used to identify a unique shipment for proof of delivery.
+
+
+
+
+ Additional customer-supplied text to be added to the body of the letter.
+
+
+
+
+ Contact and address information about the person requesting the fax to be sent.
+
+
+
+
+ Contact and address information, including the fax number, about the person to receive the fax.
+
+
+
+
+
+
+ Identifies the set of SPOD image types.
+
+
+
+
+
+
+
+ FedEx Signature Proof Of Delivery Letter reply.
+
+
+
+
+ This contains the severity type of the most severe Notification in the Notifications array.
+
+
+
+
+ Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply.
+
+
+
+
+ Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data.
+
+
+
+
+ Image of letter encoded in Base64 format.
+
+
+
+
+ Image of letter encoded in Base64 format.
+
+
+
+
+
+
+ FedEx Signature Proof Of Delivery Letter request.
+
+
+
+
+ Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services).
+
+
+
+
+ Descriptive data identifying the client submitting the transaction.
+
+
+
+
+ Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations.
+
+
+
+
+ The version of the request being used.
+
+
+
+
+ Tracking number and additional shipment data used to identify a unique shipment for proof of delivery.
+
+
+
+
+ Additional customer-supplied text to be added to the body of the letter.
+
+
+
+
+ Identifies the set of SPOD image types.
+
+
+
+
+ If provided this information will be print on the letter.
+
+
+
+
+
+
+ Each instance of this data type represents a barcode whose content must be represented as ASCII text (i.e. not binary data).
+
+
+
+
+ The kind of barcode data in this instance.
+
+
+
+
+ The data content of this instance.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The delivery location at the delivered to address.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Detailed tracking information about a particular package.
+
+
+
+
+ To report soft error on an individual track detail.
+
+
+
+
+ The FedEx package identifier.
+
+
+
+
+
+ When duplicate tracking numbers exist this data is returned with summary information for each of the duplicates. The summary information is used to determine which of the duplicates the intended tracking number is. This identifier is used on a subsequent track request to retrieve the tracking data for the desired tracking number.
+
+
+
+
+ A code that identifies this type of status. This is the most recent status.
+
+
+
+
+ A human-readable description of this status.
+
+
+
+
+ Used to report the status of a piece of a multiple piece shipment which is no longer traveling with the rest of the packages in the shipment or has not been accounted for.
+
+
+
+
+ Used to convey information such as. 1. FedEx has received information about a package but has not yet taken possession of it. 2. FedEx has handed the package off to a third party for final delivery. 3. The package delivery has been cancelled
+
+
+
+
+ Identifies a FedEx operating company (transportation).
+
+
+
+
+ Identifies operating transportation company that is the specific to the carrier code.
+
+
+
+
+ Specifies the FXO production centre contact and address.
+
+
+
+
+ Other related identifiers for this package such as reference numbers.
+
+
+
+
+ Retained for legacy compatibility only. User/screen friendly description of the Service type (e.g. Priority Overnight).
+
+
+
+
+ Strict representation of the Service type (e.g. PRIORITY_OVERNIGHT).
+
+
+
+
+ The weight of this package.
+
+
+
+
+ Physical dimensions of the package.
+
+
+
+
+ The dimensional weight of the package.
+
+
+
+
+ The weight of the entire shipment.
+
+
+
+
+ Retained for legacy compatibility only.
+
+
+
+
+ Strict representation of the Packaging type (e.g. FEDEX_BOX, YOUR_PACKAGING).
+
+
+
+
+ The sequence number of this package in a shipment. This would be 2 if it was package number 2 of 4.
+
+
+
+
+ The number of packages in this shipment.
+
+
+
+
+
+
+ The address information for the shipper.
+
+
+
+
+ The address of the FedEx pickup location/facility.
+
+
+
+
+ Estimated package pickup time for shipments that haven't been picked up.
+
+
+
+
+ Time package was shipped/tendered over to FedEx. Time portion will be populated if available, otherwise will be set to midnight.
+
+
+
+
+ The distance from the origin to the destination. Returned for Custom Critical shipments.
+
+
+
+
+ Total distance package still has to travel. Returned for Custom Critical shipments.
+
+
+
+
+ The address this package is to be (or has been) delivered.
+
+
+
+
+ The address of the FedEx delivery location/facility.
+
+
+
+
+ Projected package delivery time based on ship time stamp, service and destination. Not populated if delivery has already occurred.
+
+
+
+
+ The time the package was actually delivered.
+
+
+
+
+ Actual address where package was delivered. Differs from destinationAddress, which indicates where the package was to be delivered; This field tells where delivery actually occurred (next door, at station, etc.)
+
+
+
+
+ Identifies the method of office order delivery.
+
+
+
+
+ Strict text indicating the delivery location at the delivered to address.
+
+
+
+
+ User/screen friendly representation of the DeliveryLocationType (delivery location at the delivered to address). Can be returned in localized text.
+
+
+
+
+ This is either the name of the person that signed for the package or "Signature not requested" or "Signature on file".
+
+
+
+
+ True if signed for by signature image is available.
+
+
+
+
+ The types of email notifications that are available for the package.
+
+
+
+
+ Returned for cargo shipments only when they are currently split across vehicles.
+
+
+
+
+ Indicates redirection eligibility as determined by tracking service, subject to refinement/override by redirect-to-hold service.
+
+
+
+
+ Event information for a tracking number.
+
+
+
+
+
+
+ FedEx scanning information about a package.
+
+
+
+
+ The time this event occurred.
+
+
+
+
+ Carrier's scan code. Pairs with EventDescription.
+
+
+
+
+ Literal description that pairs with the EventType.
+
+
+
+
+ Further defines the Scan Type code's specific type (e.g., DEX08 business closed). Pairs with StatusExceptionDescription.
+
+
+
+
+ Literal description that pairs with the StatusExceptionCode.
+
+
+
+
+ Address information of the station that is responsible for the scan.
+
+
+
+
+ Indicates where the arrival actually occurred.
+
+
+
+
+
+
+ The type of track to be performed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FedEx assigned identifier for a package/shipment.
+
+
+
+
+ When duplicate tracking numbers exist this data is returned with summary information for each of the duplicates. The summary information is used to determine which of the duplicates the intended tracking number is. This identifier is used on a subsequent track request to retrieve the tracking data for the desired tracking number.
+
+
+
+
+ Identification of a FedEx operating company (transportation).
+
+
+
+
+ The date the package was shipped (tendered to FedEx).
+
+
+
+
+ The destination address of this package. Only city, state/province, and country are returned.
+
+
+
+
+ Options available for a tracking notification recipient.
+
+
+
+
+
+
+ Options available for a tracking notification recipient.
+
+
+
+
+ The types of email notifications available for this recipient.
+
+
+
+
+
+
+ FedEx Track Notification reply.
+
+
+
+
+ This contains the severity type of the most severe Notification in the Notifications array.
+
+
+
+
+ Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply.
+
+
+
+
+ Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data.
+
+
+
+
+ Contains the version of the reply being used.
+
+
+
+
+ True if duplicate packages (more than one package with the same tracking number) have been found, the packages array contains information about each duplicate. Use this information to determine which of the tracking numbers is the one you need and resend your request using the tracking number and TrackingNumberUniqueIdentifier for that package.
+
+
+
+
+ True if additional packages remain to be retrieved.
+
+
+
+
+ Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true).
+
+
+
+
+ Information about the notifications that are available for this tracking number. If there are duplicates the ship date and destination address information is returned for determining which TrackingNumberUniqueIdentifier to use on a subsequent request.
+
+
+
+
+
+
+ FedEx Track Notification request.
+
+
+
+
+ Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services).
+
+
+
+
+ Descriptive data identifying the client submitting the transaction.
+
+
+
+
+ Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations
+
+
+
+
+ Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply).
+
+
+
+
+ The tracking number to which the notifications will be triggered from.
+
+
+
+
+ Indicates whether to return tracking information for all associated packages.
+
+
+
+
+ When the MoreDataAvailable field is true in a TrackNotificationReply the PagingToken must be sent in the subsequent TrackNotificationRequest to retrieve the next page of data.
+
+
+
+
+ Use this field when your original request informs you that there are duplicates of this tracking number. If you get duplicates you will also receive some information about each of the duplicate tracking numbers to enable you to chose one and resend that number along with the TrackingNumberUniqueId to get notifications for that tracking number.
+
+
+
+
+ To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.
+
+
+
+
+ To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.
+
+
+
+
+ Included in the email notification identifying the requester of this notification.
+
+
+
+
+ Included in the email notification identifying the requester of this notification.
+
+
+
+
+ Who to send the email notifications to and for which events. The notificationRecipientType and NotifyOnShipment fields are not used in this request.
+
+
+
+
+
+
+ The type and value of the package identifier that is to be used to retrieve the tracking information for a package.
+
+
+
+
+ The value to be used to retrieve tracking information for a package.
+
+
+
+
+ The type of the Value to be used to retrieve tracking information for a package (e.g. SHIPPER_REFERENCE, PURCHASE_ORDER, TRACKING_NUMBER_OR_DOORTAG, etc..) .
+
+
+
+
+
+
+ Used to report the status of a piece of a multiple piece shipment which is no longer traveling with the rest of the packages in the shipment or has not been accounted for.
+
+
+
+
+ An identifier for this type of status.
+
+
+
+
+ A human-readable description of this status.
+
+
+
+
+
+
+ The descriptive data returned from a FedEx package tracking request.
+
+
+
+
+ This contains the severity type of the most severe Notification in the Notifications array.
+
+
+
+
+ Information about the request/reply such was the transaction successful or not, and any additional information relevant to the request and/or reply. There may be multiple Notifications in a reply.
+
+
+
+
+ Contains the CustomerTransactionDetail that is echoed back to the caller for matching requests and replies and a Localization element for defining the language/translation used in the reply data.
+
+
+
+
+ Contains the version of the reply being used.
+
+
+
+
+ True if duplicate packages (more than one package with the same tracking number) have been found, and only limited data will be provided for each one.
+
+
+
+
+ True if additional packages remain to be retrieved.
+
+
+
+
+ Value that must be passed in a TrackNotification request to retrieve the next set of packages (when MoreDataAvailable = true).
+
+
+
+
+ Contains detailed tracking information for the requested packages(s).
+
+
+
+
+
+
+ The descriptive data sent by a client to track a FedEx package.
+
+
+
+
+ Descriptive data to be used in authentication of the sender's identity (and right to use FedEx web services).
+
+
+
+
+ Descriptive data identifying the client submitting the transaction.
+
+
+
+
+ Contains a free form field that is echoed back in the reply to match requests with replies and data that governs the data payload language/translations.
+
+
+
+
+ The version of the request being used.
+
+
+
+
+ The FedEx operating company (transportation) used for this package's delivery.
+
+
+
+
+ Identifies operating transportation company that is the specific to the carrier code.
+
+
+
+
+ The type and value of the package identifier that is to be used to retrieve the tracking information for a package or group of packages.
+
+
+
+
+ Used to distinguish duplicate FedEx tracking numbers.
+
+
+
+
+ To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.
+
+
+
+
+ To narrow the search to a period in time the ShipDateRangeBegin and ShipDateRangeEnd can be used to help eliminate duplicates.
+
+
+
+
+ For tracking by references information either the account number or destination postal code and country must be provided.
+
+
+
+
+ For tracking by references information either the account number or destination postal code and country must be provided.
+
+
+
+
+ If false the reply will contain summary/profile data including current status. If true the reply contains profile + detailed scan activity for each package.
+
+
+
+
+ When the MoreData field = true in a TrackReply the PagingToken must be sent in the subsequent TrackRequest to retrieve the next page of data.
+
+
+
+
+
+
+
+
+
+
+
+
+ Used when a cargo shipment is split across vehicles. This is used to give the status of each part of the shipment.
+
+
+
+
+ The number of pieces in this part.
+
+
+
+
+ The date and time this status began.
+
+
+
+
+ A code that identifies this type of status.
+
+
+
+
+ A human-readable description of this status.
+
+
+
+
+
+
+ Descriptive data that governs data payload language/translations. The TransactionDetail from the request is echoed back to the caller in the corresponding reply.
+
+
+
+
+ Free form text to be echoed back in the reply. Used to match requests and replies.
+
+
+
+
+ Governs data payload language/translations (contrasted with ClientDetail.localization, which governs Notification.localizedMessage language selection).
+
+
+
+
+
+
+ The descriptive data for the heaviness of an object.
+
+
+
+
+ Identifies the unit of measure associated with a weight value.
+
+
+
+
+ Identifies the weight value of a package/shipment.
+
+
+
+
+
+
+ Identifies the collection of units of measure that can be associated with a weight value.
+
+
+
+
+
+
+
+
+ Used in authentication of the sender's identity.
+
+
+
+
+ Credential used to authenticate a specific software application. This value is provided by FedEx after registration.
+
+
+
+
+
+
+ Two part authentication string used for the sender's identity
+
+
+
+
+ Identifying part of authentication credential. This value is provided by FedEx after registration
+
+
+
+
+ Secret part of authentication key. This value is provided by FedEx after registration.
+
+
+
+
+
+
+ Identifies the version/level of a service operation expected by a caller (in each request) and performed by the callee (in each reply).
+
+
+
+
+ Identifies a system or sub-system which performs an operation.
+
+
+
+
+ Identifies the service business level.
+
+
+
+
+ Identifies the service interface level.
+
+
+
+
+ Identifies the service code level.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/core/Mage/Widget/Block/Adminhtml/Widget/Instance/Edit/Tab/Settings.php b/app/code/core/Mage/Widget/Block/Adminhtml/Widget/Instance/Edit/Tab/Settings.php
index e981b1cc3c..ce7da0159c 100644
--- a/app/code/core/Mage/Widget/Block/Adminhtml/Widget/Instance/Edit/Tab/Settings.php
+++ b/app/code/core/Mage/Widget/Block/Adminhtml/Widget/Instance/Edit/Tab/Settings.php
@@ -150,10 +150,10 @@ protected function _prepareForm()
public function getContinueUrl()
{
return $this->getUrl('*/*/*', array(
- '_current' => true,
- 'type' => '{{type}}',
- 'package' => '{{mpackage}}',
- 'theme' => '{{mtheme}}'
+ '_current' => true,
+ 'type' => '{{type}}',
+ 'package' => '{{package}}',
+ 'theme' => '{{theme}}'
));
}
diff --git a/app/code/core/Mage/Widget/Model/Widget/Instance.php b/app/code/core/Mage/Widget/Model/Widget/Instance.php
index 7140edb55b..c85b0c7799 100644
--- a/app/code/core/Mage/Widget/Model/Widget/Instance.php
+++ b/app/code/core/Mage/Widget/Model/Widget/Instance.php
@@ -236,7 +236,6 @@ protected function _prepareType()
public function setPackageTheme($packageTheme)
{
$this->setData('package_theme', $packageTheme);
- $this->_preparePackageTheme();
return $this;
}
@@ -248,20 +247,18 @@ public function setPackageTheme($packageTheme)
*/
public function getPackageTheme()
{
- $this->_preparePackageTheme();
return $this->_getData('package_theme');
}
/**
* Replace '_' to '/', if was set from request(GET request)
*
+ * @deprecated after 1.6.1.0-alpha1
+ *
* @return Mage_Widget_Model_Widget_Instance
*/
protected function _preparePackageTheme()
{
- if (strpos($this->_getData('package_theme'), '_') >= 0) {
- $this->setData('package_theme', str_replace('_', '/', $this->_getData('package_theme')));
- }
return $this;
}
diff --git a/app/code/core/Mage/Widget/controllers/Adminhtml/Widget/InstanceController.php b/app/code/core/Mage/Widget/controllers/Adminhtml/Widget/InstanceController.php
index 7392750f79..f77bd1873e 100644
--- a/app/code/core/Mage/Widget/controllers/Adminhtml/Widget/InstanceController.php
+++ b/app/code/core/Mage/Widget/controllers/Adminhtml/Widget/InstanceController.php
@@ -68,19 +68,22 @@ protected function _initWidgetInstance()
{
$this->_title($this->__('CMS'))->_title($this->__('Widgets'));
+ /** @var $widgetInstance Mage_Widget_Model_Widget_Instance */
$widgetInstance = Mage::getModel('widget/widget_instance');
+
$instanceId = $this->getRequest()->getParam('instance_id', null);
- $type = $this->getRequest()->getParam('type', null);
- $packageTheme = $this->getRequest()->getParam('package', null) . '/'
- . $this->getRequest()->getParam('theme', null);
- $packageTheme = $packageTheme === '/' ? null : $packageTheme;
+ $type = $this->getRequest()->getParam('type', null);
+ $package = $this->getRequest()->getParam('package', null);
+ $theme = $this->getRequest()->getParam('theme', null);
+
if ($instanceId) {
$widgetInstance->load($instanceId);
if (!$widgetInstance->getId()) {
- $this->_getSession()->addError(Mage::helper('widget')->__('Wrong wigdet instance specified.'));
+ $this->_getSession()->addError(Mage::helper('widget')->__('Wrong widget instance specified.'));
return false;
}
} else {
+ $packageTheme = $package . '/' . $theme == '/' ? null : $package . '/' . $theme;
$widgetInstance->setType($type)
->setPackageTheme($packageTheme);
}
diff --git a/app/code/core/Mage/Wishlist/Block/Abstract.php b/app/code/core/Mage/Wishlist/Block/Abstract.php
index 21ad232962..adf0da4073 100644
--- a/app/code/core/Mage/Wishlist/Block/Abstract.php
+++ b/app/code/core/Mage/Wishlist/Block/Abstract.php
@@ -42,7 +42,7 @@ abstract class Mage_Wishlist_Block_Abstract extends Mage_Catalog_Block_Product_A
protected $_collection;
/**
- * Wishlist Model
+ * Store wishlist Model
*
* @var Mage_Wishlist_Model_Wishlist
*/
@@ -99,21 +99,7 @@ protected function _getCustomerSession()
*/
protected function _getWishlist()
{
- if (is_null($this->_wishlist)) {
- if (Mage::registry('shared_wishlist')) {
- $this->_wishlist = Mage::registry('shared_wishlist');
- }
- elseif (Mage::registry('wishlist')) {
- $this->_wishlist = Mage::registry('wishlist');
- }
- else {
- $this->_wishlist = Mage::getModel('wishlist/wishlist');
- if ($this->_getCustomerSession()->isLoggedIn()) {
- $this->_wishlist->loadByCustomer($this->_getCustomerSession()->getCustomer());
- }
- }
- }
- return $this->_wishlist;
+ return $this->_getHelper()->getWishlist();
}
/**
@@ -136,9 +122,7 @@ public function getWishlistItems()
{
if (is_null($this->_collection)) {
$this->_collection = $this->_getWishlist()
- ->getItemCollection()
- ->addStoreFilter();
-
+ ->getItemCollection();
$this->_prepareCollection($this->_collection);
}
@@ -160,11 +144,12 @@ public function getWishlist()
* Retrieve URL for Removing item from wishlist
*
* @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
+ *
* @return string
*/
- public function getItemRemoveUrl($product)
+ public function getItemRemoveUrl($item)
{
- return $this->_getHelper()->getRemoveUrl($product);
+ return $this->_getHelper()->getRemoveUrl($item);
}
/**
@@ -229,7 +214,7 @@ public function getItemConfigureUrl($product)
public function getEscapedDescription($item)
{
if ($item->getDescription()) {
- return $this->htmlEscape($item->getDescription());
+ return $this->escapeHtml($item->getDescription());
}
return ' ';
}
@@ -279,7 +264,7 @@ public function isSaleable()
*/
public function getWishlistItemsCount()
{
- return $this->getWishlistItems()->count();
+ return $this->_getWishlist()->getItemsCount();
}
/**
@@ -352,8 +337,10 @@ protected function _getItemPriceBlock($productType)
* non-configured products
*
* @param Mage_Catalog_Model_Product $product
- * @param boolean $displayMinimalPrice
+ * @param bool $displayMinimalPrice
* @param string $idSuffix
+ *
+ * @return string
*/
public function getPriceHtml($product, $displayMinimalPrice = false, $idSuffix = '')
{
diff --git a/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php b/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php
index bb8ee012aa..c1cae4e840 100644
--- a/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php
+++ b/app/code/core/Mage/Wishlist/Block/Customer/Sidebar.php
@@ -45,7 +45,7 @@ protected function _prepareCollection($collection)
$collection->setCurPage(1)
->setPageSize(3)
->setInStockFilter(true)
- ->addWishListSortOrder('added_at', 'desc');
+ ->setOrder('added_at');
return $this;
}
@@ -57,7 +57,7 @@ protected function _prepareCollection($collection)
*/
protected function _toHtml()
{
- if (($this->getCustomWishlist() && $this->getItemCount()) || $this->_getHelper()->hasItems()) {
+ if (($this->getCustomWishlist() && $this->getItemCount()) || $this->hasWishlistItems()) {
return parent::_toHtml();
}
@@ -125,6 +125,6 @@ public function getItemCount()
return $this->getCustomWishlist()->getItemsCount();
}
- return $this->helper('wishlist')->getItemCount();
+ return $this->getWishlistItemsCount();
}
}
diff --git a/app/code/core/Mage/Wishlist/Block/Share/Wishlist.php b/app/code/core/Mage/Wishlist/Block/Share/Wishlist.php
index 6fcac49a11..c09ef2f5cc 100644
--- a/app/code/core/Mage/Wishlist/Block/Share/Wishlist.php
+++ b/app/code/core/Mage/Wishlist/Block/Share/Wishlist.php
@@ -80,6 +80,6 @@ public function getWishlistCustomer()
*/
public function getHeader()
{
- return Mage::helper('wishlist')->__("%s's Wishlist", $this->htmlEscape($this->getWishlistCustomer()->getFirstname()));
+ return Mage::helper('wishlist')->__("%s's Wishlist", $this->escapeHtml($this->getWishlistCustomer()->getFirstname()));
}
}
diff --git a/app/code/core/Mage/Wishlist/Helper/Data.php b/app/code/core/Mage/Wishlist/Helper/Data.php
index 062e9963ad..3940e0d83b 100644
--- a/app/code/core/Mage/Wishlist/Helper/Data.php
+++ b/app/code/core/Mage/Wishlist/Helper/Data.php
@@ -103,8 +103,18 @@ protected function _getCurrentCustomer()
public function getWishlist()
{
if (is_null($this->_wishlist)) {
- $this->_wishlist = Mage::getModel('wishlist/wishlist')
- ->loadByCustomer($this->_getCurrentCustomer());
+ if (Mage::registry('shared_wishlist')) {
+ $this->_wishlist = Mage::registry('shared_wishlist');
+ }
+ elseif (Mage::registry('wishlist')) {
+ $this->_wishlist = Mage::registry('wishlist');
+ }
+ else {
+ $this->_wishlist = Mage::getModel('wishlist/wishlist');
+ if ($this->_getCustomerSession()->isLoggedIn()) {
+ $this->_wishlist->loadByCustomer($this->_getCustomerSession()->getCustomer());
+ }
+ }
}
return $this->_wishlist;
}
@@ -112,15 +122,18 @@ public function getWishlist()
/**
* Retrieve wishlist items availability
*
+ * @deprecated after 1.6.0.0
+ *
* @return bool
*/
public function hasItems()
{
- return $this->getItemCount() > 0;
+ return $this->getWishlist()->getItemsCount() > 0;
}
/**
- * Retrieve wishlist item count (inchlude config settings)
+ * Retrieve wishlist item count (include config settings)
+ * Used in top link menu only
*
* @return int
*/
@@ -247,8 +260,9 @@ public function getConfigureUrl($item)
/**
* Retrieve url for adding product to wishlist
*
- * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $product
- * @return string|boolean
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
+ *
+ * @return string|bool
*/
public function getAddUrl($item)
{
@@ -258,8 +272,9 @@ public function getAddUrl($item)
/**
* Retrieve url for updating product in wishlist
*
- * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $product
- * @return string|boolean
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
+ *
+ * @return string|bool
*/
public function getUpdateUrl($item)
{
@@ -282,9 +297,10 @@ public function getUpdateUrl($item)
/**
* Retrieve url for adding product to wishlist with params
*
- * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $product
- * @param array $param
- * @return string|boolean
+ * @param Mage_Catalog_Model_Product|Mage_Wishlist_Model_Item $item
+ * @param array $params
+ *
+ * @return string|bool
*/
public function getAddUrlWithParams($item, array $params = array())
{
@@ -431,10 +447,7 @@ public function getRssUrl()
*/
public function isRssAllow()
{
- if (Mage::getStoreConfig('rss/wishlist/active')) {
- return true;
- }
- return false;
+ return Mage::getStoreConfigFlag('rss/wishlist/active');
}
/**
@@ -457,15 +470,13 @@ public function defaultCommentString()
public function calculate()
{
$session = $this->_getCustomerSession();
- if (!$this->_isCustomerLogIn()) {
- $count = 0;
- } else {
+ $count = 0;
+ if ($this->_isCustomerLogIn()) {
+ $collection = $this->getWishlistItemCollection()->setInStockFilter(true);
if (Mage::getStoreConfig(self::XML_PATH_WISHLIST_LINK_USE_QTY)) {
- $count = $this->getWishlistItemCollection()
- ->setInStockFilter(true)
- ->getItemsQty();
+ $count = $collection->getItemsQty();
} else {
- $count = count($this->getWishlistItemCollection()->setInStockFilter(true));
+ $count = $collection->getSize();
}
$session->setWishlistDisplayType(Mage::getStoreConfig(self::XML_PATH_WISHLIST_LINK_USE_QTY));
$session->setDisplayOutOfStockProducts(
diff --git a/app/code/core/Mage/Wishlist/Model/Resource/Item/Collection.php b/app/code/core/Mage/Wishlist/Model/Resource/Item/Collection.php
index e2c3dc0284..30954dabaf 100755
--- a/app/code/core/Mage/Wishlist/Model/Resource/Item/Collection.php
+++ b/app/code/core/Mage/Wishlist/Model/Resource/Item/Collection.php
@@ -130,8 +130,11 @@ protected function _afterLoad()
protected function _assignOptions()
{
$itemIds = array_keys($this->_items);
- $optionCollection = Mage::getModel('wishlist/item_option')->getCollection()
- ->addItemFilter($itemIds);
+ /* @var $optionCollection Mage_Wishlist_Model_Resource_Item_Option_Collection */
+ $optionCollection = Mage::getModel('wishlist/item_option')->getCollection();
+ $optionCollection->addItemFilter($itemIds);
+
+ /* @var $item Mage_Wishlist_Model_Item */
foreach ($this as $item) {
$item->setOptions($optionCollection->getOptionsByItem($item));
}
@@ -227,21 +230,18 @@ public function addWishlistFilter(Mage_Wishlist_Model_Wishlist $wishlist)
/**
* Add filter by shared stores
*
- * @param int|array $store
+ * @param array $storeIds
+ *
* @return Mage_Wishlist_Model_Resource_Item_Collection
*/
- public function addStoreFilter($store = null)
+ public function addStoreFilter($storeIds = array())
{
- if (is_null($store)) {
- $store = Mage::app()->getStore()->getId();
+ if (!is_array($storeIds)) {
+ $storeIds = array($storeIds);
}
+ $this->_storeIds = $storeIds;
+ $this->addFieldToFilter('store_id', array('in' => $this->_storeIds));
- if (!is_array($store)) {
- $store = array($store);
- }
- $this->_storeIds = $store;
-
- $this->addFieldToFilter('store_id', $store);
return $this;
}
@@ -263,6 +263,9 @@ public function addStoreData()
/**
* Add wishlist sort order
*
+ * @deprecated after 1.6.0.0-rc2
+ * @see Varien_Data_Collection_Db::setOrder() is used instead
+ *
* @param string $attribute
* @param string $dir
* @return Mage_Wishlist_Model_Resource_Item_Collection
diff --git a/app/code/core/Mage/Wishlist/Model/Resource/Wishlist.php b/app/code/core/Mage/Wishlist/Model/Resource/Wishlist.php
index e0d7394bed..b4e42feb86 100755
--- a/app/code/core/Mage/Wishlist/Model/Resource/Wishlist.php
+++ b/app/code/core/Mage/Wishlist/Model/Resource/Wishlist.php
@@ -26,7 +26,7 @@
/**
- * Wishlist model resource
+ * Wishlist resource model
*
* @category Mage
* @package Mage_Wishlist
@@ -35,22 +35,21 @@
class Mage_Wishlist_Model_Resource_Wishlist extends Mage_Core_Model_Resource_Db_Abstract
{
/**
- * Items count
+ * Store wishlist items count
*
- * @var int
+ * @var null|int
*/
- protected $_itemsCount = null;
+ protected $_itemsCount = null;
/**
- * CustomerId field name
+ * Store customer ID field name
*
* @var string
*/
- protected $_customerIdFieldName = 'customer_id';
+ protected $_customerIdFieldName = 'customer_id';
/**
- * Wishlist constructor
- *
+ * Set main entity table name and primary key field name
*/
protected function _construct()
{
@@ -58,7 +57,7 @@ protected function _construct()
}
/**
- * CustomerId field name getter
+ * Getter for customer ID field name
*
* @return string
*/
@@ -68,9 +67,10 @@ public function getCustomerIdFieldName()
}
/**
- * CustomerId field name setter
+ * Setter for customer ID field name
+ *
+ * @param $fieldName
*
- * @param string $fieldName
* @return Mage_Wishlist_Model_Resource_Wishlist
*/
public function setCustomerIdFieldName($fieldName)
@@ -80,21 +80,22 @@ public function setCustomerIdFieldName($fieldName)
}
/**
- * Fetch items count
+ * Retrieve wishlist items count
+ *
+ * @deprecated after 1.6.0.0-rc2
+ * @see Mage_Wishlist_Model_Wishlist::getItemsCount()
*
* @param Mage_Wishlist_Model_Wishlist $wishlist
+ *
* @return int
*/
public function fetchItemsCount(Mage_Wishlist_Model_Wishlist $wishlist)
{
if (is_null($this->_itemsCount)) {
- $collection = $wishlist->getItemCollection()
- ->addStoreFilter()
- ->setVisibilityFilter();
-
- $this->_itemsCount = $collection->getSize();
+ $this->_itemsCount = $wishlist->getItemsCount();
}
return $this->_itemsCount;
}
+
}
diff --git a/app/code/core/Mage/Wishlist/Model/Wishlist.php b/app/code/core/Mage/Wishlist/Model/Wishlist.php
index 5126b828ff..df9965b8ed 100644
--- a/app/code/core/Mage/Wishlist/Model/Wishlist.php
+++ b/app/code/core/Mage/Wishlist/Model/Wishlist.php
@@ -66,7 +66,6 @@ class Mage_Wishlist_Model_Wishlist extends Mage_Core_Model_Abstract
/**
* Initialize resource model
- *
*/
protected function _construct()
{
@@ -86,6 +85,7 @@ public function loadByCustomer($customer, $create = false)
$customer = $customer->getId();
}
+ $customer = (int) $customer;
$customerIdFieldName = $this->_getResource()->getCustomerIdFieldName();
$this->_getResource()->load($this, $customer, $customerIdFieldName);
if (!$this->getId() && $create) {
@@ -151,11 +151,12 @@ protected function _afterSave()
}
/**
- * Adding catalog product object data to wishlist
+ * Add catalog product object data to wishlist
*
* @param Mage_Catalog_Model_Product $product
* @param int $qty
* @param bool $forciblySetQty
+ *
* @return Mage_Wishlist_Model_Item
*/
protected function _addCatalogProduct(Mage_Catalog_Model_Product $product, $qty = 1, $forciblySetQty = false)
@@ -198,8 +199,12 @@ protected function _addCatalogProduct(Mage_Catalog_Model_Product $product, $qty
public function getItemCollection()
{
if (is_null($this->_itemCollection)) {
+ /** @var $currentWebsiteOnly boolean */
+ $currentWebsiteOnly = !Mage::app()->getStore()->isAdmin();
$this->_itemCollection = Mage::getResourceModel('wishlist/item_collection')
- ->addWishlistFilter($this);
+ ->addWishlistFilter($this)
+ ->addStoreFilter($this->getSharedStoreIds($currentWebsiteOnly))
+ ->setVisibilityFilter();
}
return $this->_itemCollection;
@@ -381,12 +386,13 @@ public function getDataForSave()
*/
public function getSharedStoreIds($current = true)
{
- if (is_null($this->_storeIds)) {
+ if (is_null($this->_storeIds) || !is_array($this->_storeIds)) {
if ($current) {
$this->_storeIds = $this->getStore()->getWebsite()->getStoreIds();
} else {
$_storeIds = array();
- foreach (Mage::app()->getStores() as $store) {
+ $stores = Mage::app()->getStores();
+ foreach ($stores as $store) {
$_storeIds[] = $store->getId();
}
$this->_storeIds = $_storeIds;
@@ -403,7 +409,7 @@ public function getSharedStoreIds($current = true)
*/
public function setSharedStoreIds($storeIds)
{
- $this->_storeIds = $storeIds;
+ $this->_storeIds = (array) $storeIds;
return $this;
}
@@ -439,7 +445,7 @@ public function setStore($store)
*/
public function getItemsCount()
{
- return $this->_getResource()->fetchItemsCount($this);
+ return $this->getItemCollection()->getSize();
}
/**
@@ -509,7 +515,18 @@ public function updateItem($itemId, $buyRequest, $params = null)
$buyRequest = Mage::helper('catalog/product')->addParamsToBuyRequest($buyRequest, $params);
$product->setWishlistStoreId($item->getStoreId());
- $resultItem = $this->addNewItem($product, $buyRequest, true);
+ $items = $this->getItemCollection();
+ $isForceSetQuantity = true;
+ foreach ($items as $_item) {
+ /* @var $_item Mage_Wishlist_Model_Item */
+ if ($_item->getProductId() == $product->getId()
+ && $_item->representProduct($product)
+ && $_item->getId() != $item->getId()) {
+ // We do not add new wishlist item, but updating the existing one
+ $isForceSetQuantity = false;
+ }
+ }
+ $resultItem = $this->addNewItem($product, $buyRequest, $isForceSetQuantity);
/**
* Error message
*/
@@ -523,18 +540,9 @@ public function updateItem($itemId, $buyRequest, $params = null)
}
$item->isDeleted(true);
$this->setDataChanges(true);
-
- $items = $this->getItemCollection();
- 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);
+ $resultItem->setQty($buyRequest->getQty() * 1);
+ $resultItem->setOrigData('qty', 0);
}
} else {
Mage::throwException(Mage::helper('checkout')->__('The product does not exist.'));
diff --git a/app/code/core/Mage/Wishlist/controllers/IndexController.php b/app/code/core/Mage/Wishlist/controllers/IndexController.php
index 9bcc4db7c9..db76caa080 100644
--- a/app/code/core/Mage/Wishlist/controllers/IndexController.php
+++ b/app/code/core/Mage/Wishlist/controllers/IndexController.php
@@ -200,7 +200,6 @@ 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.'));
}
@@ -602,7 +601,7 @@ public function downloadCustomOptionAction()
$option = Mage::getModel('wishlist/item_option')->load($optionId);
$hasError = false;
- if ($option->getId()) {
+ if ($option->getId() && $option->getCode() !== 'info_buyRequest') {
$info = unserialize($option->getValue());
$filePath = Mage::getBaseDir() . $info['quote_path'];
$secretKey = $this->getRequest()->getParam('key');
@@ -615,7 +614,8 @@ public function downloadCustomOptionAction()
}
}
} catch(Exception $e) {
+ $this->_forward('noRoute');
}
- $this->_forward('noRoute');
+ exit(0);
}
}
diff --git a/app/code/core/Mage/Wishlist/controllers/SharedController.php b/app/code/core/Mage/Wishlist/controllers/SharedController.php
index afa38845c1..947718b619 100644
--- a/app/code/core/Mage/Wishlist/controllers/SharedController.php
+++ b/app/code/core/Mage/Wishlist/controllers/SharedController.php
@@ -97,7 +97,7 @@ public function cartAction()
$session = Mage::getSingleton('wishlist/session');
$cart = Mage::getSingleton('checkout/cart');
- $redirectUrl = Mage::getUrl('*/*');
+ $redirectUrl = $this->_getRefererUrl();
try {
$options = Mage::getModel('wishlist/item_option')->getCollection()
@@ -109,18 +109,13 @@ public function cartAction()
if (Mage::helper('checkout/cart')->getShouldRedirectToCart()) {
$redirectUrl = Mage::helper('checkout/cart')->getCartUrl();
- } else if ($this->_getRefererUrl()) {
- $redirectUrl = $this->_getRefererUrl();
}
} catch (Mage_Core_Exception $e) {
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) {
- Mage::getSingleton('catalog/session')->addNotice($e->getMessage());
- $redirectUrl = Mage::getUrl('*/*/configure/', array('id' => $item->getId()));
} else {
Mage::getSingleton('catalog/session')->addNotice($e->getMessage());
- $redirectUrl = Mage::getUrl('*/*/configure/', array('id' => $item->getId()));
+ $redirectUrl = $item->getProductUrl();
}
} catch (Exception $e) {
$session->addException($e, Mage::helper('wishlist')->__('Cannot add item to shopping cart'));
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/History.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/History.php
index 08a88462f3..eb4169af97 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/History.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/History.php
@@ -27,9 +27,9 @@
/**
* XmlConnect application submission history grid
*
- * @category Mage
- * @package Mage_XmlConnect
- * @author Magento Core Team
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
*/
class Mage_XmlConnect_Block_Adminhtml_History extends Mage_Adminhtml_Block_Widget_Grid_Container
{
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/History/Grid.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/History/Grid.php
index 4a159a7dc5..79fb163932 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/History/Grid.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/History/Grid.php
@@ -27,9 +27,9 @@
/**
* XmlConnect application history grid
*
- * @category Mage
- * @package Mage_XmlConnect
- * @author Magento Core Team
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
*/
class Mage_XmlConnect_Block_Adminhtml_History_Grid extends Mage_Adminhtml_Block_Widget_Grid
{
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile.php
index 04ceb529da..310acf8d36 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile.php
@@ -27,9 +27,9 @@
/**
* XmlConnect application grid
*
- * @category Mage
- * @package Mage_XmlConnect
- * @author Magento Core Team
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
*/
class Mage_XmlConnect_Block_Adminhtml_Mobile extends Mage_Adminhtml_Block_Widget_Grid_Container
{
@@ -40,7 +40,12 @@ public function __construct()
{
$this->_controller = 'adminhtml_mobile';
$this->_blockGroup = 'xmlconnect';
- $this->_headerText = $this->__('Manage Apps');
+ $xmlconnectVersion = Mage::getConfig()->getNode(
+ Mage_XmlConnect_Model_Application::XML_PATH_MODULE_VERSION
+ );
+ $this->_headerText = $this->__('Manage Apps')
+ . ' '
+ . $this->__('ver. %s', $xmlconnectVersion);
$this->_addButtonLabel = $this->__('Add App');
parent::__construct();
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit.php
index 02bd7a268b..2144e9bab0 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
+
+/**
+ * Application edit block
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit
+ extends Mage_Adminhtml_Block_Widget_Form_Container
{
/**
* Setting app action buttons for application
@@ -119,7 +128,7 @@ public function getHeaderText()
}
if (isset($app) && $app->getId()) {
- return $this->__('Edit App "%s"', $this->htmlEscape($app->getName()));
+ return $this->__('Edit App "%s"', $this->escapeHtml($app->getName()));
} else {
return $this->__('New App');
}
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php
index a9a93f2983..0117686836 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Form.php
@@ -23,6 +23,14 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+
+/**
+ * Application Form block
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
/**
@@ -33,9 +41,10 @@ class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Form extends Mage_Adminhtml_Bl
*/
protected function _prepareForm()
{
- $form = new Varien_Data_Form(array('id' => 'edit_form',
+ $form = new Varien_Data_Form(array('id' => 'edit_form',
'action' => Mage::getSingleton('adminhtml/session')->getNewApplication()
- ? $this->getUrl('*/mobile/edit', array('_current' => true)) : $this->getUrl('*/mobile/save'),
+ ? $this->getUrl('*/mobile/edit', array('_current' => true))
+ : $this->getUrl('*/mobile/save'),
'method' => 'post',
'enctype' => 'multipart/form-data'
));
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php
index 3ac44d0e0f..6c1af9ac6e 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Submission.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Submission extends Mage_Adminhtml_Block_Widget_Tabs
+
+/**
+ * Application Submission block
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Submission
+ extends Mage_Adminhtml_Block_Widget_Tabs
{
/**
* Constructor
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Cache.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Cache.php
index a351fd658b..fd5ed70bce 100755
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Cache.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Cache.php
@@ -31,7 +31,8 @@
* @package Mage_XmlConnect
* @author Magento Core Team
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Cache extends Mage_Adminhtml_Block_Widget_Form
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Cache
+ extends Mage_Adminhtml_Block_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
/**
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php
index 031b42b80f..57e97bb4e6 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Content.php
@@ -23,6 +23,14 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+
+/**
+ * Tab for Content Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Content
extends Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
@@ -47,10 +55,10 @@ public function __construct()
*/
protected function _addPage($fieldset, $fieldPrefix)
{
- $el = $fieldset->addField($fieldPrefix, 'page', array(
+ $element = $fieldset->addField($fieldPrefix, 'page', array(
'name' => $fieldPrefix,
));
- $el->initFields(array(
+ $element->initFields(array(
'name' => $fieldPrefix,
'values' => $this->_pages,
));
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php
index 39e6cbbab7..5ef12f4e69 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design extends Mage_Adminhtml_Block_Template
+
+/**
+ * Tab for Design Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design
+ extends Mage_Adminhtml_Block_Template
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
/**
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php
index 80f3db6d00..5045b69c57 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design_Accordion extends Mage_Adminhtml_Block_Widget_Accordion
+
+/**
+ * Tab design accordion xml renderer
+ *
+ * @category Mage
+ * @package Mage_Xmlconnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design_Accordion
+ extends Mage_Adminhtml_Block_Widget_Accordion
{
/**
* Add accordion item by specified block
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php
index 7ac9589ea0..38f366cc6e 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Images.php
@@ -23,6 +23,14 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+
+/**
+ * Tab design Accordion Images xml renderer
+ *
+ * @category Mage
+ * @package Mage_Xmlconnect
+ * @author Magento Core Team
+ */
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design_Accordion_Images
extends Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
{
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php
index ca8cc9e8ca..d62626d6fb 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Accordion/Tabs.php
@@ -25,7 +25,7 @@
*/
/**
- * Device tabs accourdion block
+ * Device tabs accordion block
*
* @category Mage
* @package Mage_XmlConnect
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php
index 876a80553a..527edf358a 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Preview.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design_Preview extends Mage_Adminhtml_Block_Template
+
+/**
+ * Tab design preview xml renderer
+ *
+ * @category Mage
+ * @package Mage_Xmlconnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design_Preview
+ extends Mage_Adminhtml_Block_Template
{
/**
* Set preview template
@@ -36,7 +45,9 @@ public function __construct()
if (array_key_exists($device, Mage::helper('xmlconnect')->getSupportedDevices())) {
$template = 'xmlconnect/edit/tab/design/preview_' . strtolower($device) . '.phtml';
} else {
- Mage::throwException($this->__('Device doesn\'t recognized. Unable to load a template.'));
+ Mage::throwException(
+ $this->__('Device doesn\'t recognized. Unable to load a template.')
+ );
}
$this->setTemplate($template);
@@ -58,7 +69,6 @@ public function getPreviewActionUrl($page = 'home')
} else {
$params = array('devtype' => $model->getType());
}
-
}
return $this->getUrl('*/*/preview' . $page, $params);
}
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php
index a10067cab2..4307b30df1 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Design/Themes.php
@@ -34,8 +34,7 @@
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Design_Themes extends Mage_Adminhtml_Block_Template
{
/**
- * Set themes template
- * Set color fieldsets
+ * Set themes template and color fieldsets
*/
public function __construct()
{
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Flurryanalytics.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Flurryanalytics.php
index 2216fb75c9..2a4124638e 100755
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Flurryanalytics.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Flurryanalytics.php
@@ -23,6 +23,14 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+
+/**
+ * Tab for Flurry Analytics Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Flurryanalytics
extends Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
@@ -30,7 +38,7 @@ class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Flurryanalytics
protected $_pages;
/**
- * Construnctor
+ * Constructor
* Setting view options
*/
public function __construct()
@@ -74,7 +82,7 @@ protected function _prepareForm()
Mage::getStoreConfig('xmlconnect/flurry_analytics/statistics_url')
);
- $flurryLink = $fieldset->addField('flurry_analytics_link', 'link', array(
+ $fieldset->addField('flurry_analytics_link', 'link', array(
'title' => $this->__('Flurry Analytics Site'),
'label' => $this->__('Flurry Analytics Site'),
'value' => $flurryAnalyticsUrl,
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php
index 8de396d899..0b325ccf95 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/General.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_General extends Mage_Adminhtml_Block_Widget_Form
+
+/**
+ * Tab for General Info Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_General
+ extends Mage_Adminhtml_Block_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
/**
@@ -57,7 +66,7 @@ protected function _prepareForm()
));
if ($model->getId()) {
- $field = $fieldset->addField('code', 'label', array(
+ $fieldset->addField('code', 'label', array(
'label' => $this->__('App Code'),
'title' => $this->__('App Code'),
'value' => $model->getCode(),
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Notification.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Notification.php
index 6c14ba4109..e339b4065b 100755
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Notification.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Notification.php
@@ -23,12 +23,20 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+
+/**
+ * Tab for Notifications Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Notification
extends Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
/**
- * Construnctor
+ * Constructor
* Setting view options
*/
public function __construct()
@@ -179,7 +187,7 @@ public function getTabTitle()
public function canShowTab()
{
return (bool) !Mage::getSingleton('adminhtml/session')->getNewApplication()
- && Mage::helper('xmlconnect')->getDeviceType() == Mage_XmlConnect_Helper_Data::DEVICE_TYPE_IPHONE;
+ && Mage::helper('xmlconnect')->isNotificationsAllowed();
}
/**
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php
index e61c124b6e..742d212785 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Payment.php
@@ -23,6 +23,14 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
+
+/**
+ * Tab for Payments Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Payment
extends Mage_XmlConnect_Block_Adminhtml_Mobile_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
@@ -30,7 +38,7 @@ class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Payment
protected $_pages;
/**
- * Construnctor
+ * Constructor
* Setting view options
*/
public function __construct()
@@ -77,32 +85,33 @@ protected function _prepareForm()
/**
* PayPal MEP management
*/
- $isExpressCheckoutAvailable = Mage::getModel('xmlconnect/payment_method_paypal_mep')
+ $fieldsetPaypal = $form->addFieldset('paypal_mep_checkout', array(
+ 'legend' => $this->__('PayPal Mobile Embedded Payment (MEP)')
+ ));
+
+ $paypalMepIsAvailable = Mage::getModel('xmlconnect/payment_method_paypal_mep')
->isAvailable(null);
$paypalActive = 0;
if (isset($data['conf[native][paypal][isActive]'])) {
- $paypalActive = (int)($data['conf[native][paypal][isActive]'] && $isExpressCheckoutAvailable);
+ $paypalActive = (int)($data['conf[native][paypal][isActive]'] && $paypalMepIsAvailable);
}
- $fieldsetPaypal = $form->addFieldset('paypal_mep_checkout', array(
- 'legend' => $this->__('PayPal Mobile Embedded Payment (MEP)')
- ));
-
- $activateMepMethodNote = $this->__('To activate PayPal MEP payment method activate Express checkout first. ');
$paypalConfigurationUrl = $this->escapeHtml(
$this->getUrl('adminhtml/system_config/edit', array('section' => 'paypal'))
);
+ $activateMepMethodNote = $this->__('To activate PayPal MEP payment method activate Express checkout first. ');
+
$businessAccountNote = $this->__('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' => $this->__('Activate PayPal Checkout'),
'name' => 'conf[native][paypal][isActive]',
- 'note' => (!$isExpressCheckoutAvailable ? $activateMepMethodNote : $businessAccountNote),
+ 'note' => (!$paypalMepIsAvailable ? $activateMepMethodNote : $businessAccountNote),
'values' => $yesNoValues,
'value' => $paypalActive,
- 'disabled' => !$isExpressCheckoutAvailable
+ 'disabled' => !$paypalMepIsAvailable
));
if (isset($data['conf[special][merchantLabel]'])) {
@@ -184,6 +193,41 @@ protected function _prepareForm()
);
break;
case Mage_XmlConnect_Helper_Data::DEVICE_TYPE_ANDROID:
+ /**
+ * PayPal MECL management
+ */
+ if (Mage::app()->isSingleStoreMode() || Mage::helper('xmlconnect')->getApplication()->getId()) {
+ $paypalMeclIsAvailable = Mage::getModel('xmlconnect/payment_method_paypal_mecl')
+ ->isAvailable();
+ $activateMeclMethodNote = $this->__('You need to enable PayPal Express Checkout first from the Payment configuration before enabling PayPal MECL.');
+ } else {
+ $paypalMeclIsAvailable = false;
+ $activateMeclMethodNote = $this->__('Please create and save an application first.');
+ }
+
+ $fieldsetMecl = $form->addFieldset('paypal_mecl_checkout', array(
+ 'legend' => $this->__('PayPal Mobile Express Checkout Library (MECL)')
+ ));
+
+ $meclAccountNote = $this->__('PayPal MECL is the mobile version of PayPal\'s Express Checkout service. You can choose to use MECL alongside standard checkout, or use it as your only checkout method for Magento Mobile.');
+
+ $paypalMeclActive = 0;
+ if (isset($data['config_data[payment][paypalmecl_is_active]'])) {
+ $paypalMeclActive = (int) $data['config_data[payment][paypalmecl_is_active]'];
+ }
+
+ $fieldsetMecl->addField('config_data/paypalmecl_is_active', 'select', array(
+ 'label' => $this->__('Activate PayPal MECL'),
+ 'name' => 'config_data[payment:paypalmecl_is_active]',
+ 'note' => (!$paypalMeclIsAvailable ? $activateMeclMethodNote : $meclAccountNote),
+ 'values' => $yesNoValues,
+ 'value' => $paypalMeclActive,
+ 'disabled' => !$paypalMeclIsAvailable
+ ));
+
+ /**
+ * PayPal MEP management
+ */
$fieldsetPaypal = $form->addFieldset('paypal_mep_checkout', array(
'legend' => $this->__('PayPal Mobile Embedded Payment (MEP)')
));
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Settings.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Settings.php
index 7b450ae565..faac69b2e4 100755
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Settings.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Settings.php
@@ -23,7 +23,16 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Settings extends Mage_Adminhtml_Block_Widget_Form
+
+/**
+ * Tab for Settings Management
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Settings
+ extends Mage_Adminhtml_Block_Widget_Form
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
protected function _prepareLayout()
@@ -34,8 +43,9 @@ protected function _prepareLayout()
'label' => Mage::helper('catalog')->__('Continue'),
'onclick' => "if (editForm.submit()) { return false }",
'class' => 'save'
- ))
- );
+ )
+ )
+ );
return parent::_prepareLayout();
}
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php
index 9119471835..c73fc34e76 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tab/Submission/History.php
@@ -27,11 +27,12 @@
/**
* XmlConnect application history grid
*
- * @category Mage
- * @package Mage_XmlConnect
- * @author Magento Core Team
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Submission_History extends Mage_Adminhtml_Block_Widget_Grid
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tab_Submission_History
+ extends Mage_Adminhtml_Block_Widget_Grid
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
/**
@@ -92,8 +93,8 @@ public function isHidden()
}
/**
- * Initialize history colelction
- * Set aaplication filter
+ * Initialize history collection
+ * Set application filter
*
* @return Mage_Adminhtml_Block_Widget_Grid
*/
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php
index 3d9042b07f..7cfc88b7ba 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Edit/Tabs.php
@@ -23,13 +23,20 @@
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
+
+/**
+ * Application Tabs block
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Edit_Tabs
+ extends Mage_Adminhtml_Block_Widget_Tabs
{
/**
* Constructor
- *
* Setting grid_id, DOM destination element id, Title
- *
*/
public function __construct()
{
@@ -49,7 +56,9 @@ protected function _prepareLayout()
if (Mage::getSingleton('adminhtml/session')->getNewApplication()) {
$this->addTab('set', array(
'label' => $this->__('Settings'),
- 'content' => $this->getLayout()->createBlock('xmlconnect/adminhtml_mobile_edit_tab_settings')->toHtml(),
+ 'content' => $this->getLayout()
+ ->createBlock('xmlconnect/adminhtml_mobile_edit_tab_settings')
+ ->toHtml(),
'active' => true
));
}
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php
index 02dae6f2a5..67cabb2c70 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Addrow.php
@@ -24,7 +24,15 @@
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Addrow extends Varien_Data_Form_Element_Button
+/**
+ * Xmlconnect Add row form element
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Addrow
+ extends Varien_Data_Form_Element_Button
{
/**
* Render Element Html
@@ -33,10 +41,17 @@ class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Addrow extends Varien_
*/
public function getElementHtml()
{
- $html = $this->getBeforeElementHtml() . ''
+ . $this->getAfterElementHtml();
return $html;
}
@@ -52,25 +67,27 @@ public function getBeforeElementHtml()
/**
* Return label html code
- *
+ *
* @param string $idSuffix
* @return string
*/
public function getLabelHtml($idSuffix = '')
{
- if (!is_null($this->getLabel())) {
- $html = '';
+ if ($this->getLabel() !== null) {
+ $html = '';
} else {
$html = '';
}
return $html;
}
-
+
/**
* Overriding toHtml parent method
* Adding addrow Block to element renderer
- *
+ *
* @return string
*/
public function toHtml()
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php
index 060d0153b6..b4e7472c54 100644
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Color.php
@@ -24,11 +24,19 @@
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Color extends Varien_Data_Form_Element_Text
+/**
+ * Xmlconnect color form element
+ *
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
+ */
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Color
+ extends Varien_Data_Form_Element_Text
{
/**
* Return html code for current block
- *
+ *
* @return mixed|string
*/
public function getHtml()
diff --git a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Country.php b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Country.php
index b0c8842e42..75143b51d8 100755
--- a/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Country.php
+++ b/app/code/core/Mage/XmlConnect/Block/Adminhtml/Mobile/Form/Element/Country.php
@@ -27,11 +27,12 @@
/**
* XmlConnect Country selector form element
*
- * @category Mage
- * @package Mage_XmlConnect
- * @author Magento Core Team
+ * @category Mage
+ * @package Mage_XmlConnect
+ * @author Magento Core Team
*/
-class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Country extends Varien_Data_Form_Element_Checkboxes
+class Mage_XmlConnect_Block_Adminhtml_Mobile_Form_Element_Country
+ extends Varien_Data_Form_Element_Checkboxes
{
/**
* Flag of using the border in the table's TD
@@ -90,7 +91,7 @@ public function getElementHtml()
$id = $this->getData('id');
$id = empty($id) ? '' : ' id="' . $id . '-table"';
$class = $this->getData('class');
- $html = "\n
\n";
+ $html = PHP_EOL . "
" . PHP_EOL;
$zebrine = '';
$stripy = false;
@@ -100,7 +101,7 @@ public function getElementHtml()
$columns--;
foreach ($options as $row) {
- $html .= "
\n ";
+ $html .= "
" . PHP_EOL;
if ($stripy) {
$zebrine = empty($zebrine) ? ' class="odd"' : '';
@@ -123,11 +124,10 @@ public function getElementHtml()
}
}
- $html .= "\n
- __('Do not set any fields in the Billing and Shipping Information block as editable in your Payflow accout.') ?>
+ __('Do not set any fields in the Billing and Shipping Information block as editable in your Payflow account.'); ?>
__('Do not enable AVS or CSC options. The do not work when using Payflow Link Silent Mode.') ?>
@@ -81,7 +81,32 @@
__('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.') ?>
+ __('Please navigate to Hosted Checkout Pages - Customize menu and select Layout C.') ?>
+
+
+
+
+ __('When using Payflow Link in Magento, a payment authorization transaction must be performed after the shopper enters their credit card information on the Payment page of checkout. If a full authorization is performed for the entire dollar amount of the transaction, then in some cases, the transaction amount might be reserved on the shopper\'s credit card for up to 30 days, even if they abandon their cart. This is not an ideal customer experience. Using this advanced setting in Magento, you can configure key details of this authorization.') ?>
+
+
+
+ __('Select $0 Auth if your credit card processor supports $0 Auth capability and Reference Transactions, or if you are unsure what to select. This setting provides the best experience for shoppers.') ?>
+
+
+ __('Select $1 Auth if your credit card processor does not support $0 Auth, but does support Reference Transactions. This will provide a very good shopper experience, but might require you to pay a small additional authorization fee from your merchant account provider for any cart abandoned after payment details are entered. If you select $0 Auth, but your credit card processor does not support $0 Auth, your transaction will run as a $1 Auth instead.') ?>
+
+
+ __('Select Full Auth if you want to minimize your credit card processing fees, or if your credit card processor does not permit reference transactions. Please note that in some cases, shoppers who abandon your cart late in the process may find that there is a payment authorization outstanding from your company, which will go away on its own in a few days/weeks. This authorization can be reversal by voiding it, however, there is no guarantee the card-issuing bank will accept this request.') ?>