FI_Checkout - Version 1.0.3

Version Notes

- Refactored javascript code using pattern builder to make it easily support and customized.
- Fixed few bugs with wrong logic.
- Refactored PHP code, put all process that used customer session into helper. It makes some parts of code shared between different parts of the extension.

Version 1.0 released
2012/05/16
Version number: 1.0
Stability: stable
Compatibility: 1.5, 1.6, 1.6.0.0, 1.6.1, 1.6.2.0, 1.7

Download this release

Release Info

Developer Sergiy Stotskiy
Extension FI_Checkout
Version 1.0.3
Comparing to
See all releases


Version 1.0.3

Files changed (39) hide show
  1. app/code/local/FI/Checkout/Block/Block.php +66 -0
  2. app/code/local/FI/Checkout/Block/Block/Info.php +270 -0
  3. app/code/local/FI/Checkout/Block/Newsletter.php +28 -0
  4. app/code/local/FI/Checkout/Block/Payment/Methods.php +38 -0
  5. app/code/local/FI/Checkout/Helper/Data.php +429 -0
  6. app/code/local/FI/Checkout/Model/Observer.php +50 -0
  7. app/code/local/FI/Checkout/Model/Page.php +316 -0
  8. app/code/local/FI/Checkout/Model/Resource/Countries.php +166 -0
  9. app/code/local/FI/Checkout/Model/Source.php +102 -0
  10. app/code/local/FI/Checkout/Model/Subscriber.php +37 -0
  11. app/code/local/FI/Checkout/controllers/CheckoutController.php +704 -0
  12. app/code/local/FI/Checkout/etc/config.xml +96 -0
  13. app/code/local/FI/Checkout/etc/system.xml +135 -0
  14. app/code/local/FI/Checkout/sql/fi_checkout_setup/mysql4-install-1.0.0.php +28 -0
  15. app/design/frontend/default/default/layout/freaks/checkout.xml +69 -0
  16. app/design/frontend/default/default/template/freaks/autocomplete.phtml +8 -0
  17. app/design/frontend/default/default/template/freaks/checkout/agreements.phtml +26 -0
  18. app/design/frontend/default/default/template/freaks/checkout/block.phtml +35 -0
  19. app/design/frontend/default/default/template/freaks/checkout/block/info.phtml +119 -0
  20. app/design/frontend/default/default/template/freaks/checkout/centinel/authentication.phtml +4 -0
  21. app/design/frontend/default/default/template/freaks/checkout/centinel/complete.phtml +17 -0
  22. app/design/frontend/default/default/template/freaks/checkout/coupon.phtml +19 -0
  23. app/design/frontend/default/default/template/freaks/checkout/link.phtml +6 -0
  24. app/design/frontend/default/default/template/freaks/checkout/newsletter.phtml +5 -0
  25. app/design/frontend/default/default/template/freaks/checkout/payment.phtml +13 -0
  26. app/design/frontend/default/default/template/freaks/checkout/payment_methods.phtml +21 -0
  27. app/design/frontend/default/default/template/freaks/checkout/shipping/available.phtml +31 -0
  28. app/etc/modules/FI_Checkout.xml +9 -0
  29. package.xml +26 -0
  30. skin/frontend/default/default/css/freaks.css +423 -0
  31. skin/frontend/default/default/images/fi/button.jpg +0 -0
  32. skin/frontend/default/default/images/fi/loader-old.gif +0 -0
  33. skin/frontend/default/default/images/fi/loader.gif +0 -0
  34. skin/frontend/default/default/images/fi/popup_arrow-blue.gif +0 -0
  35. skin/frontend/default/default/images/fi/popup_arrow-white.gif +0 -0
  36. skin/frontend/default/default/images/fi/select-loader-old.gif +0 -0
  37. skin/frontend/default/default/images/fi/select-loader.gif +0 -0
  38. skin/frontend/default/default/images/fi/select-tip.gif +0 -0
  39. skin/frontend/default/default/js/freaks_checkout.js +52 -0
