Source for file Data.php

Documentation is available at Data.php

  1. <?php
  2. /**
  3.  *  Magentron EmailImages Extension
  4.  *
  5.  *  @category   Magentron
  6.  *  @package    Magentron_EmailImages
  7.  *  @author     Jeroen Derks
  8.  *  @copyright  Copyright (c) 2011 Jeroen Derks http://www.magentron.com
  9.  *  @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  10.  */
  11. {
  12.     /** Configuration path for extension enablement.
  13.      *  @var    string 
  14.      *  @see    isEnabled()
  15.      */
  16.     const XML_EMAIL_IMAGES_ENABLE       = 'system/emailimages/enable';
  17.     
  18.     /** Configuration path for maximum cache lifetime.
  19.      *  @var    string 
  20.      *  @see    getCacheTime()
  21.      */
  22.     const XML_EMAIL_IMAGES_CACHE_TIME   = 'system/emailimages/cache_time';
  23.  
  24.     /** Configuration path for regular expression used to find image URLs in HTML.
  25.      *  @var    string 
  26.      *  @see    getRegularExpression()
  27.      */
  28.     const XML_EMAIL_IMAGES_REGEXP       = 'system/emailimages/regexp';
  29.  
  30.     /** Configuration path for index into matches of regular expression used to find image URLs in HTML.
  31.      *  @var    string 
  32.      *  @see    XML_EMAIL_IMAGES_REGEXP,
  33.      *           getRegularExpressionIndex()
  34.      */
  35.     const XML_EMAIL_IMAGES_REGEXP_INDEX = 'system/emailimages/regexp_index';
  36.     
  37.     /** Default maximum lifetime used for cache.
  38.      *  @var    integer 
  39.      *  @see    getCacheTime()
  40.      */
  41.     const DEFAULT_CACHE_TIME            = 86400;
  42.     
  43.     /** Default regular expression to extract image URLs from the email HTML body.
  44.      *  @var    string 
  45.      *  @see    getRegularExpression()
  46.      */
  47.     const DEFAULT_REGEXP                = '/((<[iI][mM][gG] [^>]*[sS][rR][cC]|[Bb][Aa][Cc][Kk][Gg][Rr][Oo][Uu][Nn][Dd])="|image:url\(\'?)([^\'"\)]*)(["\'\)])/';
  48.     
  49.     /** Default index in the regular expression matches to extract the image URLs from the email HTML body.
  50.      *  @var    integer 
  51.      *  @see    getRegularExpressionIndex()
  52.      */
  53.     const DEFAULT_REGEXP_INDEX          = 3;
  54.     
  55.     /** Cache tag to use.
  56.      *  @var    string 
  57.      */
  58.     const CACHE_TAG                     = 'MAGENTRON_EMAILIMAGES';
  59.  
  60.     /** Cache type to use.
  61.      *  @var    string 
  62.      */
  63.     const CACHE_TYPE                    = 'emailimages';
  64.     
  65.     
  66.     /**
  67.      *  Is the EmailImages extension enabled to actually attach images?
  68.      *
  69.      *  @return boolean 
  70.      *
  71.      *  @see    XML_EMAIL_IMAGES_ENABLE
  72.      */
  73.     public function isEnabled()
  74.     {
  75.         return (boolean) Mage::getStoreConfig(self::XML_EMAIL_IMAGES_ENABLE);
  76.     }
  77.  
  78.     
  79.     /**
  80.      *  Retrieve the maximum lifetime for caching in seconds.
  81.      *
  82.      *  @return integer 
  83.      *
  84.      *  @see    XML_EMAIL_IMAGES_CACHE_TIME, DEFAULT_CACHE_TIME
  85.      */
  86.     public function getCacheTime()
  87.     {
  88.         $config Mage::getStoreConfig(self::XML_EMAIL_IMAGES_CACHE_TIME);
  89.  
  90.         if !is_numeric($config) )
  91.             $config self::DEFAULT_CACHE_TIME;
  92.  
  93.         return (integer) $config;   
  94.     }
  95.  
  96.  
  97.     /**
  98.      *  Retrieve the regular expression to extract the image URLs from the email HTML body.
  99.      *
  100.      *  @return string 
  101.      *
  102.      *  @see    XML_EMAIL_IMAGES_REGEXP, DEFAULT_REGEXP
  103.      */
  104.     public function getRegularExpression()
  105.     {
  106.         $config Mage::getStoreConfig(self::XML_EMAIL_IMAGES_REGEXP);
  107.  
  108.         if '' == $config )
  109.             $config self::DEFAULT_REGEXP;
  110.  
  111.         return (string) $config;    
  112.     }
  113.  
  114.  
  115.     /**
  116.      *  Retrieve the index in the regular expression matches to extract the image URLs from the email HTML body.
  117.      *
  118.      *  @return integer 
  119.      *
  120.      *  @see    XML_EMAIL_IMAGES_REGEXP_INDEX, DEFAULT_REGEXP_INDEX
  121.      */
  122.     public function getRegularExpressionIndex()
  123.     {
  124.         $config Mage::getStoreConfig(self::XML_EMAIL_IMAGES_REGEXP_INDEX);
  125.  
  126.         if !is_numeric($config) )
  127.             $config self::DEFAULT_REGEXP_INDEX;
  128.             
  129.         return (integer) $config;   
  130.     }
  131.     
  132.     /**
  133.      *  Attach images to mail object.
  134.      *
  135.      *  @param  Zend_Mail   $mail       Zend_Mail instance to attach images to.
  136.      *  @param  string      $context    [optional] Set to unique identifier for template, so that body needs to be parsed only once per template (NB: case-insensitive).
  137.      *  @return void                    Fails silently if unable to attach image, warning message sent to log.
  138.      *
  139.      *  @see    isEnabled(), _getImageUrlsFromMail(), _attachImageUrls()
  140.      */
  141.     public function addImagesZend_Mail $mail$context null )
  142.     {
  143.         // check whether the administrator has enabled the module
  144.         if !$this->isEnabled() )
  145.         {
  146.             Mage::log('EmailImages - extension disabled');
  147.             return
  148.         }
  149.  
  150.         try
  151.         {
  152.             $urls $this->_getImageUrlsFromMail($mail$context);
  153.             if $urls )
  154.                 $this->_attachImageUrls($mail$urls);
  155.         }
  156.         catch Exception $e )
  157.         {
  158.             // ignore exception, but do log it
  159.             Mage::log('EmailImages - ERROR: exception caught: ' $eZend_Log::ERR);
  160.         }
  161.     }
  162.     
  163.     
  164.     /**
  165.      *  Remove cached image and context data from the cache.
  166.      *
  167.      *  @return Magentron_EmailImages_Helper_Data               Provides fluent interface
  168.      *
  169.      *  @see    CACHE_TAG,
  170.      *           ;Mage_Core::_Model_Cache()
  171.      */
  172.     public function cleanCache()
  173.     {
  174.         /** @var    $cache  Mage_Core_Model_Cache */
  175.         $cache Mage::getSingleton('core/cache');
  176.         $cache->flush(self::CACHE_TAG);
  177.         
  178.         return $this;
  179.     }
  180.  
  181.     /**
  182.      *  Retrieve image URLs from email content
  183.      *
  184.      *  @param  Zend_Mail   $mail       Zend_Mail instance to attach images to.
  185.      *  @param  string      $context    [optional] Set to unique identifier for template, so that body needs to be parsed only once per template (NB: case-insensitive).
  186.      *  @return array                   Array of image URLs.
  187.      *
  188.      *  @see    CACHE_TYPE,
  189.      *           _getContextDataFromCache(), _getBodyHtml(), _getImageUrlsFromBodyHtml(), _saveContextDataToCache(),
  190.      *           ;Mage_Core::_Model_Cache()
  191.      */
  192.     protected function _getImageUrlsFromMailZend_Mail $mail$context null )
  193.     {
  194.         // check cache for context
  195.         /** @var    $cache  Mage_Core_Model_Cache */
  196.         $cache          Mage::getSingleton('core/cache');
  197.         $context_data   null;
  198.         $use_cache      null !== $context && $cache->canUse(self::CACHE_TYPE);
  199.         
  200.         Mage::log(__CLASS__ . '::' . __FUNCTION__ . '(): use_cache = ' var_export($use_cache1));
  201.         
  202.         if $use_cache )
  203.         {
  204.             $context_cache_id   self::CACHE_TYPE '-urls-' (is_string($context$context md5(serialize($context)));
  205.             $context_data       $this->_getContextDataFromCache($context_cache_id);
  206.         }
  207.         
  208.         if !$context_data )
  209.         {
  210.             $bodyHtml   $this->_getBodyHtml($mail);
  211.             $urls       $this->_getImageUrlsFromBodyHtml($bodyHtml);
  212.             
  213.             // save URLs to cache, if context defined
  214.             if $use_cache )
  215.             {
  216.                 $isHtml = (boolean) $bodyHtml;
  217.  
  218.                 $this->_saveContextDataToCache($context_cache_id$isHtml$urls);
  219.             }
  220.         }
  221.         else
  222.         {
  223.             $urls $context_data['is_html'$context_data['urls'array();
  224.  
  225.             Mage::log('EmailImages - loaded URLs from cache (cache ID: ' $context_cache_id ')');
  226.         }
  227.         
  228.         return $urls;
  229.     }
  230.  
  231.     /**
  232.      *  Retrieve image URL from email body HTML
  233.      *
  234.      *  @param  string  $bodyHtml       Email body HTML to use.
  235.      *  @return array                   Array of image URLs.
  236.      *
  237.      *  @see    getRegularExpression(), getRegularExpressionIndex()
  238.      */
  239.     protected function _getImageUrlsFromBodyHtml$bodyHtml )
  240.     {
  241.         $urls array();
  242.  
  243.         Mage::log('EmailImages - parsing HTML body');
  244.  
  245.         if $bodyHtml )
  246.         {
  247.             // find image URLs in email HTML body
  248.             $regexp $this->getRegularExpression();
  249.             if preg_match_all($regexp$bodyHtml$matches) )
  250.             {
  251.                 $index  $this->getRegularExpressionIndex();
  252.                 $urls   $matches[$index];
  253.                 $urls   array_unique($urls);
  254.             }
  255.             
  256.             if == count($urls) )    // no URLs in HTML body?
  257.                 Mage::log('EmailImages - no images found in email HTML body'Zend_Log::WARN);
  258.         }
  259.         else    // otherwise no HTML body?
  260.         {
  261.             Mage::log('EmailImages - no HTML body for email'Zend_Log::WARN);
  262.         }
  263.         
  264.         return $urls;
  265.     }
  266.  
  267.     /**
  268.      *  Retrieve cached context data.
  269.      *
  270.      *  @param  string  $context_cache_id   Cached context data cache ID.
  271.      *  @return array                       Array containing keys 'isHtml' to indicate a HTML body, 'urls' for image URLs from that HTML body.
  272.      *
  273.      *  @see    ;Mage_Core::_Model_Cache()
  274.      */
  275.     protected function _getContextDataFromCache$context_cache_id )
  276.     {
  277.         /** @var    $cache  Mage_Core_Model_Cache */
  278.         $cache          Mage::getSingleton('core/cache');
  279.         $context_data   $cache->load($context_cache_id);
  280.         
  281.         if $context_data )
  282.             $context_data unserialize($context_data);
  283.  
  284.         Mage::log(__CLASS__ . '::' . __FUNCTION__ . '(): context_data=' print_r($context_data1));
  285.         
  286.         return $context_data;
  287.     }
  288.  
  289.     /**
  290.      *  Retrieve HTML body from mail object.
  291.      *
  292.      *  @param  Zend_Mail       $mail   Mail object instance to use.
  293.      *  @return string|false           HTML body from the mail object instance, if any;
  294.      *                                   false, otherwise.
  295.      *
  296.      *  @see    Zend_Mail::getBodyHtml(), Zend_Mime_Part::getContent()
  297.      */
  298.     protected function _getBodyHtmlZend_Mail $mail )
  299.     {
  300.         $bodyHtmlObject $mail->getBodyHtml();
  301.         if $bodyHtmlObject instanceof Zend_Mime_Part )
  302.         {
  303.             $bodyHtml $bodyHtmlObject->getContent();
  304.  
  305.             if $bodyHtmlObject->encoding == Zend_Mime::ENCODING_QUOTEDPRINTABLE )
  306.                 $bodyHtml quoted_printable_decode($bodyHtml);
  307.         }
  308.         else
  309.         {
  310.             $bodyHtml $bodyHtmlObject;
  311.         }
  312.         
  313.         if !is_string($bodyHtml) )
  314.         {
  315.             Mage::log(__CLASS__ . '::' . __FUNCTION__ . '(): unsupported bodyHtml = ' substr(var_export($bodyHtml1)0128'...');
  316.  
  317.             $bodyHtml false;
  318.         }
  319.         
  320.         Mage::log(__CLASS__ . '::' . __FUNCTION__ . '(): bodyHtml = ' ($bodyHtml preg_replace('/[\s\t\r\n\k]+/'' 'substr($bodyHtml0128)) '<empty>'));
  321.         
  322.         return $bodyHtml;
  323.     }               
  324.  
  325.     /**
  326.      *  Save context data to cache.
  327.      *
  328.      *  @param  string  $context_cache_id   Cache ID to use.
  329.      *  @param  boolean $isHtml             Set to true if email body is HTML.
  330.      *  @param  array   $urls               Array of image URLs from HTML body.
  331.      *  @return void 
  332.      *
  333.      *  @see    CACHE_TAG,
  334.      *           getCacheTime(),
  335.      *           ;Mage_Core::_Model_Cache()
  336.      */
  337.     protected function _saveContextDataToCache$context_cache_id$isHtml$urls )
  338.     {
  339.         /** @var    $cache  Mage_Core_Model_Cache */
  340.         $cache          Mage::getSingleton('core/cache');
  341.         $cache_time     $this->getCacheTime();
  342.  
  343.         $context_data   array(
  344.                                 'urls'      => $urls,
  345.                                 'is_html'   => $isHtml,
  346.                              );
  347.         $context_data   serialize($context_data);
  348.  
  349.         $cache->save($context_data$context_cache_idarrayself::CACHE_TAG )$cache_time);
  350.  
  351.         Mage::log('EmailImages - saved context URLs to cache');
  352.     }
  353.     
  354.     /**
  355.      *  Attach image URLs to the email.
  356.      *
  357.      *  @param  Zend_Mail   $mail       Zend_Mail instance to attach images to.
  358.      *  @param  array       $urls       Array of image URLs to attach.
  359.      *  @return void 
  360.      *
  361.      *  @see    _retrieveImageData(),
  362.      *           Zend_Mime::MULTIPART_RELATED,
  363.      *           Zend_Mail::createAttachment(), Zend_Mail::setType(),
  364.      *           Zend_Mime_Part
  365.      */
  366.     protected function _attachImageUrlsZend_Mail $mailarray $urls )
  367.     {
  368.         foreach $urls as $index => $url )
  369.         {
  370.             if $url )
  371.             {
  372.                 // retrieved image data
  373.                 $data $this->_retrieveImageData($url);
  374.                 
  375.                 if $data )
  376.                 {
  377.                     // attach image data
  378.                     $mp             $mail->createAttachment($data['image']
  379.                                                                 $data['size']['mime']
  380.                                                                 Zend_Mime::DISPOSITION_INLINE
  381.                                                                 Zend_Mime::ENCODING_BASE64basename($url)
  382.                                                               );
  383.                     $mp->id         md5($url);
  384.                     $mp->location   $url;
  385.                 }
  386.                 else
  387.                 {
  388.                     Mage::log('EmailImages - unable to retrieve image from URL ' $urlZend_Log::WARN);
  389.                     
  390.                     // remove images that failed to load
  391.                     UnSet($urls[$index]);
  392.                 }
  393.             }
  394.         }
  395.     
  396.         // set Content-Type to multipart/related to properly display the images inline, if any
  397.         if count($urls) )
  398.             $mail->setType(Zend_Mime::MULTIPART_RELATED);
  399.     }
  400.     
  401.     /**
  402.      *  Retrieve image data from URL.
  403.      *  NB: uses file_get_contents().
  404.      *
  405.      *  @TODO   should we try to use curl if available? should that be configurable by admin?
  406.      * 
  407.      *  @param  string      $url        URL to retrieve image data from.
  408.      *  @return array|false            Array with keys 'image' for image binary, 'size' for image size, if successfully retrieved image from URL;
  409.      *                                   false, otherwise.
  410.      *
  411.      *  @see    CACHE_TAG, CACHE_TYPE,
  412.      *           getCacheTime(),
  413.      *           ;Mage_Core::_Model_Cache(), ;Mage_Core::_Model_Cache(), ;Mage_Core::_Model_Cache(),
  414.      *           file_get_contents()
  415.      */
  416.     protected function _retrieveImageData$url )
  417.     {
  418.         // retrieve image from cache or URL
  419.         /** @var    $cache  Mage_Core_Model_Cache */
  420.         $cache      Mage::getSingleton('core/cache');
  421.         $use_cache  $cache->canUse(self::CACHE_TYPE);
  422.         $data       false;
  423.  
  424.         if $use_cache )
  425.         {
  426.             $cache_id   self::CACHE_TYPE $url;
  427.             $data       $cache->load(self::CACHE_TYPE $url);
  428.  
  429.             if $data )
  430.                 $data unserialize($data);
  431.         }
  432.         
  433.         if !$data )
  434.         {
  435.             // retrieve image data from URL
  436.             Mage::log('EmailImages - loading image from URL ' $url);
  437.  
  438.             $data file_get_contents($url);
  439.             if $data )
  440.             {
  441.                 $data array(
  442.                                 'image' => $data,
  443.                                 'size'  => getimagesize($url),
  444.                              );
  445.             }
  446.  
  447.             // save retrieved image data to cache even if retrieving the image failed, if allowed
  448.             if $use_cache )
  449.             {
  450.                 $serialized_data    serialize($data);
  451.                 $cache_time         $this->getCacheTime();
  452.  
  453.                 $cache->save($serialized_data$cache_idarrayself::CACHE_TAG )$cache_time);
  454.  
  455.                 Mage::log('EmailImages - saved image to cache');
  456.             }
  457.         }
  458.         else
  459.         {
  460.             Mage::log('EmailImages - loaded image from cache');
  461.         }
  462.         
  463.         return $data;
  464.     }
  465. }

Documentation generated on Fri, 09 Oct 2015 03:37:09 +0200 by phpDocumentor 1.4.4