📜 ⬆️ ⬇️

Magento, news subscription during checkout

Oh, it turns out that there is even a whole one post about Magento development. I also have something to say. I wonder if it will be interesting to anyone ...

So, the task is to add a tick "Receive news" to one of the checkout steps (checkout - "pass through the cashier").



It immediately became clear that we would have to write a new module, since modification of design files is not enough. How you can add your field to any checkout step, you can peep from the Desitex Checkoutnewsletter modules (it adds a “sign for news” checkbox in the second step, where you need to specify the billing address) and from Biebersdorf CustomerOrderComment (it adds a field to add a comment to the last step - order confirmation page).
')
I omit the process of digging into the specified modules and finding a solution :) In the end, what would have happened, we need:

Module creation


First of all, create a module. Let it be in the namespace Mage , and be called NewsletterSubscribe .

First you need to tell Magento that our module is - create the file Mage_NewsletterSubscribe.xml in the app/etc/modules folder:

  <? xml version = "1.0"?>
 <config>
     <modules>
         <Mage_NewsletterSubscribe>
             <active> true </ active>
             <codePool> local </ codePool>
         </ Mage_NewsletterSubscribe>
     </ modules>
 </ config> 

According to XML, the module is active and is in the local pool.

Next, create a folder where the new module will be located - app/code/local/Mage/NewsletterSubscribe , and the config.xml configuration file in the app/code/local/Mage/NewsletterSubscribe/etc folder:

  <? xml version = "1.0"?>
 <config>
     <global>
         <helpers>
             <newslettersubscribe>
                 <class> Mage_NewsletterSubscribe_Helper </ class>
             </ newslettersubscribe>
         </ helpers>
     </ global>
 </ config> 

Without a helper, the module will not work as expected, but will instead fall. Therefore, we give the Magento helper, even if it is empty, the Data.php file in the Helper folder:
  <? php

 class Mage_NewsletterSubscribe_Helper_Data extends Mage_Core_Helper_Abstract {

 } 

Modification of the checkout page


The file that draws the desired checkout page is app\design\frontend\default\sunnyD\template\checkout\onepage\payment\methods.phtml . Add a tick:

  ...
 <? php / * bof Subscribe for newsletter checkbox * /?>
 <dt> Join Our Mailing List </ dt>
 <dd>
     <input type = "checkbox" name = "NewsletterSubscribe" id = "NewsletterSubscribe" checked = "checked" />
     <label for = "NewsletterSubscribe"> <? php echo Mage :: helper ('newslettersubscribe') -> __ ('would
 </ dd>
 <? php / * eof Subscribe for newsletter checkbox * /?>
 ... 

Yes, now we see our check mark on the payment method selection page. But why is it inactive? And because it is made inactive by JS code located at the end of the file:

  <script type = "text / javascript"> payment.init (); </ script> 

I did not understand why it is needed, but in this case it makes inactive all the <input> tags. It turns out that we need to activate our checkbox after executing this code:

  <script type = "text / javascript"> payment.init (); </ script>

 <script type = "text / javascript"> $ ('NewsletterSubscribe'). disabled = false; </ script> 

Now the tick has become active, we go further.

Event "save page checkout"


I spied how it does Checkoutnewsletter. In the module configuration file there are lines that apparently intercept actions related to the entire checkout, all its pages:

  <? xml version = "1.0"?>
 <config>
     ...
     <global>
         <models>
             <checkout>
                 <rewrite>
                     <type_onepage> Desitex_Checkoutnewsletter_Model_Checkout_Type_Onepage </ type_onepage>
                 </ rewrite>
             </ checkout>
     ...
 </ config> 

The standard class Mage_Checkout_Model_Type_Onepage is replaced by the module class Desitex_Checkoutnewsletter_Model_Checkout_Type_Onepage (which is inherited from the original class Mage_Checkout_Model_Type_Onepage ). In this class, only one method is redefined:

  <? php

 class Desitex_Checkoutnewsletter_Model_Checkout_Type_Onepage extends Mage_Checkout_Model_Type_Onepage
 {
     public function saveBilling ($ data, $ customerAddressId)
     {
         if (isset ($ data ['is_subscribed']) &&! empty ($ data ['is_subscribed'])) {
             $ this-> getCheckout () -> setCustomerIsSubscribed (1);
         }
         else {
             $ this-> getCheckout () -> setCustomerIsSubscribed (0);
         }
         return parent :: saveBilling ($ data, $ customerAddressId);
     }
 } 

Obviously, the saveBilling action occurs when the user moves from the input page to the billing address (presses the Continue button). Here the module saves the value of its checkbox “subscribe to news” in the current session (or checkout ...). After that calls the original method of the standard class.

We will proceed in a similar way - we will make a class, inherit it from the standard one, and redefine only one method that occurs when the form is saved on our page. The method will keep the value of our checkbox. Model/Onepage.php class in the Model/Onepage.php file:

  <? php

 class Mage_NewsletterSubscribe_Model_Onepage extends Mage_Checkout_Model_Type_Onepage {
     public function savePayment ($ data) {
         if (isset ($ _ POST ['NewsletterSubscribe'])) {
             $ this-> getCheckout () -> setNewsletterSubscribe ((bool) $ _POST ['NewsletterSubscribe']);
         }
         else {
             $ this-> getCheckout () -> setNewsletterSubscribe (false);
         }
         return parent :: savePayment ($ data);
     }
 } 

Here I was overtaken by a little stupor. The tick value is among the form values, but I do not have access to these variables from the current place. Those. access to the Magento Request object, which stores all GET and POST variables. There are various interesting objects like Quote, Checkout, etc., with different interesting data, but not form values. I was almost desperate, thinking that rewriting the kernel code was very bad, but then I remembered that it was Php, which means that the $ _GET and $ _POST variables are available at any place :) The problem was solved.