app/code/local/FI/Checkout/Block/Block.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout main block wrapper
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Block_Block extends Mage_Checkout_Block_Onepage_Abstract
10
+ {
11
+ protected
12
+ /**
13
+ * Messages block
14
+ *
15
+ * @var Mage_Core_Block_Messages
16
+ */
17
+ $_loginMessagesBlock;
18
+
19
+ /**
20
+ * Constructor. Set block template
21
+ */
22
+ protected function _construct()
23
+ {
24
+ $this->setTemplate('freaks/checkout/block.phtml');
25
+ }
26
+
27
+ /**
28
+ * Return login url
29
+ *
30
+ * @return string
31
+ */
32
+ public function getLoginUrl()
33
+ {
34
+ return $this->getUrl('fi_order/checkout/login');
35
+ }
36
+
37
+ /**
38
+ * Return login messages block
39
+ *
40
+ * @return Mage_Core_Block_Messages
41
+ */
42
+ public function getLoginMessagesBlock()
43
+ {
44
+ if (!$this->_loginMessagesBlock) {
45
+ $this->_loginMessagesBlock = $this->getLayout()->createBlock('core/messages');
46
+ $this->_loginMessagesBlock->addMessages(Mage::getSingleton('customer/session')->getMessages(true));
47
+ }
48
+ return $this->_loginMessagesBlock;
49
+ }
50
+
51
+ /**
52
+ * Convert block to html.
53
+ * Does not display if quote items count equals 0
54
+ *
55
+ * @return string
56
+ */
57
+ protected function _toHtml()
58
+ {
59
+ $quote = Mage::getSingleton('checkout/session')->getQuote();
60
+ if (!$quote->getItemsCount()) {
61
+ return '';
62
+ }
63
+
64
+ return parent::_toHtml();
65
+ }
66
+ }
app/code/local/FI/Checkout/Block/Block/Info.php ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout user information block
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Block_Block_Info extends Mage_Checkout_Block_Onepage_Shipping
10
+ {
11
+ /**
12
+ * Information about user stored in session
13
+ *
14
+ * @var Varien_Object
15
+ */
16
+ protected $_user;
17
+
18
+ /**
19
+ * Constructor. Set block template.
20
+ * Set user values to block. Update addresses
21
+ */
22
+ protected function _construct()
23
+ {
24
+ $this->setTemplate('freaks/checkout/block/info.phtml');
25
+
26
+ $user = $this->getCustomerInfo();
27
+ $streetIndex = 2;
28
+
29
+ if ($this->isCustomerLoggedIn()) {
30
+ $customer = $this->getCustomer();
31
+ $address = $this->getAddress();
32
+ $additional = $user->getAddress();
33
+
34
+ if (is_array($additional) && !empty($additional)) {
35
+ $address->addData(array_filter($additional));
36
+ }
37
+ $customer->setNote($user->getNote());
38
+ } else {
39
+ $customer = $user;
40
+ $address = new Varien_Object($customer->getAddress());
41
+ $streetIndex--;
42
+ $this->helper('fi_checkout')->updateAddress($address);
43
+ }
44
+
45
+ $this->setCustomerEmail($customer->getEmail())
46
+ ->setCustomerRegion($address->getRegion())
47
+ ->setCustomerCity($address->getCity())
48
+ ->setCustomerBuilding($address->getStreet($streetIndex))
49
+ ->setCustomerRoom($address->getStreet($streetIndex + 1))
50
+ ->setCustomerNote($customer->getNote())
51
+ ->setCustomerPhone($address->getTelephone())
52
+ ->setCustomerZip($address->getPostcode());
53
+
54
+ $this->_updateAddress();
55
+ }
56
+
57
+ /**
58
+ * Return customer full name
59
+ *
60
+ * @return string
61
+ */
62
+ public function getCustomerName()
63
+ {
64
+ return $this->isCustomerLoggedIn()
65
+ ? $this->getFirstname() . ' ' . $this->getLastname()
66
+ : $this->getCustomerInfo()->getName();
67
+ }
68
+
69
+ /**
70
+ * Return Customer Address First Name
71
+ * If Sales Quote Address First Name is not defined - return Customer First Name
72
+ *
73
+ * @return string
74
+ */
75
+ public function getFirstname()
76
+ {
77
+ $firstname = $this->getAddress()->getFirstname();
78
+ if (empty($firstname) && $this->getQuote()->getCustomer()) {
79
+ return $this->getQuote()->getCustomer()->getFirstname();
80
+ }
81
+ return $firstname;
82
+ }
83
+
84
+ /**
85
+ * Return Customer Address Last Name
86
+ * If Sales Quote Address Last Name is not defined - return Customer Last Name
87
+ *
88
+ * @return string
89
+ */
90
+ public function getLastname()
91
+ {
92
+ $lastname = $this->getAddress()->getLastname();
93
+ if (empty($lastname) && $this->getQuote()->getCustomer()) {
94
+ return $this->getQuote()->getCustomer()->getLastname();
95
+ }
96
+ return $lastname;
97
+ }
98
+
99
+ /**
100
+ * Return address street
101
+ *
102
+ * @return string
103
+ */
104
+ public function getStreet()
105
+ {
106
+ if ($this->isCustomerLoggedIn()) {
107
+ $street1 = $this->getAddress()->getStreet(1);
108
+ } else {
109
+ $street1 = '';
110
+ $address = $this->getCustomerInfo()->getAddress();
111
+ if (!empty($address['street']) && is_array($address['street'])) {
112
+ $street1 = reset($address['street']);
113
+ }
114
+ }
115
+
116
+ return $street1;
117
+ }
118
+
119
+ /**
120
+ * Return address id
121
+ *
122
+ * @return int
123
+ */
124
+ public function getAddressId()
125
+ {
126
+ $addressId = $this->getAddress()->getCustomerAddressId();
127
+ if (empty($addressId)) {
128
+ $address = $this->getCustomer()->getPrimaryShippingAddress();
129
+ if ($address) {
130
+ $addressId = $address->getId();
131
+ }
132
+ }
133
+ return $addressId;
134
+ }
135
+
136
+ /**
137
+ * Return customer information stored in session
138
+ *
139
+ * @return Varien_Object
140
+ */
141
+ public function getCustomerInfo()
142
+ {
143
+ if ($this->_user) {
144
+ return $this->_user;
145
+ }
146
+ $data = Mage::getSingleton('customer/session')->getCheckoutUser();
147
+
148
+ $this->_user = new Varien_Object($data);
149
+ return $this->_user;
150
+ }
151
+
152
+ /**
153
+ * Return address. If address object is empty import customer address into it
154
+ *
155
+ * @return Mage_Sales_Quote_Address
156
+ */
157
+ public function getAddress()
158
+ {
159
+ $address = parent::getAddress();
160
+ if ($this->isCustomerLoggedIn() && !$address->getEmail()) {
161
+ $customerAddress = $this->getCustomer()->getPrimaryShippingAddress();
162
+ if (is_object($customerAddress)) {
163
+ $address->importCustomerAddress($customerAddress)
164
+ ->setSaveInAddressBook(0);
165
+ }
166
+ }
167
+
168
+ return $address;
169
+ }
170
+
171
+ /**
172
+ * Return customer location (country, region, city)
173
+ *
174
+ * @return string
175
+ */
176
+ public function getCustomerLocation()
177
+ {
178
+ $address = $this->getCustomerInfo()->getAddress();
179
+ if (!empty($address['location'])) {
180
+ return $address['location'];
181
+ }
182
+
183
+ $address = $this->getAddress();
184
+
185
+ if (!$this->helper('fi_checkout')->useOnlyDefaultCountry()) {
186
+ $location[] = $address->getCountryModel()->getName();
187
+ }
188
+ if ($address->getRegionId()) {
189
+ $location[] = $address->getRegionModel()->getName();
190
+ } elseif ($address->getRegion()) {
191
+ $location[] = $address->getRegion();
192
+ }
193
+ $location[] = $address->getCity();
194
+
195
+ return join(', ', array_filter($location));
196
+ }
197
+
198
+ /**
199
+ * Return location help message based on configuration
200
+ *
201
+ * @see FI_Checkout_Helper_Data::useOnlyDefaultCountry
202
+ * @return string
203
+ */
204
+ public function getLocationHelp()
205
+ {
206
+ if ($this->helper('fi_checkout')->useOnlyDefaultCountry()) {
207
+ return $this->__('City');
208
+ } else {
209
+ return $this->__('Country, Region, City (e.g. Ukraine, Kyiv, Kyiv)');
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Update addresses with session values
215
+ *
216
+ * @return FI_Checkout_Block_Block_Info
217
+ */
218
+ protected function _updateAddress()
219
+ {
220
+ $shipping = $this->helper('fi_checkout')
221
+ ->updateAddress($this->getAddress())
222
+ ->implodeStreetAddress();
223
+
224
+ $billing = $this->getQuote()->getBillingAddress();
225
+ if ($billing) {
226
+ $this->helper('fi_checkout')
227
+ ->copyAddress($shipping, $billing)
228
+ ->implodeStreetAddress();
229
+ }
230
+ return $this;
231
+ }
232
+
233
+ /**
234
+ * Return country select box block
235
+ *
236
+ * @param string $type
237
+ * @return Mage_Core_Block_Html_Select
238
+ */
239
+ public function getCountryBlock($type = 'shipping')
240
+ {
241
+ $countryId = $this->getAddress()->getCountryId();
242
+ if (!$countryId) {
243
+ $countryId = Mage::helper('fi_checkout')->getDefaultCountry();
244
+ }
245
+ $select = $this->getLayout()->createBlock('core/html_select')
246
+ ->setTitle($this->helper('checkout')->__('Country'))
247
+ ->setClass('validate-select')
248
+ ->setValue($countryId)
249
+ ->setOptions($this->getCountryOptions());
250
+
251
+ return $select;
252
+ }
253
+
254
+ /**
255
+ * Return region select box block
256
+ *
257
+ * @param string $type
258
+ * @return Mage_Core_Block_Html_Select
259
+ */
260
+ public function getRegionBlock()
261
+ {
262
+ $select = $this->getLayout()->createBlock('core/html_select')
263
+ ->setTitle($this->helper('checkout')->__('State/Province'))
264
+ ->setClass('required-entry validate-state')
265
+ ->setValue($this->getAddress()->getRegionId())
266
+ ->setOptions($this->getRegionCollection()->toOptionArray());
267
+
268
+ return $select;
269
+ }
270
+ }
app/code/local/FI/Checkout/Block/Newsletter.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout Newsletter block
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
9
+ */
10
+ class FI_Checkout_Block_Newsletter extends Mage_Core_Block_Template
11
+ {
12
+ /**
13
+ * Convert block to html sting.
14
+ * Checks is possible to show newsletter checkbox
15
+ *
16
+ * @return string
17
+ */
18
+ protected function _toHtml()
19
+ {
20
+ if (!$this->helper('fi_checkout')->isVisibleNewsletter()
21
+ || Mage::helper('fi_checkout')->isCustomerSubscribed()
22
+ ) {
23
+ return '';
24
+ }
25
+
26
+ return parent::_toHtml();
27
+ }
28
+ }
app/code/local/FI/Checkout/Block/Payment/Methods.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout payment methods block
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Block_Payment_Methods extends Mage_Checkout_Block_Onepage_Payment_Methods
10
+ {
11
+ /**
12
+ * Checks if 3D secure enabled for payment method
13
+ *
14
+ * @param Mage_Payment_Model_Method_Abstract $method
15
+ * @return bool
16
+ */
17
+ public function isVerificationRequired(Mage_Payment_Model_Method_Abstract $method)
18
+ {
19
+ $result = $this->helper('fi_checkout')->isCentinelValidationRequired($method);
20
+ $this->setIsCentinelValidationRequired($result);
21
+ return $result;
22
+ }
23
+
24
+ /**
25
+ * Return verifier url
26
+ *
27
+ * @param Mage_Payment_Model_Method_Abstract $method
28
+ * @return string
29
+ */
30
+ public function getVerifyCcUrl(Mage_Payment_Model_Method_Abstract $method)
31
+ {
32
+ $verifyUrl = '';
33
+ if ($this->isVerificationRequired($method)) {
34
+ $verifyUrl = $this->getUrl('fi_order/checkout/verify');
35
+ }
36
+ return $verifyUrl;
37
+ }
38
+ }
app/code/local/FI/Checkout/Helper/Data.php ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout helper
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
9
+ */
10
+ class FI_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
11
+ {
12
+ /**
13
+ * Xml configuration pathes
14
+ */
15
+ const XML_PATH_DEFAULT_COUNTRY = 'checkout/easyco/default_country';
16
+ const XML_PATH_DEFAULT_REGION = 'checkout/easyco/default_region';
17
+ const XML_PATH_DEFAULT_CITY = 'checkout/easyco/default_city';
18
+ const XML_PATH_ALLOW_GUEST_CO = 'checkout/easyco/allow_guest_checkout';
19
+ const XML_PATH_USE_DEFAULT_COUNTRY = 'checkout/easyco/use_default_country';
20
+ const XML_PATH_PASSWORD_FIELD_TYPE = 'checkout/easyco/password_type';
21
+ const XML_PATH_LOCATION_FIELD_TYPE = 'checkout/easyco/location_type';
22
+ const XML_PATH_SHOW_BUILD_FIELDS = 'checkout/easyco/show_build_fields';
23
+ const XML_PATH_MAY_SUBSCRIBE_GUEST ='newsletter/subscription/allow_guest_subscribe';
24
+ const XML_PATH_SHOW_NEWSLETTER = 'checkout/easyco/show_newsletter';
25
+ const XML_PATH_NEWSLETTER_SEND_SUCCESS_EMAIL = 'checkout/easyco/newsletter_send_success';
26
+ const XML_PATH_NEWSLETTER_SEND_REQUEST_EMAIL = 'checkout/easyco/newsletter_send_request';
27
+
28
+ protected
29
+ /**
30
+ * List of specific address fields
31
+ *
32
+ * @var array
33
+ */
34
+ $_copyAddressFields = array('country_id', 'region', 'region_id', 'city', 'postcode');
35
+
36
+ /**
37
+ * Return attribute options
38
+ *
39
+ * @param string $entityType
40
+ * @param string $attrCode
41
+ * @param bool $withEmpty
42
+ * @return array
43
+ */
44
+ public function getAttributeOptions($entityType, $attrCode, $withEmpty = false)
45
+ {
46
+ $data = Mage::getModel('eav/entity_attribute')
47
+ ->loadByCode($entityType, $attrCode)
48
+ ->setSourceModel('eav/entity_attribute_source_table')
49
+ ->getSource()
50
+ ->getAllOptions($withEmpty);
51
+
52
+ $set = array();
53
+ foreach ($data as &$row) {
54
+ $set[$row['value']] = $row['label'];
55
+ }
56
+
57
+ return $set;
58
+ }
59
+
60
+ /**
61
+ * Return default shipping address
62
+ *
63
+ * @return array
64
+ */
65
+ public function getDefaultShippingAddress()
66
+ {
67
+ return array(
68
+ 'country_id' => $this->getDefaultCountry(),
69
+ 'region' => $this->getDefaultRegion(),
70
+ 'region_id' => null,
71
+ 'city' => $this->getDefaultCity()
72
+ );
73
+ }
74
+
75
+ /**
76
+ * Lower case text using mb_string
77
+ *
78
+ * @param string $text
79
+ * @return string
80
+ */
81
+ public function lowerCase($text)
82
+ {
83
+ if (function_exists('mb_convert_case')) {
84
+ $text = mb_convert_case($text, MB_CASE_LOWER, Mage_Core_Helper_String::ICONV_CHARSET);
85
+ }
86
+ return $text;
87
+ }
88
+
89
+ /**
90
+ * Copy specific fields from one address to another
91
+ *
92
+ * @param Mage_Sales_Model_Quote_Address $from
93
+ * @param $to
94
+ * @return Mage_Sales_Model_Quote_Address
95
+ */
96
+ public function copyAddress(Mage_Sales_Model_Quote_Address $from, Mage_Sales_Model_Quote_Address $to)
97
+ {
98
+ foreach ($this->_copyAddressFields as $field) {
99
+ $to->setData($field, $from->getData($field));
100
+ }
101
+ return $to;
102
+ }
103
+
104
+ /**
105
+ * Return default city
106
+ *
107
+ * @return string
108
+ */
109
+ public function getDefaultCity()
110
+ {
111
+ return Mage::getStoreConfig(self::XML_PATH_DEFAULT_CITY);
112
+ }
113
+
114
+ /**
115
+ * Return default region
116
+ *
117
+ * @return string
118
+ */
119
+ public function getDefaultRegion()
120
+ {
121
+ return Mage::getStoreConfig(self::XML_PATH_DEFAULT_REGION);
122
+ }
123
+
124
+ /**
125
+ * Return default country code
126
+ *
127
+ * @return string
128
+ */
129
+ public function getDefaultCountry()
130
+ {
131
+ return Mage::getStoreConfig(self::XML_PATH_DEFAULT_COUNTRY);
132
+ }
133
+
134
+ /**
135
+ * Return choosen location type
136
+ *
137
+ * @return string
138
+ */
139
+ public function getLocationType()
140
+ {
141
+ return Mage::getStoreConfig(self::XML_PATH_LOCATION_FIELD_TYPE);
142
+ }
143
+
144
+ /**
145
+ * Return choosen password type
146
+ *
147
+ * @return string
148
+ */
149
+ public function getPasswordType()
150
+ {
151
+ return Mage::getStoreConfig(self::XML_PATH_PASSWORD_FIELD_TYPE);
152
+ }
153
+
154
+ /**
155
+ * Check possibility to show password field on checkout form
156
+ *
157
+ * @return bool
158
+ */
159
+ public function canShowPasswordField()
160
+ {
161
+ return $this->getPasswordType() == FI_Checkout_Model_Source::PASSWORD_FIELD;
162
+ }
163
+
164
+ /**
165
+ * Checks possibility to use telephone field like password
166
+ *
167
+ * @return bool
168
+ */
169
+ public function isPasswordAsTelephone()
170
+ {
171
+ return $this->getPasswordType() == FI_Checkout_Model_Source::PASSWORD_PHONE;
172
+ }
173
+
174
+ /**
175
+ * Checks possibility to automatically generate password
176
+ *
177
+ * @return bool
178
+ */
179
+ public function isPasswordAuto()
180
+ {
181
+ return $this->getPasswordType() == FI_Checkout_Model_Source::PASSWORD_GENERATE;
182
+ }
183
+
184
+ /**
185
+ * Check is checkout only for one default country
186
+ *
187
+ * @return bool
188
+ */
189
+ public function useOnlyDefaultCountry()
190
+ {
191
+ return Mage::getStoreConfig(self::XML_PATH_USE_DEFAULT_COUNTRY);
192
+ }
193
+
194
+ /**
195
+ * Check is country/region/city in one field
196
+ *
197
+ * @return bool
198
+ */
199
+ public function isLocationAsOneField()
200
+ {
201
+ return $this->getLocationType() == FI_Checkout_Model_Source::LOCATION_ONE;
202
+ }
203
+
204
+ /**
205
+ * Return address information stored in session.
206
+ * If session is empty, return default shipping information.
207
+ *
208
+ * @return array
209
+ */
210
+ public function getAddressInfo()
211
+ {
212
+ $session = Mage::getSingleton('customer/session');
213
+ $data = $session->getShippingInfo();
214
+
215
+ return $data;
216
+ }
217
+
218
+ /**
219
+ * Update Shipping Address based on session and default config values.
220
+ *
221
+ * @param Varien_Object $address
222
+ * @return Varien_Object
223
+ */
224
+ public function updateAddress(Varien_Object $address)
225
+ {
226
+ $data = $this->getAddressInfo();
227
+ if (!($data || $address->getCountryId() || $address->getCity())) {
228
+ $data = $this->getDefaultShippingAddress();
229
+ }
230
+
231
+ $shippingMethod = Mage::getSingleton('customer/session')->getShippingMethod();
232
+ if ($shippingMethod) {
233
+ $address->setShippingMethod($shippingMethod)
234
+ ->setCollectShippingRates(true);
235
+ }
236
+
237
+ if (is_array($data)) {
238
+ $address->addData($data);
239
+ }
240
+ return $address;
241
+ }
242
+
243
+ /**
244
+ * Auto assign shipping method if there is only one available method
245
+ *
246
+ * @param Mage_Sales_Model_Quote_Address $address
247
+ * @return FI_Checkout_Helper_Data
248
+ */
249
+ public function autoAssignShippingMethod(Mage_Sales_Model_Quote_Address $address)
250
+ {
251
+ $rates = $address->collectShippingRates()->getGroupedAllShippingRates();
252
+ if (is_array($rates) && count($rates) == 1 && count(reset($rates)) == 1) {
253
+ $rate = reset($rates);
254
+ $rate = reset($rate);
255
+ if (is_object($rate)) {
256
+ $address->setShippingMethod($rate->getCode());
257
+ }
258
+ }
259
+ $address->setCollectShippingRates(true);
260
+ return $this;
261
+ }
262
+
263
+ /**
264
+ * Check posibility to place order
265
+ *
266
+ * return bool
267
+ */
268
+ public function canPlaceOrder()
269
+ {
270
+ $quote = Mage::getSingleton('checkout/session')->getQuote();
271
+ return $quote->validateMinimumAmount();
272
+ }
273
+
274
+ /**
275
+ * Generate random string
276
+ *
277
+ * @param int $len
278
+ * return string
279
+ */
280
+ public function generateRandomKey($len = 20){
281
+ $string = '';
282
+ $pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
283
+ for ($i = 1; $i <= $len; $i++)
284
+ $string .= substr($pool, rand(0, 61), 1);
285
+
286
+ return $string;
287
+ }
288
+
289
+ /**
290
+ * Return password based on choosen type
291
+ *
292
+ * @param array $data user information
293
+ * @return string
294
+ */
295
+ public function getPassword($data)
296
+ {
297
+ $password = '';
298
+ switch ($this->getPasswordType()) {
299
+ case FI_Checkout_Model_Source::PASSWORD_FIELD:
300
+ if (!empty($data['password'])) {
301
+ $password = $data['password'];
302
+ }
303
+ break;
304
+ case FI_Checkout_Model_Source::PASSWORD_PHONE:
305
+ if (!empty($data['address']['telephone'])) {
306
+ $password = $data['address']['telephone'];
307
+ $plen = strlen($password);
308
+ if ($plen < 6) {
309
+ $password .= $this->generateRandomKey(6 - $plen);
310
+ }
311
+ }
312
+ break;
313
+ }
314
+
315
+ return $password ? $password : $this->generateRandomKey(8);
316
+ }
317
+
318
+ /**
319
+ * Check is 3D secure validation required
320
+ *
321
+ * @param Mage_Payment_Model_Method_Abstract $paymentMethod
322
+ * @return bool
323
+ */
324
+ public function isCentinelValidationRequired(Mage_Payment_Model_Method_Abstract $paymentMethod)
325
+ {
326
+ $result = false;
327
+ if ($paymentMethod->getIsCentinelValidationEnabled()) {
328
+ $centinel = $paymentMethod->getCentinelValidator();
329
+ $result = is_object($centinel);
330
+ }
331
+ return $result;
332
+ }
333
+
334
+ /**
335
+ * Check is room and building fields enabled
336
+ *
337
+ * @return bool
338
+ */
339
+ public function showBuildRoomFields()
340
+ {
341
+ return Mage::getStoreConfig(self::XML_PATH_SHOW_BUILD_FIELDS);
342
+ }
343
+
344
+ /**
345
+ * Check is guest checkout allowed
346
+ * for future usage
347
+ *
348
+ * @return bool
349
+ */
350
+ public function isGuestCheckoutAllowed()
351
+ {
352
+ return Mage::getStoreConfig(self::XML_PATH_ALLOW_GUEST_CO);
353
+ }
354
+
355
+ /**
356
+ * Return newsletter type
357
+ *
358
+ * @return string
359
+ */
360
+ public function getNewsletterType()
361
+ {
362
+ return Mage::getStoreConfig(self::XML_PATH_SHOW_NEWSLETTER);
363
+ }
364
+
365
+ /**
366
+ * Check is newsletter visible on checkout page
367
+ *
368
+ * @return bool
369
+ */
370
+ public function isVisibleNewsletter()
371
+ {
372
+ return $this->getNewsletterType() != FI_Checkout_Model_Source::CHECKBOX_UNVISIBLE;
373
+ }
374
+
375
+ /**
376
+ * Check is newsletter checkbox checked
377
+ *
378
+ * @return bool
379
+ */
380
+ public function isNewsletterChecked()
381
+ {
382
+ return $this->getNewsletterType() == FI_Checkout_Model_Source::CHECKBOX_CHECKED;
383
+ }
384
+
385
+ /**
386
+ * Check is guest may subscribe to newsletter
387
+ *
388
+ * @return bool
389
+ */
390
+ public function maySubscribeGuest()
391
+ {
392
+ return Mage::getStoreConfig(self::XML_PATH_MAY_SUBSCRIBE_GUEST);
393
+ }
394
+
395
+ /**
396
+ * Check is customer subscribed
397
+ *
398
+ * @return bool
399
+ */
400
+ public function isCustomerSubscribed()
401
+ {
402
+ $session = Mage::getSingleton('customer/session');
403
+ if (!$this->isVisibleNewsletter()
404
+ || !$session->isLoggedIn()
405
+ && !$this->maySubscribeGuest()
406
+ ) {
407
+ return false;
408
+ }
409
+
410
+ $subscriber = Mage::getModel('newsletter/subscriber')->loadByCustomer($session->getCustomer());
411
+ return $subscriber->isSubscribed();
412
+ }
413
+
414
+ /**
415
+ * Check is need to send email to customer about subscription
416
+ *
417
+ * @return bool
418
+ */
419
+ public function isNeedSendNewsletterEmail($type)
420
+ {
421
+ switch ($type) {
422
+ case 'request':
423
+ return Mage::getStoreConfig(self::XML_PATH_NEWSLETTER_SEND_REQUEST_EMAIL);
424
+ case 'success':
425
+ return Mage::getStoreConfig(self::XML_PATH_NEWSLETTER_SEND_SUCCESS_EMAIL);
426
+ }
427
+ return true;
428
+ }
429
+ }
app/code/local/FI/Checkout/Model/Observer.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout observer model
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Model_Observer
10
+ {
11
+ /**
12
+ * Restore shipping method from session or auto assign if there is only one available method.
13
+ * Listen event sales_quote_collect_totals_before
14
+ *
15
+ * @param Varien_Event_Observer $observer
16
+ * @return FI_Checkout_Model_Observer
17
+ */
18
+ public function collectTotalsBefore(Varien_Event_Observer $observer)
19
+ {
20
+ $helper = Mage::helper('fi_checkout');
21
+ $quote = $observer->getEvent()->getQuote();
22
+ $address = $quote->getShippingAddress();
23
+
24
+ $helper->updateAddress($address);
25
+ $helper->autoAssignShippingMethod($address);
26
+ return $this;
27
+ }
28
+
29
+ /**
30
+ * Add user comment to order.
31
+ * Listen event checkout_type_onepage_save_order
32
+ *
33
+ * @param Varien_Event_Observer $observer
34
+ * @return FI_Checkout_Model_Observer
35
+ */
36
+ public function addOrderComment(Varien_Event_Observer $observer)
37
+ {
38
+ $order = $observer->getEvent()->getOrder();
39
+ $request = Mage::app()->getRequest();
40
+
41
+ $data = $request->getParam('user');
42
+ if ($data && !empty($data['note'])) {
43
+ $comment = strip_tags($data['note']);
44
+ if (!empty($comment)) {
45
+ $order->setCustomerNote($comment);
46
+ }
47
+ }
48
+ return $this;
49
+ }
50
+ }
app/code/local/FI/Checkout/Model/Page.php ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout page model
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Model_Page extends Mage_Checkout_Model_Type_Onepage
10
+ {
11
+ /**
12
+ * Error message. Shows if customer with the same email already exists
13
+ *
14
+ * @var string
15
+ */
16
+ protected $_customerEmailExistsMessage;
17
+
18
+ /**
19
+ * Constructor. Fix Onepage model bug with error message private property
20
+ */
21
+ public function __construct()
22
+ {
23
+ parent::__construct();
24
+
25
+ $this->_customerEmailExistsMessage = $this->_helper->__('There is already a customer registered using this email address. Please login using this email address or enter a different email address to register your account.');
26
+ }
27
+
28
+ /**
29
+ * Validate customer address
30
+ *
31
+ * @param Mage_Sales_Model_Quote_Address $address
32
+ * @return bool
33
+ */
34
+ public function validateAddress(Mage_Sales_Model_Quote_Address $address)
35
+ {
36
+ $errors = array();
37
+ $helper = Mage::helper('customer');
38
+ $address->implodeStreetAddress();
39
+ if (!Zend_Validate::is($address->getFirstname(), 'NotEmpty')) {
40
+ $errors[] = $helper->__('Please enter the first name.');
41
+ }
42
+
43
+ /*
44
+ if (!Zend_Validate::is($address->getLastname(), 'NotEmpty')) {
45
+ $errors[] = $helper->__('Please enter the last name.');
46
+ }
47
+ */
48
+
49
+ if (!Zend_Validate::is($address->getStreet(1), 'NotEmpty')) {
50
+ $errors[] = $helper->__('Please enter the street.');
51
+ }
52
+
53
+ if (!Zend_Validate::is($address->getCity(), 'NotEmpty')) {
54
+ $errors[] = $helper->__('Please enter the city.');
55
+ }
56
+
57
+ if (!Zend_Validate::is($address->getTelephone(), 'NotEmpty')) {
58
+ $errors[] = $helper->__('Please enter the telephone number.');
59
+ }
60
+
61
+ /*
62
+ $_havingOptionalZip = Mage::helper('directory')->getCountriesWithOptionalZip();
63
+ if (!in_array($address->getCountryId(), $_havingOptionalZip) && !Zend_Validate::is($address->getPostcode(), 'NotEmpty')) {
64
+ $errors[] = $helper->__('Please enter the zip/postal code.');
65
+ }
66
+ */
67
+
68
+ if (!Zend_Validate::is($address->getCountryId(), 'NotEmpty')) {
69
+ $errors[] = $helper->__('Please enter the country.');
70
+ }
71
+
72
+ if ($address->getCountryModel()->getRegionCollection()->getSize()
73
+ && !Zend_Validate::is($address->getRegionId(), 'NotEmpty')) {
74
+ $errors[] = $helper->__('Please enter the state/province.');
75
+ }
76
+
77
+ if (empty($errors) || $address->getShouldIgnoreValidation()) {
78
+ return true;
79
+ }
80
+ return $errors;
81
+ }
82
+
83
+ /**
84
+ * Save billing address information to quote
85
+ * Return an array of error information
86
+ *
87
+ * @param array $data
88
+ * @param int $customerAddressId
89
+ * @return array
90
+ */
91
+ public function saveBilling($data, $customerAddressId)
92
+ {
93
+ if (empty($data)) {
94
+ return array('error' => -1, 'message' => $this->_helper->__('Invalid data.'));
95
+ }
96
+
97
+ $address = $this->getQuote()->getBillingAddress();
98
+
99
+ $addressForm = Mage::getModel('customer/form');
100
+ $addressForm->setFormCode('customer_address_edit')
101
+ ->setEntityType('customer_address')
102
+ ->setIsAjaxRequest(Mage::app()->getRequest()->isAjax());
103
+
104
+ if (!empty($customerAddressId)) {
105
+ $customerAddress = Mage::getModel('customer/address')->load($customerAddressId);
106
+ if ($customerAddress->getId()) {
107
+ if ($customerAddress->getCustomerId() != $this->getQuote()->getCustomerId()) {
108
+ return array('error' => 1,
109
+ 'message' => $this->_helper->__('Customer Address is not valid.')
110
+ );
111
+ }
112
+
113
+ $address->importCustomerAddress($customerAddress)->setSaveInAddressBook(0);
114
+ $addressForm->setEntity($address);
115
+
116
+ $addressData = array_filter($addressForm->extractData($addressForm->prepareRequest($data)));
117
+ unset($addressData['id'], $addressData['entity_id'], $addressData['address_id']);
118
+ $address->addData($addressData);
119
+
120
+ $addressErrors = $addressForm->validateData($address->getData());
121
+ if ($addressErrors !== true) {
122
+ return array('error' => 1, 'message' => $addressErrors);
123
+ }
124
+ $customerAddress->addData($addressData)
125
+ ->implodeStreetAddress()
126
+ ->save();
127
+ }
128
+ } else {
129
+ $addressForm->setEntity($address);
130
+ // emulate request object
131
+ $addressData = $addressForm->extractData($addressForm->prepareRequest($data));
132
+ $addressErrors = $addressForm->validateData($addressData);
133
+ if ($addressErrors !== true) {
134
+ return array('error' => 1, 'message' => $addressErrors);
135
+ }
136
+ $addressForm->compactData($addressData);
137
+
138
+ // Additional form data, not fetched by extractData (as it fetches only attributes)
139
+ $address->setSaveInAddressBook(empty($data['save_in_address_book']) ? 0 : 1);
140
+ }
141
+
142
+ // validate billing address
143
+ if (($validateRes = $this->validateAddress($address)) !== true) {
144
+ return array('error' => 1, 'message' => $validateRes);
145
+ }
146
+
147
+ $address->implodeStreetAddress();
148
+
149
+ if (true !== ($result = $this->_validateCustomerData($data))) {
150
+ return $result;
151
+ }
152
+
153
+ if (!$this->getQuote()->getCustomerId() && self::METHOD_REGISTER == $this->getQuote()->getCheckoutMethod()) {
154
+ if ($this->_customerEmailExists($address->getEmail(), Mage::app()->getWebsite()->getId())) {
155
+ return array('error' => 1, 'message' => $this->_customerEmailExistsMessage);
156
+ }
157
+ }
158
+
159
+ if (!$this->getQuote()->isVirtual()) {
160
+ /**
161
+ * Billing address using otions
162
+ */
163
+ $usingCase = isset($data['use_for_shipping']) ? (int)$data['use_for_shipping'] : 0;
164
+
165
+ switch($usingCase) {
166
+ case 0:
167
+ $shipping = $this->getQuote()->getShippingAddress();
168
+ $shipping->setSameAsBilling(0);
169
+ break;
170
+ case 1:
171
+ $billing = clone $address;
172
+ $billing->unsAddressId()->unsAddressType();
173
+ $shipping = $this->getQuote()->getShippingAddress();
174
+ $shippingMethod = $shipping->getShippingMethod();
175
+ $shipping->addData($billing->getData())
176
+ ->setSameAsBilling(1)
177
+ ->setSaveInAddressBook(1)
178
+ ->setShippingMethod($shippingMethod)
179
+ ->setCollectShippingRates(true);
180
+ break;
181
+ }
182
+ }
183
+
184
+ $this->getQuote()->collectTotals();
185
+ $this->getQuote()->save();
186
+
187
+ return array();
188
+ }
189
+
190
+ /**
191
+ * Validate customer data and set some its data for further usage in quote
192
+ * Will return either true or array with error messages
193
+ *
194
+ * @param array $data
195
+ * @return true|array
196
+ */
197
+ protected function _validateCustomerData(array $data)
198
+ {
199
+ /* @var $customerForm Mage_Customer_Model_Form */
200
+ $customerForm = Mage::getModel('customer/form');
201
+ $customerForm->setFormCode('checkout_register')
202
+ ->setIsAjaxRequest(Mage::app()->getRequest()->isAjax());
203
+
204
+ $quote = $this->getQuote();
205
+ if ($quote->getCustomerId()) {
206
+ $customer = $quote->getCustomer();
207
+ $customerForm->setEntity($customer);
208
+ $customerData = $quote->getCustomer()->getData();
209
+ } else {
210
+ /* @var $customer Mage_Customer_Model_Customer */
211
+ $customer = Mage::getModel('customer/customer');
212
+ $customerForm->setEntity($customer);
213
+ $customerRequest = $customerForm->prepareRequest($data);
214
+ $customerData = $customerForm->extractData($customerRequest);
215
+ }
216
+
217
+ $customerErrors = $customerForm->validateData($customerData);
218
+ if ($customerErrors !== true) {
219
+ return array(
220
+ 'error' => -1,
221
+ 'message' => implode(', ', $customerErrors)
222
+ );
223
+ }
224
+
225
+ if ($quote->getCustomerId()) {
226
+ return true;
227
+ }
228
+
229
+ $customerForm->compactData($customerData);
230
+
231
+ if ($quote->getCheckoutMethod() == self::METHOD_REGISTER) {
232
+ // set customer password
233
+ $customer->setPassword($customerRequest->getParam('customer_password'));
234
+ $customer->setConfirmation($customerRequest->getParam('confirm_password'));
235
+ } else {
236
+ // emulate customer password for quest
237
+ $password = $customer->generatePassword();
238
+ $customer->setPassword($password);
239
+ $customer->setConfirmation($password);
240
+ }
241
+
242
+ $result = $this->validateCustomerAttributes($customer);
243
+ if (true !== $result && is_array($result)) {
244
+ return array(
245
+ 'error' => -1,
246
+ 'message' => implode(', ', $result)
247
+ );
248
+ }
249
+
250
+ if ($quote->getCheckoutMethod() == self::METHOD_REGISTER) {
251
+ // save customer encrypted password in quote
252
+ $quote->setPasswordHash($customer->encryptPassword($customer->getPassword()));
253
+ }
254
+
255
+ // copy customer/guest email to address
256
+ $quote->getBillingAddress()->setEmail($customer->getEmail());
257
+
258
+ // copy customer data to quote
259
+ Mage::helper('core')->copyFieldset('customer_account', 'to_quote', $customer, $quote);
260
+
261
+ return true;
262
+ }
263
+
264
+ /**
265
+ * Validate customer attributes
266
+ *
267
+ * @param Mage_Customer_Model_Customer $customer
268
+ * @return bool
269
+ */
270
+ public function validateCustomerAttributes(Mage_Customer_Model_Customer $customer)
271
+ {
272
+ $errors = array();
273
+ $customerHelper = Mage::helper('customer');
274
+ if (!Zend_Validate::is( trim($customer->getFirstname()) , 'NotEmpty')) {
275
+ $errors[] = $customerHelper->__('The first name cannot be empty.');
276
+ }
277
+
278
+ /*
279
+ if (!Zend_Validate::is( trim($customer->getLastname()) , 'NotEmpty')) {
280
+ $errors[] = $customerHelper->__('The last name cannot be empty.');
281
+ }
282
+ */
283
+
284
+ if (!Zend_Validate::is($customer->getEmail(), 'EmailAddress')) {
285
+ $errors[] = $customerHelper->__('Invalid email address "%s".', $customer->getEmail());
286
+ }
287
+
288
+ $password = $customer->getPassword();
289
+ if (!$customer->getId() && !Zend_Validate::is($password , 'NotEmpty')) {
290
+ $errors[] = $customerHelper->__('The password cannot be empty.');
291
+ }
292
+ if (strlen($password) && !Zend_Validate::is($password, 'StringLength', array(6))) {
293
+ $errors[] = $customerHelper->__('The minimum password length is %s', 6);
294
+ }
295
+ $confirmation = $customer->getConfirmation();
296
+ if ($password != $confirmation) {
297
+ $errors[] = $customerHelper->__('Please make sure your passwords match.');
298
+ }
299
+
300
+ $entityType = Mage::getSingleton('eav/config')->getEntityType('customer');
301
+ $attribute = Mage::getModel('customer/attribute')->loadByCode($entityType, 'dob');
302
+ if ($attribute->getIsRequired() && '' == trim($customer->getDob())) {
303
+ $errors[] = $customerHelper->__('The Date of Birth is required.');
304
+ }
305
+ $attribute = Mage::getModel('customer/attribute')->loadByCode($entityType, 'taxvat');
306
+ if ($attribute->getIsRequired() && '' == trim($customer->getTaxvat())) {
307
+ $errors[] = $customerHelper->__('The TAX/VAT number is required.');
308
+ }
309
+ $attribute = Mage::getModel('customer/attribute')->loadByCode($entityType, 'gender');
310
+ if ($attribute->getIsRequired() && '' == trim($customer->getGender())) {
311
+ $errors[] = $customerHelper->__('Gender is required.');
312
+ }
313
+
314
+ return empty($errors) ? true : $errors;
315
+ }
316
+ }
app/code/local/FI/Checkout/Model/Resource/Countries.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout Counrty/region helper model
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Model_Resource_Countries extends Mage_Directory_Model_Mysql4_Country_Collection
10
+ {
11
+ protected
12
+ /**
13
+ * Table name of region locale names
14
+ *
15
+ * @var string
16
+ */
17
+ $_regionNameTable,
18
+
19
+ /**
20
+ * Table name of region
21
+ *
22
+ * @var string
23
+ */
24
+ $_regionTable;
25
+
26
+ /**
27
+ * Constructor. Assign table names to properties
28
+ */
29
+ public function __construct()
30
+ {
31
+ parent::__construct();
32
+
33
+ $r = Mage::getSingleton('core/resource');
34
+ $this->_countryTable = $r->getTableName('directory/country');
35
+ $this->_regionTable = $r->getTableName('directory/country_region');
36
+ $this->_regionNameTable = $r->getTableName('directory/country_region_name');
37
+
38
+ $this->setItemObjectClass('Varien_Object');
39
+ }
40
+
41
+ /**
42
+ * Add region names to collection
43
+ *
44
+ * @return FI_Checkout_Model_Resource_Countries
45
+ */
46
+ public function addRegionNames()
47
+ {
48
+ $this->getSelect()
49
+ ->joinLeft(
50
+ array('r' => $this->_regionTable),
51
+ 'country.country_id = r.country_id',
52
+ array('default_name')
53
+ )
54
+ ->joinInner(
55
+ array('rn' => $this->_regionNameTable),
56
+ $this->getSelect()->getAdapter()->quote('rn.region_id = r.region_id AND locale = ?', Mage::app()->getLocale()->getLocaleCode()),
57
+ array('name')
58
+ );
59
+
60
+ return $this;
61
+ }
62
+
63
+ /**
64
+ * Filter collection of country/regions by specific value.
65
+ * Uses for autocomplete.
66
+ *
67
+ * @param string $location
68
+ * @param int $limit
69
+ * @return array
70
+ */
71
+ public function filter($location, $limit = 15)
72
+ {
73
+ $result = array();
74
+ $helper = Mage::helper('core/string');
75
+ $location = explode(',', $location);
76
+ $location = array_map('trim', $location);
77
+ $countries = Mage::app()->getLocale()
78
+ ->getCountryTranslationList();
79
+
80
+ if (empty($location[0])) {
81
+ return $result;
82
+ }
83
+
84
+ $checkoutHelper = Mage::helper('fi_checkout');
85
+ if (empty($location[1])) {
86
+ $i = 0;
87
+ $exp = $checkoutHelper->lowerCase($location[0]);
88
+ foreach ($countries as $code => $name) {
89
+ $title = $checkoutHelper->lowerCase($name);
90
+ if ($helper->strpos($title, $exp) !== false) {
91
+ $result[] = $name;
92
+ $i++;
93
+ if ($i == $limit) {
94
+ break;
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ if (empty($result) && empty($location[2])) {
101
+ if (empty($location[1])) {
102
+ $location[1] = $location[0];
103
+ }
104
+ $location[0] = $checkoutHelper->lowerCase($location[0]);
105
+ $countries = array_flip(array_map(array($checkoutHelper, 'lowerCase'), $countries));
106
+ if (isset($countries[$location[0]])) {
107
+ $countryCode = $countries[$location[0]];
108
+ } else {
109
+ $countryCode = $checkoutHelper->getDefaultCountry();
110
+ }
111
+
112
+ $adapter = $this->getSelect()->getAdapter();
113
+ $select = $adapter->select()
114
+ ->from(array('r' => $this->_regionTable), 'default_name')
115
+ ->joinLeft(
116
+ array('rn' => $this->_regionNameTable),
117
+ $adapter->quote('rn.region_id = r.region_id AND locale = ?', Mage::app()->getLocale()->getLocaleCode()),
118
+ array('name')
119
+ )
120
+ ->where('r.country_id = ?', $countryCode)
121
+ ->where('IF(name, name, default_name) LIKE ?', '%' . $location[1] . '%')
122
+ ->limit($limit);
123
+
124
+ $result = $adapter->fetchAll($select);
125
+ foreach ($result as &$row) {
126
+ $row = $row['name'] ? $row['name'] : $row['default_name'];
127
+ }
128
+ }
129
+
130
+ if (empty($result) && empty($location[3])) {
131
+ if (empty($location[2])) {
132
+ $location[2] = $location[1];
133
+ }
134
+ // city autocomplete
135
+ }
136
+
137
+ return $result;
138
+ }
139
+
140
+ /**
141
+ * Get region id by name
142
+ *
143
+ * @param string $name
144
+ * @param string $countryId
145
+ * @return int|null
146
+ */
147
+ public function getRegionIdByName($name, $countryId = null)
148
+ {
149
+ $adapter = $this->getSelect()->getAdapter();
150
+ $select = $adapter->select()
151
+ ->from(array('r' => $this->_regionTable), array('default_name', 'region_id'))
152
+ ->joinLeft(
153
+ array('rn' => $this->_regionNameTable),
154
+ $adapter->quote('rn.region_id = r.region_id AND locale = ?', Mage::app()->getLocale()->getLocaleCode()),
155
+ array('name')
156
+ )
157
+ ->where('name = ? OR default_name = ?', $name, $name);
158
+
159
+ if ($countryId) {
160
+ $select->where('r.country_id = ?', $countryId);
161
+ }
162
+
163
+ $row = $adapter->fetchRow($select);
164
+ return empty($row['region_id']) ? null : $row['region_id'];
165
+ }
166
+ }
app/code/local/FI/Checkout/Model/Source.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout source model
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_Model_Source
10
+ {
11
+ /**
12
+ * Constants for password types
13
+ */
14
+ const PASSWORD_FIELD = 'field';
15
+ const PASSWORD_GENERATE = 'generate';
16
+ const PASSWORD_PHONE = 'phone';
17
+
18
+ /**
19
+ * Constants for location types
20
+ */
21
+ const LOCATION_ONE = 'one';
22
+ const LOCATION_FEW = 'few';
23
+
24
+ /**
25
+ * Constants for checkbox types
26
+ */
27
+ const CHECKBOX_UNVISIBLE = 'unvisible';
28
+ const CHECKBOX_UNCHECKED = 'unchecked';
29
+ const CHECKBOX_CHECKED = 'checked';
30
+
31
+ /**
32
+ * Return a list of password types
33
+ *
34
+ * @return array
35
+ */
36
+ public function getPasswordTypes()
37
+ {
38
+ return array(
39
+ self::PASSWORD_FIELD => Mage::helper('fi_checkout')->__('Password Field on Checkout'),
40
+ self::PASSWORD_PHONE => Mage::helper('fi_checkout')->__('Password as Telephone Field'),
41
+ self::PASSWORD_GENERATE => Mage::helper('fi_checkout')->__('Auto Generate Password')
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Return a list of location types
47
+ *
48
+ * @return array
49
+ */
50
+ public function getLocationTypes()
51
+ {
52
+ return array(
53
+ self::LOCATION_ONE => Mage::helper('fi_checkout')->__('Country, Region, City as One Field'),
54
+ self::LOCATION_FEW => Mage::helper('fi_checkout')->__('Country, Region, City as Different Fields')
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Return a list of checkbox types
60
+ *
61
+ * @return array
62
+ */
63
+ public function getCheckboxTypes()
64
+ {
65
+ return array(
66
+ self::CHECKBOX_UNVISIBLE => Mage::helper('fi_checkout')->__('Not Visible'),
67
+ self::CHECKBOX_UNCHECKED => Mage::helper('fi_checkout')->__('Visible, Unchecked'),
68
+ self::CHECKBOX_CHECKED => Mage::helper('fi_checkout')->__('Visible, Checked')
69
+ );
70
+ }
71
+
72
+ /**
73
+ * Return enabled payment methods exclude "googlecheckout"
74
+ *
75
+ * @return array
76
+ */
77
+ public function getPaymentMethods()
78
+ {
79
+ $data = Mage::helper('fi_checkout')->getEnabledPaymentMethods();
80
+ unset($data['googlecheckout']);
81
+ $result = array();
82
+ foreach ($data as $row) {
83
+ $result[$row['value']] = $row['label'];
84
+ }
85
+ return $result;
86
+ }
87
+
88
+ /**
89
+ * Return enabled shipping methods exclude "googlecheckout"
90
+ *
91
+ * @return array
92
+ */
93
+ public function getShippingMethods()
94
+ {
95
+ $data = Mage::helper('fi_checkout')->getEnabledShippingCarriers();
96
+ $data = array_flip($data);
97
+ unset($data['googlecheckout']);
98
+ $data = array_flip($data);
99
+
100
+ return $data;
101
+ }
102
+ }
app/code/local/FI/Checkout/Model/Subscriber.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout Newsletter Subscriber
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
9
+ */
10
+ class FI_Checkout_Model_Subscriber extends Mage_Newsletter_Model_Subscriber
11
+ {
12
+ /**
13
+ * Send confirmation request email if "is_send_request_email" value equals true
14
+ *
15
+ * @return FI_Checkout_Model_Subscriber
16
+ */
17
+ public function sendConfirmationRequestEmail()
18
+ {
19
+ if ($this->getIsSendRequestEmail()) {
20
+ return parent::sendConfirmationRequestEmail();
21
+ }
22
+ return $this;
23
+ }
24
+
25
+ /**
26
+ * Send confirmation success email if "is_send_success_email" value equals true
27
+ *
28
+ * @return FI_Checkout_Model_Subscriber
29
+ */
30
+ public function sendConfirmationSuccessEmail()
31
+ {
32
+ if ($this->getIsSendSuccessEmail()) {
33
+ return parent::sendConfirmationRequestEmail();
34
+ }
35
+ return $this;
36
+ }
37
+ }
app/code/local/FI/Checkout/controllers/CheckoutController.php ADDED
@@ -0,0 +1,704 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout controller
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ class FI_Checkout_CheckoutController extends Mage_Checkout_Controller_Action
10
+ {
11
+ /**
12
+ * Pre dispatch hook. Remove addresses created by multishipping checkout
13
+ *
14
+ */
15
+ public function preDispatch()
16
+ {
17
+ parent::preDispatch();
18
+
19
+ $checkoutSessionQuote = Mage::getSingleton('checkout/session')->getQuote();
20
+ if ($checkoutSessionQuote->getIsMultiShipping()) {
21
+ $checkoutSessionQuote->setIsMultiShipping(false);
22
+ $checkoutSessionQuote->removeAllAddresses();
23
+ }
24
+
25
+ return $this;
26
+ }
27
+
28
+ /* @var $_order Mage_Sales_Model_Order */
29
+ protected $_order;
30
+
31
+ /**
32
+ * Get Order by quoteId
33
+ *
34
+ * @return Mage_Sales_Model_Order
35
+ */
36
+ protected function _getOrder()
37
+ {
38
+ if (is_null($this->_order)) {
39
+ $this->_order = Mage::getModel('sales/order')->load($this->getOnepage()->getQuote()->getId(), 'quote_id');
40
+ if (!$this->_order->getId()) {
41
+ throw new Mage_Payment_Model_Info_Exception(Mage::helper('core')->__("Can not create invoice. Order was not found."));
42
+ }
43
+ }
44
+ return $this->_order;
45
+ }
46
+
47
+ /**
48
+ * Set specific headers if session expired and send response
49
+ *
50
+ * @return FI_Checkout_CheckoutController
51
+ */
52
+ protected function _ajaxRedirectResponse()
53
+ {
54
+ $this->getResponse()
55
+ ->setHeader('HTTP/1.1', '403 Session Expired')
56
+ ->setHeader('Login-Required', 'true')
57
+ ->sendResponse();
58
+ return $this;
59
+ }
60
+
61
+ /**
62
+ * Check if session expired. If session expired call self::_ajaxRedirectResponse method
63
+ *
64
+ * @return bool
65
+ */
66
+ protected function _expireAjax()
67
+ {
68
+ if (!$this->getOnepage()->getQuote()->hasItems()
69
+ || $this->getOnepage()->getQuote()->getHasError()
70
+ || $this->getOnepage()->getQuote()->getIsMultiShipping()
71
+ ) {
72
+ $this->_ajaxRedirectResponse();
73
+ return true;
74
+ }
75
+
76
+ return false;
77
+ }
78
+
79
+ /**
80
+ * Get customer session
81
+ *
82
+ * @return Mage_Customer_Model_Session
83
+ */
84
+ protected function _getSession()
85
+ {
86
+ return Mage::getSingleton('customer/session');
87
+ }
88
+
89
+ /**
90
+ * Process error. If error exists throw exception
91
+ *
92
+ * @param mixed $result
93
+ * @return FI_Checkout_CheckoutController
94
+ */
95
+ protected function _processError($result)
96
+ {
97
+ if (isset($result['error'])) {
98
+ $message = $result['message'];
99
+ if (is_array($message)) {
100
+ $message = join('<br>', $message);
101
+ }
102
+ Mage::throwException($message);
103
+ }
104
+ return $this;
105
+ }
106
+
107
+ /**
108
+ * Subscribe customer to newsletter
109
+ *
110
+ * @param array $data customer information
111
+ * @param bool $isWantSubscribe
112
+ * @return bool
113
+ */
114
+ protected function _subscribeCustomer($data, $isWantSubscribe)
115
+ {
116
+ $helper = Mage::helper('fi_checkout');
117
+ if (!$isWantSubscribe
118
+ || !$helper->isVisibleNewsletter()
119
+ || $isWantSubscribe && $helper->isCustomerSubscribed()
120
+ ) {
121
+ return false;
122
+ }
123
+
124
+ $ownerId = Mage::getModel('customer/customer')
125
+ ->setWebsiteId(Mage::app()->getStore()->getWebsiteId())
126
+ ->loadByEmail($data['email'])
127
+ ->getId();
128
+
129
+ $session = $this->_getSession();
130
+ if ($ownerId !== null && $ownerId != $session->getCustomer()->getId()) {
131
+ Mage::throwException(Mage::helper('newsletter')->__('Sorry, you are trying to subscribe email assigned to another user'));
132
+ }
133
+
134
+ $status = Mage::getModel('fi_checkout/subscriber')
135
+ ->setIsSendSuccessEmail($helper->isNeedSendNewsletterEmail('success'))
136
+ ->setIsSendRequestEmail($helper->isNeedSendNewsletterEmail('request'))
137
+ ->subscribe($data['email']);
138
+ return Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED == $status;
139
+ }
140
+
141
+ /**
142
+ * Prepare address information from request
143
+ *
144
+ * @param array $data
145
+ * @return array
146
+ */
147
+ protected function _prepareAddress($data)
148
+ {
149
+ $address = $data['address'];
150
+ if (empty($address['id'])) {
151
+ $address['id'] = false;
152
+ }
153
+ if (isset($data['name'])) {
154
+ $name = explode(' ', trim($data['name']), 2);
155
+ $name = array_filter($name, 'trim');
156
+ } else {
157
+ $customer = $this->_getSession()->getCustomer();
158
+ $name = array(
159
+ $customer->getFirstname(),
160
+ $customer->getLastname()
161
+ );
162
+ $data['email'] = $customer->getEmail();
163
+ if (empty($address['telephone']) && $customer->getPrimaryShippingAddress()) {
164
+ $address['telephone'] = $customer->getPrimaryShippingAddress()->getTelephone();
165
+ }
166
+ }
167
+
168
+ $address['firstname'] = trim($name[0]);
169
+ $address['lastname'] = trim(isset($name[1]) ? $name[1] : '');
170
+ $address['email'] = $data['email'];
171
+
172
+ if (!$this->_getSession()->isLoggedIn()) {
173
+ $password = Mage::helper('fi_checkout')->getPassword($data);
174
+ $address['customer_password'] = $password;
175
+ $address['confirm_password'] = $password;
176
+ }
177
+ $address['use_for_shipping'] = true;
178
+
179
+ $request = new Varien_Object($address);
180
+ if (!empty($address['location'])) {
181
+ $request->setData('value', $address['location']);
182
+ }
183
+ $locData = $this->_parseAddress($request);
184
+ $address['country_id'] = $locData['country_id'];
185
+ $address['region_id'] = $locData['region_id'];
186
+ $address['region'] = $locData['region'];
187
+ $address['city'] = $locData['city'];
188
+ $address['postcode'] = $locData['postcode'];
189
+
190
+ return $address;
191
+ }
192
+
193
+ /**
194
+ * Create invoice
195
+ *
196
+ * @return Mage_Sales_Model_Order_Invoice
197
+ */
198
+ protected function _initInvoice()
199
+ {
200
+ $items = array();
201
+ foreach ($this->_getOrder()->getAllItems() as $item) {
202
+ $items[$item->getId()] = $item->getQtyOrdered();
203
+ }
204
+ /* @var $invoice Mage_Sales_Model_Service_Order */
205
+ $invoice = Mage::getModel('sales/service_order', $this->_getOrder())->prepareInvoice($items);
206
+ $invoice->setEmailSent(true)->register();
207
+
208
+ return $invoice;
209
+ }
210
+
211
+ /**
212
+ * Place order. Check for billing agreements and zero subtotal
213
+ */
214
+ protected function _placeOrder()
215
+ {
216
+ if ($requiredAgreements = Mage::helper('checkout')->getRequiredAgreementIds()) {
217
+ $postedAgreements = array_keys($this->getRequest()->getPost('agreement', array()));
218
+ if ($diff = array_diff($requiredAgreements, $postedAgreements)) {
219
+ $result['success'] = false;
220
+ $result['error'] = true;
221
+ $result['message'] = Mage::helper('checkout')->__('Please agree to all the terms and conditions before placing the order.');
222
+ $this->_processError($result);
223
+ return;
224
+ }
225
+ }
226
+
227
+ // update payment information from request for order payment
228
+ if ($payment = $this->getRequest()->getPost('payment')) {
229
+ $this->getOnepage()
230
+ ->getQuote()
231
+ ->getPayment()
232
+ ->importData($payment);
233
+ }
234
+
235
+ $this->getOnepage()->saveOrder();
236
+
237
+ $storeId = Mage::app()->getStore()->getId();
238
+ $paymentHelper = Mage::helper("payment");
239
+ $zeroSubTotalPaymentAction = $paymentHelper->getZeroSubTotalPaymentAutomaticInvoice($storeId);
240
+ if ($paymentHelper->isZeroSubTotal($storeId)
241
+ && $this->_getOrder()->getGrandTotal() == 0
242
+ && $zeroSubTotalPaymentAction == Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE_CAPTURE
243
+ && $paymentHelper->getZeroSubTotalOrderStatus($storeId) == 'pending'
244
+ ) {
245
+ $invoice = $this->_initInvoice();
246
+ $invoice->getOrder()->setIsInProcess(true);
247
+ $invoice->save();
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Return easy checkout page model
253
+ *
254
+ * @return FI_Checkout_Model_Page
255
+ */
256
+ public function getOnepage()
257
+ {
258
+ return Mage::getSingleton('fi_checkout/page');
259
+ }
260
+
261
+ /**
262
+ * Customer login action.
263
+ * Set before_auth_url to session and forwards to Mage_Customer_AccountController::loginPost
264
+ */
265
+ public function loginAction()
266
+ {
267
+ $this->_getSession()->setBeforeAuthUrl(Mage::getUrl('checkout/cart'))
268
+ ->setCheckoutUser(array())
269
+ ->unsShippingInfo()
270
+ ->unsShippingMethod();
271
+ $this->_forward('loginPost', 'account', 'customer');
272
+ }
273
+
274
+ /**
275
+ * Country/region/city autocompleter.
276
+ * Depends on request param "location". Set html to response.
277
+ *
278
+ * @return Mage_Core_Controller_Response_Http
279
+ */
280
+ public function locationAutocompleteAction()
281
+ {
282
+ $location = $this->getRequest()->getParam('location');
283
+ if (!$location) {
284
+ return;
285
+ }
286
+
287
+ $helper = Mage::helper('fi_checkout');
288
+ if ($helper->useOnlyDefaultCountry()) {
289
+ $location = $helper->getDefaultCountry() . ',' . $location;
290
+ }
291
+
292
+ $items = Mage::getResourceModel('fi_checkout/countries')->filter($location);
293
+
294
+ return $this->getResponse()->setBody($this->getLayout()
295
+ ->createBlock('core/template')
296
+ ->setTemplate('freaks/autocomplete.phtml')
297
+ ->setItems($items)
298
+ ->toHtml()
299
+ );
300
+ }
301
+
302
+ /**
303
+ * Checkout UI updater.
304
+ * Update shipping/payment methods and totals blocks.
305
+ * Depends on POST request with fields "type" and "value". "type" specify what parts of UI should be updated.
306
+ *
307
+ * @return Mage_Core_Controller_Response_Http
308
+ */
309
+ public function updateAction()
310
+ {
311
+ $request = $this->getRequest();
312
+ if (!$request->isPost()
313
+ || !$request->getParam('type')
314
+ || !$request->getParam('value')
315
+ || $this->_expireAjax()
316
+ ) {
317
+ return $this;
318
+ }
319
+
320
+ $blocks = array();
321
+
322
+ $type = explode(',', $request->getParam('type'));
323
+ $type = array_flip($type);
324
+
325
+ if (isset($type['shipping'])) {
326
+ $data = $this->_parseAddress(new Varien_Object($request->getParams()));
327
+ if ($data) {
328
+ $this->_getSession()->setShippingInfo($data);
329
+ }
330
+ }
331
+ $this->_syncAddress($this->_getSession()->getShippingInfo());
332
+
333
+ $shippingMethod = $request->getPost('shipping_method', $this->_getSession()->getShippingMethod());
334
+ if ($shippingMethod) {
335
+ $this->_getSession()->setShippingMethod($shippingMethod);
336
+ }
337
+
338
+ $this->_syncAddress(array('shipping_method' => $shippingMethod));
339
+
340
+ $this->getLayout()->getUpdate()
341
+ ->load('fi_checkout_update');
342
+ $this->getLayout()->generateXml()
343
+ ->generateBlocks();
344
+
345
+ if (isset($type['shipping'])) {
346
+ $blocks['shipping'] = $this->getLayout()
347
+ ->getBlock('fi_checkout.shipping_method.available')
348
+ ->toHtml();
349
+ }
350
+
351
+ if (isset($type['payment'])) {
352
+ $blocks['payment'] = $this->getLayout()
353
+ ->getBlock('fi_checkout.payment_methods')
354
+ ->toHtml();
355
+ }
356
+
357
+ if (isset($type['totals'])) {
358
+ $this->getOnepage()->getQuote()->collectTotals();
359
+ $blocks['totals'] = $this->getLayout()
360
+ ->getBlock('checkout.cart.totals')
361
+ ->toHtml();
362
+ }
363
+
364
+ if ($blocks) {
365
+ $response = new Varien_Object($blocks);
366
+ return $this->getResponse()->setBody($response->toJson());
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Set html to response. Return regions html select box for specific country.
372
+ * Depends on "country_id" parameter
373
+ */
374
+ public function regionsAction()
375
+ {
376
+ $countryId = $this->getRequest()->getParam('country_id');
377
+ if (!$countryId) {
378
+ return $this;
379
+ }
380
+
381
+ $regions = Mage::getModel('directory/region')->getResourceCollection()
382
+ ->addCountryFilter($countryId)
383
+ ->load()
384
+ ->toOptionArray();
385
+
386
+ $html = $this->getLayout()->createBlock('core/html_select')
387
+ ->setTitle(Mage::helper('checkout')->__('State/Province'))
388
+ ->setClass('required-entry validate-state')
389
+ ->setName('user[address][region_id]')
390
+ ->setId('address-region')
391
+ ->setOptions($regions)
392
+ ->getHtml();
393
+
394
+ $this->getResponse()->setBody($html);
395
+ }
396
+
397
+ /**
398
+ * Update shipping/billing address information
399
+ *
400
+ * @param array $data
401
+ * @return FI_Checkout_CheckoutController
402
+ */
403
+ protected function _syncAddress($data)
404
+ {
405
+ if (!is_array($data)) {
406
+ return $this;
407
+ }
408
+
409
+ $address = $this->getOnepage()->getQuote()
410
+ ->getShippingAddress();
411
+
412
+ if (!empty($data['shipping_method'])) {
413
+ $address->setShippingMethod($data['shipping_method']);
414
+ unset($data['shipping_method']);
415
+ }
416
+
417
+ if ($data) {
418
+ $address->addData($data);
419
+
420
+ $this->getOnepage()->getQuote()
421
+ ->getBillingAddress()
422
+ ->addData($data);
423
+ }
424
+
425
+ return $this;
426
+ }
427
+
428
+ /**
429
+ * Parse address information from request
430
+ *
431
+ * @param Varien_Object $request
432
+ * @return array
433
+ */
434
+ protected function _parseAddress($request)
435
+ {
436
+ $helper = Mage::helper('fi_checkout');
437
+ $data = array(
438
+ 'country_id' => null,
439
+ 'region' => null,
440
+ 'region_id' => null,
441
+ 'city' => null
442
+ );
443
+
444
+ if ($helper->isLocationAsOneField()) {
445
+ $loc = $request->getData('value');
446
+ if ($helper->useOnlyDefaultCountry()) {
447
+ $loc = $helper->getDefaultCountry() . ',' . $loc;
448
+ }
449
+ $loc = explode(',', $loc);
450
+ $loc = array_map('trim', $loc);
451
+
452
+ if (!empty($loc[0])) {
453
+ $loc[0] = $helper->lowerCase($loc[0]);
454
+ $countries = array_flip(array_map(
455
+ array($helper, 'lowerCase'),
456
+ Mage::app()->getLocale()->getCountryTranslationList()
457
+ ));
458
+
459
+ if (!$helper->useOnlyDefaultCountry() && isset($countries[$loc[0]])) {
460
+ $data['country_id'] = $countries[$loc[0]];
461
+ } else {
462
+ $data['country_id'] = $helper->getDefaultCountry();
463
+ }
464
+
465
+ if (!empty($loc[1])) {
466
+ $data['city'] = $data['region'] = $loc[1];
467
+ }
468
+
469
+ if (!empty($loc[2])) {
470
+ $data['city'] = $loc[2];
471
+ }
472
+ }
473
+ } else {
474
+ $data['country_id'] = $request->getData('country_id');
475
+ if ($helper->useOnlyDefaultCountry() || empty($data['country_id'])) {
476
+ $data['country_id'] = $helper->getDefaultCountry();
477
+ }
478
+
479
+ $data['region'] = $request->getData('region');
480
+ $data['city'] = $request->getData('city');
481
+ }
482
+
483
+ $data['postcode'] = $request->getData('postcode');
484
+ if (!empty($data['region'])) {
485
+ $data['region_id'] = Mage::getResourceModel('fi_checkout/countries')
486
+ ->getRegionIdByName(trim($data['region']), $data['country_id']);
487
+ if ($data['region_id']) {
488
+ $data['region'] = null;
489
+ }
490
+ }
491
+
492
+ return $data;
493
+ }
494
+
495
+ /**
496
+ * Set response in special format
497
+ *
498
+ * @param Varien_Object $response
499
+ * @return FI_Checkout_CheckoutController
500
+ */
501
+ protected function _response(Varien_Object $response)
502
+ {
503
+ if ($response->hasErrorMessage()) {
504
+ $errorHtml = $this->getLayout()
505
+ ->createBlock('core/messages')
506
+ ->addError($response->getErrorMessage())
507
+ ->getGroupedHtml();
508
+
509
+ $response->setErrorMessage($errorHtml);
510
+ }
511
+
512
+ $this->getResponse()->setBody($response->toJson());
513
+
514
+ return $this;
515
+ }
516
+
517
+ /**
518
+ * Place order action. Listen for POST requests only
519
+ *
520
+ * @return FI_Checkout_CheckoutController
521
+ */
522
+ public function placeAction()
523
+ {
524
+ $response = new Varien_Object();
525
+ $data = $this->getRequest()->getPost('user');
526
+ if (!$this->getRequest()->isPost() || !$data || $this->_expireAjax()) {
527
+ $response->setRedirect(Mage::getUrl('checkout/cart'));
528
+ return $this->_response($response);
529
+ }
530
+
531
+ $session = $this->_getSession();
532
+ $hasError = false;
533
+ $quote = $this->getOnepage()->getQuote();
534
+ $session->setCheckoutUser($data);
535
+
536
+ if (!$quote->validateMinimumAmount()) {
537
+ $error = Mage::getStoreConfig('sales/minimum_order/error_message');
538
+ $response->setErrorMessage($error);
539
+ return $this->_response($response);
540
+ }
541
+
542
+ try {
543
+ // save checkout method
544
+ if ($session->isLoggedIn()) {
545
+ $quote->setCheckoutMethod(Mage_Checkout_Model_Type_Onepage::METHOD_CUSTOMER);
546
+ } elseif (empty($data['address']['id'])) {
547
+ $quote->setCheckoutMethod(Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER);
548
+ }
549
+ $this->getOnepage()->initCheckout();
550
+
551
+ // save addresses
552
+ $data['address'] = $this->_prepareAddress($data);
553
+ $result = $this->getOnepage()->saveBilling($data['address'], $data['address']['id']);
554
+ $this->_processError($result);
555
+
556
+ $this->_subscribeCustomer($data['address'], $this->getRequest()->getPost('subscribe', false));
557
+
558
+ // save shipping method
559
+ $shippingMethod = $this->getRequest()->getPost('shipping_method');
560
+ if (!$quote->getIsVirtual() && empty($shippingMethod)) {
561
+ $this->_processError(array(
562
+ 'error' => -1,
563
+ 'message' => Mage::helper('checkout')->__('Invalid shipping method.')
564
+ ));
565
+ }
566
+
567
+ /**
568
+ * Addresses has been validated in saveBilling method,
569
+ * so we are disabled validation
570
+ */
571
+ $quote->getShippingAddress()
572
+ ->setShippingMethod($shippingMethod)
573
+ ->setSaveInAddressBook(!$session->getCustomer() || !$session->getCustomer()->getDefaultShipping())
574
+ ->setShouldIgnoreValidation(true);
575
+
576
+ $quote->getBillingAddress()
577
+ ->setSaveInAddressBook(!$session->getCustomer() || !$session->getCustomer()->getDefaultBilling())
578
+ ->setShouldIgnoreValidation(true);
579
+
580
+ Mage::dispatchEvent('checkout_controller_onepage_save_shipping_method', array(
581
+ 'request' => $this->getRequest(),
582
+ 'quote' => $quote
583
+ ));
584
+
585
+ $quote->setTotalsCollectedFlag(false)
586
+ ->collectTotals();
587
+
588
+ // save payment information
589
+ $payment = $this->getRequest()->getPost('payment');
590
+ $this->getOnepage()->savePayment($payment);
591
+
592
+ $redirectUrl = $quote->getPayment()->getCheckoutRedirectUrl();
593
+ if ($redirectUrl) {
594
+ $response->setRedirect($redirectUrl);
595
+ return $this->_response($response);
596
+ }
597
+
598
+ // save order
599
+ $this->_placeOrder();
600
+ $redirectUrl = $this->getOnepage()
601
+ ->getCheckout()
602
+ ->getRedirectUrl();
603
+
604
+ $quote->setIsActive(!empty($redirectUrl))->save();
605
+
606
+ $session->setCheckoutUser(array())
607
+ ->unsShippingInfo();
608
+ } catch (Mage_Core_Exception $e) {
609
+ $hasError = true;
610
+ $response->setErrorMessage($e->getMessage());
611
+ } catch (Exception $e) {
612
+ Mage::logException($e);
613
+ $hasError = true;
614
+ $response->setErrorMessage(Mage::helper('checkout')->__('Unable to process your order. Please try again later'));
615
+ }
616
+
617
+ if (!$redirectUrl && !$hasError) {
618
+ $redirectUrl = Mage::getUrl('*/*/success');
619
+ }
620
+
621
+ $response->setError($hasError)
622
+ ->setSuccess(!$hasError)
623
+ ->setRedirect($redirectUrl);
624
+ $this->_response($response);
625
+
626
+ Mage::dispatchEvent('controller_action_postdispatch_checkout_onepage_saveOrder', array(
627
+ 'controller_action' => $this
628
+ ));
629
+
630
+ return $this;
631
+ }
632
+
633
+ /**
634
+ * Order success action
635
+ */
636
+ public function successAction()
637
+ {
638
+ $session = $this->getOnepage()->getCheckout();
639
+ if (!$session->getLastSuccessQuoteId()) {
640
+ $this->_redirect('checkout/cart');
641
+ return;
642
+ }
643
+
644
+ $lastQuoteId = $session->getLastQuoteId();
645
+ $lastOrderId = $session->getLastOrderId();
646
+ $lastRecurringProfiles = $session->getLastRecurringProfileIds();
647
+ if (!$lastQuoteId || (!$lastOrderId && empty($lastRecurringProfiles))) {
648
+ $this->_redirect('checkout/cart');
649
+ return;
650
+ }
651
+
652
+ $session->clear();
653
+ $this->loadLayout();
654
+ $this->_initLayoutMessages('checkout/session');
655
+ Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
656
+ $this->renderLayout();
657
+ }
658
+
659
+ /**
660
+ * Verify card using 3D secure
661
+ *
662
+ * @return FI_Checkout_CheckoutController
663
+ */
664
+ public function verifyAction()
665
+ {
666
+ $payment = $this->getRequest()->getPost('payment');
667
+ if (!$payment) {
668
+ return $this;
669
+ }
670
+
671
+ $verifyUrl = '';
672
+ $quote = $this->getOnepage()->getQuote();
673
+ $this->getOnepage()->savePayment($payment);
674
+
675
+ $paymentMethod = $quote->getPayment()->getMethodInstance();
676
+ if ($paymentMethod && $paymentMethod->getIsCentinelValidationEnabled()) {
677
+ $centinel = $paymentMethod->getCentinelValidator();
678
+ if ($centinel && $centinel->shouldAuthenticate()) {
679
+ $verifyUrl = $centinel->getAuthenticationStartUrl();
680
+ }
681
+ }
682
+
683
+ if ($verifyUrl) {
684
+ $html = $this->getLayout()->createBlock('core/template')
685
+ ->setTemplate('freaks/checkout/centinel/authentication.phtml')
686
+ ->setFrameUrl($verifyUrl)
687
+ ->toHtml();
688
+ } else {
689
+ $html = $this->getLayout()->createBlock('core/template')
690
+ ->setTemplate('freaks/checkout/centinel/complete.phtml')
691
+ ->setIsProcessed(true)
692
+ ->setIsSuccess(true)
693
+ ->toHtml();
694
+ }
695
+
696
+ $response = new Varien_Object(array(
697
+ 'url' => $verifyUrl,
698
+ 'html' => $html
699
+ ));
700
+
701
+ $this->getResponse()->setBody($response->toJson());
702
+ return $this;
703
+ }
704
+ }
app/code/local/FI/Checkout/etc/config.xml ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * @category FI
5
+ * @package FI_Checkout
6
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
7
+ */
8
+ -->
9
+ <config>
10
+ <modules>
11
+ <FI_Checkout>
12
+ <version>1.0.0</version>
13
+ </FI_Checkout>
14
+ </modules>
15
+ <global>
16
+ <blocks>
17
+ <fi_checkout>
18
+ <class>FI_Checkout_Block</class>
19
+ </fi_checkout>
20
+ </blocks>
21
+ <helpers>
22
+ <fi_checkout>
23
+ <class>FI_Checkout_Helper</class>
24
+ </fi_checkout>
25
+ </helpers>
26
+ <models>
27
+ <fi_checkout>
28
+ <class>FI_Checkout_Model</class>
29
+ <resourceModel>fi_checkout_resource</resourceModel>
30
+ </fi_checkout>
31
+ <fi_checkout_resource>
32
+ <class>FI_Checkout_Model_Resource</class>
33
+ </fi_checkout_resource>
34
+ </models>
35
+ <resources>
36
+ <fi_checkout_setup>
37
+ <setup>
38
+ <module>FI_Checkout</module>
39
+ <class>Mage_Eav_Model_Entity_Setup</class>
40
+ </setup>
41
+ </fi_checkout_setup>
42
+ </resources>
43
+ </global>
44
+ <frontend>
45
+ <routers>
46
+ <fi_checkout>
47
+ <use>standard</use>
48
+ <args>
49
+ <module>FI_Checkout</module>
50
+ <frontName>fi_order</frontName>
51
+ </args>
52
+ </fi_checkout>
53
+ </routers>
54
+ <layout>
55
+ <updates>
56
+ <fi_checkout>
57
+ <file>freaks/checkout.xml</file>
58
+ </fi_checkout>
59
+ </updates>
60
+ </layout>
61
+ <events>
62
+ <sales_quote_collect_totals_before>
63
+ <observers>
64
+ <fi_checkout>
65
+ <class>fi_checkout/observer</class>
66
+ <method>collectTotalsBefore</method>
67
+ </fi_checkout>
68
+ </observers>
69
+ </sales_quote_collect_totals_before>
70
+ <checkout_type_onepage_save_order>
71
+ <observers>
72
+ <fi_checkout>
73
+ <class>fi_checkout/observer</class>
74
+ <method>addOrderComment</method>
75
+ </fi_checkout>
76
+ </observers>
77
+ </checkout_type_onepage_save_order>
78
+ </events>
79
+ </frontend>
80
+ <default>
81
+ <checkout>
82
+ <easyco>
83
+ <default_country>UA</default_country>
84
+ <default_region>Kyiv</default_region>
85
+ <default_city>Kyiv</default_city>
86
+ <use_default_country>0</use_default_country>
87
+ <password_type>field</password_type>
88
+ <location_type>few</location_type>
89
+ <show_build_fields>0</show_build_fields>
90
+ <show_newsletter>unchecked</show_newsletter>
91
+ <newsletter_send_request>1</newsletter_send_request>
92
+ <newsletter_send_success>1</newsletter_send_success>
93
+ </easyco>
94
+ </checkout>
95
+ </default>
96
+ </config>
app/code/local/FI/Checkout/etc/system.xml ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * @category FI
5
+ * @package FI_Checkout
6
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
7
+ */
8
+ -->
9
+ <config>
10
+ <sections>
11
+ <checkout>
12
+ <groups>
13
+ <easyco translate="label">
14
+ <label>0 Step Checkout</label>
15
+ <frontend_type>text</frontend_type>
16
+ <sort_order>1</sort_order>
17
+ <show_in_default>1</show_in_default>
18
+ <show_in_website>1</show_in_website>
19
+ <show_in_store>0</show_in_store>
20
+ <fields>
21
+ <!--
22
+ <default_payment_method>
23
+ <label>Default Payment Method</label>
24
+ <frontend_type>select</frontend_type>
25
+ <source_model>adminhtml/system_config_source_payment_allowedmethods</source_model>
26
+ <sort_order>1</sort_order>
27
+ <show_in_default>1</show_in_default>
28
+ <show_in_website>1</show_in_website>
29
+ <show_in_store>1</show_in_store>
30
+ </default_payment_method>
31
+ <default_shipping_method>
32
+ <label>Default Payment Method</label>
33
+ <frontend_type>select</frontend_type>
34
+ <source_model>adminhtml/system_config_source_shipping_allowedmethods</source_model>
35
+ <sort_order>2</sort_order>
36
+ <show_in_default>1</show_in_default>
37
+ <show_in_website>1</show_in_website>
38
+ <show_in_store>1</show_in_store>
39
+ </default_shipping_method>
40
+ -->
41
+ <default_country translate="label">
42
+ <label>Default Country</label>
43
+ <frontend_type>select</frontend_type>
44
+ <source_model>adminhtml/system_config_source_country</source_model>
45
+ <sort_order>5</sort_order>
46
+ <show_in_default>1</show_in_default>
47
+ <show_in_website>1</show_in_website>
48
+ <show_in_store>1</show_in_store>
49
+ </default_country>
50
+ <default_region translate="label">
51
+ <label>Default Region</label>
52
+ <frontend_type>text</frontend_type>
53
+ <sort_order>10</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>1</show_in_website>
56
+ <show_in_store>1</show_in_store>
57
+ </default_region>
58
+ <default_city translate="label">
59
+ <label>Default City</label>
60
+ <frontend_type>text</frontend_type>
61
+ <sort_order>15</sort_order>
62
+ <show_in_default>1</show_in_default>
63
+ <show_in_website>1</show_in_website>
64
+ <show_in_store>1</show_in_store>
65
+ </default_city>
66
+ <use_default_country translate="label">
67
+ <label>Checkout Only For Default Country</label>
68
+ <frontend_type>select</frontend_type>
69
+ <source_model>adminhtml/system_config_source_yesno</source_model>
70
+ <sort_order>20</sort_order>
71
+ <show_in_default>1</show_in_default>
72
+ <show_in_website>1</show_in_website>
73
+ <show_in_store>0</show_in_store>
74
+ </use_default_country>
75
+ <password_type translate="label">
76
+ <label>Password Type</label>
77
+ <frontend_type>select</frontend_type>
78
+ <source_model>fi_checkout/source::getPasswordTypes</source_model>
79
+ <sort_order>25</sort_order>
80
+ <show_in_default>1</show_in_default>
81
+ <show_in_website>1</show_in_website>
82
+ <show_in_store>0</show_in_store>
83
+ </password_type>
84
+ <location_type translate="label">
85
+ <label>Location Type</label>
86
+ <frontend_type>select</frontend_type>
87
+ <source_model>fi_checkout/source::getLocationTypes</source_model>
88
+ <sort_order>25</sort_order>
89
+ <show_in_default>1</show_in_default>
90
+ <show_in_website>1</show_in_website>
91
+ <show_in_store>1</show_in_store>
92
+ </location_type>
93
+ <show_build_fields>
94
+ <label>Show Building/Room Number</label>
95
+ <frontend_type>select</frontend_type>
96
+ <source_model>adminhtml/system_config_source_yesno</source_model>
97
+ <comment>Show Address Building/Room Number as Separated Fields</comment>
98
+ <sort_order>30</sort_order>
99
+ <show_in_default>1</show_in_default>
100
+ <show_in_website>1</show_in_website>
101
+ <show_in_store>0</show_in_store>
102
+ </show_build_fields>
103
+ <show_newsletter>
104
+ <label>Show Newsletter Checkbox</label>
105
+ <frontend_type>select</frontend_type>
106
+ <source_model>fi_checkout/source::getCheckboxTypes</source_model>
107
+ <sort_order>35</sort_order>
108
+ <show_in_default>1</show_in_default>
109
+ <show_in_website>1</show_in_website>
110
+ <show_in_store>0</show_in_store>
111
+ </show_newsletter>
112
+ <newsletter_send_success>
113
+ <label>Send Newsletter Confirmation Success Email</label>
114
+ <frontend_type>select</frontend_type>
115
+ <source_model>adminhtml/system_config_source_yesno</source_model>
116
+ <sort_order>40</sort_order>
117
+ <show_in_default>1</show_in_default>
118
+ <show_in_website>1</show_in_website>
119
+ <show_in_store>0</show_in_store>
120
+ </newsletter_send_success>
121
+ <newsletter_send_request>
122
+ <label>Send Newsletter Confirmation Request Email</label>
123
+ <frontend_type>select</frontend_type>
124
+ <source_model>adminhtml/system_config_source_yesno</source_model>
125
+ <sort_order>45</sort_order>
126
+ <show_in_default>1</show_in_default>
127
+ <show_in_website>1</show_in_website>
128
+ <show_in_store>0</show_in_store>
129
+ </newsletter_send_request>
130
+ </fields>
131
+ </easyco>
132
+ </groups>
133
+ </checkout>
134
+ </sections>
135
+ </config>
app/code/local/FI/Checkout/sql/fi_checkout_setup/mysql4-install-1.0.0.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Zero Step Checkout install script
4
+ *
5
+ * @category FI
6
+ * @package FI_Checkout
7
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
8
+ */
9
+ $installer = $this;
10
+
11
+ $installer->startSetup();
12
+ foreach (array('customer', 'customer_address') as $entity) {
13
+ $attribute = Mage::getModel('eav/config')
14
+ ->getAttribute($entity, 'lastname');
15
+
16
+ $attribute->setData('validate_rules', '')
17
+ ->setIsRequired(false)
18
+ ->save();
19
+ }
20
+
21
+ $attribute = Mage::getModel('eav/config')
22
+ ->getAttribute('customer_address', 'postcode');
23
+ $attribute->setData('validate_rules', '')
24
+ ->setIsRequired(false)
25
+ ->save();
26
+
27
+
28
+ $installer->endSetup();
app/design/frontend/default/default/layout/freaks/checkout.xml ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * @category FI
5
+ * @package FI_Checkout
6
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
7
+ */
8
+ -->
9
+ <layout version="0.1.0">
10
+ <checkout_cart_index>
11
+ <remove name="checkout.cart.top_methods" />
12
+ <remove name="checkout.cart.methods.onepage" />
13
+ <remove name="checkout.cart.shipping" />
14
+
15
+ <reference name="head">
16
+ <action method="addCss"><css>css/freaks.css</css></action>
17
+ <action method="addItem"><type>skin_js</type><name>js/freaks_checkout.js</name></action>
18
+ </reference>
19
+
20
+ <reference name="content">
21
+ <block type="fi_checkout/block" name="fi_checkout.page" as="fi_checkout_page" before="checkout.cart">
22
+ <block type="fi_checkout/block_info" name="fi_checkout.user_block" as="fi_checkout_user_block">
23
+ <block type="checkout/onepage_shipping_method_available" name="fi_checkout.shipping_method.available" as="available_shipping_methods" template="freaks/checkout/shipping/available.phtml"/>
24
+ <block type="checkout/onepage_shipping_method_additional" name="fi_checkout.shipping_method.additional" as="additional_shipping_methods" template="checkout/onepage/shipping_method/additional.phtml"/>
25
+ </block>
26
+ </block>
27
+ </reference>
28
+
29
+ <reference name="checkout.cart">
30
+ <block type="core/template" name="fi_checkout.payment" as="crosssell" template="freaks/checkout/payment.phtml">
31
+ <block type="fi_checkout/payment_methods" name="fi_checkout.payment_methods" as="methods" template="freaks/checkout/payment_methods.phtml" >
32
+ <action method="setMethodFormTemplate"><method>purchaseorder</method><template>payment/form/purchaseorder.phtml</template></action>
33
+ </block>
34
+ </block>
35
+
36
+ <reference name="checkout.cart.coupon">
37
+ <block type="checkout/cart_crosssell" name="checkout.cart.crosssell" as="crosssell" template="checkout/cart/crosssell.phtml"/>
38
+ <action method="setTemplate"><template>freaks/checkout/coupon.phtml</template></action>
39
+ </reference>
40
+ </reference>
41
+
42
+ <reference name="checkout.cart.methods">
43
+ <block type="fi_checkout/newsletter" name="fi_checkout.newsletter" template="freaks/checkout/newsletter.phtml" after="checkout.onepage.agreements" />
44
+ <block type="checkout/agreements" name="checkout.onepage.agreements" as="agreements" template="freaks/checkout/agreements.phtml" before="checkout.cart.methods.multishipping" />
45
+ <block type="core/template" name="fi_checkout.place_order" template="freaks/checkout/link.phtml" after="checkout.onepage.agreements" />
46
+ </reference>
47
+ </checkout_cart_index>
48
+
49
+ <fi_checkout_update>
50
+ <reference name="content">
51
+ <block type="checkout/onepage_shipping_method_available" name="fi_checkout.shipping_method.available" as="available_shipping_methods" template="freaks/checkout/shipping/available.phtml"/>
52
+ <block type="checkout/onepage_shipping_method_additional" name="fi_checkout.shipping_method.additional" as="additional_shipping_methods" template="checkout/onepage/shipping_method/additional.phtml"/>
53
+ <block type="fi_checkout/payment_methods" name="fi_checkout.payment_methods" as="methods" template="freaks/checkout/payment_methods.phtml">
54
+ <action method="setMethodFormTemplate"><method>purchaseorder</method><template>payment/form/purchaseorder.phtml</template></action>
55
+ </block>
56
+ <block type="checkout/cart_totals" name="checkout.cart.totals" as="totals" template="checkout/cart/totals.phtml"/>
57
+ </reference>
58
+ </fi_checkout_update>
59
+
60
+ <fi_checkout_checkout_success>
61
+ <update handle="checkout_onepage_success" />
62
+ </fi_checkout_checkout_success>
63
+
64
+ <centinel_index_authenticationcomplete>
65
+ <reference name="root">
66
+ <action method="setTemplate"><template>freaks/checkout/centinel/complete.phtml</template></action>
67
+ </reference>
68
+ </centinel_index_authenticationcomplete>
69
+ </layout>
app/design/frontend/default/default/template/freaks/autocomplete.phtml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php $items = $this->getItems() ?>
2
+ <?php if ($items): ?>
3
+ <ul>
4
+ <?php foreach ($items as $item): ?>
5
+ <li><?php echo $item ?></li>
6
+ <?php endforeach ?>
7
+ </ul>
8
+ <?php endif ?>
app/design/frontend/default/default/template/freaks/checkout/agreements.phtml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form action="" id="checkout-agreements" onsubmit="return false;">
2
+ <?php if ($this->getAgreements()): ?>
3
+ <ol class="checkout-agreements" id="easyco-agreements">
4
+ <?php foreach ($this->getAgreements() as $_a): ?>
5
+ <li class="relative">
6
+ <div class="popup agreement-popup" style="display:none" id="agree-<?php echo $_a->getId()?>">
7
+ <div class="popup-arrow"></div>
8
+ <div class="popup-heading">
9
+ <h2><?php echo $this->htmlEscape($_a->getCheckboxText()) ?></h2>
10
+ </div>
11
+ <div class="popup-content"<?php echo $_a->getContentHeight() ? ' style="height:' . $_a->getContentHeight() . '"' : '' ?>>
12
+ <?php if ($_a->getIsHtml()):?>
13
+ <?php echo $_a->getContent() ?>
14
+ <?php else:?>
15
+ <?php echo nl2br($this->htmlEscape($_a->getContent())) ?>
16
+ <?php endif; ?>
17
+ </div>
18
+ </div>
19
+ <div class="total-field">
20
+ <input type="checkbox" id="agreement-<?php echo $_a->getId()?>" name="agreement[<?php echo $_a->getId()?>]" value="1" title="<?php echo $this->htmlEscape($_a->getCheckboxText()) ?>" class="checkbox required-entry" /><label for="agreement-<?php echo $_a->getId()?>"><?php echo $this->__('I accept the') ?> <a href="#agree-<?php echo $_a->getId()?>" onclick="var c=$(this).up('div').previous();c.offsetHeight ? c.hide() : c.show();return false"><?php echo $this->__('Terms and Conditions') ?></a> <em>*</em></label>
21
+ </div>
22
+ </li>
23
+ <?php endforeach ?>
24
+ </ol>
25
+ <?php endif ?>
26
+ </form>
app/design/frontend/default/default/template/freaks/checkout/block.phtml ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $isLoggedIn = $this->isCustomerLoggedIn() ?>
2
+ <div id="checkout-block" class="<?php echo $this->helper('fi_checkout')->isLocationAsOneField() ? 'join-address' : 'split-address' ?>">
3
+ <ul class="infos-menus">
4
+ <li <?php if (!$isLoggedIn): ?> class="current"<?php endif ?>><a href="#new-user"><?php echo $this->__('New User') ?></a></li>
5
+ <li <?php if ($isLoggedIn): ?> class="current"<?php endif ?>><a href="#login"><?php echo $this->__('Registered') ?></a></li>
6
+ <li class="clear"></li>
7
+ </ul>
8
+ <div class="clear"></div>
9
+ <?php if (!$isLoggedIn): ?><div class="tab-cont new-user">
10
+ <?php echo $this->getLoginMessagesBlock()->getGroupedHtml() ?>
11
+ <?php echo $this->getChildHtml('fi_checkout_user_block') ?>
12
+ </div><?php endif ?>
13
+ <div class="tab-cont login<?php $isLoggedIn && print ' registered-user'?>"<?php if (!$isLoggedIn): ?> style="display:none"<?php endif ?>>
14
+ <?php if ($isLoggedIn): ?>
15
+ <?php echo $this->getLoginMessagesBlock()->getGroupedHtml() ?>
16
+ <?php echo $this->getChild('fi_checkout_user_block')->setFilled(true)->toHtml() ?>
17
+ <?php else: ?>
18
+ <form id="checkout-login-form" action="<?php echo $this->getLoginUrl() ?>" method="post">
19
+ <div class="field">
20
+ <label><?php echo $this->__('Login') ?></label>
21
+ <input type="text" name="login[username]" class="input-text required-entry validate-email" />
22
+ </div>
23
+ <div class="field">
24
+ <label><?php echo $this->__('Password') ?></label>
25
+ <input type="password" name="login[password]" class="input-text required-entry validate-password" />
26
+ </div>
27
+ <div class="buttons">
28
+ <a href="<?php echo $this->getUrl('customer/account/forgotpassword') ?>"><?php echo $this->__('Forgot your password?') ?></a>
29
+ <button type="submit" class="button"><span><span><?php echo $this->__('Log In') ?></span></span></button>
30
+ </div>
31
+ </form>
32
+ <?php endif ?>
33
+ </div>
34
+ <div class="overlay"></div>
35
+ </div>
app/design/frontend/default/default/template/freaks/checkout/block/info.phtml ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $isLoggedIn = $this->getFilled() && $this->isCustomerLoggedIn();
3
+ $prefix = $isLoggedIn ? 'logged' : 'new';
4
+ $isLocationAsOneField = $this->helper('fi_checkout')->isLocationAsOneField();
5
+ ?>
6
+ <form id="<?php echo $isLoggedIn ? 'checkout-login-form' : 'new-user-form' ?>" action="<?php echo $this->getUrl('fi_order/checkout/place') ?>" method="post">
7
+ <div class="col2-set">
8
+ <div class="col-1 user-general">
9
+ <p class="required">* <?php echo $this->__('Required Fields') ?></p>
10
+ <div class="field">
11
+ <label><?php echo $this->__('Name') ?>*</label>
12
+ <input type="text" class="input-text required-entry<?php echo $isLoggedIn ? ' disabled' : '' ?>" name="user[name]" value="<?php echo $this->htmlEscape($this->getCustomerName()) ?>" <?php if ($isLoggedIn): ?> disabled="disabled"<?php endif ?> <?php if ($isLoggedIn): ?> disabled="disabled"<?php endif ?> />
13
+ </div>
14
+ <div class="field relative">
15
+ <label><?php echo $this->__('Telephone') ?>*</label>
16
+ <input type="text" class="input-text required-entry<?php echo $isLoggedIn && $this->getCustomerPhone() ? ' disabled' : '' ?>" name="user[address][telephone]" value="<?php echo $this->htmlEscape($this->getCustomerPhone()) ?>" <?php if ($isLoggedIn && $this->getCustomerPhone()): ?> disabled="disabled"<?php endif ?> />
17
+ </div>
18
+ <div class="field">
19
+ <label><?php echo $this->__('E-mail') ?>*</label>
20
+ <input type="text" class="validate-email input-text required-entry<?php echo $isLoggedIn ? ' disabled' : '' ?>" name="user[email]" value="<?php echo $this->htmlEscape($this->getCustomerEmail()) ?>" <?php if ($isLoggedIn): ?> disabled="disabled"<?php endif ?> />
21
+ </div>
22
+ <?php if (!$isLoggedIn): ?>
23
+ <?php if ($this->helper('fi_checkout')->canShowPasswordField()): ?>
24
+ <div class="field">
25
+ <label><?php echo $this->helper('checkout')->__('Password') ?>*</label>
26
+ <input type="password" class="input-text validate-password" name="user[password]" />
27
+ </div>
28
+ <?php elseif ($this->helper('fi_checkout')->isPasswordAsTelephone()): ?>
29
+ <span class="note">* <?php echo $this->__('Telephone number will be your password.') ?></span>
30
+ <?php elseif ($this->helper('fi_checkout')->isPasswordAuto()): ?>
31
+ <span class="note">* <?php echo $this->__('Password will be automatically generated.') ?></span>
32
+ <?php endif ?>
33
+ <?php endif ?>
34
+ </div>
35
+ <div class="col-2">
36
+ <?php if (!$this->getQuote()->getIsVirtual()): ?>
37
+ <label class="tab-title"><?php echo $this->__('Shipping Methods') ?>*</label>
38
+ <div id="shipping-method-load" class="shipping-methods" data-action="<?php echo $this->getUrl('fi_order/checkout/update') ?>">
39
+ <?php echo $this->getChildHtml('available_shipping_methods') ?>
40
+ </div>
41
+ <div id="shipping-method-additional-load">
42
+ <?php echo $this->getChildHtml('additional_shipping_methods') ?>
43
+ </div>
44
+ <?php endif ?>
45
+ </div>
46
+ </div>
47
+ <div class="col2-set row-bottom">
48
+ <div class="col-1 addresses">
49
+ <label class="tab-title"><?php echo $this->__('Shipping Address') ?></label>
50
+ <div class="field relative">
51
+ <?php if ($isLoggedIn): ?>
52
+ <input type="hidden" name="user[address][id]" value="<?php echo $this->getAddressId() ?>" />
53
+ <?php endif ?>
54
+ <?php if ($isLocationAsOneField): ?>
55
+ <div class="f-left">
56
+ <input type="text" name="user[address][postcode]" class="input-text postcode w-30" value="<?php echo $this->htmlEscape($this->getCustomerZip()) ?>" />
57
+ <p class="help"><?php echo $this->helper('checkout')->__('Zip/Post') ?></p>
58
+ </div>
59
+ <div class="f-left no-mr" data-action="<?php echo $this->getUrl('fi_order/checkout/locationAutocomplete') ?>">
60
+ <input id="<?php echo $prefix ?>_user_location" type="text" class="input-select input-text required-entry" name="user[address][location]" value="<?php echo $this->htmlEscape($this->getCustomerLocation()) ?>" />
61
+ <a href="#" class="select-tip" tabindex="-1"></a>
62
+ <div id="<?php echo $prefix ?>_user_loc_update" class="autocomplete"></div>
63
+ <p class="help"><?php echo $this->getLocationHelp() ?>*</p>
64
+ </div>
65
+ <?php else: ?>
66
+ <div class="f-left loc-diff-fields">
67
+ <?php if (!$this->helper('fi_checkout')->useOnlyDefaultCountry()): ?>
68
+ <div class="f-left" data-action="<?php echo $this->getUrl('fi_order/checkout/regions')?>">
69
+ <?php echo $this->getCountryBlock()->setName('user[address][country_id]')->getHtml() ?>
70
+ <p class="help"><?php echo $this->helper('checkout')->__('Country') ?>*</p>
71
+ </div>
72
+ <div class="f-left relative hidden-select no-mr">
73
+ <input type="text" name="user[address][region]" class="input-text required-entry fake-title" value="<?php echo $this->htmlEscape($this->getCustomerRegion()) ?>" />
74
+ <?php $select = $this->getRegionBlock()->setName('user[address][region_id]') ?>
75
+ <?php echo $select->getHtml() ?>
76
+ <p class="help"><?php echo $select->getTitle()?>*</p>
77
+ </div>
78
+ <?php endif ?>
79
+ <div class="clear"></div>
80
+ <div class="f-left">
81
+ <input type="text" name="user[address][postcode]" class="input-text postcode" value="<?php echo $this->htmlEscape($this->getCustomerZip()) ?>" />
82
+ <p class="help"><?php echo $this->helper('checkout')->__('Zip/Post') ?></p>
83
+ </div>
84
+ <div class="f-left no-mr">
85
+ <input type="text" name="user[address][city]" class="input-text required-entry w-244" value="<?php echo $this->htmlEscape($this->getAddress()->getCity()) ?>" />
86
+ <p class="help"><?php echo $this->helper('checkout')->__('City') ?>*</p>
87
+ </div>
88
+ </div>
89
+ <?php endif ?>
90
+ <div class="clear"></div>
91
+ </div>
92
+ <div class="field">
93
+ <?php $showBuildRoomFields = $this->helper('fi_checkout')->showBuildRoomFields() ?>
94
+ <div class="f-left">
95
+ <?php $street = $this->getStreet(); ?>
96
+ <input type="text" class="input-street input-text required-entry<?php $showBuildRoomFields && print ' w-229' ?>" name="user[address][street][0]" value="<?php echo $this->htmlEscape($street) ?>" />
97
+ <p class="help"><?php echo $this->__('Street') ?>*</p>
98
+ </div>
99
+ <?php if ($showBuildRoomFields): ?>
100
+ <div class="f-left small">
101
+ <input type="text" class="input-text w-30" name="user[address][street][1]" value="<?php echo $this->htmlEscape($this->getCustomerBuilding()) ?>" />
102
+ <p class="help"><?php echo $this->__('Build.') ?></p>
103
+ </div>
104
+ <div class="f-left small no-mr">
105
+ <input type="text" class="input-text" name="user[address][street][2]" value="<?php echo $this->htmlEscape($this->getCustomerRoom()) ?>" />
106
+ <p class="help"><?php echo $this->__('Room') ?></p>
107
+ </div>
108
+ <?php endif ?>
109
+ <div class="clear"></div>
110
+ </div>
111
+ </div>
112
+ <div class="col-2">
113
+ <label class="tab-title"><?php echo $this->__('Comment')?></label>
114
+ <div class="field">
115
+ <textarea name="user[note]"><?php echo $this->htmlEscape($this->getCustomerNote()) ?></textarea>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </form>
app/design/frontend/default/default/template/freaks/checkout/centinel/authentication.phtml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <p><?php echo $this->__('Please verify the card with the issuer bank:') ?></p>
2
+ <div class="authentication">
3
+ <iframe id="centinel_authenticate_iframe" frameborder="0" border="0" src="<?php echo $this->getFrameUrl()?>"></iframe>
4
+ </div>
app/design/frontend/default/default/template/freaks/checkout/centinel/complete.phtml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ($this->getIsProcessed()):?>
2
+ <?php if ($this->getIsSuccess()):?>
3
+ <h2><?php echo $this->helper('fi_checkout')->__('Verification successful') ?></h2>
4
+ <p><?php echo $this->helper('fi_checkout')->__('Please continue with placing order') ?></p>
5
+ <script type="text/javascript">
6
+ //<![CDATA[
7
+ window.parent.CentinelAuthenticateController.success();
8
+ //]]>
9
+ </script>
10
+ <?php else:?>
11
+ <h4><?php echo $this->__('Verification Failed');?></h4>
12
+ <p><?php echo $this->__('The card has failed verification with the issuer bank.')?> <strong><?php echo $this->__('Order cannot be placed.')?></strong></p>
13
+ <?php endif;?>
14
+ <?php else:?>
15
+ <h4><?php echo $this->__('Verification cannot be processed');?></h4>
16
+ <p><?php echo $this->__('There has been wrong payment information submitted or the time limit has expired. Please, try again.')?> <strong><?php echo $this->__('Order cannot be placed.')?></strong></p>
17
+ <?php endif;?>
app/design/frontend/default/default/template/freaks/checkout/coupon.phtml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form id="discount-coupon-form" action="<?php echo $this->getUrl('checkout/cart/couponPost') ?>" method="post">
2
+ <div class="discount">
3
+ <h2><?php echo $this->__('Discount Codes') ?></h2>
4
+ <div class="discount-form">
5
+ <label for="coupon_code"><?php echo $this->__('Enter your coupon code if you have one.') ?></label>
6
+ <input type="hidden" name="remove" id="remove-coupone" value="0" />
7
+ <div class="input-box">
8
+ <input class="input-text" id="coupon_code" name="coupon_code" value="<?php echo $this->htmlEscape($this->getCouponCode()) ?>" />
9
+ </div>
10
+ <div class="buttons-set">
11
+ <button type="button" title="<?php echo $this->__('Apply Coupon') ?>" class="button" name="apply" value="<?php echo $this->__('Apply Coupon') ?>"><span><span><?php echo $this->__('Apply Coupon') ?></span></span></button>
12
+ <?php if(strlen($this->getCouponCode())): ?>
13
+ &nbsp; <button type="button" title="<?php echo $this->__('Cancel Coupon') ?>" class="button" name="cancel" value="<?php echo $this->__('Cancel Coupon') ?>"><span><span><?php echo $this->__('Cancel Coupon') ?></span></span></button>
14
+ <?php endif;?>
15
+ </div>
16
+ </div>
17
+ </div>
18
+ </form>
19
+ <?php echo $this->getChildHtml('crosssell') ?>
app/design/frontend/default/default/template/freaks/checkout/link.phtml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php if ($this->helper('fi_checkout')->canPlaceOrder()): ?>
2
+ <span class="process loading" style="display:none">&nbsp;</span>
3
+ <button type="button" class="button btn-checkout" title="<?php echo $this->__('Place Order') ?>" id="place-order">
4
+ <span><span><?php echo $this->__('Place Order') ?></span></span>
5
+ </button>
6
+ <?php endif ?>
app/design/frontend/default/default/template/freaks/checkout/newsletter.phtml ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <form id="newsletter-form">
2
+ <div class="total-field">
3
+ <input <?php $this->helper('fi_checkout')->isNewsletterChecked() && print 'checked="checked" '?>type="checkbox" id="subscriber" name="subscribe" value="1" title="<?php echo $this->__('Subscribe to Newsletter') ?>" class="checkbox"><label for="subscriber" class="fs-12" style="color:#666"><?php echo $this->__('Subscribe to our newsletter') ?></label>
4
+ </div>
5
+ </form>
app/design/frontend/default/default/template/freaks/checkout/payment.phtml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="payment-methods" class="discount">
2
+ <h2><?php echo $this->__('Choose Payment Method') ?>*</h2>
3
+ <div>
4
+ <div id="payment-form" data-action="<?php echo $this->getUrl('fi_order/checkout/update') ?>">
5
+ <?php echo $this->getChildHtml('methods') ?>
6
+ </div>
7
+ </div>
8
+ <div class="popup" id="payment-popup" style="display:none">
9
+ <a href="#" class="popup-close">x</a>
10
+ <div class="popup-heading"><h2><?php echo $this->__('Card Verification')?></h2></div>
11
+ <div class="popup-content"></div>
12
+ </div>
13
+ </div>
app/design/frontend/default/default/template/freaks/checkout/payment_methods.phtml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $count = sizeof($this->getMethods()) ?>
2
+ <form id="payments" onsubmit="return false">
3
+ <dl class="sp-methods">
4
+ <?php foreach ($this->getMethods() as $_method): $_code = $_method->getCode() ?>
5
+ <?php $verifyUrl = $this->getVerifyCcUrl($_method) ?>
6
+ <dt>
7
+ <?php if ($count > 1): ?>
8
+ <input id="p_method_<?php echo $_code ?>" value="<?php echo $_code ?>" type="radio" name="payment[method]" title="<?php echo $this->htmlEscape($_method->getTitle()) ?>"<?php if($this->getSelectedMethodCode()==$_code): ?> checked="checked"<?php endif; ?> class="radio validate-one-required-by-name" data-action="<?php echo $verifyUrl ?>" />
9
+ <?php else: ?>
10
+ <span class="no-display"><input id="p_method_<?php echo $_code ?>" value="<?php echo $_code ?>" type="radio" name="payment[method]" checked="checked" class="radio" data-action="<?php echo $verifyUrl ?>" /></span>
11
+ <?php endif; ?>
12
+ <label for="p_method_<?php echo $_code ?>"><?php echo $this->getMethodTitle($_method) ?> <?php echo $this->getMethodLabelAfterHtml($_method) ?></label>
13
+ </dt>
14
+ <?php if ($html = $this->getPaymentMethodFormHtml($_method)): ?>
15
+ <dd>
16
+ <?php echo $html; ?>
17
+ </dd>
18
+ <?php endif; ?>
19
+ <?php endforeach; ?>
20
+ </dl>
21
+ </form>
app/design/frontend/default/default/template/freaks/checkout/shipping/available.phtml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (!($_shippingRateGroups = $this->getShippingRates())): ?>
2
+ <p><?php echo $this->__('Sorry, no quotes are available for this order at this time.') ?></p>
3
+ <?php else: ?>
4
+ <?php $shippingCodePrice = array(); ?>
5
+ <?php $_sole = count($_shippingRateGroups) == 1; foreach ($_shippingRateGroups as $code => $_rates): ?>
6
+ <ul class="sp-methods">
7
+ <?php $_sole = $_sole && count($_rates) == 1; foreach ($_rates as $_rate): ?>
8
+ <?php $shippingCodePrice[] = "'".$_rate->getCode()."':".(float)$_rate->getPrice(); ?>
9
+ <li>
10
+ <?php if ($_rate->getErrorMessage()): ?>
11
+ <ul class="messages"><li class="error-msg"><ul><li><?php echo $_rate->getErrorMessage() ?></li></ul></li></ul>
12
+ <?php else: ?>
13
+ <?php if ($_sole) : ?>
14
+ <span class="no-display"><input class="validate-one-required-by-name" name="shipping_method" type="radio" value="<?php echo $_rate->getCode() ?>" id="s_method_<?php echo $_rate->getCode() ?>" checked="checked" /></span>
15
+ <?php else: ?>
16
+ <input class="validate-one-required-by-name" name="shipping_method" type="radio" value="<?php echo $_rate->getCode() ?>" id="s_method_<?php echo $_rate->getCode() ?>"<?php if($_rate->getCode()===$this->getAddressShippingMethod()) echo ' checked="checked"' ?> class="radio"/>
17
+ <?php endif; ?>
18
+ <label for="s_method_<?php echo $_rate->getCode() ?>"><?php echo $_rate->getMethodTitle() ?>
19
+ <?php $_excl = $this->getShippingPrice($_rate->getPrice(), $this->helper('tax')->displayShippingPriceIncludingTax()); ?>
20
+ <?php $_incl = $this->getShippingPrice($_rate->getPrice(), true); ?>
21
+ <?php echo $_excl; ?>
22
+ <?php if ($this->helper('tax')->displayShippingBothPrices() && $_incl != $_excl): ?>
23
+ (<?php echo $this->__('Incl. Tax'); ?> <?php echo $_incl; ?>)
24
+ <?php endif; ?>
25
+ </label>
26
+ <?php endif ?>
27
+ </li>
28
+ <?php endforeach; ?>
29
+ </ul>
30
+ <?php endforeach; ?>
31
+ <?php endif; ?>
app/etc/modules/FI_Checkout.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <FI_Checkout>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ </FI_Checkout>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>FI_Checkout</name>
4
+ <version>1.0.3</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://atmagex.com/license-agreement">FreaksIdea License Agreement</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>0 Step Checkout provide One Page Checkout functionality for Magento, combine all the steps for checkout (including shopping cart) into one page only. It will made the checkout process much simpler. </summary>
10
+ <description>0 Step Checkout provide One Page Checkout functionality for Magento, combine all the steps for checkout (including shopping cart) into one page only. It will made the checkout process much simpler. To get more information please visit http://atmagex.com/0-step-checkout-magento.html</description>
11
+ <notes>- Refactored javascript code using pattern builder to make it easily support and customized.&#xD;
12
+ - Fixed few bugs with wrong logic. &#xD;
13
+ - Refactored PHP code, put all process that used customer session into helper. It makes some parts of code shared between different parts of the extension.&#xD;
14
+ &#xD;
15
+ Version 1.0 released&#xD;
16
+ 2012/05/16&#xD;
17
+ Version number: 1.0&#xD;
18
+ Stability: stable&#xD;
19
+ Compatibility: 1.5, 1.6, 1.6.0.0, 1.6.1, 1.6.2.0, 1.7</notes>
20
+ <authors><author><name>Sergiy Stotskiy</name><user>sergiy_stotskiy</user><email>sergiy.stotskiy@freaksidea.com</email></author></authors>
21
+ <date>2012-06-09</date>
22
+ <time>22:08:52</time>
23
+ <contents><target name="magelocal"><dir name="FI"><dir name="Checkout"><dir name="Block"><dir name="Block"><file name="Info.php" hash="af7479d20f4510feaf02f14173521892"/></dir><file name="Block.php" hash="e96feb1510b4bdc5ba4513e7f98490cf"/><file name="Newsletter.php" hash="19d5938be8caac3eb661fb1f45af66f3"/><dir name="Payment"><file name="Methods.php" hash="c42b6ba6678ab68312fba904cc01e2c1"/></dir></dir><dir name="Helper"><file name="Data.php" hash="97f92a65c8f3df8a5c080e7c0d3008a5"/></dir><dir name="Model"><file name="Observer.php" hash="2576097aec72d2589096fabca98be7d4"/><file name="Page.php" hash="2d8eb0a98862271c6d4f654ccf639a50"/><dir name="Resource"><file name="Countries.php" hash="75f44d3714df682941dfe9a6c7f0b440"/></dir><file name="Source.php" hash="d1984805586e356ad6e974220f1e9b2c"/><file name="Subscriber.php" hash="e0d4206673e616a136322537264f03cf"/></dir><dir name="controllers"><file name="CheckoutController.php" hash="5721f388bb522481f8629b0917b78546"/></dir><dir name="etc"><file name="config.xml" hash="ee654172d7b4ff7c4708b21243e10bd4"/><file name="system.xml" hash="d9274eefe2f17c13c39988a67c7f66fa"/></dir><dir name="sql"><dir name="fi_checkout_setup"><file name="mysql4-install-1.0.0.php" hash="1f0f6b7d41cff2569cde4c724f2909b4"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="default"><dir name="layout"><dir name="freaks"><file name="checkout.xml" hash="3b565b258eae1f7dda4d80d9ee281642"/></dir></dir><dir name="template"><dir name="freaks"><file name="autocomplete.phtml" hash="bce316a1d37a91ed952bdb3fb87998bc"/><dir name="checkout"><file name="agreements.phtml" hash="72495b7d2cf6632a9ac9d266d045a3d8"/><dir name="block"><file name="info.phtml" hash="4efd83bfd4e6d1b5ae7a05916612742c"/></dir><file name="block.phtml" hash="cb8d320fd05e9d919c504acbb14ea8da"/><dir name="centinel"><file name="authentication.phtml" hash="fe87fdc373fe0cdbcc25141f5e2696c7"/><file name="complete.phtml" hash="83f6e30a7445f8b8b8c343e9fa02b983"/></dir><file name="coupon.phtml" hash="b70b6766d72d16c2357f29453a386b98"/><file name="link.phtml" hash="e12f971b4ab1cb43bb252bada257f2af"/><file name="newsletter.phtml" hash="ecd6f19fcf11b41bedcf18cf0cdbee44"/><file name="payment.phtml" hash="6cac0f89dc309fc687b9ba711625906a"/><file name="payment_methods.phtml" hash="95f5a59dad96bac448da16cd53990508"/><dir name="shipping"><file name="available.phtml" hash="8ef4a692108627fc337f9ebafd0d221f"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="FI_Checkout.xml" hash="ecc17aa69a43cdbb28610c3636963482"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="default"><dir name="default"><dir name="css"><file name="freaks.css" hash="1b66a0f2df69524c4af78385711024c4"/></dir><dir name="js"><file name="freaks_checkout.js" hash="b54d8d784c71878146411f6f4d3c40e1"/></dir><dir name="images"><dir name="fi"><file name="button.jpg" hash="fcdf2df5b1c714a7c39c61a1be387033"/><file name="loader-old.gif" hash="cf46f7db4c452ea2a94d33eabca8ba93"/><file name="loader.gif" hash="7b9776076d5fceef4993b55c9383dedd"/><file name="popup_arrow-blue.gif" hash="051e0d2ab1f2ef9df98c347b1d7c1a24"/><file name="popup_arrow-white.gif" hash="86a112b675b3a9ed5168d4309170d732"/><file name="select-loader-old.gif" hash="55ded965cfe6095ed8c49f9f980de32a"/><file name="select-loader.gif" hash="a045769166b4cad098ffe7d5aefe95e9"/><file name="select-tip.gif" hash="196ba8fe47100e603ffdd731b6d47d90"/></dir></dir></dir></dir></dir></target></contents>
24
+ <compatible/>
25
+ <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
26
+ </package>
skin/frontend/default/default/css/freaks.css ADDED
@@ -0,0 +1,423 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* General */
2
+ .relative {position:relative}
3
+
4
+ /* Ajax Login */
5
+ .popup { background:#fff; border:1px solid #aaa; margin:12px 0 0; position:absolute; -moz-box-shadow:0 0 6px #ccc; -webkit-box-shadow:0 0 6px #ccc; box-shadow:0 0 6px #ccc; text-align:left; width:300px; z-index:100; }
6
+ .popup-heading { background:#d9e5ee; border-bottom:1px solid #ccc; padding:5px 30px 5px 10px; }
7
+ .popup-heading h2 { font-size:16px; margin:0; text-shadow:0 1px 0 #f6f6f6; overflow:hidden; white-space:nowrap; word-wrap:break-word; text-align:left; text-overflow:ellipsis; }
8
+ .popup-arrow { background:url(../images/popup_arrow.gif) no-repeat; position:absolute; left:77%; top:-10px; height:10px; width:19px; }
9
+ .popup-close { background:url(../images/btn_window_close.gif) no-repeat; display:block; position:absolute; top:8px; right:10px; height:15px; width:15px; text-indent:-9999em; -moz-box-shadow:0 0 3px #999; -webkit-box-shadow:0 0 3px #999; box-shadow:0 0 3px #999; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
10
+ .popup-content { border-top:1px solid #eee; padding:10px; text-align:left; }
11
+ #login-popup {right: -100px; top:75px; width: 625px}
12
+ .ajax-loader {display: inline-block; background: url(../images/ajax-loader.gif) no-repeat 0 0; width:16px; height:11px; vertical-align: middle; }
13
+
14
+ /* Checkout */
15
+ ul.infos-menus {
16
+ border-bottom: 5px solid #0076A9
17
+ }
18
+ ul.infos-menus li {
19
+ float:left;
20
+ }
21
+ ul.infos-menus a {
22
+ display: block;
23
+ font-size: 13px;
24
+ color:#000; padding: 6px 15px;
25
+ background:#e8e8e9;
26
+ margin-right: 5px;
27
+ text-decoration: none;
28
+ -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px;
29
+ -webkit-box-shadow: 0 0 6px #ccc;
30
+ -moz-box-shadow: 0 0 6px #ccc;
31
+ box-shadow: 0 0 6px #ccc;
32
+ }
33
+ ul.infos-menus li.current a {
34
+ background: #fff;
35
+ color: #0076A9;
36
+ }
37
+
38
+ #checkout-block {
39
+ min-height: 270px;
40
+ font-size: 14px;
41
+ line-height: 1.5em;
42
+ padding-bottom:15px;
43
+ position:relative;
44
+ zoom:1;
45
+ }
46
+
47
+ #checkout-block, .hr {
48
+ border-bottom: 2px solid #989898;
49
+ }
50
+
51
+ #checkout-block .infos-menus li a,
52
+ #checkout-block .button{
53
+ font-size:14px !important;
54
+ vertical-align:middle;
55
+ }
56
+
57
+ #checkout-block .tab-cont {
58
+ margin-left: 21px;
59
+ padding-top: 13px;
60
+ width: 722px;
61
+ }
62
+
63
+ #checkout-block .tab-title {
64
+ font-size: 14px;
65
+ margin-bottom: 8px;
66
+ text-transform: uppercase;
67
+ }
68
+
69
+ #checkout-block .radio .field {
70
+ height:23px;
71
+ color: #767676;
72
+ font-size: 14px;
73
+ vertical-align:middle;
74
+ margin-bottom:1px;
75
+ }
76
+
77
+ #checkout-block .field {
78
+ margin-bottom: 2px;
79
+ }
80
+
81
+ #checkout-block label {
82
+ display:inline-block;
83
+ min-width:75px;
84
+ }
85
+
86
+ #checkout-block .user-general .validation-advice,
87
+ #checkout-block .addresses .validation-advice {
88
+ margin-left: 75px;
89
+ display:none;
90
+ }
91
+
92
+ #checkout-block input.postcode {
93
+ width:50px;
94
+ font-size:10px !important;
95
+ height:16px;
96
+ }
97
+
98
+ .input-select {
99
+ width: 259px !important;
100
+ }
101
+
102
+ #checkout-block .row-bottom {
103
+ padding-top:15px;
104
+ }
105
+
106
+ #checkout-block .addresses {
107
+ *margin-top:6px;
108
+ }
109
+
110
+ #checkout-block .addresses .relative {
111
+ zoom:1;
112
+ }
113
+
114
+ #checkout-block .loc-diff-fields select {
115
+ width:150px;
116
+ }
117
+
118
+ #checkout-block input.fake-title {
119
+ font-size:12px !important;
120
+ }
121
+ input.fake-title.input-loading {
122
+ background-position:135px center!important
123
+ }
124
+ .hidden-select {
125
+ position:relative;
126
+ }
127
+
128
+ .hidden-select select {
129
+ position:absolute;
130
+ top:0; left:0;
131
+ opacity: 0.001;
132
+ filter:alpha(opacity=1);
133
+ }
134
+
135
+ .hidden-select select, .hidden-select input {
136
+ width: 150px !important;
137
+ }
138
+
139
+ #checkout-block .input-text, #checkout-block textarea {
140
+ border: 1px solid #b6b6b6;
141
+ width: 230px;
142
+ font-size:14px !important;
143
+ }
144
+
145
+ #checkout-block textarea {
146
+ display:block;
147
+ height:65px; width:345px;
148
+ overflow:auto;
149
+ resize:none;
150
+ }
151
+
152
+
153
+ #checkout-block .hidden-tab {
154
+ position:absolute !important;
155
+ top:40px; left:0;
156
+ zoom:1;
157
+ }
158
+
159
+ #checkout-block .overlay {
160
+ position:absolute;
161
+ top:40px; left:0;
162
+ width: 100%; height:85%;
163
+ display:none;
164
+ background: #FFFFFE url(../images/bkg_main2.gif) 0 -65px no-repeat;
165
+ filter:alpha(opacity=60);
166
+ opacity: 0.6;
167
+ z-index:1;
168
+ zoom:1;
169
+ }
170
+
171
+ #checkout-block .hidden-tab .user-general {
172
+ visibility: hidden;
173
+ }
174
+
175
+ #checkout-block .tab-cont {
176
+ position:relative;
177
+ margin-left: 21px;
178
+ padding-top: 13px;
179
+ width: 722px;
180
+ z-index:1;
181
+ }
182
+
183
+ div.join-address .tab-cont {
184
+ /*
185
+ height:228px;
186
+ */
187
+ _height:244px;
188
+ min-height:244px;
189
+ }
190
+
191
+ div.split-address .tab-cont {
192
+ _height: 288px;
193
+ min-height: 288px;
194
+ }
195
+
196
+ div.split-address textarea {
197
+ height: 90px !important;
198
+ }
199
+
200
+ #checkout-block div.login {
201
+ z-index:2;
202
+ }
203
+
204
+ #checkout-block .tab-cont {
205
+ margin-left: 21px;
206
+ padding-top: 13px;
207
+ width: 722px;
208
+ }
209
+
210
+ #checkout-block .tab-title {
211
+ font-size: 14px;
212
+ margin-bottom: 8px;
213
+ text-transform: uppercase;
214
+ }
215
+
216
+ #checkout-block .required {
217
+ font-size: 12px;
218
+ text-align: left;
219
+ margin-bottom:8px;
220
+ }
221
+
222
+ #checkout-block .small .input-text {
223
+ width:20px;
224
+ }
225
+
226
+ /*
227
+ #checkout-block .button span {
228
+ display:inline-block;
229
+ background: url(../images/fi/button.jpg) no-repeat center center !important;
230
+ color:#fff;
231
+ padding:0 !important;
232
+ font-size:14px !important;
233
+ width: 61px !important; height: 26px !important; line-height: 27px !important;
234
+ }
235
+ */
236
+
237
+ #checkout-block .buttons {
238
+ text-align: right;
239
+ width: 314px;
240
+ margin-top: 8px;
241
+ }
242
+
243
+ #checkout-block .buttons a {
244
+ display: inline-block;
245
+ font-size: 12px;
246
+ color:#767676;
247
+ margin-right: 10px;
248
+ vertical-align:middle;
249
+ }
250
+
251
+ .select-tip {
252
+ background: url(../images/fi/select-tip.gif) no-repeat center center;
253
+ width:19px; height:20px;
254
+ display:block;
255
+ position: absolute;
256
+ right:37px; top:1px;
257
+ }
258
+
259
+ .field input {margin:0; display:inline;zoom:1;}
260
+ .field .f-left {
261
+ padding-right: 9px;
262
+ }
263
+
264
+ .help {
265
+ color:#8d8d8d;
266
+ font-size:10px;
267
+ margin:0;padding:0;
268
+ line-height: 13px;
269
+ }
270
+
271
+ ::-webkit-input-placeholder {
272
+ color: #888;
273
+ font:normal 14px arial, helvetica, sans-serif;
274
+ }
275
+
276
+ :-moz-placeholder {
277
+ color: #888;
278
+ font:normal 14px arial, helvetica, sans-serif;
279
+ }
280
+
281
+ .placeholder {
282
+ color: #888;
283
+ font:normal 14px arial, helvetica, sans-serif;
284
+ }
285
+ .clear {clear:both;float:none !important; font-size:1px;height:1px;line-height:1px}
286
+ .w-229 {width:229px !important}
287
+ .w-30 {width:30px !important}
288
+ .w-244 {width:244px !important}
289
+ .fs-12 {font-size: 12px !important}
290
+ .no-mr {padding-right:0 !important}
291
+ .sp-methods {margin:0}
292
+ .sp-methods label {
293
+ font-weight: normal;
294
+ color:#000;
295
+ }
296
+ .loading{background:url(../images/fi/loader.gif) no-repeat 50% 50% !important}
297
+ .shipping-methods {min-height:80px; max-height:150px; overflow:auto}
298
+ .input-loading { background:url(../images/fi/select-loader.gif) no-repeat 228px center !important }
299
+ div.autocomplete {
300
+ position:absolute;
301
+ width:250px;
302
+ background-color:white;
303
+ border:1px solid #888;
304
+ margin:0;
305
+ padding:0;
306
+ z-index: 200;
307
+ _height: 192px;
308
+ max-height: 192px; max-width: 312px;
309
+ overflow: auto;
310
+ }
311
+ div.autocomplete ul {
312
+ list-style-type:none;
313
+ margin:0;
314
+ padding:0;
315
+ }
316
+ div.autocomplete ul li.selected { background-color: #ffb;}
317
+ div.autocomplete ul li {
318
+ list-style-type:none;
319
+ display:block;
320
+ margin:0;
321
+ padding:2px;
322
+ height:15px; line-height: 16px;
323
+ cursor:pointer;
324
+ }
325
+ #payment-methods h2 {
326
+ background-image:none;
327
+ padding-left:0;
328
+ }
329
+ #payment-methods .input-text {
330
+ width:230px
331
+ }
332
+
333
+ #payment-methods select {
334
+ width:235px;
335
+ }
336
+
337
+ #payment-methods .sp-methods select.year {
338
+ width:97px !important;
339
+ }
340
+
341
+ #payment-methods .sp-methods select.month {
342
+ width:129px !important;
343
+ }
344
+ #easyco-agreements label {
345
+ font-weight: normal;
346
+ font-size: 12px
347
+ }
348
+ #easyco-agreements .popup {
349
+ right: 235px; bottom: -27px;
350
+ width:440px;
351
+ }
352
+ #easyco-agreements .popup-content {
353
+ max-height:500px;
354
+ overflow:auto;
355
+ }
356
+
357
+ #easyco-agreements .popup-arrow {
358
+ background: url(../images/fi/popup_arrow-white.gif) no-repeat 0 0;
359
+ height:19px; width:10px;
360
+ right:-10px; left:auto;
361
+ bottom:24px; top: auto;
362
+ }
363
+ #easyco-agreements .validation-advice {
364
+ width:125px;
365
+ margin-left:15px;
366
+ }
367
+
368
+ input.disabled { background:#f6f6f6 !important; color:#bbb !important }
369
+ #checkout-block input.input-street {
370
+ width:309px;
371
+ }
372
+ #payment-methods {
373
+ position:relative;
374
+ zoom:1;
375
+ }
376
+ #payment-popup {
377
+ left:307px; top: -14px;
378
+ min-width:300px; max-width:500px;
379
+ width:auto;
380
+ background:#fff;
381
+ min-height:200px;
382
+ _height:200px;
383
+ }
384
+ #payment-popup .popup-content {
385
+ max-height:420px;
386
+ }
387
+ #payment-popup.loading {
388
+ background:#fff url(../images/fi/loader.gif) no-repeat 50% 50% !important
389
+ }
390
+ #payment-popup iframe {min-width:375px;min-height:330px;border:0;}
391
+ #payment-methods .popup-heading h2 {color:#0A263C}
392
+ .cart .totals .checkout-types li {margin:0}
393
+ .total-field {
394
+ text-align:left;
395
+ font-size:12px;
396
+ color:#666;
397
+ margin: 5px 0 5px 18px;
398
+ }
399
+ #place-order {
400
+ margin: 10px 0;
401
+ }
402
+ #checkout-block .baloon {
403
+ background-color:#EDF7FD;
404
+ top: -65px; left: 0;
405
+ height: 42px; width: 185px;
406
+ overflow:visible;
407
+ font-size:12px;
408
+ }
409
+ #checkout-block .baloon .popup-arrow {
410
+ background: url(../images/fi/popup_arrow-blue.gif) no-repeat 0 0;
411
+ bottom: -10px; top: auto;
412
+ left: 25px;
413
+ }
414
+ #checkout-block .note {
415
+ font-size: 10px;
416
+ color:#666;
417
+ text-align:right;
418
+ }
419
+ .process {
420
+ display: inline-block;
421
+ width: 20px; height: 20px;
422
+ vertical-align: middle;
423
+ }
skin/frontend/default/default/images/fi/button.jpg ADDED
Binary file
skin/frontend/default/default/images/fi/loader-old.gif ADDED
Binary file
skin/frontend/default/default/images/fi/loader.gif ADDED
Binary file
skin/frontend/default/default/images/fi/popup_arrow-blue.gif ADDED
Binary file
skin/frontend/default/default/images/fi/popup_arrow-white.gif ADDED
Binary file
skin/frontend/default/default/images/fi/select-loader-old.gif ADDED
Binary file
skin/frontend/default/default/images/fi/select-loader.gif ADDED
Binary file
skin/frontend/default/default/images/fi/select-tip.gif ADDED
Binary file
skin/frontend/default/default/js/freaks_checkout.js ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Zero Step Checkout frontend controller
3
+ *
4
+ * @category FI
5
+ * @package FI_Checkout
6
+ * @author Sergiy Stotskiy <sergiy.stotskiy@freaksidea.com>
7
+ * @copyright Copyright (c) 2012 Sergiy Stotskiy (http://freaksidea.com)
8
+ */
9
+
10
+ /**
11
+ * Storage plugin
12
+ * Provides a simple interface for storing data such as user preferences.
13
+ * Storage is useful for saving and retreiving data from the user's browser.
14
+ * For newer browsers, localStorage is used.
15
+ * If localStorage isn't supported, then cookies are used instead.
16
+ * Retrievable data is limited to the same domain as this file.
17
+ *
18
+ * Usage:
19
+ * This plugin extends jQuery by adding itself as a static method.
20
+ * $.Storage - is the class name, which represents the user's data store, whether it's cookies or local storage.
21
+ * <code>if ($.Storage)</code> will tell you if the plugin is loaded.
22
+ * $.Storage.set("name", "value") - Stores a named value in the data store.
23
+ * $.Storage.set({"name1":"value1", "name2":"value2", etc}) - Stores multiple name/value pairs in the data store.
24
+ * $.Storage.get("name") - Retrieves the value of the given name from the data store.
25
+ * $.Storage.remove("name") - Permanently deletes the name/value pair from the data store.
26
+ *
27
+ * @author Dave Schindler
28
+ * @modified by Sergiy Stotskiy
29
+ *
30
+ * Distributed under the MIT License
31
+ *
32
+ * Copyright (c) 2010 Dave Schindler
33
+ *
34
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ * of this software and associated documentation files (the "Software"), to deal
36
+ * in the Software without restriction, including without limitation the rights
37
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38
+ * copies of the Software, and to permit persons to whom the Software is
39
+ * furnished to do so, subject to the following conditions:
40
+ *
41
+ * The above copyright notice and this permission notice shall be included in
42
+ * all copies or substantial portions of the Software.
43
+ *
44
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
50
+ * THE SOFTWARE.
51
+ */
52
+ eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(4($){5 b=11 4L.1t!==\'2V\';4 4K(n,v){5 c;6(11 n==="2k"&&11 v==="2k"){1t[n]=v;7 q}B 6(11 n==="4G"&&11 v==="2V"){D(c I n){6(n.4F(c)){1t[c]=n[c]}}7 q}7 C}4 2w(n,v){5 a,e,c;a=m 5E();a.5D(a.5B()+5w);e="; 5v="+a.5t();6(11 n==="2k"&&11 v==="2k"){J.2x=n+"="+v+e+"; 4z=/";7 q}B 6(11 n==="4G"&&11 v==="2V"){D(c I n){6(n.4F(c)){J.2x=c+"="+n[c]+e+"; 4z=/"}}7 q}7 C}4 4y(n){7 1t[n]}4 4x(n){5 a,24,i,c;a=n+"=";24=J.2x.4v(\';\');D(i=0;i<24.F;i++){c=24[i];1r(c.5m(0)===\' \'){c=c.4l(1,c.F)}6(c.54(a)===0){7 c.4l(a.F,c.F)}}7 10}4 4f(n){1J{4O 1t[n]}1G(e){1t[n]=\'\'}}4 4e(n){7 2w(n,"",-1)}$.N={4c:b?4K:2w,1F:b?4y:4x,1m:b?4f:4e}})(3b);2f.r.4b=4(a){6(J.4a){5 e=J.4a(\'5C\');e.5u(a,q,q);7 3.5r(e)}6(J.45){5 e=J.45();7 3.5o(\'5l\'+a,e)}};5 2H=1h.1f();2H.r={1j:4(b,c){3.21=10;3.u={};3.X=3b.5d({2n:\'1x\',39:\'1w\'},c||{});6(!b){7 C}3.1k=$(b);5 d=3;3.1k.o(\'14\',4(e){5 a=19.8(e);6(a.1H.2s()!=\'a\'){7 q}d.2y(a.O.1I(a.O.2q(\'#\')+1));19.2E(e)})},2y:4(a){5 b=3.42(a);6(b.1i&&b.A&&b.1i!=3.1Q()){5 c={1i:3.1Q(),A:3.40()};c.A.W();c.1i.1c(3.X.2n);$(b.1i.12).Y(3.X.2n);$(b.A).1e();6(3.21&&3.21.1K){3.21({1L:c,1x:b})}}},1Q:4(){6(3.1k){7 3.1k.t(\'.\'+3.X.2n)[0]}7 10},40:4(){5 a=3.1Q().3Z(),1g=a.O.1I(a.O.2q(\'#\')+1);7 $(3.1k.12).t(3.X.39+\'.\'+1g)[0]},42:4(b){5 c=$(3.1k.12).t(3.X.39+\'.\'+b)[0],3e=\'\';3.1k.t(\'a\').Q(4(e){5 a=e.O.1I(e.O.2q(\'#\')+1);6(a==b){3e=e;7 C}});7{1i:3e,A:c}},3Y:4(a,b){3.u[a]=b;7 3},3X:4(a){7 3.u[a]},3k:4(){7 3.u},1b:4(){5 a=3.1Q();6(!a){7 10}5 b=a.3Z(),1g=b.O.1I(b.O.2q(\'#\')+1);7 3.u[1g]}};p=1h.1f();p.N=3b.N;p.r=m 1o();p.r.1j=(4(c){7 4(a,b){c.1K(3,a,b);3.3W=a;6(3.9){3.2z();3.9.o(\'13\',3.13.1l(3,\'4Y\'));3.1a={};3.2e=C;3.4U=10}}})(1o.r.1j);p.r.1y=4(a){7 3.3W+\'-\'+a};p.r.2K=4(a){5 i=a.F,2d=\'\';1r(i--){2d=3.1y(a[i]);6(p.N.1F(2d)){p.N.1m(2d)}}7 3};p.r.2z=4(){5 b=3,2N=4(e){5 a=$(3),n=a&&a.1H&&a.1H.2s();6(n!=\'K\'&&n!=\'t\'&&n!=\'4Q\'){a=a.t(\'K\')[0]}p.N.4c(b.1y(a.T),a.l)};1A.2b(3.9).Q(4(e){5 v=p.N.1F(b.1y(e.T));6(v){6(e.E==\'1u\'||e.E==\'35\'){6(e.l==v){e.36=q}}B 6(!e.l){e.l=v}B{p.N.1m(b.1y(e.T))}}6(e.E==\'1u\'||e.E==\'35\'){$(e).w().o(\'14\',2N)}B{$(e).o(\'17\',2N)}});7 3};p.r.13=4(c,d){5 e=3.1N();6(e){5 f=3,3d=3.9,1P=4(a){5 b=f.1y(a.T);6(p.N.1F(b)){p.N.1m(b)}},3Q=4(a){6(a.P||(a.E==\'1u\'||a.E==\'35\')&&!a.36){7}5 b=3d[a.T];6(!b){b=m 2f(\'K\');b.E=\'1q\';b.T=a.T;3d.5U(b)}b.l=a.l};1A.2b(3.9).Q(1P);6(3.2e){D(5 g I 3.1a){5 h=3.1a[g];1A.2b(h.9).Q(1P).Q(3Q)}}6(c==\'3L\'){3.1X()}B 6(c==\'5n\'){3.9.13()}}7 e};p.r.1X=4(){7 m 1D.20(3.9.1v(\'22\'),{Z:3.9.1v(\'Z\'),1C:1A.3J(3.9,q),25:(4(a){1J{5 b=a.26.2I()}1G(e){7}6(b.3H){1B.O=b.3H}B 6(b.2L){5 c=3.9.1s(\'16.3G\');6(c){c.w().2P(c)}3.9.2Q({58:b.2L});3.9.w(1).55()}3.9.1E(\'9:3E\',b)}).1l(3)})};p.r.1N=4(){5 a=3.1Y&&3.1Y.1U();6(a&&3.2e){D(5 b I 3.1a){5 c=3.1a[b];a=a&&c.1Y&&c.1Y.1U();6(!a){3D}}}7 a};p.r.3C=4(a){6(a.9){3.2e=q;3.1a[a.9.1g]=a}7 3};p.r.4P=4(){7 3.1a};p.r.30=4(a){7 3.1a[a]};5 23=1h.1f({1j:4(a){3.8=a;6(3.8){3.32();3.2R(q)}},2R:4(c){5 d=4(e,a){5 b=$(3).1s(\'K[E="34"]\');6(3.3A>=0&&3.l!=0){b.l=3.G[3.3A].5K}B 6(!a){b.l=\'\';p.N.1m(b.9.1g+\'-\'+b.T)}6(!a){b.1E(\'23:17\',{5k:e})}};3.8.o(\'17\',d);d.1K(3.8,10,c);7 3},32:4(a){6(a){5 b=3.8;b.2Q({3v:a});3.8=b.1d();b.w().2P(b);3.2R()}6(!3.8.5b(\'50\').F){3.8.P=q;3.8.W()}B{3.8.P=C;3.8.1e()}7 3},3c:4(a){6(3.8){5 b=3.8.1s(\'K[E="34"]\');b.o(\'23:17\',a.1l(3))}7 3},2o:4(c,d,f){d=d||\'l\';f=f||\'K-18\';5 g={},1S=3;c&&c.o(\'17\',4(e){5 b=1S.8.1s(\'K[E="34"]\');g[d]=3.l;b.Y(f);b.P=q;m 1D.20(3.12.1v(\'2r-22\'),{Z:\'1F\',1C:g,25:4(a){b.1c(f);b.P=C;1S.32(a.26)}})});7 3}});5 3q=1h.1f(1D.4V,{3p:4(){6(3.G.1W)3.8.Y(3.G.1W)},3m:4(){6(3.G.1W)3.8.1c(3.G.1W)},47:4(){3.5a=q;3.5s=C;3.3p();3.G.1C=44(3.G.3n)+\'=\'+44(3.8.l);6(3.G.3o){3.G.1C+=\'&\'+3.G.3o}m 1D.20(3.1p,3.G);3i(3.3m.1l(3),56)},3c:4(b){19.o(3.8,\'17\',(4(e){6(3.3h){5c(3.3h)}5 a=3;3.3h=3i(4(){b.1K(a,e)},5q)}).3r(3));7 3},3s:4(a){19.o(3.8.1d(a),\'14\',(4(e){19.2E(e);3.47()}).3r(3));7 3},5R:4(a){5 b=\'\';6(3.G.t){5 c=$(a).t(\'.\'+3.G.t)||[];6(c.F>0)b=2f.4M(c[0],3.G.t)}B{b=2f.4N(a,\'4R\')}5 d=3.8.l.4v(/\\s*,\\s*/);6(b!=d[d.F-2]){d[d.F-1]=b}3.8.l=d.3t(\', \');3.59=3.8.l;3.8.3u();3.8.4b(\'17\')}});5 S=1h.1f({1j:4(a){3.2l=\'\';3.H={};3.3w(a)},3x:4(){7 3.37()!=10},3w:4(a){D(5 i I a){6(a[i]){3.H[i]=a[i]}}7 3},3y:4(){5 a=\'\';D(5 b I 3.H){5 c=3.H[b];6(a=c.1v(\'2r-22\')){3D}}7 a},37:4(){6(3.2l){7 3.2l}7 3.2l=3.3y()},3z:4(a){D(5 b I 3.H){5 c=a[b],R=3.H[b];6(c){6(R.1H.2s()==\'3B\'){R.2Q({3v:c});3.H[b]=R.1d();R.w().2P(R);R=3.H[b]}B{R.2Z(c)}}R.w().1c(\'18\');R.V({2X:\'\',1n:\'2S\'})}},3F:4(a){5 b=a.26;1J{b=b.2I();3.3z(b);$(J.2a).1E(\'2O:2J\',{3I:3})}1G(e){}},2F:4(a){5 b=[];6(a){5 c=3.H[a];c.V({2X:c.3K()+\'2g\',1n:\'1q\'});$(c.12).Y(\'18\');b.27(a)}B{D(5 a I 3.H){5 c=3.H[a];c.V({2X:c.3K()+\'2g\',1n:\'1q\'});$(c.12).Y(\'18\');b.27(a)}}7 b},1X:4(a){7 m 1D.20(3.37(),{Z:\'3M\',1C:a,25:3.3F.1l(3),5z:4(){1B.O=1B.O}})},5J:4(a){7 3.H[a]||10},3N:4(a,b){5 c=3.H[a];3.2F(a);b=b||{};b.E=a;7 3.1X(b)},3O:4(a){5 b=3.2F();a=a||{};a.E=b.3t(\',\');7 3.1X(a)},3P:4(a){5 b=3.1T(a);6(b){b.1s(\'.29\').1e()}},3R:4(a){5 b=$(a);6(b){b.1s(\'.29\').W()}},1T:4(b){5 c=$(b);6(c){c.Y(\'P\');c.P=q;c.w(\'16\').t(\'3S\').Q(4(a){6(a!=c.12){a.V({1n:\'1q\'})}})}7 c},2c:4(b){5 c=$(b);6(c){c.1c(\'P\');c.P=C;c.w(\'16\').t(\'3S\').Q(4(a){6(a!=c.12){a.V({1n:\'2S\'})}})}7 c},3T:4(){5 c=3;7 4(){5 a=[\'1V\',\'3U\',\'2C\',\'3V\'],i=a.F,8=3.8||3,X={l:8.l};6(8.l.53()&&8.l!=\'0\'){1r(i--){5 b=8.9[\'z[L][\'+a[i]+\']\'];6(b&&b.l){X[a[i]]=b.l}}c.3O(X);c.1T(\'1Z-1R\')}}}});S.2T=4(a,b){5 c=a&&a.1H.2s();7 c==\'K\'&&a.E==b};5 41=1h.1f({1j:4(a){3.8=a;3.2p=\'\';3.31()},43:4(){7 3.2p},2G:4(){7 3.8&&3.8.t(\'K[E="1u"]:36\')[0]},3l:4(){5 a=3.2G();7 a?a.l:\'\'},2m:4(){7 $(\'5p\'+3.2p)},2B:4(a,b){5 c=1A.2b(a),i=c.F;1r(i--){c[i].P=!b}a[b?\'1e\':\'W\']();7 3},2A:4(a){5 b=3.2m();6(b){3.2B(b,a)}7 3},46:4(a){3.2p=a;5 b=3.2m();$(b||J.2a).1E(\'M-Z:5V\',{5A:a});7 3},2v:4(a){3.2A(C);3.46(a);3.2A(q)},31:4(){5 b=3;6(3.8){3.2v(3.3l());3.8.t(\'.9-5G\').Q(4(a){b.2B(a,a.48!=0)})}7 3}});5 49=1h.1f({1j:4(a){3.8=a;3.1N=C;6(3.8){5 b=3.8.w().t(\'a.1z-5O\')[0],1S=3;b.o(\'14\',4(e){$(3).w().W();19.2E(e);1S.8.1E(\'2i:33\')})}},1U:4(c,d){5 f=3;f.8.V({1n:\'1q\'});f.8.w().Y(\'18\');f.8.w().V({4d:\'2W\'});7 m 1D.20(c,{Z:\'3M\',1C:d,25:4(a){1J{5 b=a.26.2I()}1G(e){7}f.8.2Z(b.2U);f.8.V({1n:\'2S\'});f.8.w().1c(\'18\');6(b.1p){f.29(b.1p)}B{f.2t()}}})},4g:4(){3.8.w().W()},29:4(a){5 b=3.8.t(\'4h\')[0];b.4S=a;7 3},4T:4(x,y){6(3.8){3.8.w().V({4W:x+\'2g\',4X:y+\'2g\'})}7 3},4i:4(){7 3.1N},2t:4(){6(3.8){3i((4(){3.8.w().W()}).1l(3),4Z);3.1N=q;3.8.1E(\'2i:2t\')}}});5 4j=1h.1f({51:4(a,b){6(!a.9){7 C}5 c=$(a.9[b]);6(!c||!c.1d(\'.1z\')){7 C}c.o(\'3u\',4(){$(3).1d(\'.1z\').1e()});c.o(\'52\',4(){$(3).1d(\'.1z\').W()});7 c},4k:4(a,b,d){5 f=m 2H(a),1O=\'\';f.21=4(e){6(e.1L.A.2u(\'m-z\')&&!e.1x.A.2u(\'m-z\')){e.1L.A.1e().Y(\'1q-1O\');e.1L.A.1d(\'1w.4m\').V({4d:\'2W\'})}B 6(e.1x.A.2u(\'m-z\')){e.1x.A.1c(\'1q-1O\');e.1x.A.1d(\'1w.4m\').W()}5 c=$(e.1L.A),16=c.t(\'16.3G\')[0];16&&16.W()};D(5 g I b){f.3Y(g,m p(b[g]))}5 h=f.1b();6(h&&d){D(5 i I d){h.3C(d[i])}}6(1O=(1B.57||\' \').1I(1)){f.2y(1O)}7 f},4n:4(b){5 c=m 1o(b);c.13=4(a){6(a){$(3.9[\'4o\']).1c(\'4p-4q\');$(3.9[\'1m\']).l="1"}B{$(3.9[\'4o\']).Y(\'4p-4q\');$(3.9[\'1m\']).l="0"}7 1o.r.13.1K(3)};6(c.9){c.9.t(\'1i\').Q(4(a){a.o(\'14\',4(){c.13(3.T==\'33\')})})}},4r:4(a){5 i=a.F,u={};1r(i--){u[a[i]]=m p(a[i])}7 u},1P:4(a,b){5 c=\'\',9=\'\';D(c I a){9=a[c];6(9.2K&&!9.9){9.2K(b)}}},4s:4(c,d,e){5 f=10;6(c){f=m 3q(c.1s(\'K[1g]\'),c,c.12.1v(\'2r-22\'),{3n:\'1B\',1W:\'K-18\',5e:2,5f:4(a,b){5g.5h(b,{5i:0.15})}});f.3s(\'a.t-5j\')}B 6(e){f=m 23($(e[d.4t]));f.2o($(e[d.2o]),\'1V\',\'K-18\')}7 f},4u:4(a,b,c){6(!c){7}5 k=a.F,28=\'\';1r(k--){28=$(c[\'z[L][\'+a[k]+\']\']);6(28){28.o(\'17\',b)}}},4w:4(b,c){5 d=b.1b()&&b.1b().30(\'M-9\'),1M=[],i=0,u=b.3k(),2M=[];D(5 k I u){6(u[k].9){1M.27(u[k].9.1g);2M.27(k)}}i=1M.F;1r(i--){5 f=$$(\'#\'+1M[i]+\' 1w.2h-4A\')[0];5 g=m S({2h:f,M:d.9,3j:c});6(f){f.o(\'14\',4(e){5 a=19.8(e);6(!S.2T(a,\'1u\')){7 q}g.3N(\'3j\',{4B:a.l,l:a.l});g.1T(\'1Z-1R\')})}6(g.3x()){5 h=b.3X(2M[i]).9,3g=g.3T();5 j=3.4s($$(\'#\'+1M[i]+\' 1w.5x\')[0],{4t:\'z[L][5y]\',2o:\'z[L][1V]\'},h);j&&j.3c(3g);3.4u([\'1V\',\'2C\'],3g,h)}}$(J.2a).o(\'2O:2J\',4(a){d.2z();a.4C.3I.2c(\'1Z-1R\')});7 g},4D:4(b,c){5 d=m 41(b),U=m 49(c);6(d.8){d.8.o(\'14\',4(e){5 a=19.8(e);6(!S.2T(a,\'1u\')){7 q}6(d.43()!=a.l){d.2v(a.l);U.4g()}});$(J.2a).o(\'2O:2J\',4(){d.31()})}6(U.8){5 f=4(){S.r.2c(\'1Z-1R\')};U.8.o(\'2i:2t\',f);U.8.o(\'2i:33\',f)}7{M:d,U:U}},4E:4(d,f,g,h){6(!d){7 C}5 i=f.1b()&&f.1b().30(\'M-9\');d.o(\'14\',4(e){5 a=g.M.2G(),38=q,1p=\'\';6(a){1p=a.1v(\'2r-22\');6(1p&&!g.U.4i()){5 b=1A.3J(g.M.2m(),q);b[a.T]=a.l;6(i.1Y.1U()){g.U.1U(1p,b);S.r.1T(3)}38=C}}6(38&&f.1b().13(\'3L\')){S.r.3P(3)}});5 j=f.1b();6(j.9){j.9.o(\'9:3E\',4(b){S.r.3R(d);5 c=b.4C;6(c.2L){S.r.2c(d)}6(!c.2Y){7 q}A.w().1e();A.2Z(c.2Y.2U);1J{c.2Y.2U.5F()}1G(e){A.t(\'4h\').Q(4(a){6(!a.48){a.o(\'3a\',a.1e.1l(a))}})}})}7 q}});$(J).o(\'5H:5I\',4(){5 a=m 4j(),u=a.4r([\'M-9\']);u[\'2h-Z-3a\']=m 1o(\'2h-Z-3a\');u[\'2j-4H\']=m 1o(\'2j-4H\');u[\'4I-9\']=m 1o(\'4I-9\');5 b=a.4k($$(\'#2j-2W 16.5M-5N\')[0],{\'m-z\':\'m-z-9\',\'4J\':\'2j-4J-9\'},u);5 c=b.3k();D(5 i I c){u[i]=c[i]}a.4n(\'5P-5Q-9\');a.1P(u,[\'M[Z]\',\'4B\',\'z[L][1V]\',\'z[L][3U]\',\'z[L][1B]\',\'z[L][2C]\',\'z[L][3f][0]\',\'z[L][3f][1]\',\'z[L][3f][2]\',\'z[L][3V]\']);a.4w(b,$(\'5S-5T-3j-3B\'));5 d=$$(\'#M-1z 1w.1z-A\')[0],2D=a.4D($(\'M-4A\'),d);a.4E($(\'1Z-1R\'),b,2D,d);4L.5L=2D.U})',62,368,'|||this|function|var|if|return|element|form||||||||||||value|new||observe|RestorableForm|true|prototype||select|forms||up|||user|content|else|false|for|type|length|options|sections|in|document|input|address|payment|Storage|href|disabled|each|section|fiCheckoutViewModel|name|centinel|setStyle|hide|params|addClassName|method|null|typeof|parentNode|submit|click||ul|change|loading|Event|embededForms|getCurrentForm|removeClassName|next|show|create|id|Class|button|initialize|tabsBlock|bind|remove|visibility|VarienForm|url|hidden|while|previous|localStorage|radio|getAttribute|div|current|getKey|popup|Form|location|parameters|Ajax|fire|get|catch|nodeName|substr|try|call|prev|ids|isValid|tab|clearStorage|getCurrentTab|order|self|disableButton|validate|country_id|indicator|request|validator|place|Request|onChangeTab|action|fiSelectBox|ca|onComplete|responseText|push|el|process|body|getElements|enableButton|key|hasEmbededForms|Element|px|shipping|fiCentinel|checkout|string|updateUrl|getAdditionalForm|currentClassName|dependsOn|currentMethod|lastIndexOf|data|toLowerCase|success|hasClassName|switchMethod|wc|cookie|setCurrentTab|restoreValues|showAdditionalForm|enableFormElements|postcode|model|stop|waiting|getCurrentMethodElement|FreaksTabs|evalJSON|updated|clearValues|error_message|aliases|fn|fiCheckout|removeChild|insert|addSelectObserver|visible|isElement|html|undefined|block|height|update_section|update|getEmbededForm|restore|render|cancel|text|checkbox|checked|getUrl|result|contentTagName|load|Object|addChangeListener|mainForm|tabBtn|street|listener|changeTimeout|setTimeout|totals|getTabForms|findCurrentMethod|stopIndicator|paramName|defaultParams|startIndicator|FreaksSelectBox|bindAsEventListener|addShowResults|join|focus|after|createSections|isActive|findUrl|updateView|selectedIndex|table|addEmbededForm|break|has_response|ajaxCallback|messages|redirect|viewModel|serialize|getHeight|ajax|post|updateSection|updateAll|processing|addElements|stopProcessing|li|getChangeListener|region|city|formId|getTabForm|setTabForm|firstDescendant|getCurrentContent|fiPaymentViewModel|getTab|getCurrentMethod|encodeURIComponent|createEventObject|setMethod|showResults|offsetWidth|fiCentinelViewModel|createEvent|triggerEvent|set|display|dc|dls|idle|iframe|isSuccessfull|fiPage|createTabs|substring|overlay|createDiscount|coupon_code|required|entry|createForms|getLocationBox|box|observeAddressFields|split|createCheckout|rc|rls|path|methods|shipping_method|memo|wakeUpPayment|send|hasOwnProperty|object|agreements|newsletter|login|wls|window|collectTextNodes|collectTextNodesIgnoreClass|delete|getEmbededForms|textarea|informal|src|moveElement|responsePopup|Autocompleter|top|left|none|2000|option|addFieldPopup|blur|strip|indexOf|scrollTo|1500|hash|before|oldElementValue|hasFocus|getElementsByTagName|clearTimeout|extend|minChars|onShow|Effect|Appear|duration|tip|event|on|charAt|normal|fireEvent|payment_form_|100|dispatchEvent|changed|toGMTString|initEvent|expires|31536000000|autocomplete|region_id|onFailure|method_code|getTime|HTMLEvents|setTime|Date|evalScripts|list|dom|loaded|getSection|innerHTML|CentinelAuthenticateController|infos|menus|close|discount|coupon|updateElement|shopping|cart|appendChild|switched'.split('|'),0,{}))