Version Notes
- Updated Newsletter synchronisation
- Added webhooks subscibe/unsubscribe for Newsletter
Download this release
Release Info
| Developer | Thomas Nelson |
| Extension | Mailigen_Synchronizer |
| Version | 1.2.0 |
| Comparing to | |
| See all releases | |
Code changes from version 1.1.4 to 1.2.0
- app/code/community/Mailigen/Synchronizer/Block/Adminhtml/Sync/Information.php +125 -33
- app/code/community/Mailigen/Synchronizer/Helper/Customer.php +15 -0
- app/code/community/Mailigen/Synchronizer/Helper/Data.php +16 -6
- app/code/community/Mailigen/Synchronizer/Helper/Log.php +10 -0
- app/code/community/Mailigen/Synchronizer/Mailigen_webhooks_setup_instruction.jpg +0 -0
- app/code/community/Mailigen/Synchronizer/Model/Mailigen.php +175 -59
- app/code/community/Mailigen/Synchronizer/Model/Newsletter.php +66 -0
- app/code/community/Mailigen/Synchronizer/Model/Newsletter/Merge/Field.php +12 -2
- app/code/community/Mailigen/Synchronizer/Model/Observer.php +157 -45
- app/code/community/Mailigen/Synchronizer/Model/Resource/Subscriber/Collection.php +26 -0
- app/code/community/Mailigen/Synchronizer/Model/Schedule.php +32 -14
- app/code/community/Mailigen/Synchronizer/controllers/Adminhtml/MailigenController.php +37 -5
- app/code/community/Mailigen/Synchronizer/controllers/WebhookController.php +193 -0
- app/code/community/Mailigen/Synchronizer/etc/config.xml +21 -1
- app/code/community/Mailigen/Synchronizer/etc/system.xml +35 -14
- app/code/community/Mailigen/Synchronizer/sql/mailigen_synchronizer_setup/mysql4-upgrade-1.1.4-1.2.0.php +21 -0
- package.xml +6 -5
app/code/community/Mailigen/Synchronizer/Block/Adminhtml/Sync/Information.php
CHANGED
|
@@ -21,11 +21,13 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 21 |
$helper = Mage::helper('mailigen_synchronizer');
|
| 22 |
|
| 23 |
$lastSyncedText = $this->_getLastSyncedText();
|
|
|
|
| 24 |
$syncedCustomersProgress = $this->_getSyncedCustomersProgress();
|
| 25 |
$syncStatusText = $this->_getSyncStatusText();
|
| 26 |
|
| 27 |
$html = '<style type="text/css">
|
| 28 |
.progress {
|
|
|
|
| 29 |
padding: 2px;
|
| 30 |
background: rgba(0, 0, 0, 0.25);
|
| 31 |
border-radius: 6px;
|
|
@@ -33,9 +35,6 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 33 |
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25), 0 1px rgba(255, 255, 255, 0.08);
|
| 34 |
}
|
| 35 |
.progress-bar {
|
| 36 |
-
font-size: 12px;
|
| 37 |
-
color: #111;
|
| 38 |
-
text-align: left;
|
| 39 |
text-indent: 6px;
|
| 40 |
position: relative;
|
| 41 |
height: 16px;
|
|
@@ -79,6 +78,14 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 79 |
background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05));
|
| 80 |
background-image: linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05));
|
| 81 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
</style>
|
| 83 |
<table cellspacing="0" class="form-list">
|
| 84 |
<tr>
|
|
@@ -88,21 +95,31 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 88 |
<td></td>
|
| 89 |
</tr>
|
| 90 |
<tr>
|
| 91 |
-
<td class="label">' . $helper->__('
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
<td class="value">
|
| 93 |
<div class="progress">
|
| 94 |
-
<div class="progress-bar" style="width:' . $
|
| 95 |
-
' . $
|
| 96 |
-
</div>
|
| 97 |
</div>
|
| 98 |
</td>
|
| 99 |
-
<td class="scope-label"
|
| 100 |
<td></td>
|
| 101 |
</tr>
|
| 102 |
<tr>
|
| 103 |
-
<td class="label">' . $helper->__('
|
| 104 |
-
<td class="value">
|
| 105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
<td></td>
|
| 107 |
</tr>
|
| 108 |
</table>';
|
|
@@ -136,6 +153,38 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 136 |
return $lastSyncedText;
|
| 137 |
}
|
| 138 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
/**
|
| 140 |
* Get synced customers progress
|
| 141 |
*
|
|
@@ -147,10 +196,20 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 147 |
$syncedCustomers = Mage::getModel('mailigen_synchronizer/customer')->getCollection()
|
| 148 |
->addFieldToFilter('is_synced', 1)
|
| 149 |
->getSize();
|
| 150 |
-
$syncedCustomersPercent = round($syncedCustomers / $totalCustomers * 100);
|
| 151 |
-
$syncedCustomersText = "$syncedCustomersPercent% ($syncedCustomers/$totalCustomers)";
|
| 152 |
|
| 153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
}
|
| 155 |
|
| 156 |
/**
|
|
@@ -161,28 +220,26 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 161 |
protected function _getSyncStatusText()
|
| 162 |
{
|
| 163 |
/** @var $mailigenSchedule Mailigen_Synchronizer_Model_Schedule */
|
| 164 |
-
$mailigenSchedule = Mage::
|
| 165 |
-
$runningJob = $mailigenSchedule->getLastRunningJob();
|
| 166 |
-
$pendingJob = $mailigenSchedule->getLastPendingJob();
|
| 167 |
|
| 168 |
-
if ($
|
| 169 |
$html = "Running";
|
| 170 |
-
if (strlen($
|
| 171 |
$html .= ' (Started at: ';
|
| 172 |
-
$html .= Mage::helper('core')->formatDate($
|
| 173 |
$html .= ') ';
|
| 174 |
|
| 175 |
/**
|
| 176 |
-
* Show stop sync
|
| 177 |
*/
|
| 178 |
-
$html .= $this->
|
| 179 |
}
|
| 180 |
}
|
| 181 |
-
elseif ($
|
| 182 |
$html = "Pending";
|
| 183 |
-
if (strlen($
|
| 184 |
$html .= ' (Scheduled at: ';
|
| 185 |
-
$html .= Mage::helper('core')->formatDate($
|
| 186 |
$html .= ')';
|
| 187 |
}
|
| 188 |
}
|
|
@@ -191,20 +248,19 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 191 |
/**
|
| 192 |
* Show reset sync customers button
|
| 193 |
*/
|
| 194 |
-
$html .= ' '.$this->_getResetCustomersSyncButton();
|
| 195 |
}
|
| 196 |
|
| 197 |
return $html;
|
| 198 |
}
|
| 199 |
|
| 200 |
/**
|
| 201 |
-
* Get Stop
|
| 202 |
*
|
| 203 |
* @return string
|
| 204 |
*/
|
| 205 |
-
protected function
|
| 206 |
{
|
| 207 |
-
$stopSyncUrl = Mage::helper('adminhtml')->getUrl('*/mailigen/
|
| 208 |
$buttonJs = '<script type="text/javascript">
|
| 209 |
//<![CDATA[
|
| 210 |
function stopMailigenSynchronizer() {
|
|
@@ -240,7 +296,43 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 240 |
$resetSyncUrl = Mage::helper('adminhtml')->getUrl('*/mailigen/resetSyncCustomers');
|
| 241 |
$buttonJs = '<script type="text/javascript">
|
| 242 |
//<![CDATA[
|
| 243 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
new Ajax.Request("' . $resetSyncUrl . '", {
|
| 245 |
method: "get",
|
| 246 |
onSuccess: function(transport){
|
|
@@ -258,9 +350,9 @@ class Mailigen_Synchronizer_Block_Adminhtml_Sync_Information
|
|
| 258 |
|
| 259 |
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
|
| 260 |
->setData(array(
|
| 261 |
-
'id' => '
|
| 262 |
-
'label' => $this->helper('adminhtml')->__('Reset
|
| 263 |
-
'onclick' => 'javascript:
|
| 264 |
));
|
| 265 |
|
| 266 |
return $buttonJs . $button->toHtml();
|
| 21 |
$helper = Mage::helper('mailigen_synchronizer');
|
| 22 |
|
| 23 |
$lastSyncedText = $this->_getLastSyncedText();
|
| 24 |
+
$syncedNewsletterProgress = $this->_getSyncedNewsletterProgress();
|
| 25 |
$syncedCustomersProgress = $this->_getSyncedCustomersProgress();
|
| 26 |
$syncStatusText = $this->_getSyncStatusText();
|
| 27 |
|
| 28 |
$html = '<style type="text/css">
|
| 29 |
.progress {
|
| 30 |
+
position: relative;
|
| 31 |
padding: 2px;
|
| 32 |
background: rgba(0, 0, 0, 0.25);
|
| 33 |
border-radius: 6px;
|
| 35 |
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.25), 0 1px rgba(255, 255, 255, 0.08);
|
| 36 |
}
|
| 37 |
.progress-bar {
|
|
|
|
|
|
|
|
|
|
| 38 |
text-indent: 6px;
|
| 39 |
position: relative;
|
| 40 |
height: 16px;
|
| 78 |
background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05));
|
| 79 |
background-image: linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.05));
|
| 80 |
}
|
| 81 |
+
.progress-text {
|
| 82 |
+
position: absolute;
|
| 83 |
+
top: 1px;
|
| 84 |
+
left: 10px;
|
| 85 |
+
font-size: 12px;
|
| 86 |
+
color: #111;
|
| 87 |
+
text-align: left;
|
| 88 |
+
}
|
| 89 |
</style>
|
| 90 |
<table cellspacing="0" class="form-list">
|
| 91 |
<tr>
|
| 95 |
<td></td>
|
| 96 |
</tr>
|
| 97 |
<tr>
|
| 98 |
+
<td class="label">' . $helper->__('Sync Status') . '</td>
|
| 99 |
+
<td class="value">' . $syncStatusText . '</td>
|
| 100 |
+
<td class="scope-label"></td>
|
| 101 |
+
<td></td>
|
| 102 |
+
</tr>
|
| 103 |
+
<tr>
|
| 104 |
+
<td class="label">' . $helper->__('Synced Newsletter (subscribed)') . '</td>
|
| 105 |
<td class="value">
|
| 106 |
<div class="progress">
|
| 107 |
+
<div class="progress-bar" style="width:' . $syncedNewsletterProgress['percent'] . '%;"></div>
|
| 108 |
+
<span class="progress-text">' . $syncedNewsletterProgress['text'] . '</span>
|
|
|
|
| 109 |
</div>
|
| 110 |
</td>
|
| 111 |
+
<td class="scope-label">' . $syncedNewsletterProgress['button'] . '</td>
|
| 112 |
<td></td>
|
| 113 |
</tr>
|
| 114 |
<tr>
|
| 115 |
+
<td class="label">' . $helper->__('Synced Customers') . '</td>
|
| 116 |
+
<td class="value">
|
| 117 |
+
<div class="progress">
|
| 118 |
+
<div class="progress-bar" style="width:' . $syncedCustomersProgress['percent'] . '%;"></div>
|
| 119 |
+
<span class="progress-text">' . $syncedCustomersProgress['text'] . '</span>
|
| 120 |
+
</div>
|
| 121 |
+
</td>
|
| 122 |
+
<td class="scope-label">' . $syncedCustomersProgress['button'] . '</td>
|
| 123 |
<td></td>
|
| 124 |
</tr>
|
| 125 |
</table>';
|
| 153 |
return $lastSyncedText;
|
| 154 |
}
|
| 155 |
|
| 156 |
+
/**
|
| 157 |
+
* Get synced newsletter progress
|
| 158 |
+
*
|
| 159 |
+
* @return array
|
| 160 |
+
*/
|
| 161 |
+
protected function _getSyncedNewsletterProgress()
|
| 162 |
+
{
|
| 163 |
+
$result = array();
|
| 164 |
+
$totalNewsletter = Mage::getModel('newsletter/subscriber')->getCollection()
|
| 165 |
+
->addFieldToFilter('subscriber_status', Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED)
|
| 166 |
+
->getSize();
|
| 167 |
+
$syncedNewsletter = Mage::getModel('newsletter/subscriber')->getCollection()
|
| 168 |
+
->addFieldToFilter('subscriber_status', Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED)
|
| 169 |
+
->addFieldToFilter('mailigen_synced', 1)
|
| 170 |
+
->getSize();
|
| 171 |
+
|
| 172 |
+
$result['percent'] = round($syncedNewsletter / $totalNewsletter * 100);
|
| 173 |
+
$result['text'] = "{$result['percent']}% ($syncedNewsletter/$totalNewsletter)";
|
| 174 |
+
|
| 175 |
+
/** @var $mailigenSchedule Mailigen_Synchronizer_Model_Schedule */
|
| 176 |
+
$mailigenSchedule = Mage::getSingleton('mailigen_synchronizer/schedule');
|
| 177 |
+
$lastRunningJob = $mailigenSchedule->getLastRunningJob();
|
| 178 |
+
if (empty($lastRunningJob)) {
|
| 179 |
+
$result['button'] = $this->_getResetNewsletterSyncButton();
|
| 180 |
+
} else {
|
| 181 |
+
$result['button'] = '';
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
return $result;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
|
| 188 |
/**
|
| 189 |
* Get synced customers progress
|
| 190 |
*
|
| 196 |
$syncedCustomers = Mage::getModel('mailigen_synchronizer/customer')->getCollection()
|
| 197 |
->addFieldToFilter('is_synced', 1)
|
| 198 |
->getSize();
|
|
|
|
|
|
|
| 199 |
|
| 200 |
+
$result['percent'] = round($syncedCustomers / $totalCustomers * 100);
|
| 201 |
+
$result['text'] = "{$result['percent']}% ($syncedCustomers/$totalCustomers)";
|
| 202 |
+
|
| 203 |
+
/** @var $mailigenSchedule Mailigen_Synchronizer_Model_Schedule */
|
| 204 |
+
$mailigenSchedule = Mage::getSingleton('mailigen_synchronizer/schedule');
|
| 205 |
+
$lastRunningJob = $mailigenSchedule->getLastRunningJob();
|
| 206 |
+
if (empty($lastRunningJob)) {
|
| 207 |
+
$result['button'] = $this->_getResetCustomersSyncButton();
|
| 208 |
+
} else {
|
| 209 |
+
$result['button'] = '';
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
return $result;
|
| 213 |
}
|
| 214 |
|
| 215 |
/**
|
| 220 |
protected function _getSyncStatusText()
|
| 221 |
{
|
| 222 |
/** @var $mailigenSchedule Mailigen_Synchronizer_Model_Schedule */
|
| 223 |
+
$mailigenSchedule = Mage::getSingleton('mailigen_synchronizer/schedule');
|
|
|
|
|
|
|
| 224 |
|
| 225 |
+
if ($mailigenSchedule->getLastRunningJob()) {
|
| 226 |
$html = "Running";
|
| 227 |
+
if (strlen($mailigenSchedule->getLastRunningJob()->getExecutedAt())) {
|
| 228 |
$html .= ' (Started at: ';
|
| 229 |
+
$html .= Mage::helper('core')->formatDate($mailigenSchedule->getLastRunningJob()->getExecutedAt(), 'medium', true);
|
| 230 |
$html .= ') ';
|
| 231 |
|
| 232 |
/**
|
| 233 |
+
* Show stop sync button
|
| 234 |
*/
|
| 235 |
+
$html .= $this->_getStopSyncButton();
|
| 236 |
}
|
| 237 |
}
|
| 238 |
+
elseif ($mailigenSchedule->getLastPendingJob()) {
|
| 239 |
$html = "Pending";
|
| 240 |
+
if (strlen($mailigenSchedule->getLastPendingJob()->getScheduledAt())) {
|
| 241 |
$html .= ' (Scheduled at: ';
|
| 242 |
+
$html .= Mage::helper('core')->formatDate($mailigenSchedule->getLastPendingJob()->getScheduledAt(), 'medium', true);
|
| 243 |
$html .= ')';
|
| 244 |
}
|
| 245 |
}
|
| 248 |
/**
|
| 249 |
* Show reset sync customers button
|
| 250 |
*/
|
|
|
|
| 251 |
}
|
| 252 |
|
| 253 |
return $html;
|
| 254 |
}
|
| 255 |
|
| 256 |
/**
|
| 257 |
+
* Get Stop sync button html
|
| 258 |
*
|
| 259 |
* @return string
|
| 260 |
*/
|
| 261 |
+
protected function _getStopSyncButton()
|
| 262 |
{
|
| 263 |
+
$stopSyncUrl = Mage::helper('adminhtml')->getUrl('*/mailigen/stopSync');
|
| 264 |
$buttonJs = '<script type="text/javascript">
|
| 265 |
//<![CDATA[
|
| 266 |
function stopMailigenSynchronizer() {
|
| 296 |
$resetSyncUrl = Mage::helper('adminhtml')->getUrl('*/mailigen/resetSyncCustomers');
|
| 297 |
$buttonJs = '<script type="text/javascript">
|
| 298 |
//<![CDATA[
|
| 299 |
+
function resetCustomersSync() {
|
| 300 |
+
new Ajax.Request("' . $resetSyncUrl . '", {
|
| 301 |
+
method: "get",
|
| 302 |
+
onSuccess: function(transport){
|
| 303 |
+
if (transport.responseText == "1"){
|
| 304 |
+
window.location.reload();
|
| 305 |
+
}
|
| 306 |
+
else {
|
| 307 |
+
alert(transport.responseText);
|
| 308 |
+
}
|
| 309 |
+
}
|
| 310 |
+
});
|
| 311 |
+
}
|
| 312 |
+
//]]>
|
| 313 |
+
</script>';
|
| 314 |
+
|
| 315 |
+
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
|
| 316 |
+
->setData(array(
|
| 317 |
+
'id' => 'reset_customers_sync__button',
|
| 318 |
+
'label' => $this->helper('adminhtml')->__('Reset Customers Sync'),
|
| 319 |
+
'onclick' => 'javascript:resetCustomersSync(); return false;'
|
| 320 |
+
));
|
| 321 |
+
|
| 322 |
+
return $buttonJs . $button->toHtml();
|
| 323 |
+
}
|
| 324 |
+
|
| 325 |
+
/**
|
| 326 |
+
* Get Reset newsletter sync button html
|
| 327 |
+
*
|
| 328 |
+
* @return string
|
| 329 |
+
*/
|
| 330 |
+
protected function _getResetNewsletterSyncButton()
|
| 331 |
+
{
|
| 332 |
+
$resetSyncUrl = Mage::helper('adminhtml')->getUrl('*/mailigen/resetSyncNewsletter');
|
| 333 |
+
$buttonJs = '<script type="text/javascript">
|
| 334 |
+
//<![CDATA[
|
| 335 |
+
function resetNewsletterSync() {
|
| 336 |
new Ajax.Request("' . $resetSyncUrl . '", {
|
| 337 |
method: "get",
|
| 338 |
onSuccess: function(transport){
|
| 350 |
|
| 351 |
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
|
| 352 |
->setData(array(
|
| 353 |
+
'id' => 'reset_newsletter_sync__button',
|
| 354 |
+
'label' => $this->helper('adminhtml')->__('Reset Newsletter Sync'),
|
| 355 |
+
'onclick' => 'javascript:resetNewsletterSync(); return false;'
|
| 356 |
));
|
| 357 |
|
| 358 |
return $buttonJs . $button->toHtml();
|
app/code/community/Mailigen/Synchronizer/Helper/Customer.php
CHANGED
|
@@ -188,4 +188,19 @@ class Mailigen_Synchronizer_Helper_Customer extends Mage_Core_Helper_Abstract
|
|
| 188 |
return $this->customerIsSubscribed[0];
|
| 189 |
}
|
| 190 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
}
|
| 188 |
return $this->customerIsSubscribed[0];
|
| 189 |
}
|
| 190 |
}
|
| 191 |
+
|
| 192 |
+
/**
|
| 193 |
+
* @param $type
|
| 194 |
+
* @return mixed
|
| 195 |
+
*/
|
| 196 |
+
public function getSubscriberType($type)
|
| 197 |
+
{
|
| 198 |
+
if ($type == 1) {
|
| 199 |
+
return Mage::helper('newsletter')->__('Guest');
|
| 200 |
+
} elseif ($type == 2) {
|
| 201 |
+
return Mage::helper('newsletter')->__('Customer');
|
| 202 |
+
} else {
|
| 203 |
+
return Mage::helper('newsletter')->__('Unknown');
|
| 204 |
+
}
|
| 205 |
+
}
|
| 206 |
}
|
app/code/community/Mailigen/Synchronizer/Helper/Data.php
CHANGED
|
@@ -15,11 +15,12 @@ class Mailigen_Synchronizer_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 15 |
const XML_PATH_NEWSLETTER_NEW_LIST_TITLE = 'mailigen_synchronizer/newsletter/new_list_title';
|
| 16 |
const XML_PATH_NEWSLETTER_AUTOSYNC = 'mailigen_synchronizer/newsletter/autosync';
|
| 17 |
const XML_PATH_NEWSLETTER_HANDLE_DEFAULT_EMAILS = 'mailigen_synchronizer/newsletter/handle_default_emails';
|
|
|
|
| 18 |
const XML_PATH_CUSTOMERS_CONTACT_LIST = 'mailigen_synchronizer/customers/contact_list';
|
| 19 |
const XML_PATH_CUSTOMERS_NEW_LIST_TITLE = 'mailigen_synchronizer/customers/new_list_title';
|
| 20 |
const XML_PATH_CUSTOMERS_AUTOSYNC = 'mailigen_synchronizer/customers/autosync';
|
| 21 |
-
const
|
| 22 |
-
const
|
| 23 |
|
| 24 |
protected $_mgapi = null;
|
| 25 |
|
|
@@ -68,6 +69,15 @@ class Mailigen_Synchronizer_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 68 |
return Mage::getStoreConfigFlag(self::XML_PATH_NEWSLETTER_HANDLE_DEFAULT_EMAILS, $storeId);
|
| 69 |
}
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
/**
|
| 72 |
* @param null $storeId
|
| 73 |
* @return mixed
|
|
@@ -105,7 +115,7 @@ class Mailigen_Synchronizer_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 105 |
public function setManualSync($start = 1)
|
| 106 |
{
|
| 107 |
$config = new Mage_Core_Model_Config();
|
| 108 |
-
$config->saveConfig(self::
|
| 109 |
$config->cleanCache();
|
| 110 |
}
|
| 111 |
|
|
@@ -114,7 +124,7 @@ class Mailigen_Synchronizer_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 114 |
*/
|
| 115 |
public function getManualSync()
|
| 116 |
{
|
| 117 |
-
return Mage::getStoreConfigFlag(self::
|
| 118 |
}
|
| 119 |
|
| 120 |
/**
|
|
@@ -123,7 +133,7 @@ class Mailigen_Synchronizer_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 123 |
public function setStopSync($stop = 1)
|
| 124 |
{
|
| 125 |
$config = new Mage_Core_Model_Config();
|
| 126 |
-
$config->saveConfig(self::
|
| 127 |
}
|
| 128 |
|
| 129 |
/**
|
|
@@ -135,7 +145,7 @@ class Mailigen_Synchronizer_Helper_Data extends Mage_Core_Helper_Abstract
|
|
| 135 |
{
|
| 136 |
/** @var $stopSyncConfigCollection Mage_Core_Model_Resource_Config_Data_Collection */
|
| 137 |
$stopSyncConfigCollection = Mage::getModel('core/config_data')->getCollection()
|
| 138 |
-
->addFieldToFilter('path', self::
|
| 139 |
|
| 140 |
if ($stopSyncConfigCollection->getSize()) {
|
| 141 |
/** @var $stopSyncConfig Mage_Core_Model_Config_Data */
|
| 15 |
const XML_PATH_NEWSLETTER_NEW_LIST_TITLE = 'mailigen_synchronizer/newsletter/new_list_title';
|
| 16 |
const XML_PATH_NEWSLETTER_AUTOSYNC = 'mailigen_synchronizer/newsletter/autosync';
|
| 17 |
const XML_PATH_NEWSLETTER_HANDLE_DEFAULT_EMAILS = 'mailigen_synchronizer/newsletter/handle_default_emails';
|
| 18 |
+
const XML_PATH_NEWSLETTER_WEBHOOKS = 'mailigen_synchronizer/newsletter/webhooks';
|
| 19 |
const XML_PATH_CUSTOMERS_CONTACT_LIST = 'mailigen_synchronizer/customers/contact_list';
|
| 20 |
const XML_PATH_CUSTOMERS_NEW_LIST_TITLE = 'mailigen_synchronizer/customers/new_list_title';
|
| 21 |
const XML_PATH_CUSTOMERS_AUTOSYNC = 'mailigen_synchronizer/customers/autosync';
|
| 22 |
+
const XML_PATH_SYNC_MANUAL = 'mailigen_synchronizer/sync/manual';
|
| 23 |
+
const XML_PATH_SYNC_STOP = 'mailigen_synchronizer/sync/stop';
|
| 24 |
|
| 25 |
protected $_mgapi = null;
|
| 26 |
|
| 69 |
return Mage::getStoreConfigFlag(self::XML_PATH_NEWSLETTER_HANDLE_DEFAULT_EMAILS, $storeId);
|
| 70 |
}
|
| 71 |
|
| 72 |
+
/**
|
| 73 |
+
* @param null $storeId
|
| 74 |
+
* @return bool
|
| 75 |
+
*/
|
| 76 |
+
public function enabledWebhooks($storeId = null)
|
| 77 |
+
{
|
| 78 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_NEWSLETTER_WEBHOOKS, $storeId);
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
/**
|
| 82 |
* @param null $storeId
|
| 83 |
* @return mixed
|
| 115 |
public function setManualSync($start = 1)
|
| 116 |
{
|
| 117 |
$config = new Mage_Core_Model_Config();
|
| 118 |
+
$config->saveConfig(self::XML_PATH_SYNC_MANUAL, $start);
|
| 119 |
$config->cleanCache();
|
| 120 |
}
|
| 121 |
|
| 124 |
*/
|
| 125 |
public function getManualSync()
|
| 126 |
{
|
| 127 |
+
return Mage::getStoreConfigFlag(self::XML_PATH_SYNC_MANUAL);
|
| 128 |
}
|
| 129 |
|
| 130 |
/**
|
| 133 |
public function setStopSync($stop = 1)
|
| 134 |
{
|
| 135 |
$config = new Mage_Core_Model_Config();
|
| 136 |
+
$config->saveConfig(self::XML_PATH_SYNC_STOP, $stop);
|
| 137 |
}
|
| 138 |
|
| 139 |
/**
|
| 145 |
{
|
| 146 |
/** @var $stopSyncConfigCollection Mage_Core_Model_Resource_Config_Data_Collection */
|
| 147 |
$stopSyncConfigCollection = Mage::getModel('core/config_data')->getCollection()
|
| 148 |
+
->addFieldToFilter('path', self::XML_PATH_SYNC_STOP);
|
| 149 |
|
| 150 |
if ($stopSyncConfigCollection->getSize()) {
|
| 151 |
/** @var $stopSyncConfig Mage_Core_Model_Config_Data */
|
app/code/community/Mailigen/Synchronizer/Helper/Log.php
CHANGED
|
@@ -10,6 +10,7 @@
|
|
| 10 |
class Mailigen_Synchronizer_Helper_Log extends Mage_Core_Helper_Abstract
|
| 11 |
{
|
| 12 |
const LOG_FILE = 'mailigen_synchronizer.log';
|
|
|
|
| 13 |
|
| 14 |
/**
|
| 15 |
* @param $message
|
|
@@ -27,4 +28,13 @@ class Mailigen_Synchronizer_Helper_Log extends Mage_Core_Helper_Abstract
|
|
| 27 |
{
|
| 28 |
self::log("\n" . $e->__toString(), Zend_Log::ERR);
|
| 29 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
}
|
| 10 |
class Mailigen_Synchronizer_Helper_Log extends Mage_Core_Helper_Abstract
|
| 11 |
{
|
| 12 |
const LOG_FILE = 'mailigen_synchronizer.log';
|
| 13 |
+
const WEBHOOK_FILE = 'mailigen_webhooks.log';
|
| 14 |
|
| 15 |
/**
|
| 16 |
* @param $message
|
| 28 |
{
|
| 29 |
self::log("\n" . $e->__toString(), Zend_Log::ERR);
|
| 30 |
}
|
| 31 |
+
|
| 32 |
+
/**
|
| 33 |
+
* @param $message
|
| 34 |
+
* @param null $level
|
| 35 |
+
*/
|
| 36 |
+
public function logWebhook($message, $level = null)
|
| 37 |
+
{
|
| 38 |
+
Mage::log($message, $level, self::WEBHOOK_FILE);
|
| 39 |
+
}
|
| 40 |
}
|
app/code/community/Mailigen/Synchronizer/Mailigen_webhooks_setup_instruction.jpg
ADDED
|
Binary file
|
app/code/community/Mailigen/Synchronizer/Model/Mailigen.php
CHANGED
|
@@ -14,11 +14,21 @@ class Mailigen_Synchronizer_Model_Mailigen extends Mage_Core_Model_Abstract
|
|
| 14 |
*/
|
| 15 |
protected $_customersListId = null;
|
| 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
/**
|
| 18 |
* @var array
|
| 19 |
*/
|
| 20 |
protected $_batchedCustomersData = array();
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
/**
|
| 23 |
* @var array
|
| 24 |
*/
|
|
@@ -33,18 +43,32 @@ class Mailigen_Synchronizer_Model_Mailigen extends Mage_Core_Model_Abstract
|
|
| 33 |
'remove_count' => 0,
|
| 34 |
);
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
public function syncNewsletter()
|
| 37 |
{
|
| 38 |
-
/** @var $helper Mailigen_Synchronizer_Helper_Customer */
|
| 39 |
-
$helper = Mage::helper('mailigen_synchronizer/customer');
|
| 40 |
-
$api = Mage::helper('mailigen_synchronizer')->getMailigenApi();
|
| 41 |
-
$listid = Mage::helper('mailigen_synchronizer')->getNewsletterContactList();
|
| 42 |
-
if (!$listid) {
|
| 43 |
-
return;
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 47 |
$logger = Mage::helper('mailigen_synchronizer/log');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
/**
|
| 50 |
* Create or update Merge fields
|
|
@@ -52,70 +76,141 @@ class Mailigen_Synchronizer_Model_Mailigen extends Mage_Core_Model_Abstract
|
|
| 52 |
Mage::getModel('mailigen_synchronizer/newsletter_merge_field')->createMergeFields();
|
| 53 |
$logger->log('Newsletter merge fields created and updated');
|
| 54 |
|
| 55 |
-
//First we pull all unsubscribers from Mailigen
|
| 56 |
-
$unsubscribers = $api->listMembers($listid, "unsubscribed", 0, 500);
|
| 57 |
-
|
| 58 |
-
foreach ($unsubscribers as $unsubscriber) {
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
$email = $subscriber['email'];
|
| 79 |
|
|
|
|
|
|
|
|
|
|
| 80 |
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
);
|
| 106 |
}
|
| 107 |
-
|
| 108 |
-
$double_optin = false;
|
| 109 |
-
$update_existing = true;
|
| 110 |
-
$retval = $api->listBatchSubscribe($listid, $batch, $double_optin, $update_existing);
|
| 111 |
|
| 112 |
if ($api->errorCode) {
|
| 113 |
-
|
| 114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
} else {
|
| 116 |
-
|
| 117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
}
|
| 120 |
|
| 121 |
public function syncCustomers()
|
|
@@ -415,14 +510,35 @@ class Mailigen_Synchronizer_Model_Mailigen extends Mage_Core_Model_Abstract
|
|
| 415 |
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 416 |
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 417 |
|
| 418 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 419 |
$logger->log("Successfully updated {$this->_customersLog['update_success_count']}/{$this->_customersLog['update_count']} customers");
|
| 420 |
if (!empty($this->_customersLog['update_errors'])) {
|
| 421 |
$logger->log("Update errors: " . var_export($this->_customersLog['update_errors'], true));
|
| 422 |
}
|
| 423 |
}
|
| 424 |
|
| 425 |
-
if ($this->_customersLog['remove_count'] > 0) {
|
| 426 |
$logger->log("Successfully removed {$this->_customersLog['remove_success_count']}/{$this->_customersLog['remove_count']} customers");
|
| 427 |
$logger->log("Removed with error {$this->_customersLog['remove_error_count']}/{$this->_customersLog['remove_count']} customers");
|
| 428 |
if (!empty($this->_customersLog['remove_errors'])) {
|
| 14 |
*/
|
| 15 |
protected $_customersListId = null;
|
| 16 |
|
| 17 |
+
/**
|
| 18 |
+
* @var null
|
| 19 |
+
*/
|
| 20 |
+
protected $_newsletterListId = null;
|
| 21 |
+
|
| 22 |
/**
|
| 23 |
* @var array
|
| 24 |
*/
|
| 25 |
protected $_batchedCustomersData = array();
|
| 26 |
|
| 27 |
+
/**
|
| 28 |
+
* @var array
|
| 29 |
+
*/
|
| 30 |
+
protected $_batchedNewsletterData = array();
|
| 31 |
+
|
| 32 |
/**
|
| 33 |
* @var array
|
| 34 |
*/
|
| 43 |
'remove_count' => 0,
|
| 44 |
);
|
| 45 |
|
| 46 |
+
/**
|
| 47 |
+
* @var array
|
| 48 |
+
*/
|
| 49 |
+
protected $_newsletterLog = array(
|
| 50 |
+
'subscriber_success_count' => 0,
|
| 51 |
+
'subscriber_error_count' => 0,
|
| 52 |
+
'subscriber_errors' => array(),
|
| 53 |
+
'subscriber_count' => 0,
|
| 54 |
+
'unsubscriber_success_count' => 0,
|
| 55 |
+
'unsubscriber_error_count' => 0,
|
| 56 |
+
'unsubscriber_errors' => array(),
|
| 57 |
+
'unsubscriber_count' => 0,
|
| 58 |
+
);
|
| 59 |
+
|
| 60 |
public function syncNewsletter()
|
| 61 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 63 |
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 64 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 65 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 66 |
+
$logger->log('Newsletter synchronization started');
|
| 67 |
+
$this->_newsletterListId = $helper->getNewsletterContactList();
|
| 68 |
+
if (!$this->_newsletterListId) {
|
| 69 |
+
Mage::throwException("Newsletter contact list isn't selected");
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
|
| 73 |
/**
|
| 74 |
* Create or update Merge fields
|
| 76 |
Mage::getModel('mailigen_synchronizer/newsletter_merge_field')->createMergeFields();
|
| 77 |
$logger->log('Newsletter merge fields created and updated');
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
+
/**
|
| 81 |
+
* Update subscribers in Mailigen
|
| 82 |
+
*/
|
| 83 |
+
/** @var $subscribers Mailigen_Synchronizer_Model_Resource_Subscriber_Collection */
|
| 84 |
+
$subscribers = Mage::getResourceSingleton('mailigen_synchronizer/subscriber_collection')
|
| 85 |
+
->getSubscribers(Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED);
|
| 86 |
+
if (count($subscribers) > 0) {
|
| 87 |
+
$logger->log("Started updating subscribers in Mailigen");
|
| 88 |
+
$iterator = Mage::getSingleton('mailigen_synchronizer/resource_iterator_batched')->walk(
|
| 89 |
+
$subscribers,
|
| 90 |
+
array($this, '_prepareSubscriberData'),
|
| 91 |
+
array($this, '_updateSubscribersInMailigen'),
|
| 92 |
+
100,
|
| 93 |
+
10000
|
| 94 |
+
);
|
| 95 |
+
/**
|
| 96 |
+
* Reschedule task, to run after 2 min
|
| 97 |
+
*/
|
| 98 |
+
if ($iterator == 0) {
|
| 99 |
+
Mage::getModel('mailigen_synchronizer/schedule')->createJob(2);
|
| 100 |
+
$this->_writeResultLogs();
|
| 101 |
+
$logger->log("Reschedule task, to update subscribers in Mailigen after 2 min");
|
| 102 |
+
return;
|
| 103 |
+
}
|
| 104 |
+
$logger->log("Finished updating subscribers in Mailigen");
|
| 105 |
}
|
| 106 |
+
else {
|
| 107 |
+
$logger->log("No subscribers to sync with Mailigen");
|
| 108 |
+
}
|
| 109 |
+
unset($subscribers);
|
| 110 |
|
| 111 |
+
/**
|
| 112 |
+
* Log subscribers info
|
| 113 |
+
*/
|
| 114 |
+
$this->_writeResultLogs();
|
|
|
|
|
|
|
| 115 |
|
| 116 |
+
/**
|
| 117 |
+
* @todo Update unsubscribers in Mailigen
|
| 118 |
+
*/
|
| 119 |
|
| 120 |
+
/**
|
| 121 |
+
* Log unsubscribers info
|
| 122 |
+
*/
|
| 123 |
+
$this->_writeResultLogs();
|
| 124 |
|
| 125 |
+
$logger->log('Newsletter synchronization finished');
|
| 126 |
+
}
|
| 127 |
|
| 128 |
+
/**
|
| 129 |
+
* @param $subscriber Mage_Newsletter_Model_Subscriber
|
| 130 |
+
*/
|
| 131 |
+
public function _prepareSubscriberData($subscriber)
|
| 132 |
+
{
|
| 133 |
+
/** @var $customerHelper Mailigen_Synchronizer_Helper_Customer */
|
| 134 |
+
$customerHelper = Mage::helper('mailigen_synchronizer/customer');
|
| 135 |
|
| 136 |
+
$this->_batchedNewsletterData[$subscriber->getId()] = array(
|
| 137 |
+
/**
|
| 138 |
+
* Subscriber info
|
| 139 |
+
*/
|
| 140 |
+
'EMAIL' => $subscriber->getSubscriberEmail(),
|
| 141 |
+
'FNAME' => $subscriber->getCustomerFirstname(),
|
| 142 |
+
'LNAME' => $subscriber->getCustomerLastname(),
|
| 143 |
+
'WEBSITEID' => $subscriber->getWebsiteId(),
|
| 144 |
+
'TYPE' => $customerHelper->getSubscriberType($subscriber->getType()),
|
| 145 |
+
'STOREID' => $subscriber->getStoreId(),
|
| 146 |
+
'STORELANGUAGE' => $customerHelper->getStoreLanguage($subscriber->getStoreId()),
|
| 147 |
+
);
|
| 148 |
+
}
|
| 149 |
|
| 150 |
+
/**
|
| 151 |
+
* @param $collectionInfo
|
| 152 |
+
*/
|
| 153 |
+
public function _updateSubscribersInMailigen($collectionInfo)
|
| 154 |
+
{
|
| 155 |
+
/**
|
| 156 |
+
* Send API request to Mailigen
|
| 157 |
+
*/
|
| 158 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 159 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 160 |
+
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 161 |
+
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 162 |
+
$api = $helper->getMailigenApi();
|
| 163 |
+
$apiResponse = $api->listBatchSubscribe($this->_newsletterListId, $this->_batchedNewsletterData, false, true);
|
| 164 |
|
| 165 |
+
/**
|
| 166 |
+
* Log results
|
| 167 |
+
*/
|
| 168 |
+
if (isset($collectionInfo['currentPage']) && isset($collectionInfo['pageSize']) && isset($collectionInfo['pages'])) {
|
| 169 |
+
$curr = $collectionInfo['currentPage'] * $collectionInfo['pageSize'];
|
| 170 |
+
$total = $collectionInfo['pages'] * $collectionInfo['pageSize'];
|
| 171 |
+
$logger->log("Updated $curr/$total subscribers in Mailigen");
|
| 172 |
}
|
| 173 |
+
$this->_newsletterLog['subscriber_count'] += count($this->_batchedNewsletterData);
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
if ($api->errorCode) {
|
| 176 |
+
/**
|
| 177 |
+
* Reschedule job to run after 5 min
|
| 178 |
+
*/
|
| 179 |
+
Mage::getModel('mailigen_synchronizer/schedule')->createJob(5);
|
| 180 |
+
$this->_writeResultLogs();
|
| 181 |
+
$errorInfo = array(
|
| 182 |
+
'errorCode' => $api->errorCode,
|
| 183 |
+
'errorMessage' => $api->errorMessage,
|
| 184 |
+
'apiResponse' => $apiResponse
|
| 185 |
+
);
|
| 186 |
+
Mage::throwException('Unable to batch unsubscribe. ' . var_export($errorInfo, true));
|
| 187 |
} else {
|
| 188 |
+
/**
|
| 189 |
+
* Update Newsletter subscribers synced status
|
| 190 |
+
*/
|
| 191 |
+
Mage::getModel('mailigen_synchronizer/newsletter')->updateSyncedNewsletter(array_keys($this->_batchedNewsletterData));
|
| 192 |
+
|
| 193 |
+
$this->_newsletterLog['subscriber_success_count'] += $apiResponse['success_count'];
|
| 194 |
+
$this->_newsletterLog['subscriber_error_count'] += $apiResponse['error_count'];
|
| 195 |
+
if (count($apiResponse['errors']) > 0) {
|
| 196 |
+
$this->_newsletterLog['subscriber_errors'] = array_merge_recursive($this->_newsletterLog['subscriber_errors'], $apiResponse['errors']);
|
| 197 |
+
}
|
| 198 |
}
|
| 199 |
+
|
| 200 |
+
/**
|
| 201 |
+
* Check if sync should be stopped
|
| 202 |
+
*/
|
| 203 |
+
$this->_checkSyncStop();
|
| 204 |
+
|
| 205 |
+
$this->_batchedNewsletterData = array();
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
/**
|
| 209 |
+
* @param $unsubscriber Mage_Newsletter_Model_Subscriber
|
| 210 |
+
*/
|
| 211 |
+
public function _prepareUnsubscriberData($unsubscriber)
|
| 212 |
+
{
|
| 213 |
+
$this->_batchedNewsletterData[$unsubscriber->getId()] = $unsubscriber->getSubscriberEmail();
|
| 214 |
}
|
| 215 |
|
| 216 |
public function syncCustomers()
|
| 510 |
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 511 |
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 512 |
|
| 513 |
+
/**
|
| 514 |
+
* Newsletter logs
|
| 515 |
+
*/
|
| 516 |
+
if (isset($this->_newsletterLog['subscriber_count']) && $this->_newsletterLog['subscriber_count'] > 0) {
|
| 517 |
+
$logger->log("Successfully subscribed {$this->_newsletterLog['subscriber_success_count']}/{$this->_newsletterLog['subscriber_count']}");
|
| 518 |
+
if (!empty($this->_newsletterLog['subscriber_errors'])) {
|
| 519 |
+
$logger->log("Subscribe errors: " . var_export($this->_newsletterLog['subscriber_errors'], true));
|
| 520 |
+
}
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
if (isset($this->_newsletterLog['unsubscriber_count']) && $this->_newsletterLog['unsubscriber_count'] > 0) {
|
| 524 |
+
$logger->log("Successfully unsubscribed {$this->_newsletterLog['unsubscriber_success_count']}/{$this->_newsletterLog['unsubscriber_count']}");
|
| 525 |
+
$logger->log("Unsubscribed with error {$this->_newsletterLog['unsubscriber_error_count']}/{$this->_newsletterLog['unsubscriber_count']}");
|
| 526 |
+
if (!empty($this->_newsletterLog['unsubscriber_errors'])) {
|
| 527 |
+
$logger->log("Unsubscribe errors: " . var_export($this->_newsletterLog['unsubscriber_errors'], true));
|
| 528 |
+
}
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
/**
|
| 532 |
+
* Customer logs
|
| 533 |
+
*/
|
| 534 |
+
if (isset($this->_customersLog['update_count']) && $this->_customersLog['update_count'] > 0) {
|
| 535 |
$logger->log("Successfully updated {$this->_customersLog['update_success_count']}/{$this->_customersLog['update_count']} customers");
|
| 536 |
if (!empty($this->_customersLog['update_errors'])) {
|
| 537 |
$logger->log("Update errors: " . var_export($this->_customersLog['update_errors'], true));
|
| 538 |
}
|
| 539 |
}
|
| 540 |
|
| 541 |
+
if (isset($this->_customersLog['remove_count']) && $this->_customersLog['remove_count'] > 0) {
|
| 542 |
$logger->log("Successfully removed {$this->_customersLog['remove_success_count']}/{$this->_customersLog['remove_count']} customers");
|
| 543 |
$logger->log("Removed with error {$this->_customersLog['remove_error_count']}/{$this->_customersLog['remove_count']} customers");
|
| 544 |
if (!empty($this->_customersLog['remove_errors'])) {
|
app/code/community/Mailigen/Synchronizer/Model/Newsletter.php
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Mailigen_Synchronizer
|
| 5 |
+
*
|
| 6 |
+
* @category Mailigen
|
| 7 |
+
* @package Mailigen_Synchronizer
|
| 8 |
+
* @author Maksim Soldatjonok <maksold@gmail.com>
|
| 9 |
+
*/
|
| 10 |
+
class Mailigen_Synchronizer_Model_Newsletter extends Mage_Newsletter_Model_Subscriber
|
| 11 |
+
{
|
| 12 |
+
/**
|
| 13 |
+
* @param $subscriberIds
|
| 14 |
+
* @return int
|
| 15 |
+
*/
|
| 16 |
+
public function updateSyncedNewsletter($subscriberIds)
|
| 17 |
+
{
|
| 18 |
+
$tableName = $this->getResource()->getTable('subscriber');
|
| 19 |
+
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
|
| 20 |
+
$updated = $write->update(
|
| 21 |
+
$tableName,
|
| 22 |
+
array('mailigen_synced' => 1),
|
| 23 |
+
array('subscriber_id IN (?)' => $subscriberIds)
|
| 24 |
+
);
|
| 25 |
+
|
| 26 |
+
if ($updated < count($subscriberIds)) {
|
| 27 |
+
Mage::throwException("Updated $updated subscribers of " . count($subscriberIds));
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
return $updated;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
/**
|
| 34 |
+
* @param $subscriberId
|
| 35 |
+
* @param bool $synced
|
| 36 |
+
* @return int
|
| 37 |
+
*/
|
| 38 |
+
public function updateIsSynced($subscriberId, $synced = true)
|
| 39 |
+
{
|
| 40 |
+
$tableName = $this->getResource()->getTable('subscriber');
|
| 41 |
+
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
|
| 42 |
+
|
| 43 |
+
$updated = $write->update($tableName,
|
| 44 |
+
array('mailigen_synced' => $synced ? 1 : 0),
|
| 45 |
+
array('subscriber_id = ?' => $subscriberId)
|
| 46 |
+
);
|
| 47 |
+
|
| 48 |
+
return $updated;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
/**
|
| 52 |
+
* @return int
|
| 53 |
+
*/
|
| 54 |
+
public function setNewsletterNotSynced()
|
| 55 |
+
{
|
| 56 |
+
$tableName = $this->getResource()->getTable('subscriber');
|
| 57 |
+
$write = Mage::getSingleton('core/resource')->getConnection('core_write');
|
| 58 |
+
|
| 59 |
+
$updated = $write->update($tableName,
|
| 60 |
+
array('mailigen_synced' => 0),
|
| 61 |
+
array('subscriber_status = ?' => Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED) // @todo Remove if unsubscribers will be synced too
|
| 62 |
+
);
|
| 63 |
+
|
| 64 |
+
return $updated;
|
| 65 |
+
}
|
| 66 |
+
}
|
app/code/community/Mailigen/Synchronizer/Model/Newsletter/Merge/Field.php
CHANGED
|
@@ -16,15 +16,25 @@ class Mailigen_Synchronizer_Model_Newsletter_Merge_Field extends Mage_Core_Model
|
|
| 16 |
protected function _getMergeFieldsConfig()
|
| 17 |
{
|
| 18 |
return array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
'STOREID' => array(
|
| 20 |
'title' => 'Store id',
|
| 21 |
'field_type' => 'text',
|
| 22 |
-
'req' =>
|
| 23 |
),
|
| 24 |
'STORELANGUAGE' => array(
|
| 25 |
'title' => 'Store language',
|
| 26 |
'field_type' => 'text',
|
| 27 |
-
'req' =>
|
| 28 |
)
|
| 29 |
);
|
| 30 |
}
|
| 16 |
protected function _getMergeFieldsConfig()
|
| 17 |
{
|
| 18 |
return array(
|
| 19 |
+
'WEBSITEID' => array(
|
| 20 |
+
'title' => 'Website id',
|
| 21 |
+
'field_type' => 'text',
|
| 22 |
+
'req' => false
|
| 23 |
+
),
|
| 24 |
+
'TYPE' => array(
|
| 25 |
+
'title' => 'Type',
|
| 26 |
+
'field_type' => 'text',
|
| 27 |
+
'req' => false
|
| 28 |
+
),
|
| 29 |
'STOREID' => array(
|
| 30 |
'title' => 'Store id',
|
| 31 |
'field_type' => 'text',
|
| 32 |
+
'req' => false
|
| 33 |
),
|
| 34 |
'STORELANGUAGE' => array(
|
| 35 |
'title' => 'Store language',
|
| 36 |
'field_type' => 'text',
|
| 37 |
+
'req' => false
|
| 38 |
)
|
| 39 |
);
|
| 40 |
}
|
app/code/community/Mailigen/Synchronizer/Model/Observer.php
CHANGED
|
@@ -15,66 +15,128 @@ class Mailigen_Synchronizer_Model_Observer
|
|
| 15 |
*/
|
| 16 |
public function newsletterSubscriberSaveCommitAfter(Varien_Event_Observer $observer)
|
| 17 |
{
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 23 |
$logger = Mage::helper('mailigen_synchronizer/log');
|
|
|
|
| 24 |
|
| 25 |
-
if ($
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
$api =
|
| 29 |
-
$
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
$email_type = 'html';
|
| 34 |
-
$double_optin = false;
|
| 35 |
-
$update_existing = true;
|
| 36 |
-
$delete_member = false;
|
| 37 |
-
$send_notify = true;
|
| 38 |
-
|
| 39 |
-
//If mailigen transational emails are set from admin.
|
| 40 |
-
$send_flag = Mage::helper('mailigen_synchronizer')->canNewsletterHandleDefaultEmails();
|
| 41 |
-
|
| 42 |
-
if ($send_flag) {
|
| 43 |
-
$send_welcome = true;
|
| 44 |
-
$send_goodbye = true;
|
| 45 |
-
} else {
|
| 46 |
-
$send_welcome = false;
|
| 47 |
-
$send_goodbye = false;
|
| 48 |
}
|
|
|
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
|
|
|
| 54 |
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
| 59 |
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
|
| 63 |
-
|
| 64 |
-
$logger->log('
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
} else {
|
| 67 |
-
|
| 68 |
-
$retval =
|
| 69 |
}
|
| 70 |
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
-
|
| 73 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
}
|
| 75 |
}
|
|
|
|
| 76 |
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
}
|
| 79 |
|
| 80 |
/**
|
|
@@ -223,6 +285,56 @@ class Mailigen_Synchronizer_Model_Observer
|
|
| 223 |
$customer = $observer->getDataObject();
|
| 224 |
if ($customer && $customer->getId()) {
|
| 225 |
Mage::getModel('mailigen_synchronizer/customer')->setCustomerNotSynced($customer->getId());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
}
|
| 227 |
}
|
| 228 |
/**
|
| 15 |
*/
|
| 16 |
public function newsletterSubscriberSaveCommitAfter(Varien_Event_Observer $observer)
|
| 17 |
{
|
| 18 |
+
/**
|
| 19 |
+
* Check if it was webhook save
|
| 20 |
+
*/
|
| 21 |
+
if (Mage::registry('mailigen_webhook')) {
|
| 22 |
+
return;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 26 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 27 |
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 28 |
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 29 |
+
$subscriber = $observer->getDataObject();
|
| 30 |
|
| 31 |
+
if ($helper->isEnabled() && $subscriber
|
| 32 |
+
&& ($subscriber->getIsStatusChanged() == true || $subscriber->getOrigData('subscriber_status') != $subscriber->getData('subscriber_status'))
|
| 33 |
+
) {
|
| 34 |
+
$api = $helper->getMailigenApi();
|
| 35 |
+
$newsletterListId = $helper->getNewsletterContactList();
|
| 36 |
+
if (!$newsletterListId) {
|
| 37 |
+
$logger->log('Newsletter contact list isn\'t selected');
|
| 38 |
+
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
}
|
| 40 |
+
$email_address = $subscriber->getSubscriberEmail();
|
| 41 |
|
| 42 |
+
/**
|
| 43 |
+
* Create or update Merge fields
|
| 44 |
+
*/
|
| 45 |
+
Mage::getModel('mailigen_synchronizer/newsletter_merge_field')->createMergeFields();
|
| 46 |
+
$logger->log('Newsletter merge fields created and updated');
|
| 47 |
|
| 48 |
+
if ($subscriber->getSubscriberStatus() === Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED) {
|
| 49 |
+
/**
|
| 50 |
+
* Subscribe newsletter
|
| 51 |
+
*/
|
| 52 |
+
/** @var $customerHelper Mailigen_Synchronizer_Helper_Customer */
|
| 53 |
+
$customerHelper = Mage::helper('mailigen_synchronizer/customer');
|
| 54 |
|
| 55 |
+
// Prepare Merge vars
|
| 56 |
+
$website = $customerHelper->getWebsite($subscriber->getStoreId());
|
| 57 |
+
$merge_vars = array(
|
| 58 |
+
'EMAIL' => $subscriber->getSubscriberEmail(),
|
| 59 |
+
'WEBSITEID' => $website ? $website->getId() : 0,
|
| 60 |
+
'TYPE' => $customerHelper->getSubscriberType(1),
|
| 61 |
+
'STOREID' => $subscriber->getStoreId(),
|
| 62 |
+
'STORELANGUAGE' => $customerHelper->getStoreLanguage($subscriber->getStoreId()),
|
| 63 |
+
);
|
| 64 |
+
|
| 65 |
+
// If is a customer we also grab firstname and lastname
|
| 66 |
+
if ($subscriber->getCustomerId()) {
|
| 67 |
+
$customer = Mage::getModel('customer/customer')->load($subscriber->getCustomerId());
|
| 68 |
+
$merge_vars['FNAME'] = $customer->getFirstname();
|
| 69 |
+
$merge_vars['LNAME'] = $customer->getLastname();
|
| 70 |
+
$merge_vars['TYPE'] = $customerHelper->getSubscriberType(2);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
$send_welcome = $helper->canNewsletterHandleDefaultEmails();
|
| 74 |
|
| 75 |
+
$retval = $api->listSubscribe($newsletterListId, $email_address, $merge_vars, 'html', false, true, $send_welcome);
|
| 76 |
+
$logger->log('Subscribed newsletter with email: ' . $email_address);
|
| 77 |
+
}
|
| 78 |
+
elseif ($subscriber->getSubscriberStatus() === Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED) {
|
| 79 |
+
/**
|
| 80 |
+
* Unsubscribe newsletter
|
| 81 |
+
*/
|
| 82 |
+
$send_goodbye = $helper->canNewsletterHandleDefaultEmails();
|
| 83 |
+
$retval = $api->listUnsubscribe($newsletterListId, $email_address, false, $send_goodbye, true);
|
| 84 |
+
$logger->log('Unsubscribed newsletter with email: ' . $email_address);
|
| 85 |
} else {
|
| 86 |
+
// @todo Check Not Activated or Removed status?
|
| 87 |
+
$retval = null;
|
| 88 |
}
|
| 89 |
|
| 90 |
+
if ($retval) {
|
| 91 |
+
// Set subscriber synced
|
| 92 |
+
Mage::getModel('mailigen_synchronizer/newsletter')->updateIsSynced($subscriber->getId(), true);
|
| 93 |
|
| 94 |
+
// Set customer not synced
|
| 95 |
+
if ($subscriber->getCustomerId()) {
|
| 96 |
+
Mage::getModel('mailigen_synchronizer/customer')->setCustomerNotSynced($subscriber->getCustomerId());
|
| 97 |
+
}
|
| 98 |
+
} elseif (!is_null($retval)) {
|
| 99 |
+
$logger->log("Unable to (un)subscribe newsletter with email: $email_address. $api->errorCode: $api->errorMessage");
|
| 100 |
}
|
| 101 |
}
|
| 102 |
+
}
|
| 103 |
|
| 104 |
+
/**
|
| 105 |
+
* @param Varien_Event_Observer $observer
|
| 106 |
+
*/
|
| 107 |
+
public function newsletterSubscriberDeleteAfter(Varien_Event_Observer $observer)
|
| 108 |
+
{
|
| 109 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 110 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 111 |
+
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 112 |
+
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 113 |
+
$subscriber = $observer->getDataObject();
|
| 114 |
+
|
| 115 |
+
if ($helper->isEnabled() && $subscriber) {
|
| 116 |
+
$api = $helper->getMailigenApi();
|
| 117 |
+
$newsletterListId = $helper->getNewsletterContactList();
|
| 118 |
+
if (!$newsletterListId) {
|
| 119 |
+
$logger->log('Newsletter contact list isn\'t selected');
|
| 120 |
+
return;
|
| 121 |
+
}
|
| 122 |
+
$email_address = $subscriber->getSubscriberEmail();
|
| 123 |
+
|
| 124 |
+
/**
|
| 125 |
+
* Remove subscriber
|
| 126 |
+
*/
|
| 127 |
+
$send_goodbye = $helper->canNewsletterHandleDefaultEmails();
|
| 128 |
+
$retval = $api->listUnsubscribe($newsletterListId, $email_address, true, $send_goodbye, true);
|
| 129 |
+
$logger->log('Remove subscriber with email: ' . $email_address);
|
| 130 |
+
|
| 131 |
+
if ($retval) {
|
| 132 |
+
// Set customer not synced
|
| 133 |
+
if ($subscriber->getCustomerId()) {
|
| 134 |
+
Mage::getModel('mailigen_synchronizer/customer')->setCustomerNotSynced($subscriber->getCustomerId());
|
| 135 |
+
}
|
| 136 |
+
} elseif (!is_null($retval)) {
|
| 137 |
+
$logger->log("Unable to remove subscriber with email: $email_address. $api->errorCode: $api->errorMessage");
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
}
|
| 141 |
|
| 142 |
/**
|
| 285 |
$customer = $observer->getDataObject();
|
| 286 |
if ($customer && $customer->getId()) {
|
| 287 |
Mage::getModel('mailigen_synchronizer/customer')->setCustomerNotSynced($customer->getId());
|
| 288 |
+
|
| 289 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 290 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 291 |
+
$newsletterListId = $helper->getNewsletterContactList();
|
| 292 |
+
|
| 293 |
+
/**
|
| 294 |
+
* Check if Customer Firstname, Lastname or Email was changed
|
| 295 |
+
*/
|
| 296 |
+
if ($customer->getIsSubscribed() && $customer->hasDataChanges() && $helper->isEnabled() && !empty($newsletterListId)) {
|
| 297 |
+
$origCustomerData = $customer->getOrigData();
|
| 298 |
+
|
| 299 |
+
$nameChanged = ((isset($origCustomerData['firstname']) && $origCustomerData['firstname'] != $customer->getFirstname())
|
| 300 |
+
|| (isset($origCustomerData['lastname']) && $origCustomerData['lastname'] != $customer->getLastname()));
|
| 301 |
+
$emailChanged = (isset($origCustomerData['email']) && !empty($origCustomerData['email']) && $origCustomerData['email'] != $customer->getEmail());
|
| 302 |
+
|
| 303 |
+
/**
|
| 304 |
+
* Set subscriber not synced, if customer Firstname, Lastname changed
|
| 305 |
+
*/
|
| 306 |
+
if ($nameChanged && !$emailChanged) {
|
| 307 |
+
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($customer->getEmail());
|
| 308 |
+
if ($subscriber->getId()) {
|
| 309 |
+
Mage::getModel('mailigen_synchronizer/newsletter')->updateIsSynced($subscriber->getId(), false);
|
| 310 |
+
}
|
| 311 |
+
}
|
| 312 |
+
|
| 313 |
+
/**
|
| 314 |
+
* Unsubscribe with old email
|
| 315 |
+
*/
|
| 316 |
+
if ($emailChanged) {
|
| 317 |
+
$oldEmail = $origCustomerData['email'];
|
| 318 |
+
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($oldEmail);
|
| 319 |
+
|
| 320 |
+
if ($subscriber->getId()) {
|
| 321 |
+
/** @var $logger Mailigen_Synchronizer_Helper_Log */
|
| 322 |
+
$logger = Mage::helper('mailigen_synchronizer/log');
|
| 323 |
+
$api = $helper->getMailigenApi();
|
| 324 |
+
|
| 325 |
+
/**
|
| 326 |
+
* Remove subscriber
|
| 327 |
+
*/
|
| 328 |
+
$send_goodbye = $helper->canNewsletterHandleDefaultEmails();
|
| 329 |
+
$retval = $api->listUnsubscribe($newsletterListId, $oldEmail, true, $send_goodbye, true);
|
| 330 |
+
$logger->log('Remove subscriber with email: ' . $oldEmail);
|
| 331 |
+
|
| 332 |
+
if (!$retval) {
|
| 333 |
+
$logger->log("Unable to remove subscriber with email: $oldEmail. $api->errorCode: $api->errorMessage");
|
| 334 |
+
}
|
| 335 |
+
}
|
| 336 |
+
}
|
| 337 |
+
}
|
| 338 |
}
|
| 339 |
}
|
| 340 |
/**
|
app/code/community/Mailigen/Synchronizer/Model/Resource/Subscriber/Collection.php
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Mailigen_Synchronizer
|
| 5 |
+
*
|
| 6 |
+
* @category Mailigen
|
| 7 |
+
* @package Mailigen_Synchronizer
|
| 8 |
+
* @author Maksim Soldatjonok <maksold@gmail.com>
|
| 9 |
+
*/
|
| 10 |
+
class Mailigen_Synchronizer_Model_Resource_Subscriber_Collection extends Mage_Newsletter_Model_Resource_Subscriber_Collection
|
| 11 |
+
{
|
| 12 |
+
|
| 13 |
+
public function getSubscribers($status = null, $synced = 0)
|
| 14 |
+
{
|
| 15 |
+
$collection = $this->showCustomerInfo(true)
|
| 16 |
+
->addSubscriberTypeField()
|
| 17 |
+
->showStoreInfo()
|
| 18 |
+
->addFieldToFilter('mailigen_synced', $synced);
|
| 19 |
+
|
| 20 |
+
if (!is_null($status)) {
|
| 21 |
+
$collection->addFieldToFilter('subscriber_status', $status);
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
return $collection;
|
| 25 |
+
}
|
| 26 |
+
}
|
app/code/community/Mailigen/Synchronizer/Model/Schedule.php
CHANGED
|
@@ -19,6 +19,16 @@ class Mailigen_Synchronizer_Model_Schedule extends Mage_Core_Model_Abstract
|
|
| 19 |
*/
|
| 20 |
protected $_countPendingOrRunningJobs = null;
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
/**
|
| 23 |
* @return int|null
|
| 24 |
*/
|
|
@@ -44,14 +54,18 @@ class Mailigen_Synchronizer_Model_Schedule extends Mage_Core_Model_Abstract
|
|
| 44 |
*/
|
| 45 |
public function getLastRunningJob()
|
| 46 |
{
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
-
return $
|
| 55 |
}
|
| 56 |
|
| 57 |
/**
|
|
@@ -59,14 +73,18 @@ class Mailigen_Synchronizer_Model_Schedule extends Mage_Core_Model_Abstract
|
|
| 59 |
*/
|
| 60 |
public function getLastPendingJob()
|
| 61 |
{
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
-
return $
|
| 70 |
}
|
| 71 |
|
| 72 |
/**
|
| 19 |
*/
|
| 20 |
protected $_countPendingOrRunningJobs = null;
|
| 21 |
|
| 22 |
+
/**
|
| 23 |
+
* @var null
|
| 24 |
+
*/
|
| 25 |
+
protected $_lastRunningJob = null;
|
| 26 |
+
|
| 27 |
+
/**
|
| 28 |
+
* @var null
|
| 29 |
+
*/
|
| 30 |
+
protected $_lastPendingJob = null;
|
| 31 |
+
|
| 32 |
/**
|
| 33 |
* @return int|null
|
| 34 |
*/
|
| 54 |
*/
|
| 55 |
public function getLastRunningJob()
|
| 56 |
{
|
| 57 |
+
if (is_null($this->_lastRunningJob)) {
|
| 58 |
+
/** @var $runningJobs Mage_Cron_Model_Resource_Schedule_Collection */
|
| 59 |
+
$runningJobs = Mage::getModel('cron/schedule')->getCollection()
|
| 60 |
+
->addFieldToFilter('job_code', $this->_jobCode)
|
| 61 |
+
->addFieldToFilter('status', Mage_Cron_Model_Schedule::STATUS_RUNNING)
|
| 62 |
+
->setOrder('executed_at')
|
| 63 |
+
->setPageSize(1)->setCurPage(1);
|
| 64 |
+
|
| 65 |
+
$this->_lastRunningJob = $runningJobs->getSize() ? $runningJobs->getFirstItem() : false;
|
| 66 |
+
}
|
| 67 |
|
| 68 |
+
return $this->_lastRunningJob;
|
| 69 |
}
|
| 70 |
|
| 71 |
/**
|
| 73 |
*/
|
| 74 |
public function getLastPendingJob()
|
| 75 |
{
|
| 76 |
+
if (is_null($this->_lastPendingJob)) {
|
| 77 |
+
/** @var $pendingJobs Mage_Cron_Model_Resource_Schedule_Collection */
|
| 78 |
+
$pendingJobs = Mage::getModel('cron/schedule')->getCollection()
|
| 79 |
+
->addFieldToFilter('job_code', $this->_jobCode)
|
| 80 |
+
->addFieldToFilter('status', Mage_Cron_Model_Schedule::STATUS_PENDING)
|
| 81 |
+
->setOrder('executed_at')
|
| 82 |
+
->setPageSize(1)->setCurPage(1);;
|
| 83 |
+
|
| 84 |
+
$this->_lastPendingJob = $pendingJobs->getSize() ? $pendingJobs->getFirstItem() : false;
|
| 85 |
+
}
|
| 86 |
|
| 87 |
+
return $this->_lastPendingJob;
|
| 88 |
}
|
| 89 |
|
| 90 |
/**
|
app/code/community/Mailigen/Synchronizer/controllers/Adminhtml/MailigenController.php
CHANGED
|
@@ -1,12 +1,32 @@
|
|
| 1 |
<?php
|
| 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
class Mailigen_Synchronizer_Adminhtml_MailigenController extends Mage_Adminhtml_Controller_Action
|
| 4 |
{
|
| 5 |
public function syncNewsletterAction()
|
| 6 |
{
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
$this->_redirect('*/newsletter_subscriber/index');
|
| 12 |
}
|
|
@@ -36,13 +56,13 @@ class Mailigen_Synchronizer_Adminhtml_MailigenController extends Mage_Adminhtml_
|
|
| 36 |
/**
|
| 37 |
* Force stop customer sync
|
| 38 |
*/
|
| 39 |
-
public function
|
| 40 |
{
|
| 41 |
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 42 |
$helper = Mage::helper('mailigen_synchronizer');
|
| 43 |
$helper->setStopSync(1);
|
| 44 |
|
| 45 |
-
$this->getResponse()->setBody($this->__('
|
| 46 |
}
|
| 47 |
|
| 48 |
/**
|
|
@@ -56,4 +76,16 @@ class Mailigen_Synchronizer_Adminhtml_MailigenController extends Mage_Adminhtml_
|
|
| 56 |
|
| 57 |
$this->getResponse()->setBody('1');
|
| 58 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
}
|
| 1 |
<?php
|
| 2 |
|
| 3 |
+
/**
|
| 4 |
+
* Mailigen_Synchronizer
|
| 5 |
+
*
|
| 6 |
+
* @category Mailigen
|
| 7 |
+
* @package Mailigen_Synchronizer
|
| 8 |
+
* @author Maksim Soldatjonok <maksold@gmail.com>
|
| 9 |
+
*/
|
| 10 |
class Mailigen_Synchronizer_Adminhtml_MailigenController extends Mage_Adminhtml_Controller_Action
|
| 11 |
{
|
| 12 |
public function syncNewsletterAction()
|
| 13 |
{
|
| 14 |
+
try {
|
| 15 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 16 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 17 |
+
/** @var $mailigenSchedule Mailigen_Synchronizer_Model_Schedule */
|
| 18 |
+
$mailigenSchedule = Mage::getModel('mailigen_synchronizer/schedule');
|
| 19 |
+
|
| 20 |
+
if ($mailigenSchedule->countPendingOrRunningJobs() == 0) {
|
| 21 |
+
$mailigenSchedule->createJob();
|
| 22 |
+
$helper->setManualSync(1);
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
$this->_getSession()->addSuccess($this->__('Mailigen newsletter synchronization task will start shortly.'));
|
| 26 |
+
} catch (Exception $e) {
|
| 27 |
+
$this->_getSession()->addError($e->getMessage());
|
| 28 |
+
Mage::helper('mailigen_synchronizer/log')->logException($e);
|
| 29 |
+
}
|
| 30 |
|
| 31 |
$this->_redirect('*/newsletter_subscriber/index');
|
| 32 |
}
|
| 56 |
/**
|
| 57 |
* Force stop customer sync
|
| 58 |
*/
|
| 59 |
+
public function stopSyncAction()
|
| 60 |
{
|
| 61 |
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 62 |
$helper = Mage::helper('mailigen_synchronizer');
|
| 63 |
$helper->setStopSync(1);
|
| 64 |
|
| 65 |
+
$this->getResponse()->setBody($this->__('Sync will be stopped within a minute'));
|
| 66 |
}
|
| 67 |
|
| 68 |
/**
|
| 76 |
|
| 77 |
$this->getResponse()->setBody('1');
|
| 78 |
}
|
| 79 |
+
|
| 80 |
+
/**
|
| 81 |
+
* Force set newsletter not synced, to allow sync again
|
| 82 |
+
*/
|
| 83 |
+
public function resetSyncNewsletterAction()
|
| 84 |
+
{
|
| 85 |
+
/** @var $customer Mailigen_Synchronizer_Model_Newsletter */
|
| 86 |
+
$newsletter = Mage::getModel('mailigen_synchronizer/newsletter');
|
| 87 |
+
$newsletter->setNewsletterNotSynced();
|
| 88 |
+
|
| 89 |
+
$this->getResponse()->setBody('1');
|
| 90 |
+
}
|
| 91 |
}
|
app/code/community/Mailigen/Synchronizer/controllers/WebhookController.php
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
|
| 3 |
+
/**
|
| 4 |
+
* Mailigen_Synchronizer
|
| 5 |
+
*
|
| 6 |
+
* @category Mailigen
|
| 7 |
+
* @package Mailigen_Synchronizer
|
| 8 |
+
* @author Maksim Soldatjonok <maksold@gmail.com>
|
| 9 |
+
*/
|
| 10 |
+
class Mailigen_Synchronizer_WebhookController extends Mage_Core_Controller_Front_Action
|
| 11 |
+
{
|
| 12 |
+
/**
|
| 13 |
+
* @var null|Mailigen_Synchronizer_Helper_Log
|
| 14 |
+
*/
|
| 15 |
+
public $logger = null;
|
| 16 |
+
|
| 17 |
+
/**
|
| 18 |
+
* Mailigen Webhooks handler action
|
| 19 |
+
*
|
| 20 |
+
* @return Mage_Core_Controller_Varien_Action|string
|
| 21 |
+
*/
|
| 22 |
+
public function indexAction()
|
| 23 |
+
{
|
| 24 |
+
$this->logger = Mage::helper('mailigen_synchronizer/log');
|
| 25 |
+
$this->logger->logWebhook('============================');
|
| 26 |
+
|
| 27 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 28 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 29 |
+
if (!$helper->enabledWebhooks()) {
|
| 30 |
+
$this->logger->logWebhook('Webhooks are disabled.');
|
| 31 |
+
return '';
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
if (!$this->getRequest()->isPost()) {
|
| 35 |
+
$this->logger->logWebhook("It's not POST request.");
|
| 36 |
+
return '';
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
$this->logger->logWebhook("Webhook called with data: " . $this->getRequest()->getRawBody());
|
| 40 |
+
|
| 41 |
+
try {
|
| 42 |
+
$json = $this->getRequest()->getRawBody();
|
| 43 |
+
$json = json_decode($json);
|
| 44 |
+
|
| 45 |
+
if (!isset($json->hook) || !isset($json->data)) {
|
| 46 |
+
$this->logger->logWebhook('No hook or data in JSON.');
|
| 47 |
+
return '';
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
switch ($json->hook) {
|
| 51 |
+
case 'contact.subscribe':
|
| 52 |
+
/**
|
| 53 |
+
* Subscribe contact
|
| 54 |
+
*/
|
| 55 |
+
$this->logger->logWebhook('Called: _subscribeContact()');
|
| 56 |
+
$this->_subscribeContact($json->data);
|
| 57 |
+
break;
|
| 58 |
+
case 'contact.unsubscribe':
|
| 59 |
+
/**
|
| 60 |
+
* Unsubscribe contact
|
| 61 |
+
*/
|
| 62 |
+
$this->logger->logWebhook('Called: _unsubscribeContact()');
|
| 63 |
+
$this->_unsubscribeContact($json->data);
|
| 64 |
+
break;
|
| 65 |
+
default:
|
| 66 |
+
$this->logger->logWebhook('Incorrect JSON');
|
| 67 |
+
}
|
| 68 |
+
} catch (Exception $e) {
|
| 69 |
+
$this->_returnError('Exception: ' . $e->getMessage());
|
| 70 |
+
}
|
| 71 |
+
return '';
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
/**
|
| 75 |
+
* @todo Check Website Id by List Id
|
| 76 |
+
* @param $listId
|
| 77 |
+
* @return bool
|
| 78 |
+
*/
|
| 79 |
+
protected function _checkListId($listId)
|
| 80 |
+
{
|
| 81 |
+
/** @var $helper Mailigen_Synchronizer_Helper_Data */
|
| 82 |
+
$helper = Mage::helper('mailigen_synchronizer');
|
| 83 |
+
$check = $helper->getNewsletterContactList() == $listId;
|
| 84 |
+
|
| 85 |
+
if (!$check) {
|
| 86 |
+
$this->logger->logWebhook("Newsletter doesn't exist with List Id: $listId");
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
return $check;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
/**
|
| 93 |
+
* Subscribe webhook
|
| 94 |
+
* @todo Subscribe to necessary Website Id
|
| 95 |
+
* @param $data
|
| 96 |
+
*/
|
| 97 |
+
protected function _subscribeContact($data)
|
| 98 |
+
{
|
| 99 |
+
if (count($data) <= 0) {
|
| 100 |
+
return;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
foreach ($data as $item) {
|
| 104 |
+
if (!$this->_checkListId($item->list)) {
|
| 105 |
+
continue;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
$email = $item->email;
|
| 109 |
+
|
| 110 |
+
/**
|
| 111 |
+
* @todo Save First, Last name
|
| 112 |
+
*/
|
| 113 |
+
$firstname = $item->fields->FNAME;
|
| 114 |
+
$lastname = $item->fields->LNAME;
|
| 115 |
+
|
| 116 |
+
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
|
| 117 |
+
if ($subscriber && $subscriber->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED) {
|
| 118 |
+
$this->logger->logWebhook("Contact is already subscribed with email: $email");
|
| 119 |
+
} else {
|
| 120 |
+
/**
|
| 121 |
+
* Subscribe contact
|
| 122 |
+
*/
|
| 123 |
+
Mage::register('mailigen_webhook', true);
|
| 124 |
+
$subscriberStatus = Mage::getModel('newsletter/subscriber')->subscribe($email);
|
| 125 |
+
|
| 126 |
+
if ($subscriberStatus == Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED) {
|
| 127 |
+
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
|
| 128 |
+
if ($subscriber->getId()) {
|
| 129 |
+
Mage::getModel('mailigen_synchronizer/newsletter')->updateIsSynced($subscriber->getId());
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
$this->logger->logWebhook("Subscribed contact with email: $email");
|
| 133 |
+
} else {
|
| 134 |
+
$this->_returnError("Can't subscribe contact with email: $email");
|
| 135 |
+
}
|
| 136 |
+
Mage::unregister('mailigen_webhook');
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/**
|
| 142 |
+
* Unsubscribe webhook
|
| 143 |
+
* @todo Unsubscribe from necessary Website Id
|
| 144 |
+
* @param $data
|
| 145 |
+
*/
|
| 146 |
+
protected function _unsubscribeContact($data)
|
| 147 |
+
{
|
| 148 |
+
if (count($data) <= 0) {
|
| 149 |
+
return;
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
foreach ($data as $item) {
|
| 153 |
+
if (!$this->_checkListId($item->list)) {
|
| 154 |
+
continue;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
$email = $item->email;
|
| 158 |
+
|
| 159 |
+
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
|
| 160 |
+
|
| 161 |
+
if ($subscriber->getId()) {
|
| 162 |
+
/**
|
| 163 |
+
* Unsubscribe contact
|
| 164 |
+
*/
|
| 165 |
+
Mage::register('mailigen_webhook', true);
|
| 166 |
+
$subscriber->unsubscribe();
|
| 167 |
+
|
| 168 |
+
if ($subscriber->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED) {
|
| 169 |
+
if ($subscriber->getId()) {
|
| 170 |
+
Mage::getModel('mailigen_synchronizer/newsletter')->updateIsSynced($subscriber->getId());
|
| 171 |
+
}
|
| 172 |
+
$this->logger->logWebhook("Unsubscribed contact with email: $email");
|
| 173 |
+
} else {
|
| 174 |
+
$this->_returnError("Can't unsubscribe contact with email: $email");
|
| 175 |
+
}
|
| 176 |
+
Mage::unregister('mailigen_webhook');
|
| 177 |
+
} else {
|
| 178 |
+
$this->logger->logWebhook("Subscriber doesn't exist with email: $email");
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
/**
|
| 184 |
+
* @param $message
|
| 185 |
+
*/
|
| 186 |
+
protected function _returnError($message)
|
| 187 |
+
{
|
| 188 |
+
$this->logger->logWebhook($message);
|
| 189 |
+
$this->getResponse()->setHttpResponseCode(500);
|
| 190 |
+
$this->getResponse()->sendResponse();
|
| 191 |
+
exit;
|
| 192 |
+
}
|
| 193 |
+
}
|
app/code/community/Mailigen/Synchronizer/etc/config.xml
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
<config>
|
| 3 |
<modules>
|
| 4 |
<Mailigen_Synchronizer>
|
| 5 |
-
<version>1.
|
| 6 |
</Mailigen_Synchronizer>
|
| 7 |
</modules>
|
| 8 |
<global>
|
|
@@ -71,6 +71,15 @@
|
|
| 71 |
</newsletter_subscriber_newsletter_subscriber_create_after>
|
| 72 |
</observers>
|
| 73 |
</newsletter_subscriber_save_commit_after>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
<admin_system_config_changed_section_mailigen_synchronizer>
|
| 75 |
<observers>
|
| 76 |
<newsletter_subscriber_admin_system_config_changed_section_mailigen_synchronizer>
|
|
@@ -190,5 +199,16 @@
|
|
| 190 |
</mailigen_synchronizer>
|
| 191 |
</jobs>
|
| 192 |
</crontab>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
</config>
|
| 194 |
|
| 2 |
<config>
|
| 3 |
<modules>
|
| 4 |
<Mailigen_Synchronizer>
|
| 5 |
+
<version>1.2.0</version>
|
| 6 |
</Mailigen_Synchronizer>
|
| 7 |
</modules>
|
| 8 |
<global>
|
| 71 |
</newsletter_subscriber_newsletter_subscriber_create_after>
|
| 72 |
</observers>
|
| 73 |
</newsletter_subscriber_save_commit_after>
|
| 74 |
+
<newsletter_subscriber_delete_after>
|
| 75 |
+
<observers>
|
| 76 |
+
<mailigen_synchronizer_newsletter_subscriber_delete_after>
|
| 77 |
+
<type>singleton</type>
|
| 78 |
+
<class>Mailigen_Synchronizer_Model_Observer</class>
|
| 79 |
+
<method>newsletterSubscriberDeleteAfter</method>
|
| 80 |
+
</mailigen_synchronizer_newsletter_subscriber_delete_after>
|
| 81 |
+
</observers>
|
| 82 |
+
</newsletter_subscriber_delete_after>
|
| 83 |
<admin_system_config_changed_section_mailigen_synchronizer>
|
| 84 |
<observers>
|
| 85 |
<newsletter_subscriber_admin_system_config_changed_section_mailigen_synchronizer>
|
| 199 |
</mailigen_synchronizer>
|
| 200 |
</jobs>
|
| 201 |
</crontab>
|
| 202 |
+
<frontend>
|
| 203 |
+
<routers>
|
| 204 |
+
<mailigen>
|
| 205 |
+
<use>standard</use>
|
| 206 |
+
<args>
|
| 207 |
+
<frontName>mailigen</frontName>
|
| 208 |
+
<module>Mailigen_Synchronizer</module>
|
| 209 |
+
</args>
|
| 210 |
+
</mailigen>
|
| 211 |
+
</routers>
|
| 212 |
+
</frontend>
|
| 213 |
</config>
|
| 214 |
|
app/code/community/Mailigen/Synchronizer/etc/system.xml
CHANGED
|
@@ -24,7 +24,7 @@
|
|
| 24 |
<sort_order>10</sort_order>
|
| 25 |
<show_in_default>1</show_in_default>
|
| 26 |
<show_in_website>1</show_in_website>
|
| 27 |
-
<show_in_store>
|
| 28 |
</enabled>
|
| 29 |
<api_key translate="label">
|
| 30 |
<label>Api Key:</label>
|
|
@@ -33,7 +33,7 @@
|
|
| 33 |
<sort_order>20</sort_order>
|
| 34 |
<show_in_default>1</show_in_default>
|
| 35 |
<show_in_website>1</show_in_website>
|
| 36 |
-
<show_in_store>
|
| 37 |
</api_key>
|
| 38 |
<cron_string translate="label">
|
| 39 |
<label>Sync schedule (cron syntax)</label>
|
|
@@ -62,7 +62,7 @@
|
|
| 62 |
<sort_order>10</sort_order>
|
| 63 |
<show_in_default>1</show_in_default>
|
| 64 |
<show_in_website>1</show_in_website>
|
| 65 |
-
<show_in_store>
|
| 66 |
<comment>By selecting a new list option you'll be able to create a new Mailigen list directly from this panel. Attention! Please do not confuse Newsletter and Customer lists!</comment>
|
| 67 |
</contact_list>
|
| 68 |
<new_list_title translate="label">
|
|
@@ -71,7 +71,7 @@
|
|
| 71 |
<sort_order>20</sort_order>
|
| 72 |
<show_in_default>1</show_in_default>
|
| 73 |
<show_in_website>1</show_in_website>
|
| 74 |
-
<show_in_store>
|
| 75 |
<comment>Type the title of your new list. During the save, the list will be created and it will become the current contact list.</comment>
|
| 76 |
<depends>
|
| 77 |
<contact_list></contact_list>
|
|
@@ -84,7 +84,7 @@
|
|
| 84 |
<sort_order>30</sort_order>
|
| 85 |
<show_in_default>1</show_in_default>
|
| 86 |
<show_in_website>1</show_in_website>
|
| 87 |
-
<show_in_store>
|
| 88 |
<comment>If set to yes, this will perform batch synchronization of your list. You must have CRON setup on your store for this feature to work.</comment>
|
| 89 |
</autosync>
|
| 90 |
<handle_default_emails translate="label">
|
|
@@ -94,9 +94,19 @@
|
|
| 94 |
<sort_order>40</sort_order>
|
| 95 |
<show_in_default>1</show_in_default>
|
| 96 |
<show_in_website>1</show_in_website>
|
| 97 |
-
<show_in_store>
|
| 98 |
<comment>If set to yes, this will disable the Magento "Subscription Success","Subscription Confirmation" and the "Unsubscription Confirmation" emails. Mailigen will send these emails for you</comment>
|
| 99 |
</handle_default_emails>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
</fields>
|
| 101 |
</newsletter>
|
| 102 |
<customers translate="label" module="mailigen_synchronizer">
|
|
@@ -115,7 +125,7 @@
|
|
| 115 |
<sort_order>10</sort_order>
|
| 116 |
<show_in_default>1</show_in_default>
|
| 117 |
<show_in_website>1</show_in_website>
|
| 118 |
-
<show_in_store>
|
| 119 |
<comment>By selecting a new list option you'll be able to create a new Mailigen list directly from this panel. Attention! Please do not confuse Newsletter and Customer lists!</comment>
|
| 120 |
</contact_list>
|
| 121 |
<new_list_title translate="label">
|
|
@@ -124,7 +134,7 @@
|
|
| 124 |
<sort_order>20</sort_order>
|
| 125 |
<show_in_default>1</show_in_default>
|
| 126 |
<show_in_website>1</show_in_website>
|
| 127 |
-
<show_in_store>
|
| 128 |
<comment>Type the title of your new list. During the save, the list will be created and it will become the current contact list.</comment>
|
| 129 |
<depends>
|
| 130 |
<contact_list></contact_list>
|
|
@@ -137,16 +147,27 @@
|
|
| 137 |
<sort_order>30</sort_order>
|
| 138 |
<show_in_default>1</show_in_default>
|
| 139 |
<show_in_website>1</show_in_website>
|
| 140 |
-
<show_in_store>
|
| 141 |
<comment>If set to yes, this will perform batch synchronization of your list. You must have CRON setup on your store for this feature to work.</comment>
|
| 142 |
</autosync>
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
<frontend_model>mailigen_synchronizer/adminhtml_sync_information</frontend_model>
|
| 145 |
-
<sort_order>
|
| 146 |
<show_in_default>1</show_in_default>
|
| 147 |
<show_in_website>1</show_in_website>
|
| 148 |
-
<show_in_store>
|
| 149 |
-
</
|
| 150 |
<manual_sync>
|
| 151 |
<frontend_type>hidden</frontend_type>
|
| 152 |
<show_in_default>0</show_in_default>
|
|
@@ -160,7 +181,7 @@
|
|
| 160 |
<show_in_store>0</show_in_store>
|
| 161 |
</stop_sync>
|
| 162 |
</fields>
|
| 163 |
-
</
|
| 164 |
</groups>
|
| 165 |
</mailigen_synchronizer>
|
| 166 |
</sections>
|
| 24 |
<sort_order>10</sort_order>
|
| 25 |
<show_in_default>1</show_in_default>
|
| 26 |
<show_in_website>1</show_in_website>
|
| 27 |
+
<show_in_store>0</show_in_store>
|
| 28 |
</enabled>
|
| 29 |
<api_key translate="label">
|
| 30 |
<label>Api Key:</label>
|
| 33 |
<sort_order>20</sort_order>
|
| 34 |
<show_in_default>1</show_in_default>
|
| 35 |
<show_in_website>1</show_in_website>
|
| 36 |
+
<show_in_store>0</show_in_store>
|
| 37 |
</api_key>
|
| 38 |
<cron_string translate="label">
|
| 39 |
<label>Sync schedule (cron syntax)</label>
|
| 62 |
<sort_order>10</sort_order>
|
| 63 |
<show_in_default>1</show_in_default>
|
| 64 |
<show_in_website>1</show_in_website>
|
| 65 |
+
<show_in_store>0</show_in_store>
|
| 66 |
<comment>By selecting a new list option you'll be able to create a new Mailigen list directly from this panel. Attention! Please do not confuse Newsletter and Customer lists!</comment>
|
| 67 |
</contact_list>
|
| 68 |
<new_list_title translate="label">
|
| 71 |
<sort_order>20</sort_order>
|
| 72 |
<show_in_default>1</show_in_default>
|
| 73 |
<show_in_website>1</show_in_website>
|
| 74 |
+
<show_in_store>0</show_in_store>
|
| 75 |
<comment>Type the title of your new list. During the save, the list will be created and it will become the current contact list.</comment>
|
| 76 |
<depends>
|
| 77 |
<contact_list></contact_list>
|
| 84 |
<sort_order>30</sort_order>
|
| 85 |
<show_in_default>1</show_in_default>
|
| 86 |
<show_in_website>1</show_in_website>
|
| 87 |
+
<show_in_store>0</show_in_store>
|
| 88 |
<comment>If set to yes, this will perform batch synchronization of your list. You must have CRON setup on your store for this feature to work.</comment>
|
| 89 |
</autosync>
|
| 90 |
<handle_default_emails translate="label">
|
| 94 |
<sort_order>40</sort_order>
|
| 95 |
<show_in_default>1</show_in_default>
|
| 96 |
<show_in_website>1</show_in_website>
|
| 97 |
+
<show_in_store>0</show_in_store>
|
| 98 |
<comment>If set to yes, this will disable the Magento "Subscription Success","Subscription Confirmation" and the "Unsubscription Confirmation" emails. Mailigen will send these emails for you</comment>
|
| 99 |
</handle_default_emails>
|
| 100 |
+
<webhooks translate="label">
|
| 101 |
+
<label>Enable Mailigen Webhooks</label>
|
| 102 |
+
<frontend_type>select</frontend_type>
|
| 103 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
| 104 |
+
<sort_order>50</sort_order>
|
| 105 |
+
<show_in_default>1</show_in_default>
|
| 106 |
+
<show_in_website>1</show_in_website>
|
| 107 |
+
<show_in_store>0</show_in_store>
|
| 108 |
+
<comment><![CDATA[If set to yes, then each time the list on Mailigen changes an update will be sent to Magento store.<br/><b>Warning:</b> You should configure Webhooks in Mailigen account to get it working! Read more details in <a href="http://www.mailigen.com/assets/files/pdf/MailigenSynchronizer-MagentoModul-UserGuide-v1.pdf">documentation</a>.]]></comment>
|
| 109 |
+
</webhooks>
|
| 110 |
</fields>
|
| 111 |
</newsletter>
|
| 112 |
<customers translate="label" module="mailigen_synchronizer">
|
| 125 |
<sort_order>10</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 |
<comment>By selecting a new list option you'll be able to create a new Mailigen list directly from this panel. Attention! Please do not confuse Newsletter and Customer lists!</comment>
|
| 130 |
</contact_list>
|
| 131 |
<new_list_title translate="label">
|
| 134 |
<sort_order>20</sort_order>
|
| 135 |
<show_in_default>1</show_in_default>
|
| 136 |
<show_in_website>1</show_in_website>
|
| 137 |
+
<show_in_store>0</show_in_store>
|
| 138 |
<comment>Type the title of your new list. During the save, the list will be created and it will become the current contact list.</comment>
|
| 139 |
<depends>
|
| 140 |
<contact_list></contact_list>
|
| 147 |
<sort_order>30</sort_order>
|
| 148 |
<show_in_default>1</show_in_default>
|
| 149 |
<show_in_website>1</show_in_website>
|
| 150 |
+
<show_in_store>0</show_in_store>
|
| 151 |
<comment>If set to yes, this will perform batch synchronization of your list. You must have CRON setup on your store for this feature to work.</comment>
|
| 152 |
</autosync>
|
| 153 |
+
</fields>
|
| 154 |
+
</customers>
|
| 155 |
+
<sync translate="label" module="mailigen_synchronizer">
|
| 156 |
+
<label>Sync Information</label>
|
| 157 |
+
<frontend_type>text</frontend_type>
|
| 158 |
+
<sort_order>40</sort_order>
|
| 159 |
+
<show_in_default>1</show_in_default>
|
| 160 |
+
<show_in_website>1</show_in_website>
|
| 161 |
+
<show_in_store>1</show_in_store>
|
| 162 |
+
<expanded>1</expanded>
|
| 163 |
+
<fields>
|
| 164 |
+
<information>
|
| 165 |
<frontend_model>mailigen_synchronizer/adminhtml_sync_information</frontend_model>
|
| 166 |
+
<sort_order>10</sort_order>
|
| 167 |
<show_in_default>1</show_in_default>
|
| 168 |
<show_in_website>1</show_in_website>
|
| 169 |
+
<show_in_store>0</show_in_store>
|
| 170 |
+
</information>
|
| 171 |
<manual_sync>
|
| 172 |
<frontend_type>hidden</frontend_type>
|
| 173 |
<show_in_default>0</show_in_default>
|
| 181 |
<show_in_store>0</show_in_store>
|
| 182 |
</stop_sync>
|
| 183 |
</fields>
|
| 184 |
+
</sync>
|
| 185 |
</groups>
|
| 186 |
</mailigen_synchronizer>
|
| 187 |
</sections>
|
app/code/community/Mailigen/Synchronizer/sql/mailigen_synchronizer_setup/mysql4-upgrade-1.1.4-1.2.0.php
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
/**
|
| 3 |
+
* Mailigen_Synchronizer
|
| 4 |
+
*
|
| 5 |
+
* @category Mailigen
|
| 6 |
+
* @package Mailigen_Synchronizer
|
| 7 |
+
* @author Maksim Soldatjonok <maksold@gmail.com>
|
| 8 |
+
*/
|
| 9 |
+
/* @var $installer Mage_Core_Model_Resource_Setup */
|
| 10 |
+
$installer = $this;
|
| 11 |
+
$installer->startSetup();
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Add 'mailigen_synced' column to 'newsletter_subscriber' table
|
| 15 |
+
*/
|
| 16 |
+
$installer->run("
|
| 17 |
+
ALTER TABLE {$this->getTable('newsletter_subscriber')}
|
| 18 |
+
ADD `mailigen_synced` tinyint(1) NOT NULL default '0';
|
| 19 |
+
");
|
| 20 |
+
|
| 21 |
+
$installer->endSetup();
|
package.xml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<package>
|
| 3 |
<name>Mailigen_Synchronizer</name>
|
| 4 |
-
<version>1.
|
| 5 |
<stability>stable</stability>
|
| 6 |
<license>GNU General Public License (GPL)</license>
|
| 7 |
<channel>community</channel>
|
|
@@ -19,11 +19,12 @@ Feature-rich synchronization&#xD;
|
|
| 19 |
For more detailed information, instructions and usage of this extension, please visit Mailigen Integrations page or contact our support team.&#xD;
|
| 20 |
&#xD;
|
| 21 |
Mailigen provides email and integrated marketing services covering full email automation. See a full integration list in Mailigen Integrations page.</description>
|
| 22 |
-
<notes>-
|
|
|
|
| 23 |
<authors><author><name>Thomas Nelson</name><user>mailigen</user><email>info@mailigen.com</email></author></authors>
|
| 24 |
-
<date>2015-
|
| 25 |
-
<time>
|
| 26 |
-
<contents><target name="magecommunity"><dir name="Mailigen"><dir name="Synchronizer"><dir name="Block"><dir name="Adminhtml"><dir name="Sync"><file name="Information.php" hash="
|
| 27 |
<compatible/>
|
| 28 |
<dependencies><required><php><min>5.4.0</min><max>6.0.0</max></php></required></dependencies>
|
| 29 |
</package>
|
| 1 |
<?xml version="1.0"?>
|
| 2 |
<package>
|
| 3 |
<name>Mailigen_Synchronizer</name>
|
| 4 |
+
<version>1.2.0</version>
|
| 5 |
<stability>stable</stability>
|
| 6 |
<license>GNU General Public License (GPL)</license>
|
| 7 |
<channel>community</channel>
|
| 19 |
For more detailed information, instructions and usage of this extension, please visit Mailigen Integrations page or contact our support team.&#xD;
|
| 20 |
&#xD;
|
| 21 |
Mailigen provides email and integrated marketing services covering full email automation. See a full integration list in Mailigen Integrations page.</description>
|
| 22 |
+
<notes>- Updated Newsletter synchronisation
|
| 23 |
+
- Added webhooks subscibe/unsubscribe for Newsletter</notes>
|
| 24 |
<authors><author><name>Thomas Nelson</name><user>mailigen</user><email>info@mailigen.com</email></author></authors>
|
| 25 |
+
<date>2015-07-19</date>
|
| 26 |
+
<time>09:21:59</time>
|
| 27 |
+
<contents><target name="magecommunity"><dir name="Mailigen"><dir name="Synchronizer"><dir name="Block"><dir name="Adminhtml"><dir name="Sync"><file name="Information.php" hash="8a56f97404bad86c899294bffe6832af"/></dir></dir><dir name="Newsletter"><dir name="Subscriber"><file name="Grid.php" hash="1a975840b9f1704644cb8228468ad743"/></dir></dir></dir><dir name="Helper"><file name="Customer.php" hash="bab800ba2dfd87241f23710115eea670"/><file name="Data.php" hash="2b60a16ebc85f6a6c5ce62452ac2b658"/><file name="Log.php" hash="7cff7048604c0f75be38cbd42e9dc8e3"/></dir><file name="Mailigen_webhooks_setup_instruction.jpg" hash="27dcb35d607a919b2f3e95e2fdb96757"/><dir name="Model"><dir name="Customer"><dir name="Merge"><file name="Field.php" hash="68314df0847063e4053ffb505087b7ea"/></dir></dir><file name="Customer.php" hash="50b7d9768124f3bd9f6da86067a49494"/><file name="List.php" hash="329edb291f38861b7f2b1a79e01a4896"/><file name="Mailigen.php" hash="9db057af2ac82a84a4650db60c457e49"/><dir name="Newsletter"><dir name="Merge"><file name="Field.php" hash="b15e805b125d1d7f779730ff78232997"/></dir><file name="Subscriber.php" hash="0be821ef351f8c9ed9811c1b0054b3a2"/></dir><file name="Newsletter.php" hash="864672a8ce7686376a35eab5979f3c0b"/><file name="Observer.php" hash="ad87b3c9697df755bafefdc044ec0cb2"/><dir name="Resource"><dir name="Customer"><file name="Collection.php" hash="350fd71cb6db7688a932530256856533"/></dir><file name="Customer.php" hash="bb95830ef5e95b4a361a858d081ff4f8"/><dir name="Iterator"><file name="Batched.php" hash="d2b0ec0268773422de00cb6766083753"/></dir><dir name="Subscriber"><file name="Collection.php" hash="8b7b1f361d0257b2bcae0b8a227517f9"/></dir></dir><file name="Schedule.php" hash="6486dc9375bae5555c0e0a9c7a156be5"/><dir name="System"><dir name="Config"><dir name="Backend"><dir name="Customer"><file name="List.php" hash="5370ca37cb8d4f0a268e3ef2e9f4c673"/></dir><dir name="Newsletter"><file name="List.php" hash="05f2ce9cb0954a35cc87f7899164beaa"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="MailigenController.php" hash="5592488f4433d70aa4ceecd1c05f2318"/></dir><file name="WebhookController.php" hash="bca6a15371aea1565ff433b1d523b1e9"/></dir><dir name="data"><dir name="mailigen_synchronizer_setup"><file name="data-install-1.1.0.php" hash="30f1fdb649862fcbbd943aeb7ce65c7f"/></dir></dir><dir name="etc"><file name="config.xml" hash="a33226d20ba64be4b91ee7e1d837a55b"/><file name="system.xml" hash="93d02040f081ad1d8547733ab4e06a17"/></dir><dir name="sql"><dir name="mailigen_synchronizer_setup"><file name="install-1.1.0.php" hash="57ee87c647fca4c728f9ee988be84231"/><file name="mysql4-upgrade-1.1.4-1.2.0.php" hash="569d2880f0b52cda79bb78b632b14690"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Mailigen_Synchronizer.xml" hash="4c1560ac5f7042f57bfcf13a0e49bc00"/></dir></target><target name="magelib"><dir name="mailigen"><file name="MGAPI.class.php" hash="16b7712206e95bf61c2cf6f92ef71583"/></dir></target></contents>
|
| 28 |
<compatible/>
|
| 29 |
<dependencies><required><php><min>5.4.0</min><max>6.0.0</max></php></required></dependencies>
|
| 30 |
</package>
|