Now let's say Magento, that instead of the standard class, take ours. Editing etc/config.xml :

  <? xml version = "1.0"?>
 <config>
     <global>
         <models>
             <checkout>
                 <rewrite>
                     <type_onepage> Mage_NewsletterSubscribe_Model_Onepage </ type_onepage>
                 </ rewrite>
             </ checkout>
         </ models>
     ...
 </ config> 

Here is ready. Only apparently there is one limitation - only one module can override the standard class. My method was not called until I removed the override from the Checkoutnewsletter module. Those. This is not an ordinary event for which an arbitrary number of listeners can subscribe. Potential difficult problems to solve in the future: (

Event "checkout"


Unlike the previous “event,” ordering is a “real” checkout_type_onepage_save_order event. To subscribe to it, you need to change the configuration of the module etc/config.xml :

  <? xml version = "1.0"?>
 <config>
     <global>
         ...
         <events>
             <checkout_type_onepage_save_order>
                 <observers>
                     <mage_newslettersubscribe_observer>
                         <type> singleton </ type>
                         <class> newslettersubscribe / observer </ class>
                         <method> onOrderSave </ method>
                     </ mage_newslettersubscribe_observer>
                 </ observers>
             </ checkout_type_onepage_save_order>
         </ events>
     </ global>
 </ config> 

Here we have specified which method for which class to call ( Mage_NewsletterSubscribe_Model_Observer::onOrderSave ) when the user places an order. Now create this class and method - file /Model/Observer.php :

  <? php
 class Mage_NewsletterSubscribe_Model_Observer extends Mage_Core_Helper_Abstract {
     public function onOrderSave ($ observer) {
         $ isCustomerSubscribed = (bool) Mage :: getSingleton ('checkout / session') -> getNewsletterSubscribe ();
         if ($ isCustomerSubscribed) {
             $ quote = $ observer-> getEvent () -> getQuote ();
             $ session = Mage :: getSingleton ('core / session');
             try {
                 $ status = Mage :: getModel ('newsletter / subscriber') -> subscribe ($ quote-> getBillingAddress () -> getEmail ());
                 if ($ status == Mage_Newsletter_Model_Subscriber :: STATUS_NOT_ACTIVE) {
                     $ session-> addSuccess (Mage :: helper ('checkoutnewsletter') -> __ ('Confirmation request your newsletter subscription'));
                 }
             }
             catch (Mage_Core_Exception $ e) {
                 $ session-> addException ($ e, Mage :: helper ('checkoutnewsletter') -> __ ('There was a problem with the newsletter subscription:% s', $ e-> getMessage ()));
             }
             catch (Exception $ e) {
                 $ session-> addException ($ e, Mage :: helper ('checkoutnewsletter') -> __ ('There was a problem with the newsletter subscription'));
             }
         }

         return $ this;
     }
 } 

I took this code from the Checkoutnewsletter module, only redid it to make it work. Fortunately, Magento has a class that allows users to sign up for news. In essence, all you need to do is call Mage::getModel('newsletter/subscriber')->subscribe(<user email>);

Total


The result was a small module that performs the task.

Source: https://habr.com/ru/post/70049/


All Articles