Posted on Leave a comment

Magento Newsletter Unsubscribe Form

Magento Logo

One of the most missed functions in Magento 1 is a newsletter unsubscribe form. Although, by default you can generate newsletter unsubscribe links to be used for instance in newsletters sent out to subscribers there’s no nice out-of-the-box way to integrate a newsletter unsubscribe form in Magento 1.

Which is why there already exist some extensions on the Magento Connect Marketplace that extend the existing newsletter functionality by e.g. adding a simple unsubscribe field and toggling the action submitted (“subscribe” vs. “unsubscribe”). Unfortunately, having a look at most of the existing extensions made clear that they either include too much functionality or simply are outdated.

Implementing the Magento Newsletter Unsubscribe Extension

Luckily, implementing the newsletter unsubscribe functionality in Magento is pretty straight forward. In order to share this information here’s the gist on how to create a Magento Newsletter unsubscribe form extension.

Basically, what we are trying to achieve here is an additional Magento page with a distinct URL that incorporates our newsletter unsubscribe form, i.e. “newsletter-unsubscribe”. This form handles submissions and checks if the e-mail submitted currently is subscribed to the Magento newsletter. If that’s the case it will unsubscribe this e-mail based on the built-in Magento functionality, i.e. it will automatically sent out the un-subscription confirmation mail and execute any other events that you might have integrated for newsletter related events. Last but not least, as always everything should be translatable.

Custom route instead of CMS page

Instead of creating an additional CMS page and loading our newsletter unsubscribe form into it (e.g. using layout updates) we are going to create a custom route for our extension. By default, this route will be newsletter-unsubscribe. The relevant entries in the config.xml are as follows:

<?xml version="1.0"?>
<config>
 
  <modules>
    <BothInteract_NewsletterUnsubscribe>
      <version>1.0.1</version>
    </BothInteract_NewsletterUnsubscribe>
  </modules> 
 
  <frontend>
    <routers>
      <bothinteract_newsletterunsubscribe>
        <use>standard</use>
        <args>
          <module>BothInteract_NewsletterUnsubscribe</module>
          <frontName>newsletter-unsubscribe</frontName>
        </args>
      </bothinteract_newsletterunsubscribe>
    </routers>
 
    <secure_url>
      <bothinteract_newsletterunsubscribe>/newsletter-unsubscribe/</bothinteract_newsletterunsubscribe>
    </secure_url>

    ...
</config>

As you can see an additional frontend route is added (newsletter-unsubscribe) that maps to our extensions’s controller.

Display newsletter unsubscribe form

Now that URLs starting with “newsletter-unsubscribe” are routed to our controller we need to make sure that our custom block is loaded and unsubscribe submissions are processed correctly.

As always, the default action is index and in our case it’s responsible for rendering or newsletter unsubscribe form:

public function indexAction() {

  $this->loadLayout();

  // load 1-column page layout
  $this->getLayout()
    ->getBlock('root')
    ->setTemplate('page/1column.phtml');

  // load breadcrumb bar
  $breadcrumbs = $this->getLayout()->getBlock('breadcrumbs');
  $helper = Mage::app()->getHelper('bothinteract_newsletterunsubscribe');

  if ($breadcrumbs) {
    $breadcrumbs->addCrumb('home', array(
      'label' => $helper->__('Home'),
      'title' => $helper->__('Go to Home Page'),
      'link' => Mage::getBaseUrl()));
    $breadcrumbs->addCrumb('newsletter-unsubscribe', array(
      'label' => $helper->__('Newsletter Unsubscribe'),
      'title' => $helper->__('Newsletter Unsubscribe'),
      'link' => Mage::getUrl('newsletter-unsubscribe')));
  }

  // render our custom block
  $block = $this->getLayout()
    ->createBlock('bothinteract_newsletterunsubscribe/customblock')
    ->setTemplate('bothinteract_newsletterunsubscribe/form.phtml');

  // append to CMS content block
  $this->getLayout()->getBlock('content')->append($block);

  $this->renderLayout();
}

There’s no magic here but let’s quickly dissect what is happening:

First, we are loading the layout and setting the 1-column page layout by default .

Hint: Using additional extension backend options we can make these settings available for users to edit directly without touching the code. This will be available in version 1.1.

Since we want our page to appear in the breadcrumbs too we manually add it. Finally, we create and append our custom block while setting the corresponding template and render the final layout.

Process newsletter unsubscribe form submissions

Now that we are able to display the newsletter unsubscribe form it’s time to process form submissions. This is done using the unsubscribe action:

public function unsubscribeAction() {
  if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
    $session = Mage::getSingleton('core/session');
    $email = (string) $this->getRequest()->getPost('email');

  try {
    if (!Zend_Validate::is($email, 'EmailAddress')) {
      Mage::throwException($this->__('Please enter a valid email address.'));
    }

    $subscriber = Mage::getModel('newsletter/subscriber')
      ->loadByEmail($email);

    if ($subscriber && $subscriber->getId()) {
      // check already unsubscribed/inactivated before
      if ($subscriber->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_NOT_ACTIVE ||
        $subscriber->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED) {
        $session->addSuccess($this->__('You are not registered with this e-mail.'));
      } else {
        $subscriber->unsubscribe();
        $session->addSuccess($this->__('You have been successfully unsubscribed.'));
      }
    } else {
      $session->addSuccess($this->__('You are not registered with this e-mail.'));
    }
   } catch (Mage_Core_Exception $e) {
     $session->addException($e, $this->__('There was a problem with the unsubscription: %s', $e->getMessage()));
   } catch (Exception $e) {
     $session->addException($e, $this->__('There was a problem with the unsubscription.'));
   }
  }
  $this->_redirectReferer();
}

Again, no magic is happening here. We are simply checking the submitted e-mail, try to load the corresponding newsletter subscriber object and check it’s status. Depending on the status we are able to unsubscribe this e-mail or display the appropriate message.

Our actual custom Magento block is very slim on purpose and only returns the form action URL of our custom extension:

class BothInteract_NewsletterUnsubscribe_Block_Customblock extends Mage_Core_Block_Template {

  public function getFormActionUrl() {
    return $this->getUrl('newsletter-unsubscribe/index/unsubscribe/', array('_secure' => true));
  }
}

Yes, that’s all there is to it. Sorry to disappoint you in case you are expecting magic stuff happening here. Thus, based on Magento’s stable architecture adding a newsletter unsubscribe form can be easily achieved.

Download Magento Newsletter Unsubscribe Extension

This extension has been released by Both Interact and is available for free on the Magento Connect marketplace as Both Interact Newsletter Unsubscribe extension. Feel free to download and rate the extension.

 

Posted on Leave a comment

Automatically clean product texts in Magento

Magento Logo

So someone copied text from a PDF document and pasted it into the Magento product description (or short description) text field. Unfortunately, the copied text included non-printable control characters in the Unicode range from \x00—\x1F and \x80-\x9f (e.g. DEL, NUL, VT, etc.) thus breaking other extensions from functioning properly, or prohibiting your data export to work at all. 

Clean product texts extensions to the rescue

The Clean product texts extension helps you to automatically clean your product texts (description and short description) by removing unwanted (invisible) control characters that might cause problems with other extensions or when exporting products. Oftentimes, unwanted characters are copied into product descriptions when copying texts from PDF documents. Since these control characters are not displayed by browsers they cannot be removed manually from Magento’s editor. This extension will check your product texts and automatically remove unwanted characters. Thus, your employees can still copy texts from e.g. PDFs directly into Magento – this extension will take care of removing unwanted characters when saving products.

Simulate Product Cleaning

Furthermore, you can also simulate the process of cleaning product texts by activating the corresponding option in the configuration under General / Simulate.

Log File

In addition this extension enabled you to logs messages to a custom log file that can be specified in the configuration options to your log directory under General / Log File. So you have the option to easily track events handled by this extension and check for possible problems. Feel free to check out the Clean product texts extension on Magento Connect.

Posted on 13 Comments

Automatically copy images from parent configurable product to variants in Magento

Magento Logo

By default Magento does not copy images from parent configurable products to their child variants, i.e. associated products. So you need to manually set images for child products once they are associated with the parent configurable product, which can be rather time consuming and (let’s face it) annoying if you deal with a broader range of product variants. So, wouldn’t it be nice if Magento automatically copied images from parent products to their child product variants? Yes! Luckily, this can be achieved with the following extension.

Extension to the rescue

The Magento extension called Automatic Image assignment for configurable product variants takes care of automatically assigning required image types from parent configurable products to their associated child product variants based on the base image from the parent product once it is saved (hint: see shell script for bulk updates below). Thus, once you save the parent configurable product it checks its child products for a custom list of required image types you can set via the extension configuration. Possible required image types include

  • Base image
  • Small image
  • Thumbnail

So, you are able to set individual image types to be copied to child products based on the base image from the parent configurable product. For instance, selecting small image and thumbnail as required image types will copy the base image from the parent product and set them for the child products in case these image types do not yet exist.

Simulate Image Assignment

Since your products are your treasure the extension offers the options to simulate the process of automatically copying and assigning images. So, instead of altering products in the database the extension will log all required actions in the custom log file specified (yes, the extension offers a custom log file, see below for more information).

Shell script for bulk update

Since the extension is primarily designed as event observer for saving parent configurable products an additional shell script is included in the package. This script will either process all configurable products and check their child products for the required image types set in the configuration or limit the list of products to be checked by an additional product-IDs parameter.

Custom log file

Finally, in order to track the extension’s step you can specify a custom log file that will enable you to easily monitor actions carried out by the extension. Thus, you can easily simulate a bulk update and track events through the log file.

Download the extension

Feel free to download the extension from Magento Connect published by Both Interact.

Alternatively, you can download the latest version 1.6.3 here: BothInteract_ConfigurableProductVariantsImageAssignment-1.6.3.