emailchef - Version 2.7.5

Version Notes

First community release

Download this release

Release Info

Developer eMailChef
Extension emailchef
Version 2.7.5
Comparing to
See all releases


Version 2.7.5

Files changed (151) hide show
  1. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Emailchef/Grid.php +173 -0
  2. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Emailchefbackend.php +20 -0
  3. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Log.php +20 -0
  4. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Log/Grid.php +162 -0
  5. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Sync.php +20 -0
  6. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Sync/Grid.php +172 -0
  7. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/System/Config/Form/Field/Timezone.php +20 -0
  8. app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/System/Config/Form/Testbutton.php +36 -0
  9. app/code/community/EMailChef/EMailChefSync/Block/Checkout/Subscribe.php +11 -0
  10. app/code/community/EMailChef/EMailChefSync/Block/Filters.php +25 -0
  11. app/code/community/EMailChef/EMailChefSync/Block/Index.php +11 -0
  12. app/code/community/EMailChef/EMailChefSync/Helper/Customer.php +70 -0
  13. app/code/community/EMailChef/EMailChefSync/Helper/Data.php +1056 -0
  14. app/code/community/EMailChef/EMailChefSync/Helper/Order.php +32 -0
  15. app/code/community/EMailChef/EMailChefSync/Model/.DS_Store +0 -0
  16. app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/.DS_Store +0 -0
  17. app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/.DS_Store +0 -0
  18. app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Clone/Mappings/Custom.php +32 -0
  19. app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Source/Cron/Frequency.php +63 -0
  20. app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Source/Cron/Hours.php +19 -0
  21. app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Source/Fields.php +88 -0
  22. app/code/community/EMailChef/EMailChefSync/Model/Config.php +356 -0
  23. app/code/community/EMailChef/EMailChefSync/Model/Cron.php +256 -0
  24. app/code/community/EMailChef/EMailChefSync/Model/EMailChef.php +11 -0
  25. app/code/community/EMailChef/EMailChefSync/Model/EMailChefWsImport.php +762 -0
  26. app/code/community/EMailChef/EMailChefSync/Model/Job.php +218 -0
  27. app/code/community/EMailChef/EMailChefSync/Model/Log.php +20 -0
  28. app/code/community/EMailChef/EMailChefSync/Model/Mysql14/EMailChef.php +9 -0
  29. app/code/community/EMailChef/EMailChefSync/Model/Mysql14/EMailChef/Collection.php +10 -0
  30. app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Job.php +30 -0
  31. app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Job/Collection.php +11 -0
  32. app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Log.php +25 -0
  33. app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Log/Collection.php +11 -0
  34. app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Sync.php +67 -0
  35. app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Sync/Collection.php +11 -0
  36. app/code/community/EMailChef/EMailChefSync/Model/Observer.php +646 -0
  37. app/code/community/EMailChef/EMailChefSync/Model/Source/Groups.php +70 -0
  38. app/code/community/EMailChef/EMailChefSync/Model/Source/Lists.php +239 -0
  39. app/code/community/EMailChef/EMailChefSync/Model/Source/Store.php +59 -0
  40. app/code/community/EMailChef/EMailChefSync/Model/Subscriber.php +94 -0
  41. app/code/community/EMailChef/EMailChefSync/Model/Sync.php +126 -0
  42. app/code/community/EMailChef/EMailChefSync/Model/Webserviceusernamevalidator.php +18 -0
  43. app/code/community/EMailChef/EMailChefSync/Model/Wssend.php +127 -0
  44. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/ConfigurationController.php +85 -0
  45. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/EmailchefbackendController.php +66 -0
  46. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/FieldsmappingController.php +32 -0
  47. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/FilterController.php +439 -0
  48. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/LogController.php +16 -0
  49. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/SyncController.php +38 -0
  50. app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/ViewdatatransferlogController.php +16 -0
  51. app/code/community/EMailChef/EMailChefSync/controllers/IndexController.php +49 -0
  52. app/code/community/EMailChef/EMailChefSync/controllers/TestController.php +70 -0
  53. app/code/community/EMailChef/EMailChefSync/data/emailchef_setup/data-upgrade-2.6.1-2.7.0.php +14 -0
  54. app/code/community/EMailChef/EMailChefSync/data/emailchef_setup/data-upgrade-2.7.0-2.7.1.php +33 -0
  55. app/code/community/EMailChef/EMailChefSync/etc/config.xml +358 -0
  56. app/code/community/EMailChef/EMailChefSync/etc/system.xml +458 -0
  57. app/code/community/EMailChef/EMailChefSync/lib/emailchef/composer.json +11 -0
  58. app/code/community/EMailChef/EMailChefSync/lib/emailchef/composer.lock +68 -0
  59. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/AddEmailsToGroupCommand.php +39 -0
  60. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/CreateContactCommand.php +34 -0
  61. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/CreateSegmentCommand.php +35 -0
  62. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/DeleteContactCommand.php +31 -0
  63. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetAuthenticationTokenCommand.php +27 -0
  64. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetContactFromEmailCommand.php +30 -0
  65. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetListFieldsCommand.php +23 -0
  66. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetListSegmentsCommand.php +23 -0
  67. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetListsCommand.php +35 -0
  68. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetPredefinedFieldsCommand.php +23 -0
  69. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetSegmentCommand.php +25 -0
  70. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/ImportContactsCommand.php +42 -0
  71. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/ImportContactsInGroupCommand.php +29 -0
  72. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/UpdateSegmentCommand.php +38 -0
  73. app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Service/ApiService.php +33 -0
  74. app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/phpunit.xml +8 -0
  75. app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/AddEmailsToGroupCommandTest.php +19 -0
  76. app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/CreateSegmentCommandTest.php +30 -0
  77. app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/GetAuthenticationTokenCommandTest.php +16 -0
  78. app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/ImportContactsCommandTest.php +30 -0
  79. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/autoload.php +7 -0
  80. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/ClassLoader.php +413 -0
  81. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_classmap.php +9 -0
  82. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_namespaces.php +11 -0
  83. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_psr4.php +10 -0
  84. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_real.php +50 -0
  85. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/installed.json +54 -0
  86. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/.gitignore +5 -0
  87. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/.travis.yml +17 -0
  88. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/LICENSE.txt +7 -0
  89. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/README.md +228 -0
  90. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/bootstrap.php +4 -0
  91. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/build +51 -0
  92. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/composer.json +27 -0
  93. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/freebase.php +12 -0
  94. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/github.php +9 -0
  95. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/override.php +44 -0
  96. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/showclix.php +24 -0
  97. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Bootstrap.php +97 -0
  98. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Exception/ConnectionErrorException.php +7 -0
  99. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/CsvHandler.php +51 -0
  100. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/FormHandler.php +30 -0
  101. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/JsonHandler.php +42 -0
  102. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/MimeHandlerAdapter.php +54 -0
  103. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/README.md +44 -0
  104. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/XHtmlHandler.php +15 -0
  105. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/XmlHandler.php +152 -0
  106. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Http.php +86 -0
  107. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Httpful.php +47 -0
  108. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Mime.php +60 -0
  109. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Proxy.php +16 -0
  110. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Request.php +1186 -0
  111. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Response.php +195 -0
  112. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Response/Headers.php +88 -0
  113. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/Httpful/HttpfulTest.php +604 -0
  114. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/Httpful/requestTest.php +21 -0
  115. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/bootstrap-server.php +42 -0
  116. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/phpunit.xml +16 -0
  117. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/static/test.json +1 -0
  118. app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/test_image.jpg +0 -0
  119. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-install-0.1.0.php +4 -0
  120. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-install-2.3.0.php +39 -0
  121. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-install-2.4.0.php +67 -0
  122. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-0.1.0-1.0.0.php +4 -0
  123. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-0.3.0-1.0.0.php +11 -0
  124. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-1.0.0-1.5.2.php +11 -0
  125. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.1.3-2.2.0.php +24 -0
  126. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.2.0-2.3.0.php +46 -0
  127. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.2.1-2.3.0.php +46 -0
  128. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.3.0-2.3.1.php +15 -0
  129. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.3.1-2.3.2.php +39 -0
  130. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.3.2-2.4.0.php +67 -0
  131. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.4.0-2.4.1.php +34 -0
  132. app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.6.1-2.7.0.php +8 -0
  133. app/design/adminhtml/default/default/layout/emailchef.xml +91 -0
  134. app/design/adminhtml/default/default/template/emailchef/emailchefsync/confirm.phtml +186 -0
  135. app/design/adminhtml/default/default/template/emailchef/emailchefsync/fieldsmapping.phtml +61 -0
  136. app/design/adminhtml/default/default/template/emailchef/emailchefsync/filter.phtml +535 -0
  137. app/design/adminhtml/default/default/template/emailchef/emailchefsync/sysconfigjavascript.phtml +17 -0
  138. app/design/adminhtml/default/default/template/emailchef/emailchefsync/viewdatatransferlog.phtml +72 -0
  139. app/design/frontend/base/default/layout/emailchef.xml +27 -0
  140. app/design/frontend/base/default/template/emailchef/customer/account/dashboard/info.phtml +43 -0
  141. app/design/frontend/base/default/template/emailchef/index.phtml +0 -0
  142. app/design/frontend/base/default/template/emailchef/subscribe.phtml +38 -0
  143. app/design/frontend/enterprise/default/layout/emailchef.xml +16 -0
  144. app/etc/modules/EMailChef_EMailChefSync.xml +1 -0
  145. app/locale/en_US/EMailChef_EMailChefSync.csv +91 -0
  146. app/locale/it_IT/EMailChef_EMailChefSync.csv +139 -0
  147. js/emailchef/admin.js +38 -0
  148. package.xml +26 -0
  149. skin/adminhtml/default/default/emailchef/emailchefsync/emailchef.css +1 -0
  150. skin/adminhtml/default/default/emailchef/emailchefsync/images/EMailChef_300_200_transparent_small.png +0 -0
  151. skin/adminhtml/default/default/images/EMailChef_300_200_transparent_small.png +0 -0
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Emailchef/Grid.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Grid.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Block_Adminhtml_EMailChef_Grid extends Mage_Adminhtml_Block_Widget_Grid
6
+ {
7
+ /**
8
+ * Constructor.
9
+ */
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setId('EMailChefGrid');
14
+ $this->setDefaultSort('id');
15
+ $this->setDefaultDir('ASC');
16
+ $this->setSaveParametersInSession(true);
17
+ }
18
+
19
+ /**
20
+ * Prepare Collection.
21
+ *
22
+ * @return $this
23
+ */
24
+ protected function _prepareCollection()
25
+ {
26
+ $collection = Mage::getModel('emailchef/job')->getCollection();
27
+ $this->setCollection($collection);
28
+ // Set default sort to ID by highest to lowest (normally shows most recent first)
29
+ $this->setDefaultSort('id');
30
+ $this->setDefaultDir('desc');
31
+
32
+ //var_dump(Mage::getModel('emailchef/job')->load(1));
33
+
34
+ return parent::_prepareCollection();
35
+ }
36
+
37
+ /**
38
+ * Prepare Grid Columns.
39
+ */
40
+ protected function _prepareColumns()
41
+ {
42
+ $this->addColumn('id', array(
43
+ 'header' => Mage::helper('emailchef')->__('ID'),
44
+ //'align' =>'right',
45
+ 'width' => '80px',
46
+ 'index' => 'id',
47
+ ));
48
+
49
+ $this->addColumn('type', array(
50
+ 'header' => Mage::helper('emailchef')->__('Type'),
51
+ 'align' => 'left',
52
+ 'index' => 'type',
53
+ 'type' => 'options',
54
+ 'options' => array(
55
+ 0 => 'Manual Sync',
56
+ 1 => 'Auto Sync',
57
+ //2 => 'Disabled',
58
+ ),
59
+ ));
60
+
61
+ $this->addColumn('store_id', array(
62
+ 'header' => Mage::helper('emailchef')->__('Store'),
63
+ 'align' => 'left',
64
+ //'width' => '150px',
65
+ 'index' => 'store_id',
66
+ 'type' => 'options',
67
+ 'options' => Mage::getModel('emailchef/source_store')->getSelectOptions(),
68
+ ));
69
+
70
+ $this->addColumn('emailchefgroupid', array(
71
+ 'header' => Mage::helper('emailchef')->__('eMailChef Group ID'),
72
+ //'align' =>'right',
73
+ 'width' => '80px',
74
+ 'index' => 'emailchefgroupid',
75
+ ));
76
+
77
+ $this->addColumn('list_id', array(
78
+ 'header' => Mage::helper('emailchef')->__('eMailChef List ID'),
79
+ //'align' =>'right',
80
+ 'width' => '80px',
81
+ 'index' => 'list_id',
82
+ ));
83
+
84
+ /*$this->addColumn('list_guid', array(
85
+ 'header' => Mage::helper('emailchef')->__('eMailChef List GUID'),
86
+ 'index' => 'list_guid',
87
+ ));*/
88
+
89
+ $this->addColumn('status', array(
90
+ 'header' => Mage::helper('emailchef')->__('Status'),
91
+ //'align' =>'right',
92
+ 'index' => 'status',
93
+ ));
94
+ /*
95
+ $this->addColumn('process_id', array(
96
+ 'header' => Mage::helper('emailchef')->__('Process ID'),
97
+ //'align' =>'right',
98
+ 'width' => '80px',
99
+ 'index' => 'process_id',
100
+ ));
101
+ */
102
+ $this->addColumn('tries', array(
103
+ 'header' => Mage::helper('emailchef')->__('Tries'),
104
+ //'align' =>'right',
105
+ 'width' => '50px',
106
+ 'index' => 'tries',
107
+ ));
108
+
109
+ $this->addColumn('queue_datetime', array(
110
+ 'header' => Mage::helper('emailchef')->__('Queue Time'),
111
+ 'type' => 'datetime', // Add in Date Picker
112
+ //'type' => 'timestamp',
113
+ //'align' => 'center',
114
+ 'width' => '180px',
115
+ 'index' => 'queue_datetime',
116
+ //'gmtoffset' => true
117
+ ));
118
+
119
+ $this->addColumn('start_datetime', array(
120
+ 'header' => Mage::helper('emailchef')->__('Started'),
121
+ 'type' => 'datetime', // Add in Date Picker
122
+ //'type' => 'timestamp',
123
+ //'align' => 'center',
124
+ 'width' => '180px',
125
+ 'index' => 'start_datetime',
126
+ //'gmtoffset' => true
127
+ ));
128
+
129
+ $this->addColumn('finish_datetime', array(
130
+ 'header' => Mage::helper('emailchef')->__('Finished'),
131
+ 'type' => 'datetime', // Add in Date Picker
132
+ //'type' => 'timestamp',
133
+ //'align' => 'center',
134
+ 'width' => '180px',
135
+ 'index' => 'finish_datetime',
136
+ //'gmtoffset' => true
137
+ ));
138
+
139
+ $this->addColumn('action',
140
+ array(
141
+ 'header' => Mage::helper('emailchef')->__('Action'),
142
+ 'width' => '100',
143
+ 'type' => 'action',
144
+ 'getter' => 'getId',
145
+ 'actions' => array(
146
+ array(
147
+ 'caption' => Mage::helper('emailchef')->__('Run'),
148
+ 'url' => array('base' => '*/*/runjob'),
149
+ 'field' => 'id',
150
+ ),
151
+ array(
152
+ 'caption' => Mage::helper('emailchef')->__('Delete'),
153
+ 'url' => array('base' => '*/*/delete'),
154
+ 'field' => 'id',
155
+ ),
156
+ ),
157
+ 'filter' => false,
158
+ 'sortable' => false,
159
+ 'index' => 'stores',
160
+ 'is_system' => true,
161
+ ));
162
+
163
+ return parent::_prepareColumns();
164
+ }
165
+
166
+ /**
167
+ * Get row url - None editable.
168
+ */
169
+ public function getRowUrl($row)
170
+ {
171
+ return '';
172
+ }
173
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Emailchefbackend.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * EMailChefbackend.php.
5
+ */
6
+ class EMailChef_EMailChefSync_Block_Adminhtml_Emailchefbackend extends Mage_Adminhtml_Block_Widget_Grid_Container
7
+ {
8
+ public function __construct()
9
+ {
10
+ $this->_controller = 'adminhtml_emailchef';
11
+ $this->_blockGroup = 'emailchef';
12
+
13
+ $this->_headerText = Mage::helper('emailchef')->__('eMailChef Scheduled Tasks');
14
+ //$this->_addButtonLabel = Mage::helper('emailchef')->__('Add Item');
15
+
16
+ parent::__construct();
17
+
18
+ $this->_removeButton('add');
19
+ }
20
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Log.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Log.php.
5
+ */
6
+ class EMailChef_EMailChefSync_Block_Adminhtml_Log extends Mage_Adminhtml_Block_Widget_Grid_Container
7
+ {
8
+ public function __construct()
9
+ {
10
+ $this->_controller = 'adminhtml_log';
11
+ $this->_blockGroup = 'emailchef';
12
+
13
+ $this->_headerText = Mage::helper('emailchef')->__('eMailChef Logs');
14
+ //$this->_addButtonLabel = Mage::helper('emailchef')->__('Add Item');
15
+
16
+ parent::__construct();
17
+
18
+ $this->_removeButton('add');
19
+ }
20
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Log/Grid.php ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Grid.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Block_Adminhtml_Log_Grid extends Mage_Adminhtml_Block_Widget_Grid
6
+ {
7
+ /**
8
+ * Constructor.
9
+ */
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setId('EMailChefLogGrid');
14
+ $this->setDefaultSort('id');
15
+ $this->setDefaultDir('ASC');
16
+ $this->setSaveParametersInSession(true);
17
+ }
18
+
19
+ /**
20
+ * Prepare Collection.
21
+ *
22
+ * @return
23
+ */
24
+ protected function _prepareCollection()
25
+ {
26
+ $collection = Mage::getModel('emailchef/log')->getCollection();
27
+ $this->setCollection($collection);
28
+ // Set default sort to ID by highest to lowest (normally shows most recent first)
29
+ $this->setDefaultSort('id');
30
+ $this->setDefaultDir('desc');
31
+
32
+ //var_dump(Mage::getModel('emailchef/job')->load(1));
33
+
34
+ return parent::_prepareCollection();
35
+ }
36
+
37
+ /**
38
+ * Prepare Grid Columns.
39
+ */
40
+ protected function _prepareColumns()
41
+ {
42
+ $this->addColumn('id', array(
43
+ 'header' => Mage::helper('emailchef')->__('ID'),
44
+ //'align' =>'right',
45
+ 'width' => '80px',
46
+ 'index' => 'id',
47
+ ));
48
+
49
+ $this->addColumn('store_id', array(
50
+ 'header' => Mage::helper('emailchef')->__('Store'),
51
+ 'align' => 'left',
52
+ //'width' => '150px',
53
+ 'index' => 'store_id',
54
+ 'type' => 'options',
55
+ 'options' => Mage::getModel('emailchef/source_store')->getSelectOptions(),
56
+ ));
57
+
58
+ $this->addColumn('type', array(
59
+ 'header' => Mage::helper('emailchef')->__('Type'),
60
+ //'align' =>'right',
61
+ //'width' => '80px',
62
+ 'index' => 'type',
63
+ ));
64
+
65
+ $this->addColumn('job_id', array(
66
+ 'header' => Mage::helper('emailchef')->__('Job ID'),
67
+ //'align' =>'right',
68
+ 'width' => '80px',
69
+ 'index' => 'job_id',
70
+ ));
71
+
72
+ // Not really in use yet!
73
+ /*$this->addColumn('status', array(
74
+ 'header' => Mage::helper('emailchef')->__('Status'),
75
+ //'align' =>'right',
76
+ //'width' => '80px',
77
+ 'index' => 'status',
78
+ ));*/
79
+
80
+ $this->addColumn('data', array(
81
+ 'header' => Mage::helper('emailchef')->__('Info'),
82
+ //'align' =>'right',
83
+ //'width' => '80px',
84
+ 'index' => 'data',
85
+ ));
86
+
87
+ $this->addColumn('event_time', array(
88
+ 'header' => Mage::helper('emailchef')->__('Event Time'),
89
+ 'type' => 'datetime', // Add in Date Picker
90
+ //'type' => 'timestamp',
91
+ //'align' => 'center',
92
+ 'width' => '180px',
93
+ 'index' => 'event_time',
94
+ //'gmtoffset' => true
95
+ ));
96
+
97
+ //
98
+ //
99
+ // $this->addColumn('status', array(
100
+ // 'header' => Mage::helper('importer')->__('Status'),
101
+ // 'align' => 'left',
102
+ // 'width' => '80px',
103
+ // 'index' => 'status',
104
+ // 'type' => 'options',
105
+ // 'options' => array(
106
+ // 1 => 'Enabled',
107
+ // 2 => 'Disabled',
108
+ // ),
109
+ // ));
110
+ //
111
+
112
+ // $this->addColumn('action',
113
+ // array(
114
+ // 'header' => Mage::helper('emailchef')->__('Action'),
115
+ // 'width' => '100',
116
+ // 'type' => 'action',
117
+ // 'getter' => 'getId',
118
+ // 'actions' => array(
119
+ // array(
120
+ // 'caption' => Mage::helper('emailchef')->__('Sync'),
121
+ // 'url' => array('base'=> '*/*/sync'),
122
+ // 'field' => 'id'
123
+ // )
124
+ // ),
125
+ // 'filter' => false,
126
+ // 'sortable' => false,
127
+ // 'index' => 'stores',
128
+ // 'is_system' => true,
129
+ // ));
130
+
131
+ return parent::_prepareColumns();
132
+ }
133
+
134
+ // /**
135
+ // * Prepare Mass Action
136
+ // */
137
+ // protected function _prepareMassaction()
138
+ // {
139
+ // $this->setMassactionIdField('id');
140
+ // $this->getMassactionBlock()->setFormFieldName('importer');
141
+ //
142
+ // $this->getMassactionBlock()->addItem('delete', array(
143
+ // 'label' => Mage::helper('importer')->__('Delete'),
144
+ // 'url' => $this->getUrl('*/*/massDelete'),
145
+ // 'confirm' => Mage::helper('importer')->__('Are you sure?')
146
+ // ));
147
+ //
148
+ // $statuses = Mage::getSingleton('importer/import')->getOptionArray();
149
+ // array_unshift($statuses, array('label'=>'', 'value'=>''));
150
+ //
151
+ // return $this;
152
+ // }
153
+
154
+ /**
155
+ * Get row url - None editable.
156
+ */
157
+ public function getRowUrl($row)
158
+ {
159
+ return '';
160
+ //return $this->getUrl('*/*/edit', array('id' => $row->getId()));
161
+ }
162
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Sync.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Sync.php.
5
+ */
6
+ class EMailChef_EMailChefSync_Block_Adminhtml_Sync extends Mage_Adminhtml_Block_Widget_Grid_Container
7
+ {
8
+ public function __construct()
9
+ {
10
+ $this->_controller = 'adminhtml_sync';
11
+ $this->_blockGroup = 'emailchef';
12
+
13
+ $this->_headerText = Mage::helper('emailchef')->__('eMailChef Task Data');
14
+ //$this->_addButtonLabel = Mage::helper('emailchef')->__('Add Item');
15
+
16
+ parent::__construct();
17
+
18
+ $this->_removeButton('add');
19
+ }
20
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/Sync/Grid.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Grid.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Block_Adminhtml_Sync_Grid extends Mage_Adminhtml_Block_Widget_Grid
6
+ {
7
+ /**
8
+ * Constructor.
9
+ */
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setId('EMailChefSyncGrid');
14
+ $this->setDefaultSort('id');
15
+ $this->setDefaultDir('ASC');
16
+ $this->setSaveParametersInSession(true);
17
+ }
18
+
19
+ /**
20
+ * Prepare Collection.
21
+ *
22
+ * @return
23
+ */
24
+ protected function _prepareCollection()
25
+ {
26
+ $collection = Mage::getModel('emailchef/sync')->getCollection();
27
+ $this->setCollection($collection);
28
+ // Set default sort to ID by highest to lowest (normally shows most recent first)
29
+ $this->setDefaultSort('id');
30
+ $this->setDefaultDir('desc');
31
+
32
+ return parent::_prepareCollection();
33
+ }
34
+
35
+ /**
36
+ * Prepare Grid Columns.
37
+ */
38
+ protected function _prepareColumns()
39
+ {
40
+ $this->addColumn('id', array(
41
+ 'header' => Mage::helper('emailchef')->__('ID'),
42
+ //'align' =>'right',
43
+ 'width' => '80px',
44
+ 'index' => 'id',
45
+ ));
46
+
47
+ $this->addColumn('store_id', array(
48
+ 'header' => Mage::helper('emailchef')->__('Store'),
49
+ 'align' => 'left',
50
+ //'width' => '150px',
51
+ 'index' => 'store_id',
52
+ 'type' => 'options',
53
+ 'options' => Mage::getModel('emailchef/source_store')->getSelectOptions(),
54
+ ));
55
+
56
+ $this->addColumn('customer_id', array(
57
+ 'header' => Mage::helper('emailchef')->__('Customer ID'),
58
+ //'align' =>'right',
59
+ 'width' => '80px',
60
+ 'index' => 'customer_id',
61
+ ));
62
+
63
+ $this->addColumn('entity', array(
64
+ 'header' => Mage::helper('emailchef')->__('Entity'),
65
+ //'align' =>'right',
66
+ //'width' => '80px',
67
+ 'index' => 'entity',
68
+ ));
69
+
70
+ $this->addColumn('job_id', array(
71
+ 'header' => Mage::helper('emailchef')->__('Job ID'),
72
+ //'align' =>'right',
73
+ 'width' => '80px',
74
+ 'index' => 'job_id',
75
+ ));
76
+
77
+ $this->addColumn('needs_sync', array(
78
+ 'header' => Mage::helper('emailchef')->__('Needs Sync'),
79
+ 'align' => 'left',
80
+ 'index' => 'needs_sync',
81
+ 'type' => 'options',
82
+ 'options' => array(
83
+ 0 => 'No',
84
+ 1 => 'Yes',
85
+ ),
86
+ ));
87
+
88
+ $this->addColumn('created', array(
89
+ 'header' => Mage::helper('emailchef')->__('Created'),
90
+ 'type' => 'timestamp',
91
+ //'align' => 'center',
92
+ 'width' => '180px',
93
+ 'index' => 'created',
94
+ //'gmtoffset' => true
95
+ ));
96
+
97
+ $this->addColumn('last_sync', array(
98
+ 'header' => Mage::helper('emailchef')->__('Last Sync Time'),
99
+ 'type' => 'datetime', // Add in Date Picker
100
+ //'type' => 'timestamp',
101
+ //'align' => 'center',
102
+ 'width' => '180px',
103
+ 'index' => 'last_sync',
104
+ //'gmtoffset' => true
105
+ ));
106
+
107
+ //
108
+ //
109
+ // $this->addColumn('status', array(
110
+ // 'header' => Mage::helper('importer')->__('Status'),
111
+ // 'align' => 'left',
112
+ // 'width' => '80px',
113
+ // 'index' => 'status',
114
+ // 'type' => 'options',
115
+ // 'options' => array(
116
+ // 1 => 'Enabled',
117
+ // 2 => 'Disabled',
118
+ // ),
119
+ // ));
120
+ //
121
+
122
+ // $this->addColumn('action',
123
+ // array(
124
+ // 'header' => Mage::helper('emailchef')->__('Action'),
125
+ // 'width' => '100',
126
+ // 'type' => 'action',
127
+ // 'getter' => 'getId',
128
+ // 'actions' => array(
129
+ // array(
130
+ // 'caption' => Mage::helper('emailchef')->__('Sync'),
131
+ // 'url' => array('base'=> '*/*/sync'),
132
+ // 'field' => 'id'
133
+ // )
134
+ // ),
135
+ // 'filter' => false,
136
+ // 'sortable' => false,
137
+ // 'index' => 'stores',
138
+ // 'is_system' => true,
139
+ // ));
140
+
141
+ return parent::_prepareColumns();
142
+ }
143
+
144
+ // /**
145
+ // * Prepare Mass Action
146
+ // */
147
+ // protected function _prepareMassaction()
148
+ // {
149
+ // $this->setMassactionIdField('id');
150
+ // $this->getMassactionBlock()->setFormFieldName('importer');
151
+ //
152
+ // $this->getMassactionBlock()->addItem('delete', array(
153
+ // 'label' => Mage::helper('importer')->__('Delete'),
154
+ // 'url' => $this->getUrl('*/*/massDelete'),
155
+ // 'confirm' => Mage::helper('importer')->__('Are you sure?')
156
+ // ));
157
+ //
158
+ // $statuses = Mage::getSingleton('importer/import')->getOptionArray();
159
+ // array_unshift($statuses, array('label'=>'', 'value'=>''));
160
+ //
161
+ // return $this;
162
+ // }
163
+
164
+ /**
165
+ * Get row url - None editable.
166
+ */
167
+ public function getRowUrl($row)
168
+ {
169
+ return '';
170
+ //return $this->getUrl('*/*/edit', array('id' => $row->getId()));
171
+ }
172
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/System/Config/Form/Field/Timezone.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Block_Adminhtml_System_Config_Form_Field_Timezone
4
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
5
+ {
6
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
7
+ {
8
+ $timezoneList = Mage::app()->getLocale()->getTranslationList('windowstotimezone');
9
+
10
+ // Select only current timezone
11
+ $timezone = date_default_timezone_get();
12
+
13
+ $timezoneStr = $timezone;
14
+ if (isset($timezoneList[$timezone])) {
15
+ $timezoneStr = "{$timezoneList[$timezone]} ({$timezone})";
16
+ }
17
+
18
+ return "<span>{$timezoneStr}</span>";
19
+ }
20
+ }
app/code/community/EMailChef/EMailChefSync/Block/Adminhtml/System/Config/Form/Testbutton.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Self-test button for connection details in system configuration.
5
+ */
6
+ class EMailChef_EMailChefSync_Block_Adminhtml_System_Config_Form_Testbutton
7
+ extends Mage_Adminhtml_Block_System_Config_Form_Field
8
+ {
9
+ /**
10
+ * Return element html.
11
+ *
12
+ * @param Varien_Data_Form_Element_Abstract $element
13
+ *
14
+ * @return string
15
+ */
16
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
17
+ {
18
+ return $this->_toHtml();
19
+ }
20
+
21
+ /**
22
+ * Generate button html.
23
+ *
24
+ * @return string
25
+ */
26
+ protected function _toHtml()
27
+ {
28
+ $button = $this->getLayout()->createBlock('adminhtml/widget_button')
29
+ ->setData(array(
30
+ 'id' => 'emailchef_selftest_button',
31
+ 'label' => $this->helper('adminhtml')->__('Test Connection'),
32
+ ));
33
+
34
+ return $button->toHtml();
35
+ }
36
+ }
app/code/community/EMailChef/EMailChefSync/Block/Checkout/Subscribe.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Subscribe.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Block_Checkout_Subscribe extends Mage_Core_Block_Template
6
+ {
7
+ public function _toHtml()
8
+ {
9
+ return parent::_toHtml();
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/Block/Filters.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Filters.php.
4
+ *
5
+ * Adminhtml block for the filters section
6
+ */
7
+ class EMailChef_EMailChefSync_Block_Filters extends Mage_Core_Block_Template
8
+ {
9
+ public function _toHtml()
10
+ {
11
+ return parent::_toHtml();
12
+ }
13
+
14
+ /**
15
+ * Get an array of all stores.
16
+ *
17
+ * @return array
18
+ */
19
+ protected function _getStoresArray()
20
+ {
21
+ $config = Mage::getModel('emailchef/config');
22
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
23
+ return $config->getStoreArray();
24
+ }
25
+ }
app/code/community/EMailChef/EMailChefSync/Block/Index.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Index.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Block_Index extends Mage_Core_Block_Template
6
+ {
7
+ public function _toHtml()
8
+ {
9
+ return parent::_toHtml();
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/Helper/Customer.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Customer helper methods for EMailChef.
4
+ */
5
+ class EMailChef_EMailChefSync_Helper_Customer extends Mage_Core_Helper_Abstract
6
+ {
7
+ /**
8
+ * Check whether customer attribute is on ignore list.
9
+ *
10
+ * @param $attr string $attr Name of attribute
11
+ *
12
+ * @return bool
13
+ */
14
+ public function isAttrIgnored($attr)
15
+ {
16
+ $attrs = self::_getAttrsIgnored();
17
+
18
+ return isset($attrs[$attr]);
19
+ }
20
+
21
+ /**
22
+ * All standard attributes as a hash mapped to true for easy testing
23
+ * Note that this does not include reward attributes for EE, so these will come out as part of customer attts.
24
+ *
25
+ * @return array
26
+ */
27
+ protected static function _getAttrsIgnored()
28
+ {
29
+ static $attrs = array(
30
+ 'confirmation' => true,
31
+ 'created_at' => true,
32
+ 'created_in' => true,
33
+ 'default_billing' => true,
34
+ 'default_shipping' => true,
35
+ 'disable_auto_group_change' => true,
36
+ 'dob' => true,
37
+ 'email' => true,
38
+ 'firstname' => true,
39
+ 'gender' => true,
40
+ 'group_id' => true,
41
+ 'lastname' => true,
42
+ 'middlename' => true,
43
+ 'password_hash' => true,
44
+ 'prefix' => true,
45
+ 'rp_token' => true,
46
+ 'rp_token_created_at' => true,
47
+ 'store_id' => true,
48
+ 'suffix' => true,
49
+ 'taxvat' => true,
50
+ 'website_id' => true,
51
+ );
52
+
53
+ return $attrs;
54
+ }
55
+
56
+ /**
57
+ * Get customer attribute collection with only custom attributes.
58
+ *
59
+ * @return Varien_Data_Collection_Db
60
+ */
61
+ public function getCustomCustomerAttrCollection()
62
+ {
63
+ $attrs = self::_getAttrsIgnored();
64
+
65
+ $customerAttributes = Mage::getResourceModel('customer/attribute_collection')
66
+ ->addFieldToFilter('attribute_code', array('nin' => array_keys($attrs)));
67
+
68
+ return $customerAttributes;
69
+ }
70
+ }
app/code/community/EMailChef/EMailChefSync/Helper/Data.php ADDED
@@ -0,0 +1,1056 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__DIR__).'/Model/EMailChefWsImport.php';
4
+ require_once dirname(__DIR__).'/Model/Wssend.php';
5
+
6
+ /**
7
+ * Data.php.
8
+ *
9
+ * @todo get rid of these static methods!
10
+ */
11
+ class EMailChef_EMailChefSync_Helper_Data extends Mage_Core_Helper_Abstract
12
+ {
13
+ /**
14
+ * importType takes one of the following values, varying:
15
+ * - Whether to import email, sms or both (in the former cases, the other is discarded)
16
+ * - Whether empty fields over-write the values in EMailChef (4-6) or are ignored (1-3).
17
+ */
18
+ const IMPORT_TYPE_IGNORE_EMPTY_ONLY_EMAIL = 1;
19
+ const IMPORT_TYPE_IGNORE_EMPTY_ONLY_SMS = 2;
20
+ const IMPORT_TYPE_IGNORE_EMPTY_EMAIL_AND_SMS = 3;
21
+ const IMPORT_TYPE_REPLACE_EMPTY_ONLY_EMAIL = 4;
22
+ const IMPORT_TYPE_REPLACE_EMPTY_ONLY_SMS = 5;
23
+ const IMPORT_TYPE_REPLACE_EMPTY_EMAIL_AND_SMS = 6;
24
+
25
+ /**
26
+ * Whether the mobile input type splits the international code into a seperate field.
27
+ */
28
+ const MOBILE_INPUT_TYPE_INCLUDE_INTL_CODE = 1;
29
+ const MOBILE_INPUT_TYPE_SPLIT_INTL_CODE = 2;
30
+
31
+ /**
32
+ * split customers into batches.
33
+ */
34
+ const BATCH_SIZE = 2000;
35
+
36
+ /**
37
+ * Get the Customer Data.
38
+ *
39
+ * @param array
40
+ *
41
+ * @return array
42
+ */
43
+ public static function getCustomersData($customerCollection = null)
44
+ {
45
+ $config = Mage::getModel('emailchef/config');
46
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
47
+
48
+ if ($config->isLogEnabled()) {
49
+ $config->log('Getting customers data');
50
+ }
51
+
52
+ if (is_array($customerCollection) && empty($customerCollection)) {
53
+ if ($config->isLogEnabled()) {
54
+ $config->log('CustomerCollection is Empty!');
55
+ }
56
+ }
57
+
58
+ $dateFormat = 'm/d/y h:i:s';
59
+ $lastDateTime = date($dateFormat, Mage::getModel('core/date')->timestamp(time()) - 7 * 3600 * 24);
60
+ $thirtyDaysAgo = date($dateFormat, Mage::getModel('core/date')->timestamp(time()) - 30 * 3600 * 24);
61
+ $twelveMonthsAgo = date($dateFormat, Mage::getModel('core/date')->timestamp(time()) - 365 * 3600 * 24);
62
+
63
+ $parseSubscribers = false;
64
+ $toSend = array();
65
+ if ($customerCollection === null) {
66
+ /*
67
+ * @todo Change to only load form current store/website
68
+ */
69
+ $customerCollection = Mage::getModel('customer/customer')->getCollection();
70
+ $parseSubscribers = true;
71
+ if ($config->isLogEnabled()) {
72
+ $config->log('Parsing Subscribers, NULL collection passed.');
73
+ }
74
+ }
75
+ foreach ($customerCollection as $currentCustomerId) {
76
+ if (is_object($currentCustomerId)) {
77
+ $currentCustomerId = $currentCustomerId->getId();
78
+ }
79
+
80
+ if (!$currentCustomerId) {
81
+ if ($config->isLogEnabled()) {
82
+ $config->log('Skipping Empty Customer ID!');
83
+ continue;
84
+ }
85
+ }
86
+
87
+ if ($config->isLogEnabled()) {
88
+ $config->log('Customer with id '.$currentCustomerId);
89
+ }
90
+ $customer = Mage::getModel('customer/customer')->load($currentCustomerId);
91
+ /* @var $customer Mage_Customer_Model_Customer */
92
+ $i = $customer->getEmail();
93
+
94
+ // Get order dates, numbers and totals for the current customer
95
+ //TODO: This would be more efficient with just a few SQL statements to gather this
96
+ $allOrdersTotalAmount = 0;
97
+ $allOrdersDateTimes = array();
98
+ $allOrdersTotals = array();
99
+ $allOrdersIds = array();
100
+ $allProductsIds = array();
101
+ $last30daysOrdersAmount = 0;
102
+ $last12monthsOrdersAmount = 0;
103
+ $lastShipmentOrderId = null;
104
+ $lastShipmentOrderDate = null;
105
+
106
+ if ($config->isLogEnabled()) {
107
+ $config->log('Parsing orders of customer with id '.$currentCustomerId);
108
+ }
109
+ // Setup collection to fetch orders for this customer and valid statuses
110
+ $orders = Mage::getResourceModel('sales/order_collection')
111
+ ->addAttributeToFilter('customer_id', $currentCustomerId);
112
+ Mage::helper('emailchef/order')->addStatusFilterToOrders($orders);
113
+
114
+ foreach ($orders as $order) {
115
+ if ($config->isLogEnabled()) {
116
+ $config->log("ORDER STATUS: {$order->getState()} / {$order->getStatus()}");
117
+ }
118
+
119
+ // Get current and total orders
120
+ $currentOrderTotal = floatval($order->getGrandTotal());
121
+ $allOrdersTotalAmount += $currentOrderTotal;
122
+
123
+ $currentOrderCreationDate = $order->getCreatedAt();
124
+ if ($currentOrderCreationDate > $thirtyDaysAgo) {
125
+ $last30daysOrdersAmount += $currentOrderTotal;
126
+ }
127
+ if ($currentOrderCreationDate > $twelveMonthsAgo) {
128
+ $last12monthsOrdersAmount += $currentOrderTotal;
129
+ }
130
+
131
+ $currentOrderTotal = self::_formatPrice($currentOrderTotal);
132
+ $currentOrderId = $order->getIncrementId();
133
+ $allOrdersTotals[$currentOrderId] = $currentOrderTotal;
134
+ $allOrdersDateTimes[$currentOrderId] = $currentOrderCreationDate;
135
+ $allOrdersIds[$currentOrderId] = $currentOrderId;
136
+
137
+ if ($order->hasShipments() and ($order->getId() > $lastShipmentOrderId)) {
138
+ $lastShipmentOrderId = $order->getId();
139
+ $lastShipmentOrderDate = self::_retriveDateFromDatetime($order->getCreatedAt());
140
+ }
141
+
142
+ $items = $order->getAllItems();
143
+ foreach ($items as $item) {
144
+ $allProductsIds[] = $item->getProductId();
145
+ }
146
+ }
147
+
148
+ $toSend[$i]['TotaleFatturatoUltimi30gg'] = self::_formatPrice($last30daysOrdersAmount);
149
+ $toSend[$i]['TotaleFatturatoUltimi12Mesi'] = self::_formatPrice($last12monthsOrdersAmount);
150
+ $toSend[$i]['IDTuttiProdottiAcquistati'] = implode(',', $allProductsIds);
151
+
152
+ ksort($allOrdersDateTimes);
153
+ ksort($allOrdersTotals);
154
+ ksort($allOrdersIds);
155
+
156
+ //recupero i carrelli abbandonati del cliente
157
+ if ($config->isLogEnabled()) {
158
+ $config->log('Parsing abandoned carts of customer with id '.$currentCustomerId);
159
+ }
160
+ $cartCollection = Mage::getResourceModel('reports/quote_collection');
161
+ $cartCollection->prepareForAbandonedReport($config->getAllStoreIds());
162
+ $cartCollection->addFieldToFilter('customer_id', $currentCustomerId);
163
+ $cartCollection->load();
164
+
165
+ $datetimeCart = null;
166
+ if (!empty($cartCollection)) {
167
+ $lastCart = $cartCollection->getLastItem();
168
+ $toSend[$i]['TotaleCarrelloAbbandonato'] = '';
169
+ $toSend[$i]['DataCarrelloAbbandonato'] = '';
170
+ $toSend[$i]['IDCarrelloAbbandonato'] = '';
171
+
172
+ if (!empty($lastCart)) {
173
+ if ($config->isLogEnabled()) {
174
+ $config->log('Customer with id '.$currentCustomerId.' has abandoned cart');
175
+ }
176
+ $datetimeCart = $lastCart->getUpdatedAt();
177
+ //$toSend[$i]['TotaleCarrelloAbbandonato'] = self::_formatPrice($lastCart->getGrandTotal());
178
+ $toSend[$i]['TotaleCarrelloAbbandonato'] = self::_formatPrice($lastCart->getSubtotal());
179
+ $toSend[$i]['DataCarrelloAbbandonato'] = self::_retriveDateFromDatetime($datetimeCart);
180
+ $toSend[$i]['IDCarrelloAbbandonato'] = $lastCart->getId();
181
+ } else {
182
+ if ($config->isLogEnabled()) {
183
+ $config->log('Customer with id '.$currentCustomerId.' has empty LAST CART');
184
+ }
185
+ }
186
+ } else {
187
+ if ($config->isLogEnabled()) {
188
+ $config->log('Customer id '.$currentCustomerId.' has empty abandoned cart collection');
189
+ }
190
+ }
191
+
192
+ $toSend[$i]['IDUltimoOrdineSpedito'] = $lastShipmentOrderId;
193
+ $toSend[$i]['DataUltimoOrdineSpedito'] = $lastShipmentOrderDate;
194
+
195
+ $lastOrderDateTime = end($allOrdersDateTimes);
196
+
197
+ if ($customer->getUpdatedAt() > $lastDateTime
198
+ || $lastOrderDateTime > $lastDateTime
199
+ || ($datetimeCart && $datetimeCart > $lastDateTime)) {
200
+ if ($config->isLogEnabled()) {
201
+ $config->log('Adding customer with id '.$currentCustomerId);
202
+ }
203
+
204
+ $toSend[$i]['nome'] = $customer->getFirstname();
205
+ $toSend[$i]['cognome'] = $customer->getLastname();
206
+ $toSend[$i]['email'] = $customer->getEmail();
207
+ $toSend[$i]['IDCliente'] = $currentCustomerId;
208
+
209
+ // Custom customer attributes
210
+ $customerAttributes = Mage::helper('emailchef/customer')->getCustomCustomerAttrCollection();
211
+ foreach ($customerAttributes as $attribute) {
212
+ $code = $attribute->getAttributeCode().'_custom_customer_attributes';
213
+ $value = $customer->getData($attribute->getAttributeCode());
214
+ if ($attribute->usesSource()) {
215
+ /* Attempt to get source model. As we cannot trust customers to have not leave broken
216
+ attributes with invalid source models around, we will test this directly */
217
+ $source = Mage::getModel($attribute->getSourceModel());
218
+ if ($source == false) {
219
+ if ($config->isLogEnabled()) {
220
+ $config->log('Invalid source model for attribute '.$attribute->getAttributeCode());
221
+ }
222
+ $toSend[$i][$code] = null;
223
+ } else {
224
+ $toSend[$i][$code] = $attribute->getSource()->getOptionText($value);
225
+ }
226
+ } else {
227
+ $toSend[$i][$code] = $value;
228
+ }
229
+ }
230
+
231
+ $toSend[$i]['registeredDate'] = self::_retriveDateFromDatetime($customer->getCreatedAt());
232
+
233
+ //controllo se iscritto o meno alla newsletter
234
+ if (Mage::getModel('newsletter/subscriber')->loadByCustomer($customer)->isSubscribed()) {
235
+ $toSend[$i]['subscribed'] = 'yes';
236
+ } else {
237
+ $toSend[$i]['subscribed'] = 'no';
238
+ }
239
+
240
+ //recupero i dati dal default billing address
241
+ $customerAddressId = $customer->getDefaultBilling();
242
+ if ($customerAddressId) {
243
+ $address = Mage::getModel('customer/address')->load($customerAddressId);
244
+ $toSend[$i]['azienda'] = $address->getData('company');
245
+ $toSend[$i]['paese'] = $address->getCountry();
246
+ $toSend[$i]['città'] = $address->getData('city');
247
+ $toSend[$i]['regione'] = $address->getData('region');
248
+ $regionId = $address->getData('region_id');
249
+ $regionModel = Mage::getModel('directory/region')->load($regionId);
250
+ $regionCode = $regionModel->getCode();
251
+ $toSend[$i]['provincia'] = $regionCode;
252
+ $toSend[$i]['cap'] = $address->getData('postcode');
253
+ $toSend[$i]['indirizzo'] = $address->getData('street');
254
+ $toSend[$i]['fax'] = $address->getData('fax');
255
+ $toSend[$i]['telefono'] = $address->getData('telephone');
256
+ } else {
257
+ $toSend[$i]['azienda'] = '';
258
+ $toSend[$i]['paese'] = '';
259
+ $toSend[$i]['città'] = '';
260
+ $toSend[$i]['regione'] = '';
261
+ $toSend[$i]['provincia'] = '';
262
+ $toSend[$i]['cap'] = '';
263
+ $toSend[$i]['indirizzo'] = '';
264
+ $toSend[$i]['fax'] = '';
265
+ $toSend[$i]['telefono'] = '';
266
+ }
267
+
268
+ $toSend[$i]['DataUltimoOrdine'] = self::_retriveDateFromDatetime($lastOrderDateTime);
269
+ $toSend[$i]['TotaleUltimoOrdine'] = end($allOrdersTotals);
270
+ $toSend[$i]['IDUltimoOrdine'] = end($allOrdersIds);
271
+
272
+ $toSend[$i]['TotaleFatturato'] = self::_formatPrice($allOrdersTotalAmount);
273
+
274
+ //ottengo gli id di prodotti e categorie (dell'ultimo ordine)
275
+ $lastOrder = Mage::getModel('sales/order')->loadByIncrementId(end($allOrdersIds));
276
+ $items = $lastOrder->getAllItems();
277
+ $productIds = array();
278
+ $categoryIds = array();
279
+ foreach ($items as $item) {
280
+ $productId = $item->getProductId();
281
+ $productIds[] = $productId;
282
+ $product = Mage::getModel('catalog/product')->load($productId);
283
+ if ($product->getCategoryIds()) {
284
+ $categoryIds[] = implode(',', $product->getCategoryIds());
285
+ }
286
+ }
287
+
288
+ $toSend[$i]['IDProdottiUltimoOrdine'] = implode(',', $productIds);
289
+ if ($toSend[$i]['IDProdottiUltimoOrdine']) {
290
+ $toSend[$i]['IDProdottiUltimoOrdine'] = ",{$toSend[$i]['IDProdottiUltimoOrdine']},";
291
+ }
292
+ $toSend[$i]['IDCategorieUltimoOrdine'] = implode(',', $categoryIds);
293
+ if ($toSend[$i]['IDCategorieUltimoOrdine']) {
294
+ $toSend[$i]['IDCategorieUltimoOrdine'] = ",{$toSend[$i]['IDCategorieUltimoOrdine']},";
295
+ }
296
+ }
297
+
298
+ $toSend[$i]['DateOfBirth'] = self::_retriveDobFromDatetime($customer->getDob());
299
+ $toSend[$i]['Gender'] = $customer->getAttribute('gender')->getSource()->getOptionText($customer->getGender());
300
+
301
+ //unsetto la variabile
302
+ unset($customer);
303
+ }
304
+
305
+ /*
306
+ * disabled cause useless in segmentation
307
+ if ($parseSubscribers) {
308
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) Mage::log('Parsing subscribers', 0);
309
+ $subscriberCollection = Mage::getModel('newsletter/subscriber')
310
+ ->getCollection()
311
+ ->useOnlySubscribed()
312
+ ->addFieldToFilter('customer_id', 0);
313
+
314
+ foreach ($subscriberCollection as $subscriber) {
315
+ $subscriber = Mage::getModel('newsletter/subscriber')->load($subscriber->getId());
316
+ $i = $subscriber->getEmail();
317
+ if (strlen($i)) continue;
318
+ if (isset($toSend[$i])) continue;
319
+ $toSend[$i]['nome'] = '';
320
+ $toSend[$i]['cognome'] = '';
321
+ $toSend[$i]['email'] = $i;
322
+ $toSend[$i]['subscribed'] = 'yes';
323
+ }
324
+ }
325
+ */
326
+
327
+ if ($config->isLogEnabled()) {
328
+ $config->log('End getting customers data');
329
+ }
330
+
331
+ return $toSend;
332
+ }
333
+
334
+ /**
335
+ * Send Customer Data.
336
+ *
337
+ * @param array $emailchefCustomerIds
338
+ * @param array
339
+ * @param int
340
+ *
341
+ * @return int|false ReturnCode
342
+ */
343
+ public static function generateAndSendCustomers($emailchefCustomerIds, $post = null, $storeId = null)
344
+ {
345
+ $config = Mage::getModel('emailchef/config');
346
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
347
+
348
+ $wsSend = new EMailChefWsSend($storeId);
349
+ require_once dirname(__FILE__).'/../Model/EMailChefWsImport.php';
350
+ $wsImport = new EMailChefWsImport($storeId);
351
+ $accessKey = $wsSend->loginFromId();
352
+
353
+ if (empty($emailchefCustomerIds)) {
354
+ if ($config->isLogEnabled($storeId)) {
355
+ $config->log('generateAndSendCustomers [Empty Customer ID Array]');
356
+ }
357
+
358
+ return false;
359
+ }
360
+
361
+ $jobId = $post['id'];
362
+ $jobModel = Mage::getModel('emailchef/job')->load($post['id']);
363
+ /* @var $jobModel EMailChef_EMailChefSync_Model_Job */
364
+
365
+ if ($accessKey === false) {
366
+ Mage::throwException('no access key returned');
367
+ }
368
+
369
+ $fields_mapping = $wsImport->getFieldsMapping($storeId); // Pass StoreId
370
+ if (count($fields_mapping) == 0) {
371
+ if ($config->isLogEnabled($storeId)) {
372
+ $config->log('No mappings set, so cannot sync customers');
373
+ }
374
+
375
+ return false;
376
+ }
377
+
378
+ // Define the group we're adding customers to
379
+ $groupId = $post['emailchefGroupId'];
380
+ $listGUID = $post['emailchefListGUID'];
381
+ $idList = $post['emailchefIdList'];
382
+
383
+ /*
384
+ * Create a new EMailChef Group.
385
+ */
386
+ if ($post['emailchefNewGroup'] == 1) {
387
+ $newGroup = array(
388
+ 'idList' => $idList,
389
+ 'listGUID' => $listGUID,
390
+ 'newGroupName' => $post['emailchefNewGroupName'],
391
+ );
392
+ $groupId = $wsImport->CreaGruppo($newGroup, $accessKey);
393
+ }
394
+
395
+ $importProcessData = array(
396
+ 'idList' => $idList,
397
+ 'listGUID' => $listGUID,
398
+ 'idGroup' => $groupId,
399
+ 'xmlDoc' => '',
400
+ 'idGroups' => $groupId,
401
+ 'importType' => self::IMPORT_TYPE_REPLACE_EMPTY_ONLY_EMAIL,
402
+ 'mobileInputType' => self::MOBILE_INPUT_TYPE_SPLIT_INTL_CODE,
403
+ 'ConfirmEmail' => 0,
404
+ 'asOptOut' => 0,
405
+ 'forceOptIn' => 0, // Dangerous to use as this can over-write pending/un-subscribe statuses
406
+ 'replaceGroups' => 0,
407
+ );
408
+
409
+ $subscribers_counter = 0;
410
+ $totalCustomers = sizeof($emailchefCustomerIds);
411
+ $customers = array();
412
+ foreach ($emailchefCustomerIds as $customerId) {
413
+ ++$subscribers_counter;
414
+ $customers[] = self::getCustomerData($customerId, $fields_mapping, $storeId);
415
+ }
416
+ /*
417
+ * Build Data for StartImportProcesses
418
+ */
419
+ $startImportProcessesData = array(
420
+ 'listsIDs' => $post['emailchefIdList'],
421
+ 'listsGUIDs' => $post['emailchefListGUID'],
422
+ 'groupsIDs' => $groupId,
423
+ 'idList' => $idList,
424
+ 'customers' => $customers,
425
+ 'importType' => self::IMPORT_TYPE_REPLACE_EMPTY_ONLY_EMAIL,
426
+ 'mobileInputType' => self::MOBILE_INPUT_TYPE_SPLIT_INTL_CODE,
427
+ 'ConfirmEmail' => 0,
428
+ 'asOptOut' => 0,
429
+ 'forceOptIn' => 0, // Dangerous to use as this can over-write pending/un-subscribe statuses
430
+ 'replaceGroups' => 0,
431
+ );
432
+
433
+ if ($config->isLogEnabled($storeId)) {
434
+ $config->log("emailchef: StartImportProcesses (STORE: {$storeId})", $storeId);
435
+ $config->log($startImportProcessesData);
436
+ }
437
+ $startProcessesReturnCode = $wsImport->StartImportProcesses($startImportProcessesData, $accessKey);
438
+ /*
439
+ * Save the Job Model, and update the tries as we've just tried to Start the Process
440
+ */
441
+ $jobModel->incrementTries();
442
+ try {
443
+ $jobModel->save();
444
+ } catch (Exception $e) {
445
+ Mage::log($e->getMessage());
446
+ }
447
+ if ($config->isLogEnabled($storeId)) {
448
+ if ($startProcessesReturnCode < 0) {
449
+ $config->dbLog(sprintf('StartImportProcesses [ReturnCode] [ERROR] [%d]', $startProcessesReturnCode), $jobId, $storeId);
450
+ } else {
451
+ $config->dbLog(sprintf('StartImportProcesses [ReturnCode] [SUCCESS] [%d]', $startProcessesReturnCode), $jobId, $storeId);
452
+ }
453
+ }
454
+
455
+ return $startProcessesReturnCode;
456
+ }
457
+
458
+ /**
459
+ * Get a single customer data.
460
+ *
461
+ * @param int $customerId
462
+ * @param array $fields_mapping
463
+ * @param int $storeId
464
+ *
465
+ * @return string|false
466
+ */
467
+ protected static function getCustomerData($customerId, $fields_mapping, $storeId)
468
+ {
469
+ $config = Mage::getModel('emailchef/config');
470
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
471
+ $data = array();
472
+ $mappedData = array();
473
+ $subscriber = self::getCustomersData(array($customerId));
474
+
475
+ if (is_array($subscriber) && empty($subscriber)) {
476
+ if ($config->isLogEnabled($storeId)) {
477
+ $config->log('getCustomersData [EMPTY]');
478
+ }
479
+ }
480
+
481
+ $subscriber = array_values($subscriber);
482
+ $subscriber = $subscriber[0];
483
+
484
+ $subscriber['DataCarrelloAbbandonato'] = self::_convertUTCToStoreTimezoneAndFormatForEMailChef($subscriber['DataCarrelloAbbandonato']);
485
+ $subscriber['DataUltimoOrdineSpedito'] = self::_convertUTCToStoreTimezoneAndFormatForEMailChef($subscriber['DataUltimoOrdineSpedito']);
486
+ $subscriber['registeredDate'] = self::_convertUTCToStoreTimezoneAndFormatForEMailChef($subscriber['registeredDate']);
487
+ $subscriber['DataUltimoOrdine'] = self::_convertUTCToStoreTimezoneAndFormatForEMailChef($subscriber['DataUltimoOrdine']);
488
+
489
+ foreach ($subscriber as $k => $v) {
490
+ if (!strlen($subscriber[$k])) {
491
+ $subscriber[$k] = ' '; // blank it out in emailchef
492
+ } else {
493
+ $subscriber[$k] = str_replace(array("\r\n", "\r", "\n"), ' ', $v);
494
+ }
495
+ }
496
+
497
+ $defaultMappings = array(
498
+ 'Name' => 'nome',
499
+ 'Last' => 'cognome',
500
+ 'Email' => 'email',
501
+ 'Company' => 'azienda',
502
+ 'City' => 'città',
503
+ 'Province' => 'provincia',
504
+ 'ZIP' => 'cap',
505
+ 'Region' => 'regione',
506
+ 'Country' => 'paese',
507
+ 'Address' => 'indirizzo',
508
+ 'Fax' => 'fax',
509
+ 'Phone' => 'telefono',
510
+ 'CustomerID' => 'IDCliente',
511
+ 'LatestOrderID' => 'IDUltimoOrdine',
512
+ 'LatestOrderDate' => 'DataUltimoOrdine',
513
+ 'LatestOrderAmount' => 'TotaleUltimoOrdine',
514
+ 'LatestOrderProductIDs' => 'IDProdottiUltimoOrdine',
515
+ 'LatestOrderCategoryIDs' => 'IDCategorieUltimoOrdine',
516
+ 'LatestShippedOrderDate' => 'DataUltimoOrdineSpedito',
517
+ 'LatestShippedOrderID' => 'IDUltimoOrdineSpedito',
518
+ 'LatestAbandonedCartDate' => 'DataCarrelloAbbandonato',
519
+ 'LatestAbandonedCartTotal' => 'TotaleCarrelloAbbandonato',
520
+ 'LatestAbandonedCartID' => 'IDCarrelloAbbandonato',
521
+ 'TotalOrdered' => 'TotaleFatturato',
522
+ 'TotalOrderedLast12m' => 'TotaleFatturatoUltimi12Mesi',
523
+ 'TotalOrderedLast30d' => 'TotaleFatturatoUltimi30gg',
524
+ 'AllOrderedProductIDs' => 'IDTuttiProdottiAcquistati',
525
+ 'DateOfBirth' => 'DateOfBirth',
526
+ 'Gender' => 'Gender',
527
+ );
528
+ $defaultMappings = array_reverse($defaultMappings);
529
+
530
+ foreach ($fields_mapping as $mappingKey => $mappingValue) {
531
+ if (!$mappingValue) {
532
+ continue;
533
+ }
534
+ $mappingKeyNamed = $mappingKey;
535
+ if (isset($defaultMappings[$mappingKey])) {
536
+ $mappingKeyNamed = $defaultMappings[$mappingKey];
537
+ }
538
+ if (isset($subscriber[$mappingKeyNamed]) && trim(($subscriber[$mappingKeyNamed]))) {
539
+ $data[$mappingValue] = $subscriber[$mappingKeyNamed];
540
+ }
541
+ }
542
+
543
+ // No point in continuing if there is no mapped data
544
+ if (count($data) == 0) {
545
+ if ($config->isLogEnabled($storeId)) {
546
+ $config->log('No mappings set, so cannot sync customers');
547
+ }
548
+
549
+ return false;
550
+ }
551
+
552
+ return $data;
553
+ }
554
+
555
+ /**
556
+ * Run a particular job.
557
+ *
558
+ * @param int
559
+ */
560
+ public function runJob($jobId)
561
+ {
562
+ $config = Mage::getModel('emailchef/config');
563
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
564
+ require_once dirname(__FILE__).'/../Helper/Data.php';
565
+ $db_read = Mage::getSingleton('core/resource')->getConnection('core_read');
566
+ $db_write = Mage::getSingleton('core/resource')->getConnection('core_write');
567
+ $syncTableName = Mage::getSingleton('core/resource')->getTableName('emailchef/sync');
568
+ $jobsTableName = Mage::getSingleton('core/resource')->getTableName('emailchef/job');
569
+ $lastsync = gmdate('Y-m-d H:i:s');
570
+ // reading customers (jobid == 0, their updates)
571
+ $customer_entity_table_name = Mage::getSingleton('core/resource')->getTableName('customer_entity');
572
+ $jobModel = Mage::getModel('emailchef/job')->load($jobId);
573
+ /* @var $jobModel EMailChef_EMailChefSync_Model_Job */
574
+
575
+ if (!$jobModel) {
576
+ throw new Mage_Exception('No Job Exists: '.$jobId);
577
+ }
578
+
579
+ $job = $jobModel->getData();
580
+ $stmt = $db_write->query(
581
+ "UPDATE {$jobsTableName}
582
+ SET status='started', start_datetime='".gmdate('Y-m-d H:i:s')."'
583
+ WHERE id={$job['id']}"
584
+ );
585
+ $storeId = isset($job['store_id']) ? $job['store_id'] : null;
586
+ //$storeId = Mage::app()->getDefaultStoreView()->getStoreId(); // Fallback incase not set?!?
587
+ $customers = array();
588
+ $job['emailchefNewGroup'] = 0;
589
+ $job['emailchefIdList'] = Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $storeId);
590
+ $job['emailchefGroupId'] = $job['emailchefgroupid'];
591
+
592
+ // If group is 0 and there is a default group, set group to this group
593
+ $defaultGroupId = Mage::getStoreConfig('emailchef_newsletter/emailchef/default_group');
594
+ if ($job['emailchefGroupId'] == 0 && $defaultGroupId !== null) {
595
+ $job['emailchefGroupId'] = $defaultGroupId;
596
+ }
597
+
598
+ $tmp = Mage::getSingleton('emailchef/source_lists');
599
+ $tmp = $tmp->toOptionArray($storeId); // pass store id!
600
+ foreach ($tmp as $t) {
601
+ if ($t['value'] == $job['emailchefIdList']) {
602
+ $job['emailchefListGUID'] = $t['guid'];
603
+ $job['groups'] = $t['groups'];
604
+ break;
605
+ }
606
+ }
607
+ unset($tmp);
608
+ unset($t);
609
+ $stmt = $db_read->query("
610
+ SELECT ms.*, ce.email
611
+ FROM {$syncTableName} ms
612
+ JOIN $customer_entity_table_name ce
613
+ ON (ms.customer_id = ce.entity_id)
614
+ WHERE ms.needs_sync=1
615
+ AND ms.entity='customer'
616
+ AND job_id={$job['id']}"
617
+ );
618
+ while ($row = $stmt->fetch()) {
619
+ $customers[] = $row['customer_id'];
620
+ }
621
+ /*
622
+ * Send the Data!
623
+ */
624
+ $returnCode = self::generateAndSendCustomers($customers, $job, $storeId);
625
+ /*
626
+ * Check return OK
627
+ */
628
+ if ($returnCode === true) {
629
+ $customerCount = count($customers);
630
+ $db_write->query("
631
+ UPDATE {$syncTableName} SET needs_sync=0, last_sync='$lastsync'
632
+ WHERE job_id = {$job['id']}
633
+ AND entity='customer'"
634
+ );
635
+ $config->dbLog("Job Task [update] [Synced] [customer count:{$customerCount}]", $job['id'], $storeId);
636
+ // finishing the job also
637
+ $db_write->query("
638
+ UPDATE {$jobsTableName} SET status='finished', finish_datetime='".gmdate('Y-m-d H:i:s')."'
639
+ WHERE id={$job['id']}"
640
+ );
641
+ $config->dbLog("Jobs [Update] [Complete] [{$job['id']}]", $job['id'], $storeId);
642
+ }
643
+ /*
644
+ * Only successfull if we get 0 back. False is also a fail.
645
+ */
646
+ else {
647
+ $stmt = $db_write->query(
648
+ "UPDATE {$jobsTableName} SET status='queued' WHERE id={$job['id']}"
649
+ );
650
+ if ($config->isLogEnabled()) {
651
+ $config->dbLog(sprintf('generateAndSendCustomers [ReturnCode] [ERROR] [%d]', $returnCode), $job['id'], $storeId);
652
+ }
653
+ }
654
+ }
655
+
656
+ /**
657
+ * Get sub Categories of a Category.
658
+ *
659
+ * @param int
660
+ *
661
+ * @return array|string
662
+ */
663
+ public function getSubCategories($categoryId)
664
+ {
665
+ // Not sure what version this was introduced.
666
+ $parent = Mage::getModel('catalog/category')->load($categoryId);
667
+ $children = $parent->getAllChildren(true);
668
+
669
+ if (!empty($children) && is_array($children)) {
670
+ return $children;
671
+ }
672
+
673
+ return array();
674
+
675
+ // // Maybe fall back to this in older versions?
676
+ // $ids = array();
677
+ // $children = Mage::getModel('catalog/category')->getCategories($categoryId);
678
+ // foreach ($children as $category) {
679
+ // /* @var $category Mage_Catalog_Model_Category */
680
+ // $ids[] = $category->getId();
681
+ // }
682
+ //
683
+ // return $ids;
684
+ }
685
+
686
+ /**
687
+ * Format the Price.
688
+ *
689
+ * @param float
690
+ *
691
+ * @return string
692
+ */
693
+ private static function _formatPrice($price)
694
+ {
695
+ return number_format($price, 2, '.', '');
696
+ }
697
+
698
+ /**
699
+ * Get Date from DateTime.
700
+ *
701
+ * @param type $datetime
702
+ *
703
+ * @return string
704
+ */
705
+ private static function _retriveDateFromDatetime($datetime)
706
+ {
707
+ if (empty($datetime)) {
708
+ return '';
709
+ }
710
+
711
+ return date('Y-m-d H:i:s', strtotime($datetime));
712
+ }
713
+
714
+ /**
715
+ * Get DOB Format from DateTime.
716
+ *
717
+ * @param string $datetime
718
+ *
719
+ * @return string
720
+ */
721
+ private static function _retriveDobFromDatetime($datetime)
722
+ {
723
+ if (empty($datetime)) {
724
+ return '';
725
+ }
726
+
727
+ return date('Y-m-d', strtotime($datetime));
728
+ }
729
+
730
+ public static function _convertUTCToStoreTimezone($datetime)
731
+ {
732
+ if (empty($datetime)) {
733
+ return '';
734
+ }
735
+
736
+ $TIMEZONE_STORE = new DateTimeZone(Mage::getStoreConfig('general/locale/timezone'));
737
+ $TIMEZONE_UTC = new DateTimeZone('UTC');
738
+
739
+ $datetime = new DateTime($datetime, $TIMEZONE_UTC);
740
+ $datetime->setTimezone($TIMEZONE_STORE);
741
+ $datetime = (string) $datetime->format('Y-m-d H:i:s');
742
+
743
+ return $datetime;
744
+ }
745
+
746
+ public static function _convertUTCToStoreTimezoneAndFormatForEMailChef($datetime)
747
+ {
748
+ if (empty($datetime)) {
749
+ return '';
750
+ }
751
+ $datetime = self::_convertUTCToStoreTimezone($datetime);
752
+
753
+ return date('Y-m-d', strtotime($datetime));
754
+ }
755
+
756
+ /**
757
+ * Clean the Resource Table.
758
+ */
759
+ public function cleanResourceTable()
760
+ {
761
+ $sql = "DELETE FROM `core_resource` WHERE `code` = 'emailchef_setup';";
762
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_write');
763
+ try {
764
+ $connection->query($sql);
765
+ die('deleted module in core_resource!');
766
+ } catch (Exception $e) {
767
+ Mage::log($e->getMessage());
768
+ }
769
+ }
770
+
771
+ /**
772
+ * Clean the Resource Table.
773
+ */
774
+ public function showResourceTable()
775
+ {
776
+ $sql = 'SELECT * FROM `core_resource`';
777
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
778
+ try {
779
+ $result = $connection->fetchAll($sql);
780
+ foreach ($result as $row) {
781
+ echo $row['code'].'<br />';
782
+ }
783
+ } catch (Exception $e) {
784
+ echo $e->getMessage();
785
+ }
786
+ }
787
+
788
+ /**
789
+ * Get all product attributes.
790
+ *
791
+ * Note if we don't use a keyed array below the first item with key 0
792
+ * gets replaced by an empty option by magento. this results in a missing attribute
793
+ * from the list!
794
+ *
795
+ * @reutrn array
796
+ */
797
+ public function getAllProductAttributes()
798
+ {
799
+ //$attributes = Mage::getModel('catalog/product')->getAttributes();
800
+ $attributes = Mage::getSingleton('eav/config')
801
+ ->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getAttributeCollection()
802
+ ;
803
+ // Localize attribute label (if you need it)
804
+ $attributes->addStoreLabel(Mage::app()->getStore()->getId());
805
+ $attributeArray = array();
806
+ foreach ($attributes as $att) {
807
+ /* @var $att Mage_Catalog_Model_Resource_Eav_Attribute */
808
+ if ($att->getIsVisible()) {
809
+ $attributeArray[$att->getAttributeCode()] = array(
810
+ 'value' => $att->getAttributeCode(),
811
+ 'label' => $att->getStoreLabel() ? $att->getStoreLabel() : $att->getFrontendLabel(),
812
+ );
813
+ }
814
+ }
815
+
816
+ return $attributeArray;
817
+ }
818
+
819
+ /**
820
+ * Get all product attributes.
821
+ *
822
+ * Note if we don't use a keyed array below the first item with key 0
823
+ * gets replaced by an empty option by magento. this results in a missing attribute
824
+ * from the list!
825
+ *
826
+ * @reutrn array
827
+ */
828
+ public function getAllCustomerAttributes()
829
+ {
830
+ //$attributes = Mage::getModel('catalog/product')->getAttributes();
831
+ $attributes = Mage::getSingleton('eav/config')
832
+ ->getEntityType('customer')->getAttributeCollection()
833
+ ;
834
+ // Localize attribute label (if you need it)
835
+ $attributes->addStoreLabel(Mage::app()->getStore()->getId());
836
+ $attributeArray = array();
837
+ foreach ($attributes as $att) {
838
+ /* @var $att Mage_Catalog_Model_Resource_Eav_Attribute */
839
+ if ($att->getIsVisible()) {
840
+ $attributeArray[$att->getAttributeCode()] = array(
841
+ 'value' => $att->getAttributeCode(),
842
+ 'label' => $att->getStoreLabel() ? $att->getStoreLabel() : $att->getFrontendLabel(),
843
+ );
844
+ }
845
+ }
846
+
847
+ return $attributeArray;
848
+ }
849
+
850
+ /**
851
+ * Is someone a subscriber?
852
+ *
853
+ * @param int
854
+ * @param int
855
+ *
856
+ * @return bool
857
+ */
858
+ public function isSubscriber($customerId, $storeId)
859
+ {
860
+ $statuses = array(
861
+ Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED,
862
+ );
863
+
864
+ return $this->_isSubscriberInStatus($customerId, $statuses, $storeId);
865
+ }
866
+
867
+ /**
868
+ * Is the given customer a subscriber with the given status?
869
+ * Note that an empty set of statuses will just return true.
870
+ *
871
+ * @param $customerId
872
+ * @param array $statuses
873
+ * @param $storeId
874
+ *
875
+ * @return bool|mixed
876
+ */
877
+ protected function _isSubscriberInStatus($customerId, array $statuses, $storeId)
878
+ {
879
+ $customerId = (int) $customerId;
880
+ $storeId = (int) $storeId;
881
+
882
+ // If no status set given, just return true
883
+ if (empty($statuses)) {
884
+ return true;
885
+ }
886
+
887
+ $table = Mage::getSingleton('core/resource')->getTableName('newsletter_subscriber');
888
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
889
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
890
+ Mage::log('check subscription status '.$customerId);
891
+ }
892
+ $sql = "SELECT * FROM {$table} WHERE customer_id = '{$customerId}'";
893
+ try {
894
+ $result = $connection->fetchAll($sql); // array
895
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
896
+ Mage::log('check subscription result '.var_export($result, true).' statuses '.var_export($statuses, true));
897
+ }
898
+ if (count($result) == 0) {
899
+ return false;
900
+ }
901
+ $result = $result[0];
902
+
903
+ // Return whether status is in given set
904
+ return array_search($result['subscriber_status'], $statuses) !== false;
905
+ } catch (Exception $e) {
906
+ Mage::log($e->getMessage());
907
+ }
908
+
909
+ return false;
910
+ }
911
+
912
+ /**
913
+ * Schedule a Task.
914
+ *
915
+ * @param string
916
+ * @param string
917
+ */
918
+ public function scheduleTask($when, $type = 'EMailChef_EMailChefSync')
919
+ {
920
+ $write = Mage::getSingleton('core/resource')->getConnection('core_write');
921
+ $write->insert(Mage::getSingleton('core/resource')->getTableName('cron_schedule'), array(
922
+ 'job_code' => $type,
923
+ 'status' => 'pending',
924
+ 'created_at' => gmdate('Y-m-d H:i:s'),
925
+ 'scheduled_at' => $when,
926
+ ));
927
+ }
928
+
929
+ /**
930
+ * Retrieve Attribute Id Data By Id or Code.
931
+ *
932
+ * @param mixed
933
+ * @param int
934
+ *
935
+ * @return int
936
+ */
937
+ public function getAttributeId($id, $entityTypeId = null)
938
+ {
939
+ if ($entityTypeId == null) {
940
+ $entityTypeId = Mage::getModel('catalog/product')->getResource()->getEntityType()->getId();
941
+ }
942
+
943
+ $installer = new Mage_Catalog_Model_Resource_Eav_Mysql4_Setup('core_setup');
944
+ if (!is_numeric($id)) {
945
+ $id = $installer->getAttribute($entityTypeId, $id, 'attribute_id');
946
+ }
947
+ if (!is_numeric($id)) {
948
+ //throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Wrong attribute ID.'));
949
+ return false;
950
+ }
951
+
952
+ return $id;
953
+ }
954
+
955
+ /**
956
+ * Get ListGuid (Alphanumeric code associated to a distribution list) for given list.
957
+ *
958
+ * @param $listId
959
+ *
960
+ * @return false|string
961
+ */
962
+ public function getListGuid($listId)
963
+ {
964
+ $wsSend = new EMailChefWsSend();
965
+ $accessKey = $wsSend->loginFromId();
966
+ $wsImport = new EMailChefWsImport();
967
+ $lists = $wsImport->GetNlList($accessKey, true);
968
+
969
+ $listGUID = false;
970
+ foreach ($lists as $list) {
971
+ if ($list->id == $listId) {
972
+ $groups = $list->groups;
973
+ foreach ($groups as $group) {
974
+ // TODO: check random group ?
975
+ $listGUID = (string) $group->id;
976
+ }
977
+ break;
978
+ }
979
+ }
980
+
981
+ return $listGUID;
982
+ }
983
+
984
+
985
+ /**
986
+ * Test all EMailChef Connection details.
987
+ *
988
+ * @param $usernameWs
989
+ * @param $passwordWs
990
+ * @param $storeId
991
+ *
992
+ * @return array Return array of messages (success or errors)
993
+ */
994
+ public function testConnection($usernameWs, $passwordWs, $storeId)
995
+ {
996
+ $messages = array();
997
+
998
+ // Run test for username and password
999
+ if ($this->_testConnectionUserPassword($usernameWs, $passwordWs, $storeId) === false) {
1000
+ $messages[] = array(
1001
+ 'message' => $this->__('Error in email / password'),
1002
+ 'type' => 'error',
1003
+ );
1004
+ }
1005
+
1006
+ if (empty($messages)) {
1007
+ $messages[] = array(
1008
+ 'message' => $this->__('Success! Connection established with eMailChef with given details'),
1009
+ 'type' => 'success',
1010
+ );
1011
+ }
1012
+
1013
+ return $messages;
1014
+ }
1015
+
1016
+ /**
1017
+ * Test configuration for common issues.
1018
+ *
1019
+ * @return array Return array of messages (warnings)
1020
+ */
1021
+ public function testConfig()
1022
+ {
1023
+ $messages = array();
1024
+
1025
+ // Mysql timeout
1026
+ $timeout = ini_get('mysql.connect_timeout');
1027
+ if ($timeout !== false && $timeout < 60) {
1028
+ $messages[] = array(
1029
+ 'message' => $this->__('Config warning: mysql.connect_timeout is %d which is a bit low. '.
1030
+ 'This may cause intermittent issues when connecting with eMailChef. '.
1031
+ 'Please contact your Web host to discuss an increase in the timeout setting.', $timeout),
1032
+ 'type' => 'warning',
1033
+ );
1034
+ }
1035
+
1036
+ return $messages;
1037
+ }
1038
+
1039
+ /**
1040
+ * Test username and password.
1041
+ *
1042
+ * @param $usernameWs
1043
+ * @param $passwordWs
1044
+ * @param $storeId
1045
+ *
1046
+ * @return bool
1047
+ */
1048
+ protected function _testConnectionUserPassword($usernameWs, $passwordWs, $storeId)
1049
+ {
1050
+ $wssend = new EMailChefWsSend($storeId);
1051
+
1052
+ $loginSuccess = $wssend->loginFromId($usernameWs, $passwordWs);
1053
+
1054
+ return $loginSuccess !== false;
1055
+ }
1056
+ }
app/code/community/EMailChef/EMailChefSync/Helper/Order.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Order helper methods for EMailChef.
4
+ */
5
+ class EMailChef_EMailChefSync_Helper_Order extends Mage_Core_Helper_Abstract
6
+ {
7
+ /**
8
+ * Filter an order collection by status/state depending on EMailChef config
9
+ * NOTE that cannot override collection consistently as the class changed name in 1.6.
10
+ *
11
+ * @param Varien_Data_Collection_Db $collection
12
+ *
13
+ * @return $this
14
+ */
15
+ public function addStatusFilterToOrders($collection)
16
+ {
17
+ $config = Mage::getModel('emailchef/config');
18
+
19
+ // Add condition to skip orders that have incorrect statuses
20
+ $allowedStatuses = $config->getQualifyingOrderStatuses();
21
+ // If config options, use the given statuses
22
+ if (count($allowedStatuses) > 0) {
23
+ $collection->addAttributeToFilter('status', $allowedStatuses);
24
+ } else {
25
+ // Else, use complete, closed and processing state only
26
+ $allowedStates = $config->getDefaultQualifyingStates();
27
+ $collection->addAttributeToFilter('state', $allowedStates);
28
+ }
29
+
30
+ return $this;
31
+ }
32
+ }
app/code/community/EMailChef/EMailChefSync/Model/.DS_Store ADDED
Binary file
app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/.DS_Store ADDED
Binary file
app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/.DS_Store ADDED
Binary file
app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Clone/Mappings/Custom.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provide clone model that specifies custom customer attributes as prefixes to be
5
+ * cloned from single original field.
6
+ *
7
+ * Class EMailChef_EMailChefSync_Model_Adminhtml_System_Clone_Mappings_Custom
8
+ */
9
+ class EMailChef_EMailChefSync_Model_Adminhtml_System_Clone_Mappings_Custom
10
+ extends Mage_Core_Model_Config_Data
11
+ {
12
+ /**
13
+ * Get fields prefixes.
14
+ *
15
+ * @return array
16
+ */
17
+ public function getPrefixes()
18
+ {
19
+ $customerAttributes = Mage::helper('emailchef/customer')->getCustomCustomerAttrCollection();
20
+
21
+ $prefixes = array();
22
+ foreach ($customerAttributes as $attribute) {
23
+ /* @var $attribute Mage_Eav_Model_Entity_Attribute */
24
+ $prefixes[] = array(
25
+ 'field' => $attribute->getAttributeCode().'_',
26
+ 'label' => $attribute->getFrontend()->getLabel(),
27
+ );
28
+ }
29
+
30
+ return $prefixes;
31
+ }
32
+ }
app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Source/Cron/Frequency.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Cron_Frequency
4
+ {
5
+ const HOURLY = 0;
6
+ const EVERY_2_HOURS = 1;
7
+ const EVERY_6_HOURS = 2;
8
+ const EVERY_12_HOURS = 3;
9
+ const DAILY = 4;
10
+
11
+ /**
12
+ * Get the frequency in hours given a frequency index such as
13
+ * EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Cron_Frequency::EVERY_2_HOURS.
14
+ *
15
+ * @param int $frequencyIndex
16
+ *
17
+ * @return null|int
18
+ */
19
+ public static function getPeriod($frequencyIndex)
20
+ {
21
+ static $periodMapping = array(
22
+ self::HOURLY => 1,
23
+ self::EVERY_2_HOURS => 2,
24
+ self::EVERY_6_HOURS => 6,
25
+ self::EVERY_12_HOURS => 12,
26
+ self::DAILY => 24,
27
+ );
28
+
29
+ // If no valid entry, return null
30
+ if (!isset($periodMapping[$frequencyIndex])) {
31
+ return;
32
+ }
33
+
34
+ return $periodMapping[$frequencyIndex];
35
+ }
36
+
37
+ /**
38
+ * Fetch options array.
39
+ *
40
+ * @return array
41
+ */
42
+ public function toOptionArray()
43
+ {
44
+ return array(
45
+ array(
46
+ 'label' => 'Hourly',
47
+ 'value' => self::HOURLY, ),
48
+ array(
49
+ 'label' => 'Every 2 Hours',
50
+ 'value' => self::EVERY_2_HOURS, ),
51
+ array(
52
+ 'label' => 'Every 6 hours',
53
+ 'value' => self::EVERY_6_HOURS, ),
54
+ array(
55
+ 'label' => 'Every 12 hours',
56
+ 'value' => self::EVERY_12_HOURS, ),
57
+ array(
58
+ 'label' => 'Daily',
59
+ 'value' => self::DAILY, ),
60
+
61
+ );
62
+ }
63
+ }
app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Source/Cron/Hours.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Cron_Hours
4
+ {
5
+ /**
6
+ * Fetch options array.
7
+ *
8
+ * @return array
9
+ */
10
+ public function toOptionArray()
11
+ {
12
+ $hours = array();
13
+ for ($i = 1; $i <= 24; ++$i) {
14
+ $hours[] = array('label' => $i, 'value' => $i);
15
+ }
16
+
17
+ return $hours;
18
+ }
19
+ }
app/code/community/EMailChef/EMailChefSync/Model/Adminhtml/System/Source/Fields.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Fields.
5
+ *
6
+ * Cached EMailChef recipient fields fetched via API
7
+ *
8
+ * There are two levels of caching:
9
+ * - Within one instantiation of magento, store options in the object
10
+ * - Magento's cache is used for up to 10 minutes to save hitting the API too often
11
+ */
12
+ class EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Fields
13
+ {
14
+ const CACHE_LIFETIME = 600; // 10 min
15
+
16
+ /**
17
+ * Storage for options array for this run (assuming class used as singleton).
18
+ *
19
+ * @var null|array
20
+ */
21
+ protected $_options = null;
22
+
23
+ /**
24
+ * Options getter for EMailChef field mapping drop-down list.
25
+ *
26
+ * @return array
27
+ */
28
+ public function toOptionArray()
29
+ {
30
+ // If in this instantiation of Mage options have been fetched, return them, bypassing even cache
31
+ if ($this->_options !== null) {
32
+ return $this->_options;
33
+ }
34
+ $websiteCode = Mage::app()->getRequest()->getParam('website');
35
+ $storeCode = Mage::app()->getRequest()->getParam('store');
36
+
37
+ if ($storeCode) {
38
+ $storeId = Mage::app()->getStore($storeCode)->getId();
39
+ $cacheId = 'emailchef_fields_array_store_'.$storeId;
40
+ } elseif ($websiteCode) {
41
+ $storeId = Mage::app()
42
+ ->getWebsite($websiteCode)
43
+ ->getDefaultGroup()
44
+ ->getDefaultStoreId()
45
+ ;
46
+ $cacheId = 'emailchef_fields_array_store_'.$storeId;
47
+ } else {
48
+ $storeId = null;
49
+ $cacheId = 'emailchef_fields_array';
50
+ //$storeId = Mage::app()->getDefaultStoreView()->getStoreId();
51
+ }
52
+
53
+ // Blank option
54
+ $options = array(array('value' => '', 'label' => ''));
55
+
56
+ // Attempt to fetch options from cache (handles invalidation after CACHE_LIFETIME)
57
+ if (Mage::app()->useCache('config') && (false !== ($data = Mage::app()->getCache()->load($cacheId)))) {
58
+ $options = unserialize($data);
59
+ } else {
60
+ // If cache is invalid, make request to EMailChef via API
61
+ $wsSend = new EMailChefWsSend($storeId);
62
+ $accessKey = $wsSend->loginFromId();
63
+ if ($accessKey !== false) {
64
+ $fields = $wsSend->getFields($accessKey);
65
+ if ($fields !== null) {
66
+ foreach ($fields as $field) {
67
+ $options[] = array(
68
+ //'value' => $field->id,
69
+ 'value' => $field->place_holder,
70
+ 'label' => $field->name, //Mage::helper('adminhtml')->__($label)
71
+ );
72
+ }
73
+ }
74
+ // Only store a persistent cache of entries if there was a successful response from EMailChef
75
+ Mage::app()->getCache()->save(serialize($options), $cacheId, array(), self::CACHE_LIFETIME);
76
+ } else {
77
+ // Force options to be empty so that nothing is saved
78
+ // (thus defaults or saved values will still be available)
79
+ $options = array();
80
+ }
81
+ }
82
+
83
+ // Whether the cache was used, or a call was made (successfully or otherwise), store the result for this run
84
+ $this->_options = $options;
85
+
86
+ return $options;
87
+ }
88
+ }
app/code/community/EMailChef/EMailChefSync/Model/Config.php ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Config.php.
4
+ *
5
+ * Central config model
6
+ */
7
+ class EMailChef_EMailChefSync_Model_Config
8
+ {
9
+ const XML_LOG_ENABLE = 'emailchef_newsletter/emailchef/enable_log';
10
+ const XML_CRON_EXPORT_ENABLE = 'emailchef_newsletter/emailchef/enable_cron_export';
11
+ const XML_EMAILCHEF_USERNAME = 'emailchef_newsletter/emailchef/username_ws';
12
+ const XML_EMAILCHEF_PASSWORD = 'emailchef_newsletter/emailchef/password_ws';
13
+ const XML_EMAILCHEF_LIST_ID = 'emailchef_newsletter/emailchef/list';
14
+ const XML_EMAILCHEF_DEFAULT_GROUP_ID = 'emailchef_newsletter/emailchef/default_group';
15
+ const XML_SUBSCRIBE_IN_CHECKOUT = 'emailchef_newsletter/emailchef/enable_subscribe_in_checkout';
16
+ const XML_REQ_SUBSCRIPTION_CONF = 'emailchef_newsletter/emailchef/require_subscription_confirmation';
17
+ const XML_CRON_FREQ = 'emailchef_newsletter/emailchef/emailchef_cron_frequency';
18
+ const XML_TEST_MODE_ENABLE = 'emailchef_newsletter/emailchef/enable_testmode';
19
+ const XML_ORDER_STATUSES = 'emailchef_newsletter/emailchef/qualifying_order_statuses';
20
+
21
+ const XML_MAPPING_SECTION = 'emailchef_newsletter/emailchef_mapping';
22
+ const XML_CUSTOM_MAPPING_SECTION = 'emailchef_newsletter/emailchef_mapping_custom';
23
+
24
+ /**
25
+ * Is test mode enabled.
26
+ *
27
+ * @param int
28
+ *
29
+ * @return bool
30
+ */
31
+ public function isTestMode($storeId = null)
32
+ {
33
+ return (bool) Mage::getStoreConfig(self::XML_TEST_MODE_ENABLE, $storeId);
34
+ }
35
+
36
+ /**
37
+ * Is the log enabled?
38
+ *
39
+ * @param int
40
+ *
41
+ * @return bool
42
+ */
43
+ public function isLogEnabled($storeId = null)
44
+ {
45
+ return (int) Mage::getStoreConfig(self::XML_LOG_ENABLE, $storeId);
46
+ }
47
+
48
+ /**
49
+ * Write a log entry if enabled.
50
+ *
51
+ * @param string
52
+ * @param int
53
+ *
54
+ * @return bool
55
+ */
56
+ public function log($message, $storeId = null)
57
+ {
58
+ if (!$this->isLogEnabled($storeId)) {
59
+ return;
60
+ }
61
+
62
+ Mage::log($message, null, 'emailchef.log');
63
+ }
64
+
65
+ /**
66
+ * Get qualifying order statuses for inclusion in order totals.
67
+ *
68
+ * @param int
69
+ *
70
+ * @return array Array of statuses
71
+ */
72
+ public function getQualifyingOrderStatuses($storeId = null)
73
+ {
74
+ // Get from config storage
75
+ $statusesStr = Mage::getStoreConfig(self::XML_ORDER_STATUSES, $storeId);
76
+
77
+ if ($statusesStr === null || $statusesStr === '') {
78
+ return array();
79
+ }
80
+
81
+ // Split up comma separated values
82
+ return explode(',', $statusesStr);
83
+ }
84
+
85
+ /**
86
+ * Get default qualifying order stated for inclusion in order totals.
87
+ *
88
+ * @return array
89
+ */
90
+ public function getDefaultQualifyingStates()
91
+ {
92
+ return array('complete', 'closed', 'processing');
93
+ }
94
+
95
+ /**
96
+ * Write a log entry if enabled.
97
+ *
98
+ * @param string
99
+ * @param int
100
+ * @param int
101
+ * @param string
102
+ * @param string
103
+ *
104
+ * @return bool
105
+ */
106
+ public function dbLog($info, $jobId = 0, $storeId = null, $status = 'DEBUG', $type = 'DEBUG')
107
+ {
108
+ if (!$this->isLogEnabled($storeId)) {
109
+ return;
110
+ }
111
+
112
+ if (!isset($storeId)) {
113
+ $storeId = Mage::app()->getStore()->getId();
114
+ }
115
+
116
+ $log = Mage::getModel('emailchef/log');
117
+ /* @var $log EMailChef_EMailChefSync_Model_Log */
118
+ $log->setData(array(
119
+ 'store_id' => $storeId,
120
+ 'job_id' => $jobId,
121
+ 'type' => $type,
122
+ 'status' => $status,
123
+ 'data' => $info,
124
+ 'event_time' => date('Y-m-d H:i:s'),
125
+ ));
126
+
127
+ try {
128
+ $log->save();
129
+ } catch (Exception $e) {
130
+ $this->log($e->getMessage(), $storeId);
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Disable Magnetos Newsletter Subscription Notifiactions??
136
+ *
137
+ * @param int
138
+ *
139
+ * @return bool
140
+ */
141
+ public function isNewsletterNotificationDisabled($storeId = null)
142
+ {
143
+ return false;
144
+ }
145
+
146
+ /**
147
+ * Is the cron enabled?
148
+ *
149
+ * @param int
150
+ *
151
+ * @return int
152
+ */
153
+ public function isCronExportEnabled($storeId = null)
154
+ {
155
+ return (int) Mage::getStoreConfig(self::XML_CRON_EXPORT_ENABLE, $storeId);
156
+ }
157
+
158
+ /**
159
+ * Get the list ID.
160
+ *
161
+ * @param int
162
+ *
163
+ * @return int
164
+ */
165
+ public function getEMailChefListId($storeId = null)
166
+ {
167
+ return Mage::getStoreConfig(self::XML_EMAILCHEF_LIST_ID, $storeId);
168
+ }
169
+
170
+ /**
171
+ * Get the default Group ID.
172
+ *
173
+ * @param int
174
+ *
175
+ * @return int
176
+ */
177
+ public function getEMailChefDefaultGroupId($storeId = null)
178
+ {
179
+ return Mage::getStoreConfig(self::XML_EMAILCHEF_DEFAULT_GROUP_ID, $storeId);
180
+ }
181
+
182
+ /**
183
+ * Get the username from Config.
184
+ *
185
+ * @param int
186
+ *
187
+ * @return string
188
+ */
189
+ public function getUsername($storeId = null)
190
+ {
191
+ return Mage::getStoreConfig(self::XML_EMAILCHEF_USERNAME, $storeId);
192
+ }
193
+
194
+ /**
195
+ * Get the password from Config.
196
+ *
197
+ * @param int
198
+ *
199
+ * @return string
200
+ */
201
+ public function getPassword($storeId = null)
202
+ {
203
+ return Mage::getStoreConfig(self::XML_EMAILCHEF_PASSWORD, $storeId);
204
+ }
205
+
206
+ /**
207
+ * Is Subscribe in checkout enabled?
208
+ *
209
+ * @param int
210
+ *
211
+ * @return int
212
+ */
213
+ public function isSubscribeInCheckout($storeId = null)
214
+ {
215
+ return (int) Mage::getStoreConfig(self::XML_SUBSCRIBE_IN_CHECKOUT, $storeId);
216
+ }
217
+
218
+ /**
219
+ * Is Require Subscription Confirmation set in config?
220
+ *
221
+ * @param int
222
+ *
223
+ * @return int
224
+ */
225
+ public function isRequireSubscriptionConfirmation($storeId = null)
226
+ {
227
+ return (int) Mage::getStoreConfig(self::XML_REQ_SUBSCRIPTION_CONF, $storeId);
228
+ }
229
+
230
+ /**
231
+ * Get the cron freq settings.
232
+ *
233
+ * @param int
234
+ *
235
+ * @return string
236
+ */
237
+ public function getCronFrequency($storeId = null)
238
+ {
239
+ return Mage::getStoreConfig(self::XML_CRON_FREQ, $storeId);
240
+ }
241
+
242
+ /**
243
+ * Get Field Mapping.
244
+ *
245
+ * @param int
246
+ *
247
+ * @return array
248
+ */
249
+ public function getFieldsMapping($storeId = null)
250
+ {
251
+ // Get standard mappings
252
+ $mappingMain = Mage::getStoreConfig(self::XML_MAPPING_SECTION, $storeId);
253
+ // Get mappings for custom customer attributes
254
+ $mappingCustom = Mage::getStoreConfig(self::XML_CUSTOM_MAPPING_SECTION, $storeId);
255
+
256
+ if ($mappingCustom === null) {
257
+ $mappingCustom = array();
258
+ }
259
+
260
+ return array_merge($mappingMain, $mappingCustom);
261
+
262
+ /*$return = array();
263
+
264
+ foreach(Mage::getStoreConfig(self::XML_MAPPING_SECTION, $storeId) as $key => $field) {
265
+ var_dump($key);
266
+ var_dump($field);
267
+ }
268
+
269
+ return $return;*/
270
+ }
271
+
272
+ /**
273
+ * Get the name of the Sync Table.
274
+ *
275
+ * @return string
276
+ */
277
+ public function getSyncTableName()
278
+ {
279
+ return Mage::getSingleton('core/resource')->getTableName('emailchef/sync');
280
+ }
281
+
282
+ /**
283
+ * Get the name of the Jobs Table.
284
+ *
285
+ * @return string
286
+ */
287
+ public function getJobsTableName()
288
+ {
289
+ return Mage::getSingleton('core/resource')->getTableName('emailchef/job');
290
+ }
291
+
292
+ /**
293
+ * Get an array of Stores, for use in a dropdown.
294
+ *
295
+ * array(
296
+ * id => code
297
+ * )
298
+ *
299
+ * @return array
300
+ */
301
+ public function getStoreArray()
302
+ {
303
+ //$storeModel = Mage::getSingleton('adminhtml/system_store');
304
+ /* @var $storeModel Mage_Adminhtml_Model_System_Store */
305
+ //$websiteCollection = $storeModel->getWebsiteCollection();
306
+ //$groupCollection = $storeModel->getGroupCollection();
307
+ //$storeCollection = $storeModel->getStoreCollection();
308
+ $storesArr = array();
309
+
310
+ /*$defaultStoreId = Mage::app()->getDefaultStoreView()->getStoreId();
311
+ $storesArr[$defaultStoreId] = array(
312
+ 'id' => $defaultStoreId,
313
+ 'code' => Mage::app()->getDefaultStoreView()->getCode(),
314
+ 'name' => Mage::app()->getDefaultStoreView()->getName(),
315
+ );*/
316
+
317
+ $storesArr[0] = array(
318
+ 'id' => 0,
319
+ 'code' => 'default',
320
+ 'name' => 'Default',
321
+ );
322
+
323
+ foreach (Mage::app()->getWebsites() as $website) {
324
+ foreach ($website->getGroups() as $group) {
325
+ $stores = $group->getStores();
326
+ foreach ($stores as $store) {
327
+ /* @var $store Mage_Core_Model_Store */
328
+ $storesArr[$store->getId()] = array(
329
+ 'id' => $store->getId(),
330
+ 'code' => $store->getCode(),
331
+ 'name' => $store->getName(),
332
+ );
333
+ }
334
+ }
335
+ }
336
+
337
+ return $storesArr;
338
+ }
339
+
340
+ /**
341
+ * Get an array of all store ids.
342
+ *
343
+ * @reutrn array
344
+ */
345
+ public function getAllStoreIds()
346
+ {
347
+ $ids = array();
348
+
349
+ $allStores = Mage::app()->getStores();
350
+ foreach ($allStores as $storeId => $val) {
351
+ $ids[] = Mage::app()->getStore($storeId)->getId();
352
+ }
353
+
354
+ return $ids;
355
+ }
356
+ }
app/code/community/EMailChef/EMailChefSync/Model/Cron.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Cron.php.
4
+ *
5
+ * Scheduled Task handler.
6
+ */
7
+ require_once dirname(__FILE__).'/EMailChefWsImport.php';
8
+ require_once dirname(__FILE__).'/Wssend.php';
9
+
10
+ class EMailChef_EMailChefSync_Model_Cron
11
+ {
12
+ const LOCK_INDEX_ID = 'emailchefcronrun';
13
+ /**
14
+ * Run the Task.
15
+ *
16
+ * IF ANY Job we run fails, due to another processes being run we should
17
+ * gracefully exit and wait our next go!
18
+ *
19
+ * Also change auto sync to just create a job, and run a single job Queue!
20
+ */
21
+ public function run()
22
+ {
23
+ if ($this->_config()->isLogEnabled()) {
24
+ $this->_config()->dbLog('Cron [Triggered]');
25
+ }
26
+
27
+ /*
28
+ * This doesn't exist in 1.3.2!
29
+ */
30
+ $indexProcess = new Mage_Index_Model_Process();
31
+ $indexProcess->setId(self::LOCK_INDEX_ID);
32
+ if ($indexProcess->isLocked()) {
33
+ // Check how old the lock is - unlock after 1hr
34
+ if ($this->_lockIsOld(self::LOCK_INDEX_ID)) {
35
+ $indexProcess->unlock();
36
+ } else {
37
+ $this->_config()->log('EMAILCHEF: cron already running or locked');
38
+
39
+ return false;
40
+ }
41
+ }
42
+ $indexProcess->lockAndBlock();
43
+
44
+ try {
45
+ require_once dirname(__FILE__).'/../Helper/Data.php';
46
+ $db_read = Mage::getSingleton('core/resource')->getConnection('core_read');
47
+ $db_write = Mage::getSingleton('core/resource')->getConnection('core_write');
48
+ $syncTableName = Mage::getSingleton('core/resource')->getTableName('emailchef/sync');
49
+ $jobsTableName = Mage::getSingleton('core/resource')->getTableName('emailchef/job');
50
+ $lastsync = gmdate('Y-m-d H:i:s');
51
+ // reading customers (jobid == 0, their updates)
52
+ $customer_entity_table_name = Mage::getSingleton('core/resource')->getTableName('customer_entity');
53
+
54
+ /*
55
+ * Now Handle Jobs we need to Sync, and all customers attached to each job
56
+ */
57
+ foreach (Mage::getModel('emailchef/job')->fetchQueuedOrStartedJobsCollection() as $jobModel) {
58
+ /* @var $jobModel EMailChef_EMailChefSync_Model_Job */
59
+ $job = $jobModel->getData();
60
+
61
+ $storeId = isset($job['store_id']) ? $job['store_id'] : null;
62
+
63
+ // If job is auto-sync and cron is not enabled for the job's site, skip the job
64
+ if ($jobModel->isAutoSync() && !$this->_config()->isCronExportEnabled($storeId)) {
65
+ $this->_config()->dbLog('Auto-Task skipped as auto-sync disabled for site', $job['id'], $storeId);
66
+ continue;
67
+ }
68
+
69
+ $stmt = $db_write->query(
70
+ "UPDATE {$jobsTableName}
71
+ SET status='started', start_datetime='".gmdate('Y-m-d H:i:s')."'
72
+ WHERE id={$job['id']}"
73
+ );
74
+ $customers = array();
75
+ $job['emailchefNewGroup'] = 0;
76
+ $job['emailchefIdList'] = Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $storeId);
77
+ $job['emailchefGroupId'] = $job['emailchefgroupid'];
78
+
79
+ // If group is 0 and there is a default group, set group to this group
80
+ $defaultGroupId = Mage::getStoreConfig('emailchef_newsletter/emailchef/default_group');
81
+ if ($job['emailchefGroupId'] == 0 && $defaultGroupId !== null) {
82
+ $job['emailchefGroupId'] = $defaultGroupId;
83
+ }
84
+
85
+ $tmp = Mage::getSingleton('emailchef/source_lists');
86
+ $tmp = $tmp->toOptionArray($storeId); // pass store id!
87
+ foreach ($tmp as $t) {
88
+ if ($t['value'] == $job['emailchefIdList']) {
89
+ $job['emailchefListGUID'] = $t['guid'];
90
+ $job['groups'] = $t['groups'];
91
+ break;
92
+ }
93
+ }
94
+ unset($tmp);
95
+ unset($t);
96
+ $stmt = $db_read->query("
97
+ SELECT ms.*, ce.email
98
+ FROM {$syncTableName} ms
99
+ JOIN $customer_entity_table_name ce
100
+ ON (ms.customer_id = ce.entity_id)
101
+ WHERE ms.needs_sync=1
102
+ AND ms.entity='customer'
103
+ AND job_id={$job['id']}"
104
+ );
105
+ while ($row = $stmt->fetch()) {
106
+ $customers[] = $row['customer_id'];
107
+ }
108
+ /*
109
+ * Send the Data!
110
+ */
111
+ $returnCode = EMailChef_EMailChefSync_Helper_Data::generateAndSendCustomers($customers, $job, $storeId);
112
+ /*
113
+ * Check return OK
114
+ */
115
+ if ($returnCode === true) {
116
+ $customerCount = count($customers);
117
+ $db_write->query("
118
+ UPDATE {$syncTableName} SET needs_sync=0, last_sync='$lastsync'
119
+ WHERE job_id = {$job['id']}
120
+ AND entity='customer'"
121
+ );
122
+ $this->_config()->dbLog("Job Task [update] [Synced] [customer count:{$customerCount}]", $job['id'], $storeId);
123
+ // finishing the job also
124
+ $db_write->query("
125
+ UPDATE {$jobsTableName} SET status='finished', finish_datetime='".gmdate('Y-m-d H:i:s')."'
126
+ WHERE id={$job['id']}"
127
+ );
128
+ $this->_config()->dbLog("Jobs [Update] [Complete] [{$job['id']}]", $job['id'], $storeId);
129
+ }
130
+ /*
131
+ * Only successfull if we get 0 back. False is also a fail.
132
+ */
133
+ else {
134
+ $stmt = $db_write->query(
135
+ "UPDATE {$jobsTableName} SET status='queued' WHERE id={$job['id']}"
136
+ );
137
+ if ($this->_config()->isLogEnabled()) {
138
+ $this->_config()->dbLog(sprintf('generateAndSendCustomers [ReturnCode] [ERROR] [%d]', $returnCode), $job['id'], $storeId);
139
+ }
140
+ }
141
+ }
142
+ } catch (Exception $e) {
143
+ // In case of otherwise uncaught error, unlock and re-throw
144
+ $indexProcess->unlock();
145
+ throw $e;
146
+ }
147
+
148
+ $indexProcess->unlock();
149
+
150
+ if ($this->_config()->isLogEnabled()) {
151
+ $this->_config()->dbLog('Cron [Completed]');
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Whether a given file was modified over $hoursOld ago.
157
+ *
158
+ * @param string $id
159
+ * @param int $hoursOld
160
+ *
161
+ * @return bool
162
+ */
163
+ protected function _lockIsOld($id, $hoursOld = 1)
164
+ {
165
+ $varDir = Mage::getConfig()->getVarDir('locks');
166
+ $filename = $varDir.DS.'index_process_'.$id.'.lock';
167
+ if (!is_file($filename)) {
168
+ return true;
169
+ }
170
+ if (time() - filemtime($filename) > $hoursOld * 3600) {
171
+ return true;
172
+ }
173
+
174
+ // File exists and is less than the specified number of hours old
175
+ return false;
176
+ }
177
+
178
+ /**
179
+ * Run Auto Sync Jobs.
180
+ */
181
+ public function autoSync()
182
+ {
183
+ // Only run Auto Sync Jobs
184
+ $job = Mage::getModel('emailchef/job');
185
+ /* @var $job EMailChef_EMailChefSync_Model_Job */
186
+
187
+ foreach ($job->fetchAutoSyncQueuedJobsCollection() as $job) {
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Run Manual Sync Jobs.
193
+ */
194
+ public function manualSync()
195
+ {
196
+ // Only run Auto Sync Jobs
197
+
198
+ $job = Mage::getModel('emailchef/job');
199
+ /* @var $job EMailChef_EMailChefSync_Model_Job */
200
+
201
+ foreach ($job->fetchManualSyncQueuedJobsCollection() as $job) {
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Start the next job in the Queue!
207
+ */
208
+ public function startNextJob()
209
+ {
210
+ $jobModel = Mage::getModel('emailchef/job');
211
+ /* @var $jobModel EMailChef_EMailChefSync_Model_Job */
212
+ foreach ($jobModel->fetchQueuedJobsCollection() as $job) {
213
+ /* @var $job EMailChef_EMailChefSync_Model_Job */
214
+
215
+ /*
216
+ * Try and Start it... if it fails, we can try the next one!
217
+ */
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Add the jobs to the import queue on EMailChef.
223
+ */
224
+ public function newImportProcesses()
225
+ {
226
+ }
227
+
228
+ /**
229
+ * handle connection issues.
230
+ *
231
+ * @todo implement
232
+ */
233
+ public static function resendConnectionErrors()
234
+ {
235
+ // never implemented.
236
+ }
237
+
238
+ /**
239
+ * @var EMailChef_EMailChefSync_Model_Config
240
+ */
241
+ protected $_config;
242
+
243
+ /**
244
+ * Get the config.
245
+ *
246
+ * @reutrn EMailChef_EMailChefSync_Model_Config
247
+ */
248
+ protected function _config()
249
+ {
250
+ if (null === $this->_config) {
251
+ $this->_config = Mage::getModel('emailchef/config');
252
+ }
253
+
254
+ return $this->_config;
255
+ }
256
+ }
app/code/community/EMailChef/EMailChefSync/Model/EMailChef.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once __DIR__.'/../lib/emailchef/vendor/autoload.php';
4
+ class EMailChef_EMailChefSync_Model_EMailChef extends Mage_Core_Model_Abstract
5
+ {
6
+ public function _construct()
7
+ {
8
+ parent::_construct();
9
+ $this->_init('emailchef/emailchef');
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/Model/EMailChefWsImport.php ADDED
@@ -0,0 +1,762 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * EMailChefWsImport.php.
4
+ */
5
+ class EMailChefWsImport
6
+ {
7
+ /**
8
+ * @var EMailChef_EMailChefSync_Model_Config
9
+ */
10
+ protected $_config;
11
+ /**
12
+ * @var int
13
+ */
14
+ protected $storeId;
15
+
16
+ /**
17
+ * Constructor.
18
+ */
19
+ public function __construct($storeId = null)
20
+ {
21
+ $this->setStoreId($storeId);
22
+
23
+ $this->_config = $config = Mage::getModel('emailchef/config');
24
+ }
25
+
26
+ /**
27
+ * Set the store ID.
28
+ *
29
+ * @param int
30
+ */
31
+ public function setStoreId($id)
32
+ {
33
+ $this->storeId = $id;
34
+
35
+ return $this;
36
+ }
37
+
38
+ /**
39
+ * Create a New Group.
40
+ *
41
+ * @todo CHECK THE API - might have been updated??
42
+ * The API states the signature of this method is:
43
+ *
44
+ * CreateGroup(int idList, int listGUID, string newGroupName)
45
+ *
46
+ * @param type $newGroup
47
+ * @param type $authKey
48
+ *
49
+ * @return bool
50
+ */
51
+ public function creaGruppo($newGroup, $authKey)
52
+ {
53
+ try {
54
+ $createSegmentCommand = new \EMailChef\Command\Api\CreateSegmentCommand();
55
+ $result = $createSegmentCommand->execute($authKey, $newGroup['idList'], $newGroup['newGroupName'], $newGroup['newGroupName']);
56
+ if ($this->_config()->isLogEnabled($this->storeId)) {
57
+ $this->_config()->dbLog(sprintf(
58
+ 'eMailChef: Create a new Group [%s] [List:%s] [%s]',
59
+ $newGroup['newGroupName'],
60
+ $newGroup['listGUID'],
61
+ $result
62
+ ));
63
+ }
64
+
65
+ return $result;
66
+ } catch (Exception $e) {
67
+ Mage::log($e->getMessage(), 0);
68
+ $errorDescription = $e->getMessage();
69
+ }
70
+ }
71
+
72
+ /**
73
+ * GetNlList.
74
+ *
75
+ * KNOWN RESTRICTION
76
+ * Characters & and " are not escaped in returned response, so please avoid these
77
+ * characters in names of lists and groups otherwise you will experience some problems due to an invalid returned XML
78
+ *
79
+ * @todo parse the XML response correctly and return something nice.
80
+ *
81
+ * @return string
82
+ */
83
+ public function GetNlList($accessKey, $withGroups = false)
84
+ {
85
+ try {
86
+ $getListsCommand = new \EMailChef\Command\Api\GetListsCommand();
87
+ $result = $getListsCommand->execute($accessKey, $withGroups);
88
+ if ($this->_config()->isLogEnabled($this->storeId)) {
89
+ $this->_config()->log($result, 0);
90
+ }
91
+
92
+ return $result;
93
+ } catch (Exception $e) {
94
+ Mage::log($e->getMessage(), 0);
95
+ $errorDescription = $e->getMessage();
96
+ }
97
+ }
98
+
99
+ /**
100
+ * startImportProcesses.
101
+ *
102
+ * @param type $processData
103
+ *
104
+ * @return int|bool
105
+ */
106
+ public function startImportProcesses($processData, $accessKey)
107
+ {
108
+ try {
109
+ $importContactsInGroupCommand = new \EMailChef\Command\Api\ImportContactsInGroupCommand();
110
+ $result = $importContactsInGroupCommand->execute($accessKey, $processData['customers'], $processData['idList'], $processData['groupsIDs']);
111
+ if ($this->_config()->isLogEnabled($this->storeId)) {
112
+ $this->_config()->log($result, 0);
113
+ }
114
+
115
+ return $result;
116
+ } catch (Exception $e) {
117
+ Mage::log($e->getMessage(), 0);
118
+ $errorDescription = $e->getMessage();
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Get filtered customers.
124
+ *
125
+ * @todo refactor
126
+ *
127
+ * @param
128
+ * @param int
129
+ *
130
+ * @return array
131
+ */
132
+ public function getCustomersFiltered($request, $storeId = null)
133
+ {
134
+ $TIMEZONE_STORE = new DateTimeZone(Mage::getStoreConfig('general/locale/timezone'));
135
+ $TIMEZONE_UTC = new DateTimeZone('UTC');
136
+
137
+ //inizializzo l'array dei clienti
138
+ $customersFiltered = array();
139
+
140
+ if (!$request->getRequest()->getParam('emailchefCustomerFilteredMod')) {
141
+ //ottengo la collection con tutti i clienti
142
+ $customerCollection = Mage::getModel('customer/customer')
143
+ ->getCollection()
144
+ ->addAttributeToSelect('entity_id')
145
+ ->addAttributeToSelect('group_id')
146
+ ->addAttributeToSelect('created_at')
147
+ ->addAttributeToSelect('store_id')
148
+ //->getSelect()->query()
149
+ ;
150
+ /*
151
+ * If StoreID = 0 we will not bother to filter...
152
+ */
153
+ if (isset($storeId) && !empty($storeId)) {
154
+ $customerCollection->addAttributeToFilter('store_id', array(
155
+ 'eq' => $storeId,
156
+ ));
157
+ }
158
+ $customerCollection = $customerCollection->getSelect()->query();
159
+
160
+ while ($row = $customerCollection->fetch()) {
161
+ $customersFiltered[] = $row;
162
+ }
163
+
164
+ // if required, select only those that are (or are not) subscribed in Magento
165
+ if ($request->getRequest()->getParam('emailchefSubscribed') > 0) {
166
+ // Base status on option (1 -> must be subscribed. 2 -> must NOT be subscribed
167
+ if ($request->getRequest()->getParam('emailchefSubscribed') == 1) {
168
+ $expectedStatus = true;
169
+ } else {
170
+ $expectedStatus = false;
171
+ }
172
+ // Filter list of customers by expected subscription status
173
+ $tempSubscribed = array();
174
+ foreach ($customersFiltered as $customer) {
175
+ $customerItem = Mage::getModel('customer/customer')->load($customer['entity_id']);
176
+ $subscriptionStatus = Mage::getModel('newsletter/subscriber')->loadByCustomer($customerItem)->isSubscribed();
177
+ if ($subscriptionStatus === $expectedStatus) {
178
+ $tempSubscribed[] = $customer;
179
+ }
180
+ }
181
+
182
+ $customersFiltered = self::intersectByEntityId($tempSubscribed, $customersFiltered);
183
+ }
184
+ /*
185
+ * FILTER 1 PURCHASED: Depending on whether or not customer has made ​​purchases
186
+  * 0 = all, 1 = those who purchased, 2 = someone who has never purchased
187
+ */
188
+ $count = 0;
189
+ $result = array();
190
+ $tempPurchased = array();
191
+ $tempNoPurchased = array();
192
+
193
+ if ($request->getRequest()->getParam('emailchefCustomers') > 0) {
194
+ foreach ($customersFiltered as $customer) {
195
+ $result[] = $customer;
196
+ // Filter orders based on customer id
197
+ $orders = Mage::getResourceModel('sales/order_collection')
198
+ ->addAttributeToFilter('customer_id', $result[$count]['entity_id']);
199
+ Mage::helper('emailchef/order')->addStatusFilterToOrders($orders);
200
+
201
+ // Add customer to either purchased or non-purchased array based on whether any orders
202
+ if ($orders->getData()) {
203
+ $tempPurchased[] = $result[$count];
204
+ } else {
205
+ $tempNoPurchased[] = $result[$count];
206
+ }
207
+ //unsetto la variabile
208
+ unset($orders); //->unsetData();
209
+ ++$count;
210
+ }
211
+
212
+ if ($request->getRequest()->getParam('emailchefCustomers') == 1) {
213
+ $customersFiltered = self::intersectByEntityId($tempPurchased, $customersFiltered);
214
+ } elseif ($request->getRequest()->getParam('emailchefCustomers') == 2) {
215
+ $customersFiltered = self::intersectByEntityId($tempNoPurchased, $customersFiltered);
216
+ }
217
+ }
218
+ /*
219
+ * FILTER 1 BY PRODUCT: Based on whether customer purchased a specific product
220
+ */
221
+ $count = 0;
222
+ $result = array();
223
+ $tempProduct = array();
224
+
225
+ if ($request->getRequest()->getParam('emailchefProductSku')) {
226
+ foreach ($customersFiltered as $customer) {
227
+ $result[] = $customer;
228
+
229
+ // Filter orders based on customer id
230
+ $orders = Mage::getResourceModel('sales/order_collection')
231
+ ->addAttributeToFilter('customer_id', $result[$count]['entity_id']);
232
+ Mage::helper('emailchef/order')->addStatusFilterToOrders($orders);
233
+
234
+ $purchasedProduct = 0;
235
+ $emailchefProductId = Mage::getModel('catalog/product')
236
+ ->getIdBySku($request->getRequest()->getParam('emailchefProductSku'));
237
+
238
+ foreach ($orders->getData() as $order) {
239
+ $orderIncrementId = $order['increment_id'];
240
+
241
+ //carico i dati di ogni ordine
242
+ $orderData = Mage::getModel('sales/order')->loadByIncrementID($orderIncrementId);
243
+ $items = $orderData->getAllItems();
244
+ $ids = array();
245
+ foreach ($items as $itemId => $item) {
246
+ $ids[] = $item->getProductId();
247
+ }
248
+
249
+ if (in_array($emailchefProductId, $ids)) {
250
+ $purchasedProduct = 1;
251
+ }
252
+ }
253
+
254
+ //aggiungo il cliente ad un determinato array in base a se ha ordinato o meno
255
+ if ($purchasedProduct == 1) {
256
+ $tempProduct[] = $result[$count];
257
+ }
258
+
259
+ //unsetto la variabile
260
+ unset($orders); //->unsetData();
261
+
262
+ ++$count;
263
+ }
264
+
265
+ $customersFiltered = self::intersectByEntityId($tempProduct, $customersFiltered);
266
+ }
267
+ /*
268
+ * FILTER 3 BY CATEGORY: Depending on whether bought at least one product in a given category
269
+ */
270
+ $count = 0;
271
+ $result = array();
272
+ $tempCategory = array();
273
+ if ($request->getRequest()->getParam('emailchefCategoryId') > 0) {
274
+ foreach ($customersFiltered as $customer) {
275
+ $result[] = $customer;
276
+ // Filter orders based on customer id
277
+ $orders = Mage::getResourceModel('sales/order_collection')
278
+ ->addAttributeToFilter('customer_id', $result[$count]['entity_id']);
279
+ Mage::helper('emailchef/order')->addStatusFilterToOrders($orders);
280
+
281
+ foreach ($orders->getData() as $order) {
282
+ $orderIncrementId = $order['increment_id'];
283
+
284
+ // Load data for each order (very slow)
285
+ $orderData = Mage::getModel('sales/order')->loadByIncrementID($orderIncrementId);
286
+ $items = $orderData->getAllItems();
287
+ /*
288
+ * Category ID, and it's descendants
289
+ */
290
+ $searchCategories = Mage::helper('emailchef')->getSubCategories($request->getRequest()->getParam('emailchefCategoryId'));
291
+ foreach ($items as $product) {
292
+ $_prod = Mage::getModel('catalog/product')->load($product->getProductId()); // need to load full product for cats.
293
+ $productCategories = Mage::getResourceSingleton('catalog/product')->getCategoryIds($_prod);
294
+ $matchingCategories = array_intersect($productCategories, $searchCategories);
295
+ if (is_array($matchingCategories) && !empty($matchingCategories)) {
296
+ $tempCategory[] = $result[$count];
297
+ break 2;
298
+ }
299
+ }
300
+ }
301
+ unset($orders);
302
+ ++$count;
303
+ }
304
+ $customersFiltered = self::intersectByEntityId($tempCategory, $customersFiltered);
305
+ }
306
+
307
+ /*
308
+ * FILTER 4 CUSTOMER GROUP
309
+ */
310
+ $count = 0;
311
+ $result = array();
312
+ $tempGroup = array();
313
+
314
+ if ($request->getRequest()->getParam('emailchefCustomerGroupId') > 0) {
315
+ foreach ($customersFiltered as $customer) {
316
+ if ($customer['group_id'] == $request->getRequest()->getParam('emailchefCustomerGroupId')) {
317
+ $tempGroup[] = $customer;
318
+ }
319
+ }
320
+
321
+ $customersFiltered = self::intersectByEntityId($tempGroup, $customersFiltered);
322
+ }
323
+ //FINE FILTRO 4 GRUPPO DI CLIENTI: testato ok
324
+
325
+ //FILTRO 5 PAESE DI PROVENIENZA
326
+ $count = 0;
327
+ $result = array();
328
+ $tempCountry = array();
329
+
330
+ if ($request->getRequest()->getParam('emailchefCountry') != '0') {
331
+ foreach ($customersFiltered as $customer) {
332
+ //ottengo la nazione del primary billing address
333
+ $customerItem = Mage::getModel('customer/customer')->load($customer['entity_id']);
334
+ $customerAddress = $customerItem->getPrimaryBillingAddress();
335
+ $countryId = $customerAddress['country_id'];
336
+
337
+ if ($countryId == $request->getRequest()->getParam('emailchefCountry')) {
338
+ $tempCountry[] = $customer;
339
+ }
340
+
341
+ //unsetto la variabile
342
+ unset($customerItem); //->unsetData();
343
+ }
344
+
345
+ $customersFiltered = self::intersectByEntityId($tempCountry, $customersFiltered);
346
+ }
347
+ //FINE FILTRO 5 PAESE DI PROVENIENZA: testato ok
348
+
349
+ //FILTRO 6 CAP DI PROVENIENZA
350
+ $count = 0;
351
+ $result = array();
352
+ $tempPostCode = array();
353
+
354
+ if ($request->getRequest()->getParam('emailchefPostCode')) {
355
+ foreach ($customersFiltered as $customer) {
356
+ //ottengo la nazione del primary billing address
357
+ $customerItem = Mage::getModel('customer/customer')->load($customer['entity_id']);
358
+ $customerAddress = $customerItem->getPrimaryBillingAddress();
359
+ $postCode = $customerAddress['postcode'];
360
+
361
+ if ($postCode == $request->getRequest()->getParam('emailchefPostCode')) {
362
+ $tempPostCode[] = $customer;
363
+ }
364
+
365
+ //unsetto la variabile
366
+ unset($customerItem); //->unsetData();
367
+ }
368
+
369
+ $customersFiltered = self::intersectByEntityId($tempPostCode, $customersFiltered);
370
+ }
371
+ //FINE FILTRO 6 CAP DI PROVENIENZA: testato ok
372
+
373
+ //FILTRO 7 DATA CREAZIONE CLIENTE
374
+ $count = 0;
375
+ $result = array();
376
+ $tempDate = array();
377
+
378
+ if ($request->getRequest()->getParam('emailchefCustomerStartDate') || $request->getRequest()->getParam('emailchefCustomerEndDate')) {
379
+ foreach ($customersFiltered as $customer) {
380
+ $createdAt = $customer['created_at'];
381
+ $createdAt = new DateTime($createdAt, $TIMEZONE_UTC);
382
+ $createdAt->setTimezone($TIMEZONE_STORE);
383
+ $createdAt = (string) $createdAt->format('Y-m-d H:i:s');
384
+ $filterStart = '';
385
+ $filterEnd = '';
386
+
387
+ if ($request->getRequest()->getParam('emailchefCustomerStartDate')) {
388
+ $date = Zend_Locale_Format::getDate(
389
+ $request->getRequest()->getParam('emailchefCustomerStartDate'),
390
+ array(
391
+ 'locale' => Mage::app()->getLocale()->getLocale(),
392
+ 'date_format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT),
393
+ 'fix_date' => true,
394
+ )
395
+ );
396
+ $date['month'] = str_pad($date['month'], 2, 0, STR_PAD_LEFT);
397
+ $date['day'] = str_pad($date['day'], 2, 0, STR_PAD_LEFT);
398
+ $filterStart = "{$date['year']}-{$date['month']}-{$date['day']} 00:00:00";
399
+ }
400
+ if ($request->getRequest()->getParam('emailchefCustomerEndDate')) {
401
+ $date = Zend_Locale_Format::getDate(
402
+ $request->getRequest()->getParam('emailchefCustomerEndDate'),
403
+ array(
404
+ 'locale' => Mage::app()->getLocale()->getLocale(),
405
+ 'date_format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT),
406
+ 'fix_date' => true,
407
+ )
408
+ );
409
+ $date['month'] = str_pad($date['month'], 2, 0, STR_PAD_LEFT);
410
+ $date['day'] = str_pad($date['day'], 2, 0, STR_PAD_LEFT);
411
+ $filterEnd = "{$date['year']}-{$date['month']}-{$date['day']} 23:59:59";
412
+ }
413
+ if ($filterStart && $filterEnd) {
414
+ //compreso tra start e end date
415
+ if ($createdAt >= $filterStart and $createdAt <= $filterEnd) {
416
+ $tempDate[] = $customer;
417
+ }
418
+ } elseif ($filterStart) {
419
+ // >= di start date
420
+ if ($createdAt >= $filterStart) {
421
+ $tempDate[] = $customer;
422
+ }
423
+ } else {
424
+ // <= di end date
425
+ if ($createdAt <= $filterEnd) {
426
+ $tempDate[] = $customer;
427
+ }
428
+ }
429
+ }
430
+
431
+ $customersFiltered = self::intersectByEntityId($tempDate, $customersFiltered);
432
+ }
433
+ //FINE FILTRO 7 DATA CREAZIONE CLIENTE: testato ok
434
+
435
+ //FILTRO 8 TOTALE ACQUISTATO
436
+ $count = 0;
437
+ $result = array();
438
+ $tempTotal = array();
439
+
440
+ if ($request->getRequest()->getParam('emailchefTotalAmountValue') > 0) {
441
+ foreach ($customersFiltered as $customer) {
442
+ $result[] = $customer;
443
+
444
+ //filtro gli ordini in base al customer id
445
+ $orders = Mage::getModel('sales/order')
446
+ ->getCollection()
447
+ ->addAttributeToFilter('customer_id', $result[$count]['entity_id'])
448
+ ;
449
+
450
+ $totalOrdered = 0;
451
+
452
+ foreach ($orders->getData() as $order) {
453
+ if (isset($order['status']) && !in_array($order['status'], array('closed', 'complete', 'processing'))) {
454
+ continue;
455
+ }
456
+ $totalOrdered += $order['subtotal'];
457
+ }
458
+
459
+ if ($totalOrdered == $request->getRequest()->getParam('emailchefTotalAmountValue')
460
+ && $request->getRequest()->getParam('emailchefTotalAmountCond') == 'eq') {
461
+ $tempTotal[] = $result[$count];
462
+ }
463
+
464
+ if ($totalOrdered > $request->getRequest()->getParam('emailchefTotalAmountValue')
465
+ && $request->getRequest()->getParam('emailchefTotalAmountCond') == 'gt') {
466
+ $tempTotal[] = $result[$count];
467
+ }
468
+
469
+ if ($totalOrdered < $request->getRequest()->getParam('emailchefTotalAmountValue')
470
+ && $request->getRequest()->getParam('emailchefTotalAmountCond') == 'lt') {
471
+ $tempTotal[] = $result[$count];
472
+ }
473
+
474
+ ++$count;
475
+
476
+ //unsetto la variabile
477
+ unset($orders); //->unsetData();
478
+ }
479
+
480
+ $customersFiltered = self::intersectByEntityId($tempTotal, $customersFiltered);
481
+ }
482
+ //FINE FILTRO 8 TOTALE ACQUISTATO: testato ok
483
+
484
+ //FILTRO 9 DATA ACQUISTATO
485
+ $count = 0;
486
+ $result = array();
487
+ $tempOrderedDateYes = array();
488
+ $tempOrderedDateNo = array();
489
+
490
+ if ($request->getRequest()->getParam('emailchefOrderStartDate')
491
+ || $request->getRequest()->getParam('emailchefOrderEndDate')) {
492
+ foreach ($customersFiltered as $customer) {
493
+ $result[] = $customer;
494
+
495
+ //filtro gli ordini in base al customer id
496
+ $orders = Mage::getModel('sales/order')
497
+ ->getCollection()
498
+ ->addAttributeToFilter('customer_id', $result[$count]['entity_id'])
499
+ ;
500
+
501
+ $orderedDate = 0;
502
+
503
+ foreach ($orders->getData() as $order) {
504
+ if (isset($order['status']) && !in_array($order['status'], array('closed', 'complete', 'processing'))) {
505
+ continue;
506
+ }
507
+ $createdAt = $order['created_at'];
508
+ $createdAt = new DateTime($createdAt, $TIMEZONE_UTC);
509
+ $createdAt->setTimezone($TIMEZONE_STORE);
510
+ $createdAt = (string) $createdAt->format('Y-m-d H:i:s');
511
+ $filterStart = '';
512
+ $filterEnd = '';
513
+
514
+ if ($request->getRequest()->getParam('emailchefOrderStartDate')) {
515
+ $date = Zend_Locale_Format::getDate(
516
+ $request->getRequest()->getParam('emailchefOrderStartDate'),
517
+ array(
518
+ 'locale' => Mage::app()->getLocale()->getLocale(),
519
+ 'date_format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT),
520
+ 'fix_date' => true,
521
+ )
522
+ );
523
+ $date['month'] = str_pad($date['month'], 2, 0, STR_PAD_LEFT);
524
+ $date['day'] = str_pad($date['day'], 2, 0, STR_PAD_LEFT);
525
+ $filterStart = "{$date['year']}-{$date['month']}-{$date['day']} 00:00:00";
526
+ }
527
+ if ($request->getRequest()->getParam('emailchefOrderEndDate')) {
528
+ $date = Zend_Locale_Format::getDate(
529
+ $request->getRequest()->getParam('emailchefOrderEndDate'),
530
+ array(
531
+ 'locale' => Mage::app()->getLocale()->getLocale(),
532
+ 'date_format' => Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT),
533
+ 'fix_date' => true,
534
+ )
535
+ );
536
+ $date['month'] = str_pad($date['month'], 2, 0, STR_PAD_LEFT);
537
+ $date['day'] = str_pad($date['day'], 2, 0, STR_PAD_LEFT);
538
+ $filterEnd = "{$date['year']}-{$date['month']}-{$date['day']} 23:59:59";
539
+ }
540
+
541
+ if ($filterStart and $filterEnd) {
542
+ //compreso tra start e end date
543
+ if ($createdAt >= $filterStart and $createdAt <= $filterEnd) {
544
+ $orderedDate = 1;
545
+ }
546
+ } elseif ($filterStart) {
547
+ // >= di start date
548
+ if ($createdAt >= $filterStart) {
549
+ $orderedDate = 1;
550
+ }
551
+ } else {
552
+ // <= di end date
553
+ if ($createdAt <= $filterEnd) {
554
+ $orderedDate = 1;
555
+ }
556
+ }
557
+
558
+ //unsetto la variabile
559
+ unset($orders); //->unsetData();
560
+ }
561
+
562
+ if ($orderedDate == 1) {
563
+ $tempOrderedDateYes[] = $result[$count];
564
+ } else {
565
+ $tempOrderedDateNo[] = $result[$count];
566
+ }
567
+
568
+ ++$count;
569
+ }
570
+
571
+ if ($request->getRequest()->getParam('emailchefOrderYesNo') == 'yes') {
572
+ $customersFiltered = self::intersectByEntityId($tempOrderedDateYes, $customersFiltered);
573
+ } else {
574
+ $customersFiltered = self::intersectByEntityId($tempOrderedDateNo, $customersFiltered);
575
+ }
576
+ }
577
+ //FINE FILTRO 9 DATA ACQUISTATO: testato ok
578
+ } else {
579
+ //GESTISCO LE MODIFICHE MANUALI
580
+ $count = 0;
581
+ $result = array();
582
+ $tempMod = array();
583
+
584
+ $emails = explode("\n", $request->getRequest()->getParam('emailchefCustomerFilteredMod'));
585
+
586
+ foreach ($emails as $email) {
587
+ $email = trim($email);
588
+
589
+ if (strstr($email, '@') !== false) {
590
+ $customerModCollection = Mage::getModel('customer/customer')
591
+ ->getCollection()
592
+ ->addAttributeToSelect('email')
593
+ ->addAttributeToFilter('email', $email);
594
+
595
+ $added = 0;
596
+
597
+ foreach ($customerModCollection as $customerMod) {
598
+ $tempMod[] = $customerMod->toArray();
599
+ $added = 1;
600
+ }
601
+
602
+ if ($added == 0) {
603
+ $tempMod[] = array('entity_id' => 0, 'firstname' => '', 'lastname' => '', 'email' => $email);
604
+ }
605
+ }
606
+ }
607
+
608
+ //$customersFiltered = self::intersectByEntityId($tempMod, $customersFiltered);
609
+ $customersFiltered = $tempMod;
610
+ }
611
+ //FINE GESTISCO LE MODIFICHE MANUALI
612
+
613
+ return $customersFiltered;
614
+ }
615
+
616
+ /**
617
+ * Get Filter Hints.
618
+ *
619
+ * @return array
620
+ */
621
+ public function getFilterHints()
622
+ {
623
+ $filter_hints = array();
624
+ try {
625
+ // fetch write database connection that is used in Mage_Core module
626
+ $connectionRead = Mage::getSingleton('core/resource')->getConnection('core_read');
627
+
628
+ // now $write is an instance of Zend_Db_Adapter_Abstract
629
+ $result = $connectionRead->query('select * from emailchef_filter_hints');
630
+
631
+ while ($row = $result->fetch()) {
632
+ array_push($filter_hints, array('filter_name' => $row['filter_name'], 'hints' => $row['hints']));
633
+ }
634
+ } catch (Exception $e) {
635
+ Mage::log('Exception: '.$e->getMessage(), 0);
636
+ die($e);
637
+ }
638
+
639
+ return $filter_hints;
640
+ }
641
+
642
+ /**
643
+ * Save Filter Hint.
644
+ *
645
+ * @param type $filter_name
646
+ * @param type $post
647
+ */
648
+ public function saveFilterHint($filter_name, $post)
649
+ {
650
+ try {
651
+ $hints = '';
652
+ foreach ($post as $k => $v) {
653
+ if ($v != '' && $k != 'form_key') {
654
+ if ($hints != '') {
655
+ $hints .= '|';
656
+ }
657
+ $hints .= $k.'='.$v;
658
+ }
659
+ }
660
+ //(e.g. $hints = 'emailchefCustomers=2|emailchefSubscribed=1';)
661
+ $connectionWrite = Mage::getSingleton('core/resource')->getConnection('core_write');
662
+ $connectionWrite->query("INSERT INTO emailchef_filter_hints (filter_name, hints) VALUES ('".$filter_name."', '".$hints."')");
663
+ } catch (Exception $e) {
664
+ Mage::log('Exception: '.$e->getMessage(), 0);
665
+ die($e);
666
+ }
667
+ }
668
+
669
+ /**
670
+ * Delete Filter Hint.
671
+ *
672
+ * @param type $filter_name
673
+ */
674
+ public function deleteFilterHint($filter_name)
675
+ {
676
+ try {
677
+ $connectionWrite = Mage::getSingleton('core/resource')->getConnection('core_write');
678
+ $connectionWrite->query("DELETE FROM emailchef_filter_hints WHERE filter_name LIKE '".$filter_name."'");
679
+ } catch (Exception $e) {
680
+ Mage::log('Exception: '.$e->getMessage(), 0);
681
+ die($e);
682
+ }
683
+ }
684
+
685
+ /**
686
+ * Get Field Mapping.
687
+ *
688
+ * @todo Fix to use the config for mappings, per store..
689
+ *
690
+ * @param int
691
+ *
692
+ * @return array
693
+ */
694
+ public function getFieldsMapping($storeId = null)
695
+ {
696
+ $config = Mage::getModel('emailchef/config');
697
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
698
+ return $config->getFieldsMapping($storeId);
699
+ }
700
+
701
+ /**
702
+ * @depreciated
703
+ *
704
+ * @param array
705
+ */
706
+ public function saveFieldMapping($post)
707
+ {
708
+ try {
709
+ $connectionWrite = Mage::getSingleton('core/resource')->getConnection('core_write');
710
+ $connectionWrite->query('DELETE FROM emailchef_fields_mapping');
711
+ foreach ($post as $k => $v) {
712
+ if (strlen($v) == 0) {
713
+ continue;
714
+ }
715
+ $connectionWrite->insert('emailchef_fields_mapping', array(
716
+ 'magento_field_name' => $k,
717
+ 'emailchef_field_id' => $v,
718
+ ));
719
+ }
720
+ } catch (Exception $e) {
721
+ Mage::log('Exception: '.$e->getMessage(), 0);
722
+ die($e);
723
+ }
724
+ }
725
+
726
+ /**
727
+ * Get the config.
728
+ *
729
+ * @return EMailChef_EMailChefSync_Model_Config
730
+ */
731
+ protected function _config()
732
+ {
733
+ return $this->_config;
734
+ }
735
+
736
+ /**
737
+ * Recursive intersection of $array1 and $array2 by entity IDs
738
+ * NOTE that php's self::intersectByEntityId is not recursive, so cannot be used on arrays of arrays.
739
+ *
740
+ * @param array $array1
741
+ * @param array $array2
742
+ *
743
+ * @return array
744
+ */
745
+ public static function intersectByEntityId($array1, $array2)
746
+ {
747
+ $tempIds = array();
748
+ foreach ($array1 as $entity1) {
749
+ if (isset($entity1['entity_id'])) {
750
+ $tempIds[$entity1['entity_id']] = true;
751
+ }
752
+ }
753
+ $tempArray = array();
754
+ foreach ($array2 as $entity2) {
755
+ if (isset($entity2['entity_id']) && isset($tempIds[$entity2['entity_id']])) {
756
+ $tempArray[] = $entity2;
757
+ }
758
+ }
759
+
760
+ return $tempArray;
761
+ }
762
+ }
app/code/community/EMailChef/EMailChefSync/Model/Job.php ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * EMailChefjob.php.
4
+ *
5
+ * @method int getStoreId()
6
+ * @method string getListid()
7
+ * @method int getProcessId()
8
+ * @method void setStoreId(int $storeId) Set the Store ID
9
+ * @method void setProcessId(int $id) Set the Mailedup Process ID
10
+ * @method void setStatus(string $status)
11
+ * @method void setTries(int $num) How many times we've tried.
12
+ * @method void setType(string $type) What type of job?
13
+ * @method void setQueueDatetime(string $dateTime) Set the Datetime the job was queued.
14
+ * @method void setStartDatetime(string $dateTime) Set when the job was started
15
+ * @method void setFinishDatetime(string $dateTime) Set when the job was finished / completed
16
+ */
17
+ class EMailChef_EMailChefSync_Model_Job extends Mage_Core_Model_Abstract
18
+ {
19
+ const STATUS_FINISHED = 'finished';
20
+ const STATUS_QUEUED = 'queued';
21
+ const STATUS_STARTED = 'started';
22
+ const STATUS_IMPORTED = 'imported'; // NewImportProccess has been called
23
+
24
+ const TYPE_MANUAL_SYNC = 0;
25
+ const TYPE_AUTO_SYNC = 1;
26
+
27
+ /**
28
+ * Constructor.
29
+ */
30
+ protected function _construct()
31
+ {
32
+ parent::_construct();
33
+ $this->_init('emailchef/job');
34
+ }
35
+
36
+ /**
37
+ * Increment the number of tries we've attempted.
38
+ *
39
+ * @return int
40
+ */
41
+ public function incrementTries()
42
+ {
43
+ $tries = (int) $this->getTries();
44
+ ++$tries;
45
+ $this->setTries($tries);
46
+
47
+ return $tries;
48
+ }
49
+
50
+ /**
51
+ * Mark as finished.
52
+ *
53
+ * @return \EMailChef_EMailChefSync_Model_Job
54
+ */
55
+ public function finished()
56
+ {
57
+ $this->setStatus(self::STATUS_FINISHED);
58
+ $this->setFinishDatetime(gmdate('Y-m-d H:i:s'));
59
+
60
+ return $this;
61
+ }
62
+
63
+ /**
64
+ * Mark as Queued.
65
+ *
66
+ * @return \EMailChef_EMailChefSync_Model_Job
67
+ */
68
+ public function queue()
69
+ {
70
+ $this->setStatus(self::STATUS_QUEUED);
71
+ $this->setQueueDatetime(gmdate('Y-m-d H:i:s'));
72
+
73
+ return $this;
74
+ }
75
+
76
+ /**
77
+ * Is this job finished?
78
+ *
79
+ * @return bool
80
+ */
81
+ public function isFinished()
82
+ {
83
+ return $this->getStatus() == self::STATUS_FINISHED;
84
+ }
85
+
86
+ /**
87
+ * Is this job queued?
88
+ *
89
+ * @return bool
90
+ */
91
+ public function isQueued()
92
+ {
93
+ return $this->getStatus() == self::STATUS_QUEUED;
94
+ }
95
+
96
+ /**
97
+ * Process the job / Start.
98
+ *
99
+ * @return bool
100
+ */
101
+ public function process()
102
+ {
103
+ $this->setStatus(self::STATUS_STARTED);
104
+ $this->setStartDatetime(gmdate('Y-m-d H:i:s'));
105
+
106
+ /*
107
+ * Now we need to do the heavy lifting!
108
+ */
109
+ }
110
+
111
+ /**
112
+ * Get a collection of jobs in the Queue.
113
+ *
114
+ * @param int
115
+ *
116
+ * @return EMailChef_EMailChefSync_Model_Mysql4_Job_Collection
117
+ */
118
+ public function fetchQueuedJobsCollection($type = null)
119
+ {
120
+ $collection = $this->getCollection();
121
+ /* @var $collection EMailChef_EMailChefSync_Model_Mysql4_Job_Collection */
122
+ $collection
123
+ ->addFieldToSelect('*')
124
+ ->addFieldToFilter('status', array('eq' => self::STATUS_QUEUED))
125
+ ;
126
+
127
+ if ($type !== null) {
128
+ $collection->addFieldToFilter('type', array('eq' => (int) $type));
129
+ }
130
+
131
+ return $collection;
132
+ }
133
+
134
+ /**
135
+ * Get a collection of jobs in the Queue marked as Queued or Started.
136
+ *
137
+ * @param int
138
+ *
139
+ * @return EMailChef_EMailChefSync_Model_Mysql4_Job_Collection
140
+ */
141
+ public function fetchQueuedOrStartedJobsCollection($type = null)
142
+ {
143
+ $collection = $this->getCollection();
144
+ /* @var $collection EMailChef_EMailChefSync_Model_Mysql4_Job_Collection */
145
+ $collection
146
+ ->addFieldToSelect('*')
147
+ ->addFieldToFilter('status', array('in' => array(self::STATUS_QUEUED, self::STATUS_STARTED)))
148
+ ;
149
+
150
+ if ($type !== null) {
151
+ $collection->addFieldToFilter('type', array('eq' => (int) $type));
152
+ }
153
+
154
+ return $collection;
155
+ }
156
+
157
+ /**
158
+ * Get a collection of jobs in the Queue.
159
+ *
160
+ * @return EMailChef_EMailChefSync_Model_Mysql4_Job_Collection
161
+ */
162
+ public function fetchManualSyncQueuedJobsCollection()
163
+ {
164
+ return $this->fetchQueuedJobsCollection(self::TYPE_MANUAL_SYNC);
165
+ }
166
+
167
+ /**
168
+ * Get a collection of jobs in the Queue.
169
+ *
170
+ * @return EMailChef_EMailChefSync_Model_Mysql4_Job_Collection
171
+ */
172
+ public function fetchAutoSyncQueuedJobsCollection()
173
+ {
174
+ return $this->fetchQueuedJobsCollection(self::TYPE_AUTO_SYNC);
175
+ }
176
+
177
+ /**
178
+ * Get associated job data (customers to sync).
179
+ *
180
+ * @return array
181
+ */
182
+ public function getJobData()
183
+ {
184
+ $jobTasks = Mage::getModel('emailchef/sync');
185
+ /* @var $jobTasks EMailChef_EMailChefSync_Model_Sync */
186
+ return $jobTasks->fetchByJobId($this->getId());
187
+ }
188
+
189
+ /**
190
+ * Mark as an Auto Sync Job.
191
+ */
192
+ public function setAsAutoSync()
193
+ {
194
+ $this->setType(self::TYPE_AUTO_SYNC);
195
+
196
+ return $this;
197
+ }
198
+
199
+ /**
200
+ * Mark as an Manul Sync Job, done using Sync/Segment feature.
201
+ */
202
+ public function setAsManualSync()
203
+ {
204
+ $this->setType(self::TYPE_MANUAL_SYNC);
205
+
206
+ return $this;
207
+ }
208
+
209
+ /**
210
+ * Whether job is an auto-sync job or manual.
211
+ *
212
+ * @return bool
213
+ */
214
+ public function isAutoSync()
215
+ {
216
+ return (int) $this->getType() === self::TYPE_AUTO_SYNC;
217
+ }
218
+ }
app/code/community/EMailChef/EMailChefSync/Model/Log.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Log.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Model_Log extends Mage_Core_Model_Abstract
6
+ {
7
+ const TYPE_DEBUG = 'DEBUG';
8
+ const TYPE_API = 'API';
9
+ const TYPE_JOB = 'JOB';
10
+ const TYPE_JOB_DATA = 'SYNC';
11
+
12
+ /**
13
+ * Constructor.
14
+ */
15
+ protected function _construct()
16
+ {
17
+ parent::_construct();
18
+ $this->_init('emailchef/log');
19
+ }
20
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql14/EMailChef.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Model_Mysql4_EMailChef extends Mage_Core_Model_Mysql4_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ $this->_init('emailchef/emailchef', 'emailchef_id');
8
+ }
9
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql14/EMailChef/Collection.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Model_Mysql4_EMailChef_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ //parent::__construct();
8
+ $this->_init('emailchef/emailchef');
9
+ }
10
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Job.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Job.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Model_Mysql4_Job extends Mage_Core_Model_Mysql4_Abstract
6
+ {
7
+ protected function _construct()
8
+ {
9
+ $this->_init('emailchef/job', 'id');
10
+ }
11
+
12
+ // /**
13
+ // * Get product identifier by sku
14
+ // *
15
+ // * @param string $sku
16
+ // * @return int|false
17
+ // */
18
+ // public function getIdBySku($sku)
19
+ // {
20
+ // $adapter = $this->_getReadAdapter();
21
+ //
22
+ // $select = $adapter->select()
23
+ // ->from('phpsolut_import')
24
+ // ->where('sku = :sku');
25
+ //
26
+ // $bind = array(':sku' => (string)$sku);
27
+ //
28
+ // return $adapter->fetchOne($select, $bind);
29
+ // }
30
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Job/Collection.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Collection.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Model_Mysql4_Job_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
6
+ {
7
+ public function _construct()
8
+ {
9
+ $this->_init('emailchef/job');
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Log.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Log.php.
4
+ *
5
+ * @method string getType()
6
+ * @method void setType(string $type)
7
+ * @method string getStatus()
8
+ * @method void setStatus(string $type)
9
+ * @method int getStoreId()
10
+ * @method void setStoreId(int $storeId)
11
+ * @method int getJobId()
12
+ * @method void setJobId(int $jobId)
13
+ */
14
+ class EMailChef_EMailChefSync_Model_Mysql4_Log extends Mage_Core_Model_Mysql4_Abstract
15
+ {
16
+ const TYPE_ERROR = 'ERROR';
17
+ const TYPE_DEBUG = 'DEBUG';
18
+ const TYPE_CRON = 'CRON';
19
+ const TYPE_WARN = 'WARNING';
20
+
21
+ protected function _construct()
22
+ {
23
+ $this->_init('emailchef/log', 'id');
24
+ }
25
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Log/Collection.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Collection.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Model_Mysql4_Log_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
6
+ {
7
+ public function _construct()
8
+ {
9
+ $this->_init('emailchef/log');
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Sync.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Job.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Model_Mysql4_Sync extends Mage_Core_Model_Mysql4_Abstract
6
+ {
7
+ protected function _construct()
8
+ {
9
+ $this->_init('emailchef/sync', 'id');
10
+ }
11
+
12
+ /**
13
+ * Get the ID from the unique values.
14
+ *
15
+ * @param int
16
+ * @param int
17
+ * @param int
18
+ */
19
+ public function getIdByUniqueKey($customerId, $jobId, $storeId)
20
+ {
21
+ $adapter = $this->_getReadAdapter();
22
+ $select = $adapter->select()
23
+ ->from($this->getMainTable())
24
+ ->where('customer_id = :customer_id AND job_id = :job_id AND store_id = :store_id')
25
+ ;
26
+
27
+ $bind = array(
28
+ ':customer_id' => $customerId,
29
+ ':job_id' => $jobId,
30
+ ':store_id' => $storeId,
31
+ );
32
+
33
+ return $adapter->fetchOne($select, $bind);
34
+ }
35
+
36
+ /**
37
+ * Load by unique Key.
38
+ */
39
+ public function loadByUniqueKey()
40
+ {
41
+ //(`customer_id`,`entity`,`job_id`, `store_id`)
42
+ }
43
+
44
+ // /**
45
+ // * Get product identifier by sku
46
+ // *
47
+ // * @param string $sku
48
+ // * @return int|false
49
+ // */
50
+ // public function getIdBySku($sku)
51
+ // {
52
+ // $adapter = $this->_getReadAdapter();
53
+ //
54
+ // $select = $adapter->select()
55
+ // ->from('phpsolut_import')
56
+ // ->where('sku = :sku');
57
+ //
58
+ // $bind = array(':sku' => (string)$sku);
59
+ //
60
+ // return $adapter->fetchOne($select, $bind);
61
+ // }
62
+
63
+ //return $this->_getReadAdapter()->fetchOne(
64
+ // 'select connect_id from '.$this->getMainTable().' where sku=?',
65
+ // $sku
66
+ // );
67
+ }
app/code/community/EMailChef/EMailChefSync/Model/Mysql4/Sync/Collection.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Collection.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Model_Mysql4_Sync_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
6
+ {
7
+ public function _construct()
8
+ {
9
+ $this->_init('emailchef/sync');
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/Model/Observer.php ADDED
@@ -0,0 +1,646 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once __DIR__.'/../lib/emailchef/vendor/autoload.php';
4
+ require_once dirname(__FILE__).'/EMailChefWsImport.php';
5
+ require_once dirname(__FILE__).'/Wssend.php';
6
+
7
+ class EMailChef_EMailChefSync_Model_Observer
8
+ {
9
+ const CRON_STRING_PATH = 'crontab/jobs/emailchef_emailchefsync/schedule/cron_expr';
10
+
11
+ /**
12
+ * @var EMailChef_EMailChefSync_Model_Config
13
+ */
14
+ protected $_config;
15
+
16
+ protected $_beforeSaveCalled = array();
17
+ protected $_afterSaveCalled = array();
18
+
19
+ /**
20
+ * Save system config event.
21
+ *
22
+ * @param Varien_Object $observer
23
+ */
24
+ public function saveSystemConfig($observer)
25
+ {
26
+ Mage::getSingleton('adminhtml/session')->setMessages(Mage::getModel('core/message_collection'));
27
+
28
+ Mage::getModel('core/config_data')
29
+ ->load(self::CRON_STRING_PATH, 'path')
30
+ ->setValue($this->_getSchedule())
31
+ ->setPath(self::CRON_STRING_PATH)
32
+ ->save();
33
+
34
+ Mage::app()->cleanCache();
35
+
36
+ $this->configCheck();
37
+
38
+ // If there are errors in config, do not progress further as it may be testing old data
39
+ $currentMessages = Mage::getSingleton('adminhtml/session')->getMessages();
40
+ foreach ($currentMessages->getItems() as $msg) {
41
+ if ($msg->getType() != 'success') {
42
+ return;
43
+ }
44
+ }
45
+
46
+ $messages = array();
47
+
48
+ // Close connection to avoid mysql gone away errors
49
+ $res = Mage::getSingleton('core/resource');
50
+ $res->getConnection('core_write')->closeConnection();
51
+
52
+ // Test connection
53
+ $storeId = Mage::app()->getStore();
54
+ $usernameWs = Mage::getStoreConfig('emailchef_newsletter/emailchef/username_ws');
55
+ $passwordWs = Mage::getStoreConfig('emailchef_newsletter/emailchef/password_ws');
56
+ $retConn = Mage::helper('emailchef')->testConnection($usernameWs, $passwordWs, $storeId);
57
+ $messages = array_merge($messages, $retConn);
58
+
59
+ // Config tests
60
+ $retConfig = Mage::helper('emailchef')->testConfig();
61
+ $messages = array_merge($messages, $retConfig);
62
+
63
+ // Re-open connection to avoid mysql gone away errors
64
+ $res->getConnection('core_write')->getConnection();
65
+
66
+ // Add messages from test
67
+ if (count($messages) > 0) {
68
+ foreach ($messages as $msg) {
69
+ $msgObj = Mage::getSingleton('core/message')->$msg['type']($msg['message']);
70
+ Mage::getSingleton('adminhtml/session')->addMessage($msgObj);
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Transform system settings option to cron schedule string.
77
+ *
78
+ * @return string
79
+ */
80
+ protected function _getSchedule()
81
+ {
82
+ // Get frequency and offset from posted data
83
+ $data = Mage::app()->getRequest()->getPost('groups');
84
+ $frequency = !empty($data['emailchef']['fields']['emailchef_cron_frequency']['value']) ?
85
+ $data['emailchef']['fields']['emailchef_cron_frequency']['value'] :
86
+ EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Cron_Frequency::HOURLY;
87
+ $offset = !empty($data['emailchef']['fields']['emailchef_cron_offset']['value']) ?
88
+ $data['emailchef']['fields']['emailchef_cron_offset']['value'] :
89
+ 0;
90
+
91
+ // Get period between calls and calculate explicit hours using this and offset
92
+ $period = EMailChef_EMailChefSync_Model_Adminhtml_System_Source_Cron_Frequency::getPeriod($frequency);
93
+ if ($period === null) {
94
+ Mage::log('eMailChef: Could not find cron frequency in valid list. Defaulted to hourly', Zend_Log::ERR);
95
+ $period = 1;
96
+ }
97
+ $hoursStr = $this->_calculateHourFreqString($period, $offset);
98
+
99
+ return "0 {$hoursStr} * * *";
100
+ }
101
+
102
+ /**
103
+ * Get comma-separated list of hours in a day spaced by $periodInHours and offset by
104
+ * $offset hours. Note that if $offset is greater than $periodInHours then it loops (modulo).
105
+ *
106
+ * @param int $periodInHours Hours between each call
107
+ * @param int $offset Offset (in hours) for each entry
108
+ *
109
+ * @return string Comma-separated list of hours
110
+ */
111
+ private function _calculateHourFreqString($periodInHours, $offset)
112
+ {
113
+ $hours = array();
114
+ // Repeat as many times as the period fits into 24 hours
115
+ for ($n = 0; $n < (24 / $periodInHours); ++$n) {
116
+ $hours[] = $n * $periodInHours + ($offset % $periodInHours);
117
+ }
118
+ $hourStr = implode(',', $hours);
119
+
120
+ return $hourStr;
121
+ }
122
+
123
+
124
+ /**
125
+ * Observes: customer_customer_authenticated
126
+ *
127
+ * @param type $observer
128
+ * @return \EMailChef_EMailChefSync_Model_Observer
129
+ */
130
+ public function checkUser($observer)
131
+ {
132
+ $model = $observer->getEvent()->getModel();
133
+ if (empty($model)) $model = $model = $observer->getEvent()->getDataObject();
134
+ if (isset($GLOBALS["__sl_emailchef_check_user"])) return $this;
135
+ $GLOBALS["__sl_emailchef_check_user"] = true;
136
+
137
+ $listId = Mage::getStoreConfig('emailchef_newsletter/emailchef/list');
138
+ $defaultGroupId = Mage::getStoreConfig('emailchef_newsletter/emailchef/default_group');
139
+ $confirm = Mage::getStoreConfig('emailchef_newsletter/emailchef/require_subscription_confirmation');
140
+
141
+ try {
142
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) Mage::log("stato registrazione: " . $stato_registrazione);
143
+ $model = $observer->getEvent()->getModel();
144
+ $storeId = $model->getStoreId(); // Is this always correct??
145
+
146
+ // Get from list
147
+ $wsSend = new EMailChefWsSend($storeId);
148
+ $accessKey = $wsSend->loginFromId();
149
+ $getContactFromEmailCommand = new \EMailChef\Command\Api\GetContactFromEmailCommand();
150
+ $contact = $getContactFromEmailCommand->execute($listId, $model->getEmail(), $accessKey);
151
+
152
+ // Ensure that before_save does not fire
153
+ $this->_authenticationCalled[$model->getEmail()] = true;
154
+ // Set subscription based on returned $stato_registrazione
155
+
156
+ $subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($model->getEmail());
157
+
158
+ $status = $subscriber->getStatus();
159
+
160
+ if($contact->status=='UNSUBSCRIBED' && $status != Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED ){
161
+ $model->setIsSubscribed(0);
162
+ $model->save();
163
+ }
164
+ } catch (Exception $e) {
165
+ Mage::logException($e);
166
+ }
167
+
168
+ return $this;
169
+ }
170
+
171
+ /**
172
+ * Observes Before save, sets the status based on single or double opt-in.
173
+ *
174
+ * @see newsletter_subscriber_save_before
175
+ *
176
+ * @param $observer
177
+ */
178
+ public function beforeSave($observer)
179
+ {
180
+ $model = $observer->getEvent()->getDataObject();
181
+
182
+ $confirm = Mage::getStoreConfig('emailchef_newsletter/emailchef/require_subscription_confirmation');
183
+
184
+ // If change is to subscribe, and confirmation required, set to confirmation pending
185
+ if ($model->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED &&
186
+ $confirm
187
+ ) {
188
+ // Always change the status
189
+ $model->setStatus(Mage_Newsletter_Model_Subscriber::STATUS_UNCONFIRMED);
190
+ }
191
+
192
+ // Check whether there is a status to change
193
+ $origModel = Mage::getModel('newsletter/subscriber')->load($model->getId());
194
+ if ($origModel->getStatus() == $model->getStatus()) {
195
+ $model->setDoNotChangeSubscription(true);
196
+
197
+ return;
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Observes subscription.
203
+ *
204
+ * @see newsletter_subscriber_save_after
205
+ *
206
+ * @param $observer
207
+ *
208
+ * @return \EMailChef_EMailChefSync_Model_Observer
209
+ */
210
+ public function sendUser($observer)
211
+ {
212
+ $model = $observer->getEvent()->getDataObject();
213
+
214
+ // Ensure that (if called as singleton), this will only get called once per customer
215
+ if (isset($this->_afterSaveCalled[$model->getEmail()])) {
216
+ return $this;
217
+ }
218
+ $this->_afterSaveCalled[$model->getEmail()] = true;
219
+
220
+ // If there is no change to status, do not subscribe/unsubscribe
221
+ if ($model->getDoNotChangeSubscription()) {
222
+ return $this;
223
+ }
224
+
225
+ // If the status has changed, and it is now unconfirmed, set notification
226
+ if ($model->getStatus() == Mage_Newsletter_Model_Subscriber::STATUS_UNCONFIRMED) {
227
+ Mage::getSingleton('core/session')->addNotice(Mage::helper('emailchef')->__('Your subscription is waiting for confirmation'));
228
+ }
229
+
230
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
231
+ Mage::log($model->getData());
232
+ }
233
+ $subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($model->getEmail());
234
+ $status = $subscriber->getStatus();
235
+
236
+ $module = Mage::app()->getRequest()->getModuleName();
237
+ $controller = Mage::app()->getRequest()->getControllerName();
238
+ $action = Mage::app()->getRequest()->getActionName();
239
+
240
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
241
+ Mage::log('emailchef: invia utente');
242
+ }
243
+
244
+ if (($module == 'customer' and $controller == 'account' and $action == 'createpost') or ($module == 'checkout' and $controller == 'onepage' and $action == 'saveOrder')) {
245
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
246
+ Mage::log('SONO in registrazione');
247
+ }
248
+ /*
249
+ * are recording, monitoring the status of magento subscribe,
250
+ * if you do not result in writing I read status from EMailChef and if
251
+ * they are registered with the subject of magento before continuing
252
+ */
253
+ if (!$status) {
254
+ //rileggo lo status perché potrebbe essere stato modificato dalla precedente chiamata
255
+ $status = Mage::getModel('newsletter/subscriber')->loadByEmail($model->getEmail())->getStatus();
256
+ // se non sono iscritto nemmeno lato emailchef allora posso evitare di andare oltre
257
+ if (!$status) {
258
+ return $this;
259
+ }
260
+ }
261
+ }
262
+
263
+ $listId = Mage::getStoreConfig('emailchef_newsletter/emailchef/list');
264
+ $defaultGroupId = Mage::getStoreConfig('emailchef_newsletter/emailchef/default_group');
265
+ $confirm = Mage::getStoreConfig('emailchef_newsletter/emailchef/require_subscription_confirmation');
266
+
267
+ try {
268
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
269
+ Mage::log("STATO ISCRIZIONE: $status");
270
+ }
271
+
272
+ $storeId = $observer->getEvent()->getSubscriber()->getStoreId(); // Is this always correct??
273
+
274
+ // Get from list
275
+ $wsSend = new EMailChefWsSend($storeId);
276
+ $accessKey = $wsSend->loginFromId();
277
+ $getContactFromEmailCommand = new \EMailChef\Command\Api\GetContactFromEmailCommand();
278
+ $contact = $getContactFromEmailCommand->execute($listId, $model->getEmail(), $accessKey);
279
+
280
+ if ($status == Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED && !$contact) {
281
+ // send it
282
+ $deleteContactCommand = new \EMailChef\Command\Api\CreateContactCommand();
283
+ $deleteContactCommand->execute($listId, $model->getEmail(), $accessKey);
284
+ // add default list if available
285
+ if ($defaultGroupId) {
286
+ $addEmailsToGroupCommand = new \EMailChef\Command\Api\AddEmailsToGroupCommand();
287
+ $addEmailsToGroupCommand->execute($accessKey, array($model->getEmail()), $listId, $defaultGroupId);
288
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
289
+ Mage::log('emailchef aggiunta utente a gruppo');
290
+ }
291
+ }
292
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
293
+ Mage::log('emailchef invio utente');
294
+ }
295
+
296
+ // Customer data sync if customerId
297
+ $modelData = $model->getData();
298
+ if (isset($modelData['customer_id'])) {
299
+ self::setCustomerForDataSync($modelData['customer_id'], $storeId);
300
+ }
301
+ } elseif ($status != Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED && $contact && $contact->status!='UNSUBSCRIBED') {
302
+ // remove it
303
+ $deleteContactCommand = new \EMailChef\Command\Api\DeleteContactCommand();
304
+ $deleteContactCommand->execute($listId, $contact->id, $accessKey);
305
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
306
+ Mage::log('emailchef cancello utente');
307
+ }
308
+ }
309
+ } catch (Exception $e) {
310
+ Mage::logException($e);
311
+ }
312
+
313
+ return $this;
314
+ }
315
+
316
+ /**
317
+ * Config Check.
318
+ *
319
+ * @return type
320
+ */
321
+ public function configCheck()
322
+ {
323
+ $user = Mage::getStoreConfig('emailchef_newsletter/emailchef/username_ws');
324
+ $password = Mage::getStoreConfig('emailchef_newsletter/emailchef/password_ws');
325
+ $list = Mage::getStoreConfig('emailchef_newsletter/emailchef/list');
326
+
327
+ if (!strlen($user) or !strlen($password) or !strlen($list)) {
328
+ $url = Mage::getModel('adminhtml/url');
329
+ $url = $url->getUrl('emailchef/adminhtml_configuration');
330
+ $message = Mage::helper('emailchef')->__('eMailChef configuration is not complete');
331
+ $message = str_replace("href=''", "href='$url'", $message);
332
+ Mage::getSingleton('adminhtml/session')->addWarning($message);
333
+
334
+ return;
335
+ }
336
+
337
+ $wsimport = new EMailChefWsImport();
338
+ $mapping = $wsimport->getFieldsMapping();
339
+ if (empty($mapping)) {
340
+ $url = Mage::getModel('adminhtml/url');
341
+ $url = $url->getUrl('emailchef/adminhtml_configuration');
342
+ $message = Mage::helper('emailchef')->__('eMailChef fields mapping is not complete');
343
+ $message = str_replace("href=''", "href='$url'", $message);
344
+ Mage::getSingleton('adminhtml/session')->addWarning($message);
345
+
346
+ return;
347
+ }
348
+ }
349
+
350
+ /**
351
+ * Called on completion of an order (saved during one-page checkout)
352
+ * NOTE: If another checkout is used, this will not be called!
353
+ */
354
+ public function onCheckoutSaveOrder()
355
+ {
356
+ $order_id = Mage::getSingleton('checkout/session')->getLastRealOrderId();
357
+ $order = Mage::getModel('sales/order')->loadByIncrementId($order_id);
358
+
359
+ $this->clearAbandonment($order);
360
+ $this->subscribeDuringCheckout($order);
361
+ }
362
+
363
+ /**
364
+ * If customer already subscribed, or pending, then set abandoned cart details to null.
365
+ *
366
+ * @param Mage_Sales_Model_Order $order
367
+ */
368
+ public function clearAbandonment($order)
369
+ {
370
+ // Get subscriber status
371
+ $storeId = $order->getStoreId();
372
+ $customerId = $order->getCustomerId();
373
+ $email = $order->getCustomerEmail();
374
+ $subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
375
+ if ($subscriber === null) {
376
+ return;
377
+ }
378
+ $status = $subscriber->getStatus();
379
+
380
+ // Check status and make API request to clear abandonment fields
381
+ if ($status == Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED ||
382
+ $status == Mage_Newsletter_Model_Subscriber::STATUS_UNCONFIRMED) {
383
+ //Mage::helper('emailchef')->clearAbandonmentFields($id,$email);
384
+ self::setCustomerForDataSync($customerId, $storeId);
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Subscribe the user, during checkout.
390
+ *
391
+ * @param Mage_Sales_Model_Order $order
392
+ */
393
+ public function subscribeDuringCheckout($order)
394
+ {
395
+ // If subscription option chosen, then subscribe
396
+ if (isset($_REQUEST['emailchef_subscribe2']) && $_REQUEST['emailchef_subscribe2']) {
397
+ try {
398
+ Mage::getModel('newsletter/subscriber')->subscribe($order->getCustomerEmail());
399
+ } catch (Exception $e) {
400
+ }
401
+ }
402
+ }
403
+
404
+ /**
405
+ * @var bool
406
+ */
407
+ protected $_hasCustomerDataSynced = false;
408
+
409
+ /**
410
+ * Attach to sales_order_save_after event.
411
+ *
412
+ * @see sales_order_save_after
413
+ *
414
+ * @param type $observer
415
+ */
416
+ public function prepareOrderForDataSync($observer)
417
+ {
418
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
419
+ Mage::log('TRIGGERED prepareOrderForDataSync');
420
+ }
421
+
422
+ $order = $observer->getEvent()->getOrder();
423
+ /* @var $order Mage_Sales_Model_Order */
424
+ $customerId = $order->getCustomerId();
425
+ //$customer = Mage::getmodel('customer/customer')->load($customerId);
426
+ /* @var $customer Mage_Customer_Model_Customer */
427
+ if ($this->_hasCustomerDataSynced) {
428
+ return; // Don't bother if nothing has updated.
429
+ }
430
+
431
+ //$storeId = $customer->getStoreId(); // Is this always correct??
432
+ $storeId = $order->getStoreId();
433
+
434
+ if ($customerId) {
435
+ self::setCustomerForDataSync($customerId, $storeId);
436
+ $this->_hasCustomerDataSynced = true;
437
+ }
438
+ }
439
+
440
+ /**
441
+ * Attach to customer_save_after even.
442
+ *
443
+ * Track if we've synced this run, only do it once.
444
+ * This event can be triggers 3+ times per run as the customer
445
+ * model is saved! we only want one Sync though.
446
+ *
447
+ * @todo refactor
448
+ * @observes customer_save_after
449
+ */
450
+ public function prepareCustomerForDataSync($observer)
451
+ {
452
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
453
+ Mage::log('TRIGGERED prepareCustomerForDataSync');
454
+ }
455
+
456
+ $customer = $observer->getEvent()->getCustomer();
457
+ /* @var $customer Mage_Customer_Model_Customer */
458
+ if (!$customer->hasDataChanges() || $this->_hasCustomerDataSynced) {
459
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
460
+ Mage::log('Nothing changed '.$this->_hasCustomerDataSynced);
461
+ }
462
+
463
+ return; // Don't bother if nothing has updated.
464
+ }
465
+ $customerId = $customer->getId();
466
+ $storeId = $customer->getStoreId(); // Is this always correct??
467
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
468
+ Mage::log('Prepare for sending '.$customerId);
469
+ }
470
+ /*
471
+ * Possibly getting issues here with store id not being right...
472
+ *
473
+ * @todo possible issue
474
+ *
475
+ * If the customer is saved, how do we know which store to sync with?
476
+ * he could possibly have made sales on multiple websites...
477
+ */
478
+ if ($customerId) {
479
+ self::setCustomerForDataSync($customerId, $storeId);
480
+ $this->_hasCustomerDataSynced = true;
481
+ }
482
+ }
483
+
484
+ /**
485
+ * Add customer data to sync table and creates job if required.
486
+ *
487
+ * @param $customerId
488
+ * @param null $storeId
489
+ *
490
+ * @return bool|null
491
+ *
492
+ * @throws Exception
493
+ */
494
+ private static function setCustomerForDataSync($customerId, $storeId = null)
495
+ {
496
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
497
+ Mage::log("TRIGGERED setCustomerForDataSync [StoreID:{$storeId}, CustomerId:{$customerId}]");
498
+ }
499
+
500
+ // If no storeId specified, use current store
501
+ if (!isset($storeId)) {
502
+ $storeId = Mage::app()->getStore()->getId();
503
+ }
504
+
505
+ if (!$customerId) {
506
+ return false;
507
+ }
508
+
509
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
510
+ Mage::log('setCustomerForDataSync preparing to send');
511
+ }
512
+
513
+ $helper = Mage::helper('emailchef');
514
+ /* @var $helper EMailChef_EMailChefSync_Helper_Data */
515
+ $config = Mage::getModel('emailchef/config');
516
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
517
+ $lists = Mage::getSingleton('emailchef/source_lists');
518
+ /* @var $lists EMailChef_EMailChefSync_Model_Source_Lists */
519
+ $listID = $config->getEMailChefListId($storeId);
520
+
521
+ //$listGuid = $lists->getListGuid($listID, $storeId);
522
+ $defaultGroupId = Mage::getStoreConfig('emailchef_newsletter/emailchef/default_group', $storeId);
523
+ if (!$defaultGroupId) {
524
+ $defaultGroupId = 0;
525
+ }
526
+
527
+ // If list is not available, then cancel sync
528
+ if (!$listID) {
529
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
530
+ Mage::log('Could not fetch valid list, so cancelling customer sync');
531
+ }
532
+
533
+ return false;
534
+ }
535
+
536
+ // If cron export is not enabled, skip data sync for this customer
537
+ if (!$config->isCronExportEnabled($storeId)) {
538
+ return;
539
+ }
540
+
541
+ /* @var $job EMailChef_EMailChefSync_Model_Job */
542
+
543
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
544
+ Mage::log('setCustomerForDataSync preparing to send 2');
545
+ }
546
+
547
+ /*
548
+ * Only Sync if they are a subscriber!
549
+ */
550
+ if (!$helper->isSubscriber($customerId, $storeId)) {
551
+ return;
552
+ }
553
+
554
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log')) {
555
+ Mage::log('setCustomerForDataSync preparing to send 3');
556
+ }
557
+
558
+ // Set options for those already subscribed (not pending and no opt-in)
559
+ $data = array(
560
+ 'emailchefgroupid' => $defaultGroupId,
561
+ 'status' => 'queued',
562
+ 'store_id' => $storeId,
563
+ 'list_id' => $listID,
564
+ 'list_guid' => $defaultGroupId,
565
+ );
566
+
567
+ // Find a matching job if exists
568
+ $job = Mage::getModel('emailchef/job');
569
+ self::loadMatchingJob($job, $data);
570
+ // If no matching job, set data on new one
571
+ if (!$job->getId()) {
572
+ $job->setData($data);
573
+ $job->setQueueDatetime(gmdate('Y-m-d H:i:s'));
574
+ $job->setAsAutoSync();
575
+ }
576
+ // Save new or existing job
577
+ try {
578
+ $job->save();
579
+ $config->dbLog('Job [Insert] [Group:NO GROUP] ', $job->getId(), $storeId);
580
+ } catch (Exception $e) {
581
+ $config->dbLog('Job [Insert] [FAILED] [NO GROUP] ', $job->getId(), $storeId);
582
+ $config->log($e);
583
+ throw $e;
584
+ }
585
+
586
+ // Add task - do this whether or not job is new
587
+ try {
588
+ // Check if task already exists for this customer
589
+ $jobTask = Mage::getModel('emailchef/sync');
590
+ if ($jobTask->getIdByUniqueKey($customerId, $job->getId(), $storeId) == null) {
591
+ // If task does not exist, create and save
592
+ /* @var $jobTask EMailChef_EMailChefSync_Model_Sync */
593
+ $jobTask->setData(array(
594
+ 'store_id' => $storeId,
595
+ 'customer_id' => $customerId,
596
+ 'entity' => 'customer',
597
+ 'job_id' => $job->getId(),
598
+ 'needs_sync' => true,
599
+ 'last_sync' => null,
600
+ ));
601
+ $jobTask->save();
602
+ $config->dbLog("Sync [Insert] [customer] [{$customerId}]", $job->getId(), $storeId);
603
+ }
604
+ } catch (Exception $e) {
605
+ $config->dbLog("Sync [Insert] [customer] [FAILED] [{$customerId}]", $job->getId(), $storeId);
606
+ $config->log($e);
607
+ throw $e;
608
+ }
609
+
610
+ return true;
611
+ }
612
+
613
+ /**
614
+ * Load job that matches data, or leave job as is.
615
+ *
616
+ * @param EMailChef_EMailChefSync_Model_Job $job
617
+ * @param array $data
618
+ */
619
+ public static function loadMatchingJob(&$job, $data)
620
+ {
621
+ $collection = Mage::getModel('emailchef/job')->getCollection();
622
+ foreach ($data as $key => $value) {
623
+ $collection->addFieldToFilter($key, $value);
624
+ }
625
+
626
+ if ($collection->getSize() == 0) {
627
+ return;
628
+ }
629
+
630
+ $job = $collection->getFirstItem();
631
+ }
632
+
633
+ /**
634
+ * Get the config.
635
+ *
636
+ * @reutrn EMailChef_EMailChefSync_Model_Config
637
+ */
638
+ protected function _config()
639
+ {
640
+ if (null === $this->_config) {
641
+ $this->_config = Mage::getModel('emailchef/config');
642
+ }
643
+
644
+ return $this->_config;
645
+ }
646
+ }
app/code/community/EMailChef/EMailChefSync/Model/Source/Groups.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Groups.
4
+ */
5
+
6
+ /**
7
+ * Source for groups per list.
8
+ */
9
+ class EMailChef_EMailChefSync_Model_Source_Groups
10
+ {
11
+ /**
12
+ * @var array
13
+ */
14
+ protected $_cache = array();
15
+
16
+ /**
17
+ * Get groups as array of options.
18
+ *
19
+ * @param int|null $storeId
20
+ * @param int|null $listId
21
+ *
22
+ * @return array
23
+ */
24
+ public function toOptionArray($storeId = null, $listId = null)
25
+ {
26
+ $websiteCode = Mage::app()->getRequest()->getParam('website');
27
+ $storeCode = Mage::app()->getRequest()->getParam('store');
28
+
29
+ // Get store
30
+ if (isset($storeId) && $storeId == false) {
31
+ $storeId = Mage::app()->getStore($storeCode)->getId();
32
+ } elseif ($websiteCode) {
33
+ $storeId = Mage::app()
34
+ ->getWebsite($websiteCode)
35
+ ->getDefaultGroup()
36
+ ->getDefaultStoreId();
37
+ } else {
38
+ $storeId = null;
39
+ }
40
+
41
+ // Get List ID
42
+ if ($listId === null) {
43
+ $listId = Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $storeId);
44
+ }
45
+
46
+ // Create select
47
+ $selectLists = array();
48
+ $selectLists[0] = array('value' => '', 'label' => '-- No groups available --');
49
+
50
+ // Only attempt to get groups if there is a list specified
51
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $storeId)) {
52
+ // Get groups from list source (which gets both)
53
+ $sourcelist = Mage::getModel('emailchef/source_lists');
54
+ $groups = $sourcelist->getListGroups($listId, $storeId);
55
+
56
+ // Put groups into option array
57
+ if ($groups !== false) {
58
+ $selectLists[0] = array('value' => '0', 'label' => '-- Select a group (if any) --');
59
+ foreach ($groups as $index => $groupName) {
60
+ $selectLists[] = array(
61
+ 'value' => $index,
62
+ 'label' => $groupName,
63
+ );
64
+ }
65
+ }
66
+ }
67
+
68
+ return $selectLists;
69
+ }
70
+ }
app/code/community/EMailChef/EMailChefSync/Model/Source/Lists.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Lists.php.
4
+ */
5
+ require_once dirname(__DIR__).'/EMailChefWsImport.php';
6
+ require_once dirname(__DIR__).'/Wssend.php';
7
+
8
+ class EMailChef_EMailChefSync_Model_Source_Lists
9
+ {
10
+ /**
11
+ * @var array
12
+ */
13
+ protected $_cache = array();
14
+
15
+ /**
16
+ * Get as options.
17
+ *
18
+ * array(
19
+ * array(
20
+ * 'value' => (string)$list['idList'],
21
+ 'label' => (string)$list['listName'],
22
+ 'guid' =>(string)$list['listGUID'],
23
+ "groups" => array(
24
+ * ...
25
+ * )
26
+ * )
27
+ * )
28
+ *
29
+ * @return array
30
+ */
31
+ public function toOptionArray($storeId = null)
32
+ {
33
+ $websiteCode = Mage::app()->getRequest()->getParam('website');
34
+ $storeCode = Mage::app()->getRequest()->getParam('store');
35
+
36
+ if (isset($storeId) && $storeId != false) {
37
+ $storeId = $storeId; // ?
38
+ } elseif ($storeCode) {
39
+ $storeId = Mage::app()->getStore($storeCode)->getId();
40
+ $cacheId = 'emailchef_fields_array_store_'.$storeId;
41
+ } elseif ($websiteCode) {
42
+ $storeId = Mage::app()
43
+ ->getWebsite($websiteCode)
44
+ ->getDefaultGroup()
45
+ ->getDefaultStoreId()
46
+ ;
47
+ $cacheId = 'emailchef_fields_array_store_'.$storeId;
48
+ } else {
49
+ $storeId = null;
50
+ $cacheId = 'emailchef_fields_array';
51
+ //$storeId = Mage::app()->getDefaultStoreView()->getStoreId();
52
+ }
53
+
54
+ // Create select
55
+ $selectLists = array();
56
+
57
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/username_ws', $storeId)
58
+ && Mage::getStoreConfig('emailchef_newsletter/emailchef/password_ws', $storeId)) {
59
+ $wsSend = new EMailChefWsSend($storeId);
60
+ $accessKey = $wsSend->loginFromId();
61
+
62
+ if ($accessKey !== false) {
63
+ require_once dirname(__DIR__).'/EMailChefWsImport.php';
64
+ $wsImport = new EMailChefWsImport($storeId);
65
+
66
+ $lists = $wsImport->GetNlList($accessKey);
67
+
68
+ $selectLists = array(array('value' => 0, 'label' => '-- Select a list (if any) --'));
69
+
70
+ foreach ($lists as $list) {
71
+ $rGroups = array();
72
+ /*
73
+ $groups= $list->groups;
74
+ foreach($groups as $group){
75
+ $rGroups[(string)$group->id] = (string)$group->name;
76
+ }*/
77
+ $selectLists[] = array(
78
+ 'value' => (string) $list->id,
79
+ 'label' => (string) $list->name,
80
+ 'guid' => (string) $list->id,
81
+ 'groups' => $rGroups,
82
+ );
83
+ }
84
+ } else {
85
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log', $storeId)) {
86
+ Mage::log('LoginFromId failed');
87
+ }
88
+ $selectLists[0] = array('value' => 0, 'label' => $GLOBALS['__sl_emailchef_login_error']);
89
+ }
90
+ }
91
+
92
+ return $selectLists;
93
+ }
94
+
95
+ /**
96
+ * Get an array of list data, and its groups.
97
+ *
98
+ * @param $listId
99
+ * @param $storeId
100
+ *
101
+ * @return bool|array
102
+ */
103
+ public function getListDataArray($listId, $storeId)
104
+ {
105
+ $listData = $this->getDataArray($storeId);
106
+ if (isset($listData[$listId])) {
107
+ return $listData[$listId];
108
+ }
109
+
110
+ // If list not found, return false
111
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log', $storeId)) {
112
+ Mage::log('Invalid List ID: '.$listId);
113
+ }
114
+
115
+ return false;
116
+ }
117
+
118
+ /**
119
+ * Get an array of all lists, and their groups!
120
+ *
121
+ * @param string $storeId
122
+ *
123
+ * @return array
124
+ */
125
+ public function getDataArray($storeId)
126
+ {
127
+ $selectLists = array();
128
+
129
+ // If cache is set, use that
130
+ if (isset($this->_cache[$storeId])) {
131
+ return $this->_cache[$storeId];
132
+ }
133
+
134
+ // If login details not set, return empty list
135
+ if (!$this->_config()->getUsername($storeId) ||
136
+ !$this->_config()->getPassword($storeId)) {
137
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log', $storeId)) {
138
+ Mage::log('Login details not complete - cannot retrieve lists');
139
+ }
140
+
141
+ return $selectLists;
142
+ }
143
+
144
+ // Attempt login (return empty if fails)
145
+ $wsSend = new EMailChefWsSend($storeId);
146
+ $accessKey = $wsSend->loginFromId();
147
+ if ($accessKey === false) {
148
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log', $storeId)) {
149
+ Mage::log('Login failed - cannot retrieve lists');
150
+ }
151
+
152
+ return $selectLists;
153
+ }
154
+
155
+ // Attempt to make call to get lists from API
156
+ require_once dirname(__DIR__).'/EMailChefWsImport.php';
157
+ $wsImport = new EMailChefWsImport($storeId);
158
+ $lists = $wsImport->GetNlList($accessKey, true);
159
+ if (!$lists) {
160
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_log', $storeId)) {
161
+ Mage::log('eMailChefWsImport got empty response when fetching lists even though login succeeded');
162
+ }
163
+
164
+ return $selectLists;
165
+ }
166
+
167
+ foreach ($lists as $list) {
168
+ $rGroups = array();
169
+ $groups = $list->groups;
170
+ foreach ($groups as $group) {
171
+ $rGroups[(string) $group->id] = (string) $group->name;
172
+ }
173
+ $selectLists[$list->id] = array(
174
+ 'value' => (string) $list->id,
175
+ 'label' => (string) $list->name,
176
+ 'guid' => (string) $list->id,
177
+ 'groups' => $rGroups,
178
+ );
179
+ }
180
+ // Cache results as this is a success
181
+ $this->_cache[$storeId] = $selectLists;
182
+
183
+ return $selectLists;
184
+ }
185
+
186
+ /**
187
+ * Get a List Guid.
188
+ *
189
+ * @param int
190
+ * @param int
191
+ *
192
+ * @return string|false
193
+ */
194
+ public function getListGuid($listId, $storeId)
195
+ {
196
+ $listData = $this->getListDataArray($listId, $storeId);
197
+
198
+ if ($listData === false || !isset($listData['listGUID'])) {
199
+ return false;
200
+ }
201
+
202
+ return $listData['listGUID'];
203
+ }
204
+
205
+ /**
206
+ * Get the groups for a given list.
207
+ *
208
+ * @param int|false
209
+ */
210
+ public function getListGroups($listId, $storeId)
211
+ {
212
+ $listData = $this->getListDataArray($listId, $storeId);
213
+
214
+ if ($listData === false || !isset($listData['groups'])) {
215
+ return false;
216
+ }
217
+
218
+ return $listData['groups'];
219
+ }
220
+
221
+ /**
222
+ * @var EMailChef_EMailChefSync_Model_Config
223
+ */
224
+ protected $_config;
225
+
226
+ /**
227
+ * Get the config.
228
+ *
229
+ * @reutrn EMailChef_EMailChefSync_Model_Config
230
+ */
231
+ protected function _config()
232
+ {
233
+ if (null === $this->_config) {
234
+ $this->_config = Mage::getModel('emailchef/config');
235
+ }
236
+
237
+ return $this->_config;
238
+ }
239
+ }
app/code/community/EMailChef/EMailChefSync/Model/Source/Store.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Config.php.
4
+ *
5
+ * Central config model
6
+ */
7
+ class EMailChef_EMailChefSync_Model_Source_Store
8
+ {
9
+ /**
10
+ * Options getter.
11
+ *
12
+ * This would be used in Admin config.
13
+ *
14
+ * @return array
15
+ */
16
+ public function toOptionArray()
17
+ {
18
+ $return = array();
19
+
20
+ foreach (Mage::app()->getWebsites() as $website) {
21
+ foreach ($website->getGroups() as $group) {
22
+ $stores = $group->getStores();
23
+ foreach ($stores as $store) {
24
+ /* @var $store Mage_Core_Model_Store */
25
+ $return[] = array(
26
+ 'value' => $store->getId(),
27
+ 'label' => $store->getName(),
28
+ );
29
+ }
30
+ }
31
+ }
32
+
33
+ return $return;
34
+ }
35
+
36
+ /**
37
+ * Get options as we'd use in a select box.
38
+ *
39
+ * @return array
40
+ */
41
+ public function getSelectOptions()
42
+ {
43
+ $return = array();
44
+
45
+ $return[0] = 'Default'; // include default site / admin
46
+
47
+ foreach (Mage::app()->getWebsites() as $website) {
48
+ foreach ($website->getGroups() as $group) {
49
+ $stores = $group->getStores();
50
+ foreach ($stores as $store) {
51
+ /* @var $store Mage_Core_Model_Store */
52
+ $return[$store->getId()] = $store->getName();
53
+ }
54
+ }
55
+ }
56
+
57
+ return $return;
58
+ }
59
+ }
app/code/community/EMailChef/EMailChefSync/Model/Subscriber.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Subscriber.php.
4
+ *
5
+ * Override Magento subscriber to allow us to enable / disable the Notifications
6
+ */
7
+ class EMailChef_EMailChefSync_Model_Subscriber extends Mage_Newsletter_Model_Subscriber
8
+ {
9
+ /**
10
+ * Send Success Email.
11
+ *
12
+ * @override
13
+ *
14
+ * @todo make this per store scope!
15
+ *
16
+ * @return EMailChef_EMailChefSync_Model_Subscriber
17
+ */
18
+ public function sendConfirmationSuccessEmail()
19
+ {
20
+ if ($this->_getConfig()->isNewsletterNotificationDisabled()) {
21
+ Mage::log('Newsletter Notification DISABLED: sendConfirmationSuccessEmail');
22
+
23
+ return $this;
24
+ } else {
25
+ return parent::sendConfirmationSuccessEmail();
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Send Confirmation request Email.
31
+ *
32
+ * @override
33
+ *
34
+ * @todo make this per store scope!
35
+ *
36
+ * @return EMailChef_EMailChefSync_Model_Subscriber
37
+ */
38
+ public function sendConfirmationRequestEmail()
39
+ {
40
+ if ($this->_getConfig()->isNewsletterNotificationDisabled()) {
41
+ Mage::log('Newsletter Notification DISABLED: sendConfirmationRequestEmail');
42
+
43
+ return $this;
44
+ } else {
45
+ return parent::sendConfirmationRequestEmail();
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Send the Emails.
51
+ *
52
+ * @override
53
+ *
54
+ * @todo make this per store scope!
55
+ *
56
+ * @return EMailChef_EMailChefSync_Model_Subscriber
57
+ */
58
+ public function sendUnsubscriptionEmail()
59
+ {
60
+ if ($this->_getConfig()->isNewsletterNotificationDisabled()) {
61
+ Mage::log('Newsletter Notification DISABLED: sendUnsubscriptionEmail');
62
+
63
+ return $this;
64
+ } else {
65
+ return parent::sendUnsubscriptionEmail();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Get the config.
71
+ *
72
+ * @return EMailChef_EMailChefSync_Model_Config
73
+ */
74
+ protected function _getConfig()
75
+ {
76
+ return Mage::getModel('emailchef/config');
77
+ }
78
+
79
+ /**
80
+ * Return customer subscription status.
81
+ *
82
+ * @return bool
83
+ */
84
+ public function isSubscribed()
85
+ {
86
+ if ($this->getId() &&
87
+ $this->getStatus() == self::STATUS_SUBSCRIBED ||
88
+ $this->getStatus() == self::STATUS_UNCONFIRMED) {
89
+ return true;
90
+ }
91
+
92
+ return false;
93
+ }
94
+ }
app/code/community/EMailChef/EMailChefSync/Model/Sync.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Sync.php.
4
+ *
5
+ * @method int getStoreId()
6
+ * @method int getCustomerId()
7
+ * @method int getJobId()
8
+ */
9
+ class EMailChef_EMailChefSync_Model_Sync extends Mage_Core_Model_Abstract
10
+ {
11
+ /**
12
+ * Constructor.
13
+ */
14
+ protected function _construct()
15
+ {
16
+ parent::_construct();
17
+ $this->_init('emailchef/sync');
18
+ }
19
+
20
+ /**
21
+ * Get the ID from the unique values.
22
+ *
23
+ * @param int
24
+ * @param int
25
+ * @param int
26
+ *
27
+ * @return int|false
28
+ */
29
+ public function getIdByUniqueKey($customerId, $jobId, $storeId)
30
+ {
31
+ return $this->_getResource()->getIdByUniqueKey(
32
+ $customerId,
33
+ $jobId,
34
+ $storeId
35
+ );
36
+
37
+ /*return $this->_getResource()->getIdByUniqueKey(
38
+ $this->getCustomerId(),
39
+ $this->getJobId(),
40
+ $this->getStoreId()
41
+ );*/
42
+ }
43
+
44
+ /**
45
+ * Load by unique Key.
46
+ */
47
+ public function loadByUniqueKey()
48
+ {
49
+ //(`customer_id`,`entity`,`job_id`, `store_id`)
50
+ return $this->_getResource()->loadByUniqueKey();
51
+ }
52
+
53
+ /**
54
+ * Mark as Synced.
55
+ */
56
+ public function setAsSynced()
57
+ {
58
+ $this->setNeedsSync(0);
59
+
60
+ return $this;
61
+ }
62
+
63
+ /**
64
+ * Do we need Synced?
65
+ *
66
+ * @return bool
67
+ */
68
+ public function isNeedningSynced()
69
+ {
70
+ return $this->getNeedsSync() == 1;
71
+ }
72
+
73
+ /**
74
+ * Get a collection of items which need Synced.
75
+ *
76
+ * @return EMailChef_EMailChefSync_Model_Mysql4_Sync_Collection
77
+ */
78
+ public function getSyncItemsCollection()
79
+ {
80
+ // SELECT ms.*, ce.email FROM {$syncTableName} ms
81
+ // JOIN $customer_entity_table_name ce
82
+ // ON (ms.customer_id = ce.entity_id)
83
+ // WHERE
84
+ // ms.needs_sync=1
85
+ // AND ms.entity='customer'
86
+ // AND job_id=0"
87
+
88
+ $customerEntityTable = Mage::getSingleton('core/resource')->getTableName('customer_entity');
89
+ //$customerEntityTable = $this->getTable('customer/entity');
90
+ $collection = $this->getCollection();
91
+ /* @var $collection EMailChef_EMailChefSync_Model_Mysql4_Sync_Collection */
92
+
93
+ $collection
94
+ ->addFieldToSelect('*')
95
+ ->addFieldToFilter('job_id', array('eq' => 0))
96
+ ->addFieldToFilter('needs_sync', array('eq' => 1))
97
+ ->getSelect()->join($customerEntityTable, "main_table.customer_id = {$customerEntityTable}.entity_id", 'email')
98
+ ;
99
+
100
+ return $collection;
101
+ }
102
+
103
+ /**
104
+ * Get Sync entries for a particular job.
105
+ *
106
+ * @return EMailChef_EMailChefSync_Model_Mysql4_Sync_Collection
107
+ */
108
+ public function fetchByJobId($jobId)
109
+ {
110
+ //return $this->_getResource()->fetchByJobId($jobId);
111
+ return $this->getCollection()
112
+ ->addFieldToSelect('*')
113
+ ->addFieldToFilter('job_id', array('eq' => $jobId))
114
+ ;
115
+ }
116
+
117
+ /**
118
+ * Get the job model.
119
+ *
120
+ * @return EMailChef_EMailChefSync_Model_Job
121
+ */
122
+ public function getJob()
123
+ {
124
+ return Mage::getModel('emailchef/job')->load($this->getJobId());
125
+ }
126
+ }
app/code/community/EMailChef/EMailChefSync/Model/Webserviceusernamevalidator.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Model_Webserviceusernamevalidator extends Mage_Core_Model_Config_Data
4
+ {
5
+ public function save()
6
+ {
7
+ $value = $this->getValue();
8
+ if (strlen($value) == 0) {
9
+ Mage::throwException(Mage::helper('emailchef')->__('Please fill the email'));
10
+ }
11
+
12
+ if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
13
+ Mage::throwException(Mage::helper('emailchef')->__('Email is not in the right format'));
14
+ }
15
+
16
+ return parent::save();
17
+ }
18
+ }
app/code/community/EMailChef/EMailChefSync/Model/Wssend.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once __DIR__.'/../lib/emailchef/vendor/autoload.php';
4
+ class EMailChefWsSend
5
+ {
6
+ /**
7
+ * @var int
8
+ */
9
+ protected $storeId;
10
+ /**
11
+ * @var EMailChef_EMailChefSync_Model_Config
12
+ */
13
+ protected $_config;
14
+
15
+ public function __construct($storeId = null)
16
+ {
17
+ $this->setStoreId($storeId);
18
+ }
19
+
20
+ /**
21
+ * Set the store ID.
22
+ *
23
+ * @param int
24
+ */
25
+ public function setStoreId($id)
26
+ {
27
+ $this->storeId = $id;
28
+
29
+ return $this;
30
+ }
31
+
32
+ public function __destruct()
33
+ {
34
+ }
35
+
36
+ /**
37
+ * Login, returning access key or false on failing to login.
38
+ *
39
+ * @param null $user
40
+ * @param null $pwd
41
+ *
42
+ * @return false|string Access key or false
43
+ */
44
+ public function loginFromId($user = null, $pwd = null)
45
+ {
46
+ // login with webservice user
47
+ $user = ($user !== null) ? $user : Mage::getStoreConfig('emailchef_newsletter/emailchef/username_ws', $this->storeId);
48
+ $pwd = ($pwd !== null) ? $pwd : Mage::getStoreConfig('emailchef_newsletter/emailchef/password_ws', $this->storeId);
49
+
50
+ return $this->_loginFromId($user, $pwd);
51
+ }
52
+
53
+ /**
54
+ * Login, returning access key or false on failing to login.
55
+ *
56
+ * @param null $user
57
+ * @param null $pwd
58
+ *
59
+ * @return string|false Access key or false
60
+ */
61
+ protected function _loginFromId($user, $pwd)
62
+ {
63
+ try {
64
+ $getAuthenticationTokenCommand = new \EMailChef\Command\Api\GetAuthenticationTokenCommand();
65
+ $accessKey = $getAuthenticationTokenCommand->execute($user, $pwd);
66
+
67
+ return $accessKey;
68
+ } catch (Exception $e) {
69
+ Mage::log($e->getMessage(), 0);
70
+ $errorDescription = $e->getMessage();
71
+ }
72
+
73
+ $GLOBALS['__sl_emailchef_login_error'] = $errorDescription;
74
+
75
+ return false;
76
+ }
77
+
78
+ public function GetFields($accessKey, $list = null)
79
+ {
80
+ $list = ($list !== null) ? $list : Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $this->storeId);
81
+ $fields = array();
82
+ try {
83
+ $getPredefinedFieldsCommand = new \EMailChef\Command\Api\GetPredefinedFieldsCommand();
84
+ $predefinedFields = $getPredefinedFieldsCommand->execute($accessKey);
85
+
86
+ $getListFieldsCommand = new \EMailChef\Command\Api\GetListFieldsCommand();
87
+ $fields = $getListFieldsCommand->execute($list, $accessKey);
88
+
89
+ $fields = array_merge($predefinedFields, $fields);
90
+ } catch (Exception $e) {
91
+ Mage::log('Custom exception', 0);
92
+ Mage::log($e->getMessage(), 0);
93
+ }
94
+
95
+ return $fields;
96
+ }
97
+
98
+ public function logout()
99
+ {
100
+ throw new \Exception('not yet implemented');
101
+ }
102
+
103
+ //TODO: seems unused, remove if so
104
+ public function getAccessKey()
105
+ {
106
+ return $this->accessKey;
107
+ }
108
+
109
+ public function option($key, $value)
110
+ {
111
+ return array('Key' => $key, 'Value' => $value);
112
+ }
113
+
114
+ /**
115
+ * Get the config.
116
+ *
117
+ * @reutrn EMailChef_EMailChefSync_Model_Config
118
+ */
119
+ protected function _config()
120
+ {
121
+ if (null === $this->_config) {
122
+ $this->_config = Mage::getModel('emailchef/config');
123
+ }
124
+
125
+ return $this->_config;
126
+ }
127
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/ConfigurationController.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__FILE__).'/../../Model/EMailChefWsImport.php';
4
+ require_once dirname(__FILE__).'/../../Model/Wssend.php';
5
+ class EMailChef_EMailChefSync_Adminhtml_ConfigurationController extends Mage_Adminhtml_Controller_Action
6
+ {
7
+ public function indexAction()
8
+ {
9
+ $url = Mage::getModel('adminhtml/url');
10
+ $url = $url->getUrl('adminhtml/system_config/edit', array(
11
+ 'section' => 'emailchef_newsletter',
12
+ ));
13
+ Mage::app()->getResponse()->setRedirect($url);
14
+ }
15
+
16
+ /**
17
+ * Get groups for given list.
18
+ */
19
+ public function getgroupsAction()
20
+ {
21
+ // Get passed list ID to get groups for
22
+ $listId = $this->getRequest()->getParam('list');
23
+ if ($listId === null) {
24
+ $output = '<option>-- Could not find list --</option>';
25
+ } else {
26
+ $groups = Mage::getSingleton('emailchef/source_groups')->toOptionArray(null, $listId);
27
+
28
+ // Render output directly (as output is so simple)
29
+ $output = '';
30
+ foreach ($groups as $group) {
31
+ $output .= "<option value=\"{$group['value']}\">{$group['label']}</option>\n";
32
+ }
33
+ }
34
+
35
+ $this->getResponse()->setBody($output);
36
+ }
37
+
38
+ /**
39
+ * Run connection-to-emailchef test other system configurations that area relevant.
40
+ */
41
+ public function testconnectionAction()
42
+ {
43
+ // Get login details from AJAX
44
+ $usernameWs = $this->getRequest()->getParam('username_ws');
45
+ $passwordWs = $this->getRequest()->getParam('password_ws');
46
+
47
+ // Ensure that all required fields are given
48
+ if ($usernameWs === null || $passwordWs === null) {
49
+ $class = 'notice';
50
+ $message = $this->__('Please fill in eMailChef Email and Password before testing');
51
+ $output = '<ul class="messages"><li class="'.$class.'-msg"><ul><li>'.$message.'</li></ul></li></ul>';
52
+ $this->getResponse()->setBody($output);
53
+
54
+ return;
55
+ }
56
+
57
+ $messages = array();
58
+
59
+ // Close connection to avoid mysql gone away errors
60
+ $res = Mage::getSingleton('core/resource');
61
+ $res->getConnection('core_write')->closeConnection();
62
+
63
+ // Test connection
64
+ $storeId = Mage::app()->getStore();
65
+ $retConn = Mage::helper('emailchef')->testConnection($usernameWs, $passwordWs, $storeId);
66
+ $messages = array_merge($messages, $retConn);
67
+
68
+ // Config tests
69
+ $retConfig = Mage::helper('emailchef')->testConfig();
70
+ $messages = array_merge($messages, $retConfig);
71
+
72
+ // Re-open connection to avoid mysql gone away errors
73
+ $res->getConnection('core_write')->getConnection();
74
+
75
+ // Connect up the messages to be returned as ajax
76
+ $renderedMessages = array();
77
+ if (count($messages) > 0) {
78
+ foreach ($messages as $msg) {
79
+ $renderedMessages[] = '<li class="'.$msg['type'].'-msg"><ul><li>'.$msg['message'].'</li></ul></li>';
80
+ }
81
+ }
82
+ $output = '<ul class="messages">'.implode("\n", $renderedMessages).'</ul>';
83
+ $this->getResponse()->setBody($output);
84
+ }
85
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/EmailchefbackendController.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Adminhtml_EMailChefbackendController extends Mage_Adminhtml_Controller_Action
4
+ {
5
+ /**
6
+ * Default Action.
7
+ */
8
+ public function indexAction()
9
+ {
10
+ $this->loadLayout();
11
+ $this->_title($this->__('eMailChef Jobs'));
12
+ $this->renderLayout();
13
+ }
14
+
15
+ /**
16
+ * Run The Job.
17
+ */
18
+ public function runjobAction()
19
+ {
20
+ /** @var $session Mage_Admin_Model_Session */
21
+ $session = Mage::getSingleton('adminhtml/session');
22
+ $id = $this->getRequest()->getParam('id');
23
+
24
+ if (!$id) {
25
+ $session->addError(
26
+ Mage::helper('emailchef')->__('Invalid Entity')
27
+ );
28
+ }
29
+
30
+ $entity = Mage::getModel('emailchef/job')->load($id);
31
+ if ($entity) {
32
+ Mage::helper('emailchef')->runJob($entity->getId());
33
+ }
34
+
35
+ $session->addSuccess(
36
+ Mage::helper('emailchef')->__("Run Job [{$entity->getId()}]")
37
+ );
38
+
39
+ $this->_redirect('*/*/index');
40
+ }
41
+
42
+ /**
43
+ * Delete a job.
44
+ */
45
+ public function deleteAction()
46
+ {
47
+ /** @var $session Mage_Admin_Model_Session */
48
+ $session = Mage::getSingleton('adminhtml/session');
49
+ $id = $this->getRequest()->getParam('id');
50
+
51
+ if (!$id) {
52
+ $session->addError(
53
+ Mage::helper('emailchef')->__('Invalid Entity')
54
+ );
55
+ }
56
+
57
+ $entity = Mage::getModel('emailchef/job')->load($id);
58
+ $entity->delete();
59
+
60
+ $session->addSuccess(
61
+ Mage::helper('emailchef')->__("Job [{$entity->getId()}] [Deleted]")
62
+ );
63
+
64
+ $this->_redirect('*/*/index');
65
+ }
66
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/FieldsmappingController.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @deprectiated
4
+ */
5
+ require_once dirname(__FILE__).'/../../Model/EMailChefWsImport.php';
6
+ require_once dirname(__FILE__).'/../../Model/Wssend.php';
7
+ class EMailChef_EMailChefSync_Adminhtml_FieldsMappingController extends Mage_Adminhtml_Controller_Action
8
+ {
9
+ public function indexAction()
10
+ {
11
+ $this->loadLayout()->renderLayout();
12
+ }
13
+
14
+ public function saveAction()
15
+ {
16
+ try {
17
+ $post = $this->getRequest()->getPost();
18
+ unset($post['form_key']);
19
+ require_once dirname(__FILE__).'/../../Model/EMailChefWsImport.php';
20
+ $wsImport = new EMailChefWsImport();
21
+ $wsImport->saveFieldMapping($post);
22
+ } catch (Exception $e) {
23
+ $errorMessage = $this->__('Error: unable to save current filter');
24
+ Mage::getSingleton('adminhtml/session')->addError($errorMessage);
25
+ }
26
+
27
+ $observer = Mage::getModel('emailchef/observer');
28
+ $observer->configCheck();
29
+
30
+ $this->_redirect('*/*');
31
+ }
32
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/FilterController.php ADDED
@@ -0,0 +1,439 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__FILE__).'/../../Model/EMailChefWsImport.php';
4
+ require_once dirname(__FILE__).'/../../Model/Wssend.php';
5
+ /**
6
+ * FilterController.php.
7
+ */
8
+ class EMailChef_EMailChefSync_Adminhtml_FilterController extends Mage_Adminhtml_Controller_Action
9
+ {
10
+ /**
11
+ * split customers into batches.
12
+ */
13
+ const BATCH_SIZE = 2000;
14
+ const STATUS_SUBSCRIBED = 'subscribed';
15
+ const STATUS_NOT_SUBSCRIBED = 'not_subscribed';
16
+
17
+ /**
18
+ * Default Action.
19
+ */
20
+ public function indexAction()
21
+ {
22
+ $this->checkRunningImport();
23
+ $this->loadLayout()->renderLayout();
24
+ }
25
+
26
+ /**
27
+ * Confirm / Final Step.
28
+ */
29
+ public function confirmAction()
30
+ {
31
+ $this->checkRunningImport();
32
+ $this->loadLayout()->renderLayout();
33
+ }
34
+
35
+ /**
36
+ * Handle Posted Data.
37
+ */
38
+ public function postAction()
39
+ {
40
+ $post = $this->getRequest()->getPost();
41
+ $storeId = isset($post['store_id']) ? (int) $post['store_id'] : null;
42
+
43
+ if (empty($post)) {
44
+ Mage::throwException($this->__('Invalid form data.'));
45
+ }
46
+
47
+ $config = Mage::getModel('emailchef/config');
48
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
49
+ //$subscriber = Mage::getModel('newsletter/subscriber');
50
+ /* @var $subscriber Mage_Newsletter_Model_Subscriber */
51
+
52
+ $emailchefCustomerIds = Mage::getSingleton('core/session')->getEMailChefCustomerIds();
53
+ //$totalCustomers = count($emailchefCustomerIds);
54
+ $batches = $this->_getBatches($emailchefCustomerIds, $storeId);
55
+ //$totalBatches = count($customerIdBatches);
56
+ $db_write = Mage::getSingleton('core/resource')->getConnection('core_write');
57
+
58
+ $wsSend = new EMailChefWsSend($storeId);
59
+ $accessKey = $wsSend->loginFromId();
60
+
61
+ /*
62
+ * Create a New Group on EMailChef
63
+ */
64
+ $post['emailchefNewGroupName'] = trim($post['emailchefNewGroupName']);
65
+ if ($post['emailchefNewGroup'] && strlen($post['emailchefNewGroupName'])) {
66
+ require_once dirname(__FILE__).'/../../Model/EMailChefWsImport.php';
67
+ $wsImport = new EMailChefWsImport($storeId);
68
+ $post['emailchefGroupId'] = $wsImport->CreaGruppo(array(
69
+ 'idList' => $post['emailchefIdList'],
70
+ 'listGUID' => $post['emailchefListGUID'],
71
+ 'newGroupName' => $post['emailchefNewGroupName'],
72
+ ), $accessKey);
73
+ }
74
+
75
+ /*
76
+ * Makes batches if required. Separate the jobs into max amount of customers.
77
+ * Create a new job for each batch.
78
+ */
79
+ foreach ($batches as $batchNumber => $batch) {
80
+ try {
81
+ $customerCount = 0;
82
+ /*
83
+ * We have split into subscribers and non-subscribers
84
+ */
85
+ foreach ($batch as $subscribeStatus => $customerIdArray) {
86
+ if (empty($customerIdArray)) {
87
+ continue;
88
+ }
89
+
90
+ $job = Mage::getModel('emailchef/job');
91
+ /* @var $job EMailChef_EMailChefSync_Model_Job */
92
+ $job->setData(array(
93
+ 'emailchefgroupid' => $post['emailchefGroupId'],
94
+ 'status' => 'queued',
95
+ 'queue_datetime' => gmdate('Y-m-d H:i:s'),
96
+ 'store_id' => $storeId,
97
+ 'list_id' => $post['emailchefIdList'],
98
+ 'list_guid' => $post['emailchefListGUID'],
99
+ ));
100
+ try {
101
+ $job->save();
102
+ $config->dbLog(
103
+ sprintf(
104
+ 'Job [Insert] [Group:%s] [%s] [%d]',
105
+ $post['emailchefGroupId'],
106
+ $subscribeStatus,
107
+ count($customerIdArray)
108
+ ),
109
+ $job->getId(),
110
+ $storeId
111
+ );
112
+ } catch (Exception $e) {
113
+ $config->dbLog("Job [Insert] [FAILED] [Group:{$post['emailchefGroupId']}] ", 0, $storeId);
114
+ $config->log($e);
115
+ throw $e;
116
+ }
117
+ /*
118
+ * Each Customer
119
+ */
120
+ foreach ($customerIdArray as $customerId) {
121
+ ++$customerCount;
122
+ //$customer = Mage::getModel('customer/customer');
123
+ /* @var $customer Mage_Customer_Model_Customer */
124
+ $jobTask = Mage::getModel('emailchef/sync');
125
+ /* @var $jobTask EMailChef_EMailChefSync_Model_Sync */
126
+ try {
127
+ $jobTask->setData(array(
128
+ 'customer_id' => $customerId,
129
+ 'entity' => 'customer',
130
+ 'job_id' => $job->getId(),
131
+ 'needs_sync' => true,
132
+ 'last_sync' => null,
133
+ 'store_id' => $storeId,
134
+ ));
135
+ $jobTask->save();
136
+ } catch (Exception $e) {
137
+ $config->dbLog("Job Task [Sync] [FAILED] [customer:{$customerId}] [Update]", $job->getId(), $storeId);
138
+ $config->log($e);
139
+ }
140
+ }
141
+ }
142
+ $config->dbLog("Job Task [Sync] [Customer Count:{$customerCount}]", $job->getId(), $storeId);
143
+ /*
144
+ * Insert a new scheduled Task for the job.
145
+ */
146
+ $cronDelay = (int) ($batchNumber * 15) + 2;
147
+ $db_write->insert(Mage::getSingleton('core/resource')->getTableName('cron_schedule'), array(
148
+ 'job_code' => 'emailchef_emailchefsync',
149
+ 'status' => 'pending',
150
+ 'created_at' => gmdate('Y-m-d H:i:s'),
151
+ 'scheduled_at' => gmdate('Y-m-d H:i:s', strtotime("+{$cronDelay}minutes")),
152
+ ));
153
+
154
+ /*$schedule = Mage::getModel('cron/schedule');
155
+ $schedule->setJobCode($jobCode)
156
+ ->setCreatedAt($timecreated)
157
+ ->setScheduledAt($timescheduled)
158
+ ->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING)
159
+ ->save();*/
160
+
161
+ //$config->dbLog("Secheduled Task: " . gmdate("Y-m-d H:i:s"), $job_id, $storeId);
162
+ $message = $this->__('Members have been sent correctly');
163
+ Mage::getSingleton('adminhtml/session')->addSuccess($message);
164
+ } catch (Exception $e) {
165
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
166
+ $errorMessage = $this->__('Warning: no member has been selected');
167
+ Mage::getSingleton('adminhtml/session')->addError($errorMessage);
168
+ }
169
+ }
170
+
171
+ $this->_redirect('*/*');
172
+ }
173
+
174
+ /**
175
+ * Build batches from the list of ids.
176
+ *
177
+ * We will make batches of a certain size to avoid huge long running proceses.
178
+ * We also need to generate a different job for subscribers and none subscribers
179
+ *
180
+ * array(
181
+ * 0 => array(
182
+ * 'subscribed' => array(),
183
+ * 'not_subscribed' => array(),
184
+ * )
185
+ * )
186
+ *
187
+ * @param array array of ids
188
+ * @param int
189
+ *
190
+ * @return array
191
+ */
192
+ protected function _getBatches($emailchefCustomerIds, $storeId)
193
+ {
194
+ $helper = Mage::helper('emailchef');
195
+ /* @var $helper EMailChef_EMailChefSync_Helper_Data */
196
+ $totalCustomers = count($emailchefCustomerIds);
197
+ $batches = array_chunk($emailchefCustomerIds, self::BATCH_SIZE);
198
+ //$totalBatches = count($customerIdBatches);
199
+ if ($totalCustomers > self::BATCH_SIZE) {
200
+ $this->_config()->dbLog("Batching Customers [{$totalCustomers}] CHUNKS [".self::BATCH_SIZE.']', 0, $storeId);
201
+ }
202
+ $batchArray = array();
203
+ $customerCount = 0;
204
+ foreach ($batches as $batch) {
205
+ $subscribed = array();
206
+ $notSubscribed = array();
207
+ foreach ($batch as $customerId) {
208
+ ++$customerCount;
209
+ if ($helper->isSubscriber($customerId, $storeId)) {
210
+ $subscribed[] = $customerId;
211
+ } else {
212
+ $notSubscribed[] = $customerId;
213
+ }
214
+ }
215
+ /*
216
+ * @todo only return segmented if both not empty.
217
+ */
218
+ $batchArray[] = array(
219
+ self::STATUS_SUBSCRIBED => $subscribed,
220
+ self::STATUS_NOT_SUBSCRIBED => $notSubscribed,
221
+ );
222
+ }
223
+
224
+ return $batchArray;
225
+ }
226
+
227
+ /**
228
+ * @var EMailChef_EMailChefSync_Model_Config
229
+ */
230
+ protected $_config;
231
+
232
+ /**
233
+ * Get the config.
234
+ *
235
+ * @reutrn EMailChef_EMailChefSync_Model_Config
236
+ */
237
+ protected function _config()
238
+ {
239
+ if (null === $this->_config) {
240
+ $this->_config = Mage::getModel('emailchef/config');
241
+ }
242
+
243
+ return $this->_config;
244
+ }
245
+
246
+ /**
247
+ * Generate CSV.
248
+ *
249
+ * @todo include stores
250
+ */
251
+ public function csvAction()
252
+ {
253
+ $post = $this->getRequest()->getPost();
254
+ $file = '';
255
+
256
+ if ($post['countPost'] > 0) {
257
+ //preparo l'elenco degli iscritti da salvare nel csv
258
+ $emailchefCustomerIds = Mage::getSingleton('core/session')->getEMailChefCustomerIds();
259
+
260
+ //require_once(dirname(__FILE__) . '/../Helper/Data.php');
261
+ $customersData = EMailChef_EMailChefSync_Helper_Data::getCustomersData();
262
+
263
+ //CSV Column names
264
+ $file = '"Email","First Name","Last Name"';
265
+ if (Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_emailchef_synchro') == 1) {
266
+ $file .= ',"Company","City","Province","Zip code","Region","Country code","Address","Fax","Phone","Customer id"';
267
+ $file .= ',"Last Order id","Last Order date","Last Order total","Last order product ids","Last order category ids"';
268
+ $file .= ',"Last sent order date","Last sent order id"';
269
+ $file .= ',"Last abandoned cart date","Last abandoned cart total","Last abandoned cart id"';
270
+ $file .= ',"Total orders amount","Last 12 months amount","Last 30 days amount","All products ids"';
271
+ }
272
+ $file .= ';';
273
+
274
+ foreach ($emailchefCustomerIds as $customerId) {
275
+ foreach ($customersData as $subscriber) {
276
+ if ($subscriber['email'] == $customerId['email']) {
277
+ $file .= "\n";
278
+ $file .= '"'.$subscriber['email'].'"';
279
+ $file .= ',"'.((!empty($subscriber['nome'])) ? $subscriber['nome'] : '').'"';
280
+ $file .= ',"'.((!empty($subscriber['cognome'])) ? $subscriber['cognome'] : '').'"';
281
+
282
+ $synchroConfig = Mage::getStoreConfig('emailchef_newsletter/emailchef/enable_emailchef_synchro') == 1;
283
+
284
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['azienda'])) ? $subscriber['azienda'] : '').'"';
285
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['città'])) ? $subscriber['città'] : '').'"';
286
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['provincia'])) ? $subscriber['provincia'] : '').'"';
287
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['cap'])) ? $subscriber['cap'] : '').'"';
288
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['regione'])) ? $subscriber['regione'] : '').'"';
289
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['paese'])) ? $subscriber['paese'] : '').'"';
290
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['indirizzo'])) ? $subscriber['indirizzo'] : '').'"';
291
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['fax'])) ? $subscriber['fax'] : '').'"';
292
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['telefono'])) ? $subscriber['telefono'] : '').'"';
293
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDCliente'])) ? $subscriber['IDCliente'] : '').'"';
294
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDUltimoOrdine'])) ? $subscriber['IDUltimoOrdine'] : '').'"';
295
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['DataUltimoOrdine'])) ? $subscriber['DataUltimoOrdine'] : '').'"';
296
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['TotaleUltimoOrdine'])) ? $subscriber['TotaleUltimoOrdine'] : '').'"';
297
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDProdottiUltimoOrdine'])) ? $subscriber['IDProdottiUltimoOrdine'] : '').'"';
298
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDCategorieUltimoOrdine'])) ? $subscriber['IDCategorieUltimoOrdine'] : '').'"';
299
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['DataUltimoOrdineSpedito'])) ? $subscriber['DataUltimoOrdineSpedito'] : '').'"';
300
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDUltimoOrdineSpedito'])) ? $subscriber['IDUltimoOrdineSpedito'] : '').'"';
301
+
302
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['DataCarrelloAbbandonato'])) ? $subscriber['DataCarrelloAbbandonato'] : '').'"';
303
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['TotaleCarrelloAbbandonato'])) ? $subscriber['TotaleCarrelloAbbandonato'] : '').'"';
304
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDCarrelloAbbandonato'])) ? $subscriber['IDCarrelloAbbandonato'] : '').'"';
305
+
306
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['TotaleFatturato'])) ? $subscriber['TotaleFatturato'] : '').'"';
307
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['TotaleFatturatoUltimi12Mesi'])) ? $subscriber['TotaleFatturatoUltimi12Mesi'] : '').'"';
308
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['TotaleFatturatoUltimi30gg'])) ? $subscriber['TotaleFatturatoUltimi30gg'] : '').'"';
309
+ $file .= ',"'.($synchroConfig && (!empty($subscriber['IDTuttiProdottiAcquistati'])) ? $subscriber['IDTuttiProdottiAcquistati'] : '').'"';
310
+ $file .= ';';
311
+
312
+ continue 2;
313
+ }
314
+ }
315
+ }
316
+ }
317
+
318
+ //lancio il download del file
319
+ header('Content-type: application/csv');
320
+ header('Content-Disposition: attachment;Filename=filtered_customers.csv');
321
+
322
+ echo $file;
323
+ }
324
+
325
+ /**
326
+ * Save Filters.
327
+ */
328
+ public function saveFilterHintAction()
329
+ {
330
+ $this->checkRunningImport();
331
+ try {
332
+ $post = $this->getRequest()->getPost();
333
+ $filter_name = $post['filter_name'];
334
+ unset($post['filter_name']);
335
+
336
+ $EMailChefWsImport = Mage::getModel('emailchef/ws');
337
+ $wsImport = new EMailChefWsImport();
338
+ $wsImport->saveFilterHint($filter_name, $post);
339
+ } catch (Exception $e) {
340
+ $errorMessage = $this->__('Error: unable to save current filter');
341
+ Mage::getSingleton('adminhtml/session')->addError($errorMessage);
342
+ }
343
+
344
+ $this->_redirect('*/*');
345
+ }
346
+
347
+ /**
348
+ * Delete a Filter Hint.
349
+ */
350
+ public function deleteFilterHintAction()
351
+ {
352
+ $this->checkRunningImport();
353
+ try {
354
+ $post = $this->getRequest()->getPost();
355
+
356
+ $EMailChefWsImport = Mage::getModel('emailchef/ws');
357
+ $wsImport = new EMailChefWsImport();
358
+ $wsImport->deleteFilterHint($post['filter_name']);
359
+ } catch (Exception $e) {
360
+ $errorMessage = $this->__('Error: unable to delete the filter');
361
+ Mage::getSingleton('adminhtml/session')->addError($errorMessage);
362
+ }
363
+
364
+ $this->_redirect('*/*');
365
+ }
366
+
367
+ /**
368
+ * Check if an import is currently running.
369
+ *
370
+ * @return type
371
+ */
372
+ public function checkRunningImport()
373
+ {
374
+ $syncTableName = Mage::getSingleton('core/resource')->getTableName('emailchef/sync');
375
+ $db = Mage::getSingleton('core/resource')->getConnection('core_read');
376
+ $cron_schedule_table = Mage::getSingleton('core/resource')->getTableName('cron_schedule');
377
+
378
+ /*
379
+ * @todo check if a cron has been run in the past X minites
380
+ * notify if cron is npt up and running
381
+ */
382
+ $lastTime = $db->fetchOne("SELECT max(last_sync) FROM {$syncTableName}"); // 2013-04-18 19:23:55
383
+ if (!empty($lastTime)) {
384
+ $dateTime = \DateTime::createFromFormat('Y-m-d H:i:s', $lastTime);
385
+ $lastTimeObject = clone $dateTime;
386
+ if ($dateTime) {
387
+ $dateTime->modify('+30 minutes');
388
+ $now = new DateTime();
389
+ //if($dateTime < $now) {
390
+ Mage::getSingleton('adminhtml/session')
391
+ ->addNotice($this->__("Last Sync Performed: {$lastTimeObject->format('Y-m-d H:i:s e')}"))
392
+ ;
393
+ //}
394
+ }
395
+ }
396
+
397
+ $running_processes = $db->fetchOne(
398
+ "SELECT count(*)
399
+ FROM $cron_schedule_table
400
+ WHERE job_code='emailchef_emailchefsync' AND status='running'"
401
+ );
402
+ if ($running_processes) {
403
+ Mage::getSingleton('adminhtml/session')->addNotice($this->__('A eMailChef import process is running.'));
404
+
405
+ return;
406
+ }
407
+
408
+ $scheduled_processes = $db->fetchOne(
409
+ "SELECT count(*)
410
+ FROM $cron_schedule_table
411
+ WHERE job_code='emailchef_emailchefsync' AND status='pending'"
412
+ );
413
+ if ($scheduled_processes) {
414
+ Mage::getSingleton('adminhtml/session')->addNotice($this->__('A eMailChef import process is schedules and will be executed soon.'));
415
+
416
+ return;
417
+ }
418
+ }
419
+
420
+ public function testCronAction()
421
+ {
422
+ $cron = new EMailChef_EMailChefSync_Model_Cron();
423
+ $cron->run();
424
+ }
425
+
426
+ public function testFieldsAction()
427
+ {
428
+ $wsSend = new EMailChefWsSend();
429
+ $accessKey = $wsSend->loginFromId();
430
+
431
+ if ($accessKey !== false) {
432
+ $fields = $wsSend->GetFields($accessKey);
433
+ print_r($fields);
434
+ die('success');
435
+ } else {
436
+ die('no access key returned');
437
+ }
438
+ }
439
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/LogController.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * LogController.php.
4
+ */
5
+ class EMailChef_EMailChefSync_Adminhtml_LogController extends Mage_Adminhtml_Controller_Action
6
+ {
7
+ /**
8
+ * Default Action.
9
+ */
10
+ public function indexAction()
11
+ {
12
+ $this->loadLayout();
13
+ $this->_title($this->__('Log Queue'));
14
+ $this->renderLayout();
15
+ }
16
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/SyncController.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EMailChef_EMailChefSync_Adminhtml_SyncController extends Mage_Adminhtml_Controller_Action
4
+ {
5
+ /**
6
+ * Default Action.
7
+ */
8
+ public function indexAction()
9
+ {
10
+ $this->loadLayout();
11
+ $this->_title($this->__('Sync Queue'));
12
+ $this->renderLayout();
13
+ }
14
+
15
+ /**
16
+ * Sync the Entity.
17
+ */
18
+ public function syncAction()
19
+ {
20
+ /** @var $session Mage_Admin_Model_Session */
21
+ $session = Mage::getSingleton('adminhtml/session');
22
+ $id = $this->getRequest()->getParam('id');
23
+
24
+ if (!$id) {
25
+ $session->addError(
26
+ Mage::helper('emailchef')->__('Invalid Entity')
27
+ );
28
+ }
29
+
30
+ $entity = Mage::getModel('emailchef/sync')->load($id);
31
+
32
+ $session->addSuccess(
33
+ Mage::helper('emailchef')->__("Synced Entity [{$entity->getEntity()}]")
34
+ );
35
+
36
+ $this->_redirect('*/*/index');
37
+ }
38
+ }
app/code/community/EMailChef/EMailChefSync/controllers/Adminhtml/ViewdatatransferlogController.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once dirname(__FILE__).'/../../Model/EMailChefWsImport.php';
4
+ require_once dirname(__FILE__).'/../../Model/Wssend.php';
5
+ class EMailChef_EMailChefSync_Adminhtml_ViewdatatransferlogController extends Mage_Adminhtml_Controller_Action
6
+ {
7
+ public function indexAction()
8
+ {
9
+ $this->loadLayout()->renderLayout();
10
+ }
11
+
12
+ public function searchAction()
13
+ {
14
+ $this->loadLayout()->renderLayout();
15
+ }
16
+ }
app/code/community/EMailChef/EMailChefSync/controllers/IndexController.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * IndexController.php.
4
+ */
5
+ class EMailChef_EMailChefSync_IndexController extends Mage_Core_Controller_Front_Action
6
+ {
7
+ /**
8
+ * Predispatch: should set layout area.
9
+ *
10
+ * @return Mage_Core_Controller_Front_Action
11
+ */
12
+ public function preDispatch()
13
+ {
14
+ $config = Mage::getModel('emailchef/config');
15
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
16
+
17
+ //if( ! $config->isTestMode()) {
18
+ // die('Access Denied.');
19
+ //}
20
+
21
+ parent::preDispatch();
22
+
23
+ return $this;
24
+ }
25
+
26
+ /**
27
+ * Default Action.
28
+ */
29
+ public function indexAction()
30
+ {
31
+ }
32
+
33
+ /**
34
+ * Clean the Resource Table.
35
+ */
36
+ public function cleanAction()
37
+ {
38
+ return;
39
+
40
+ Mage::helper('emailchef')->cleanResourceTable();
41
+ }
42
+
43
+ public function showAction()
44
+ {
45
+ return;
46
+
47
+ Mage::helper('emailchef')->showResourceTable();
48
+ }
49
+ }
app/code/community/EMailChef/EMailChefSync/controllers/TestController.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * TestController.php.
4
+ */
5
+ class EMailChef_EMailChefSync_TestController extends Mage_Core_Controller_Front_Action
6
+ {
7
+ /**
8
+ * Predispatch: should set layout area.
9
+ *
10
+ * This is causing an issue and making 404s, something to do with the install
11
+ * being messed up and the code inside parent method doing something strange!
12
+ *
13
+ * @return Mage_Core_Controller_Front_Action
14
+ */
15
+ public function preDispatch()
16
+ {
17
+ $config = Mage::getModel('emailchef/config');
18
+ /* @var $config EMailChef_EMailChefSync_Model_Config */
19
+
20
+ if (!$config->isTestMode()) {
21
+ die('Access Denied.');
22
+ }
23
+
24
+ return parent::preDispatch();
25
+ }
26
+
27
+ /**
28
+ * Default Action.
29
+ */
30
+ public function indexAction()
31
+ {
32
+ //$this->loadLayout();
33
+ //$this->renderLayout();
34
+ //var_dump(Mage::helper('emailchef')->getAllCustomerAttributes());
35
+
36
+ die('done');
37
+ }
38
+
39
+ public function SubscriberAction()
40
+ {
41
+ $helper = Mage::helper('emailchef');
42
+
43
+ var_dump($helper->isSubscriber(27, 1));
44
+ var_dump($helper->isSubscriber(29, 99));
45
+ }
46
+
47
+ /**
48
+ * Test the models..
49
+ */
50
+ public function modelsAction()
51
+ {
52
+ $jobTask = Mage::getModel('emailchef/sync');
53
+ /* @var $jobTask EMailChef_EMailChefSync_Model_Sync */
54
+
55
+ $job = Mage::getModel('emailchef/job');
56
+ /* @var $job EMailChef_EMailChefSync_Model_Job */
57
+
58
+ $tasks = $jobTask->getSyncItemsCollection();
59
+ foreach ($tasks as $task) {
60
+ var_dump($task->getData());
61
+ }
62
+
63
+ foreach ($jobTask->fetchByJobId(0) as $task) {
64
+ var_dump($task->getData());
65
+ }
66
+
67
+ var_dump($jobTask->getJob());
68
+ }
69
+
70
+ }
app/code/community/EMailChef/EMailChefSync/data/emailchef_setup/data-upgrade-2.6.1-2.7.0.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Update EMailChef.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ /*
9
+ * Rename sync jobs to remove sevenlike reference
10
+ */
11
+ $cron_schedule_table = Mage::getSingleton('core/resource')->getTableName('cron_schedule');
12
+ $installer->run("UPDATE {$cron_schedule_table} SET job_code='emailchef_emailchefsync' WHERE job_code='sevenlike_emailchef'");
13
+
14
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/data/emailchef_setup/data-upgrade-2.7.0-2.7.1.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Update EMailChef.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ /*
9
+ * Rename sync jobs to remove sevenlike reference
10
+ */
11
+ $cron_schedule_table = Mage::getSingleton('core/resource')->getTableName('cron_schedule');
12
+ $installer->run("UPDATE {$cron_schedule_table} SET job_code='emailchef_emailchefsync' WHERE job_code='EMailChef_EMailChefSync'");
13
+ $installer->run("UPDATE {$cron_schedule_table} SET job_code='emailchef_emailchefsync_autosync' WHERE job_code='sevenlike_emailchef_autosync'");
14
+ $installer->run("UPDATE {$cron_schedule_table} SET job_code='emailchef_emailchefsync_autosync' WHERE job_code='EMailChef_EMailChefSync_autosync'");
15
+
16
+ /*
17
+ * Remove or rename old sevenlike cron settings
18
+ */
19
+ // Get all sevenlike_emailchef cron entries
20
+ $collection = Mage::getModel('core/config_data')->getCollection();
21
+ $collection->addPathFilter('crontab/jobs/sevenlike_emailchef/schedule');
22
+ // Foreach entry, try to insert. If exists, ignore. Delete originals
23
+ $config_table = Mage::getSingleton('core/resource')->getTableName('core_config_data');
24
+ foreach ($collection as $conf) {
25
+ $installer->run("INSERT IGNORE INTO {$config_table} (`scope`, `scope_id`, `path`, `value`) VALUES (".
26
+ "'{$conf->getScope()}', ".
27
+ "'{$conf->getScopeId()}', ".
28
+ "'crontab/jobs/emailchef_emailchefsync/schedule/cron_expr', ".
29
+ "'{$conf->getValue()}')");
30
+ $installer->run("DELETE FROM {$config_table} WHERE config_id='{$conf->getConfigId()}'");
31
+ }
32
+
33
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/etc/config.xml ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <EMailChef_EMailChefSync>
5
+ <version>2.7.5</version>
6
+ </EMailChef_EMailChefSync>
7
+ </modules>
8
+ <!-- frontend -->
9
+ <frontend>
10
+ <routers>
11
+ <emailchef>
12
+ <use>standard</use>
13
+ <args>
14
+ <module>EMailChef_EMailChefSync</module>
15
+ <frontName>emailchef</frontName>
16
+ </args>
17
+ </emailchef>
18
+ </routers>
19
+ <translate>
20
+ <modules>
21
+ <emailchef>
22
+ <files>
23
+ <default>EMailChef_EMailChefSync.csv</default>
24
+ </files>
25
+ </emailchef>
26
+ </modules>
27
+ </translate>
28
+ <layout>
29
+ <updates>
30
+ <emailchef>
31
+ <file>emailchef.xml</file>
32
+ </emailchef>
33
+ </updates>
34
+ </layout>
35
+ </frontend>
36
+ <!-- global -->
37
+ <global>
38
+ <!-- models -->
39
+ <models>
40
+ <emailchef>
41
+ <class>EMailChef_EMailChefSync_Model</class>
42
+ <resourceModel>emailchef_mysql4</resourceModel>
43
+ </emailchef>
44
+ <emailchef_mysql4>
45
+ <class>EMailChef_EMailChefSync_Model_Mysql4</class>
46
+ <entities>
47
+ <job>
48
+ <table>emailchef_sync_jobs</table>
49
+ </job>
50
+ <sync>
51
+ <table>emailchef_sync</table>
52
+ </sync>
53
+ <log>
54
+ <table>emailchef_log</table>
55
+ </log>
56
+ </entities>
57
+ </emailchef_mysql4>
58
+ <!-- Override Subscriber so we can disable Notifiactions -->
59
+ <newsletter>
60
+ <rewrite>
61
+ <subscriber>EMailChef_EMailChefSync_Model_Subscriber</subscriber>
62
+ </rewrite>
63
+ </newsletter>
64
+ </models>
65
+ <!-- blocks -->
66
+ <blocks>
67
+ <emailchef>
68
+ <class>EMailChef_EMailChefSync_Block</class>
69
+ </emailchef>
70
+ </blocks>
71
+ <helpers>
72
+ <emailchef>
73
+ <class>EMailChef_EMailChefSync_Helper</class>
74
+ </emailchef>
75
+ </helpers>
76
+ <!-- resources -->
77
+ <resources>
78
+ <emailchef_setup>
79
+ <setup>
80
+ <module>EMailChef_EMailChefSync</module>
81
+ </setup>
82
+ <connection>
83
+ <use>core_setup</use>
84
+ </connection>
85
+ </emailchef_setup>
86
+ <emailchef_write>
87
+ <connection>
88
+ <use>core_write</use>
89
+ </connection>
90
+ </emailchef_write>
91
+ <emailchef_read>
92
+ <connection>
93
+ <use>core_read</use>
94
+ </connection>
95
+ </emailchef_read>
96
+ </resources>
97
+ <!-- events -->
98
+ <events>
99
+ <newsletter_subscriber_save_before>
100
+ <observers>
101
+ <emailchef_observer>
102
+ <type>singleton</type>
103
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
104
+ <method>beforeSave</method>
105
+ </emailchef_observer>
106
+ </observers>
107
+ </newsletter_subscriber_save_before>
108
+ <newsletter_subscriber_save_after>
109
+ <observers>
110
+ <emailchefsenduser_observer>
111
+ <type>singleton</type>
112
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
113
+ <method>sendUser</method>
114
+ </emailchefsenduser_observer>
115
+ </observers>
116
+ </newsletter_subscriber_save_after>
117
+ <customer_customer_authenticated>
118
+ <observers>
119
+ <emailchefcheckuser_observer>
120
+ <type>singleton</type>
121
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
122
+ <method>checkUser</method>
123
+ </emailchefcheckuser_observer>
124
+ </observers>
125
+ </customer_customer_authenticated>
126
+ <controller_action_postdispatch_adminhtml_system_config_save>
127
+ <observers>
128
+ <emailchefconfigsave_observer>
129
+ <type>singleton</type>
130
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
131
+ <method>saveSystemConfig</method>
132
+ </emailchefconfigsave_observer>
133
+ </observers>
134
+ </controller_action_postdispatch_adminhtml_system_config_save>
135
+ <admin_session_user_login_success>
136
+ <observers>
137
+ <emailchefconfigtest_observer>
138
+ <type>singleton</type>
139
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
140
+ <method>configCheck</method>
141
+ </emailchefconfigtest_observer>
142
+ </observers>
143
+ </admin_session_user_login_success>
144
+ <controller_action_postdispatch_checkout_onepage_saveOrder>
145
+ <observers>
146
+ <emailchef_subscribe_during_checkout>
147
+ <type>singleton</type>
148
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
149
+ <method>onCheckoutSaveOrder</method>
150
+ </emailchef_subscribe_during_checkout>
151
+ </observers>
152
+ </controller_action_postdispatch_checkout_onepage_saveOrder>
153
+ <controller_action_postdispatch_checkout_multishipping_saveOrder>
154
+ <observers>
155
+ <emailchef_checkout_order_save>
156
+ <type>singleton</type>
157
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
158
+ <method>onCheckoutSaveOrder</method>
159
+ </emailchef_checkout_order_save>
160
+ </observers>
161
+ </controller_action_postdispatch_checkout_multishipping_saveOrder>
162
+ <customer_save_after>
163
+ <observers>
164
+ <emailchef_checkout_order_save>
165
+ <type>singleton</type>
166
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
167
+ <method>prepareCustomerForDataSync</method>
168
+ </emailchef_checkout_order_save>
169
+ </observers>
170
+ </customer_save_after>
171
+ <sales_order_save_after>
172
+ <observers>
173
+ <emailchef_sales_order_save_after>
174
+ <type>singleton</type>
175
+ <class>EMailChef_EMailChefSync_Model_Observer</class>
176
+ <method>prepareOrderForDataSync</method>
177
+ </emailchef_sales_order_save_after>
178
+ </observers>
179
+ </sales_order_save_after>
180
+ </events>
181
+ </global>
182
+ <!-- admin -->
183
+ <admin>
184
+ <routers>
185
+ <emailchef>
186
+ <use>admin</use>
187
+ <args>
188
+ <module>EMailChef_EMailChefSync</module>
189
+ <frontName>emailchef</frontName>
190
+ </args>
191
+ </emailchef>
192
+ </routers>
193
+ </admin>
194
+ <!-- default -->
195
+ <default>
196
+ <emailchef_newsletter>
197
+ <emailchef>
198
+ <model>emailchef/ws</model>
199
+ <require_subscription_confirmation>0</require_subscription_confirmation>
200
+ <enable_testmode>0</enable_testmode>
201
+ <emailchef_cron_frequency>0</emailchef_cron_frequency>
202
+ <emailchef_cron_offset>0</emailchef_cron_offset>
203
+ </emailchef>
204
+ <emailchef_mapping>
205
+ <!-- Default mapping from Magento fields (or this extensions mapper) to EMailChef fields -->
206
+ <Name>1</Name>
207
+ <Last>2</Last>
208
+ <Email>111</Email>
209
+ <Company>3</Company>
210
+ <Address>9</Address>
211
+ <City>4</City>
212
+ <ZIP>6</ZIP>
213
+ <Province>5</Province>
214
+ <Region>8</Region>
215
+ <LatestAbandonedCartTotal>21</LatestAbandonedCartTotal>
216
+ <LatestAbandonedCartDate>20</LatestAbandonedCartDate>
217
+ <LatestShippedOrderDate>18</LatestShippedOrderDate>
218
+ <LatestShippedOrderID>19</LatestShippedOrderID>
219
+ <AllOrderedProductIDs>26</AllOrderedProductIDs>
220
+ <LatestOrderCategoryIDs>17</LatestOrderCategoryIDs>
221
+ <TotalOrderedLast30d>25</TotalOrderedLast30d>
222
+ <TotalOrderedLast12m>24</TotalOrderedLast12m>
223
+ <TotalOrdered>23</TotalOrdered>
224
+ <LatestAbandonedCartID>22</LatestAbandonedCartID>
225
+ <Gender>10</Gender>
226
+ <CustomerID>12</CustomerID>
227
+ <Phone>11</Phone>
228
+ <LatestOrderAmount>15</LatestOrderAmount>
229
+ <LatestOrderDate>14</LatestOrderDate>
230
+ <LatestOrderID>13</LatestOrderID>
231
+ <LatestOrderProductIDs>16</LatestOrderProductIDs>
232
+ </emailchef_mapping>
233
+ </emailchef_newsletter>
234
+ </default>
235
+ <!-- adminhtml -->
236
+ <adminhtml>
237
+ <menu>
238
+ <newsletter>
239
+ <children>
240
+ <emailchef translate="title">
241
+ <title>eMailChef</title>
242
+ <children>
243
+ <emailchef_configuration translate="title">
244
+ <title><![CDATA[Settings & Field Mapping]]></title>
245
+ <action>emailchef/adminhtml_configuration</action>
246
+ <sort_order>0</sort_order>
247
+ </emailchef_configuration>
248
+ <emailchef_filters translate="title">
249
+ <title>Filters</title>
250
+ <action>emailchef/adminhtml_filter</action>
251
+ <sort_order>10</sort_order>
252
+ </emailchef_filters>
253
+ <emailchef_jobs module="emailchef">
254
+ <title>View eMailChef Tasks</title>
255
+ <sort_order>20</sort_order>
256
+ <action>emailchef/adminhtml_emailchefbackend</action>
257
+ </emailchef_jobs>
258
+ <emailchef_sync module="emailchef">
259
+ <title>View Task Data</title>
260
+ <sort_order>30</sort_order>
261
+ <action>emailchef/adminhtml_sync</action>
262
+ </emailchef_sync>
263
+ <emailchef_log module="emailchef">
264
+ <title>View Logs</title>
265
+ <sort_order>40</sort_order>
266
+ <action>emailchef/adminhtml_log</action>
267
+ </emailchef_log>
268
+ </children>
269
+ </emailchef>
270
+ </children>
271
+ </newsletter>
272
+ </menu>
273
+ <acl>
274
+ <resources>
275
+ <all>
276
+ <title>Allow everything</title>
277
+ </all>
278
+ <admin>
279
+ <children>
280
+ <newsletter>
281
+ <children>
282
+ <emailchef>
283
+ <title>eMailChef</title>
284
+ <children>
285
+ <emailchef_configuration>
286
+ <title>eMailChef Configuration</title>
287
+ </emailchef_configuration>
288
+ <emailchef_filters>
289
+ <title>eMailChef Filters</title>
290
+ </emailchef_filters>
291
+ <emailchef_fieldsmapping>
292
+ <title>eMailChef Fields Mapping</title>
293
+ </emailchef_fieldsmapping>
294
+ <emailchef_viewdatatransferlog>
295
+ <title>View data transfer log</title>
296
+ </emailchef_viewdatatransferlog>
297
+ <emailchef_jobs translate="title">
298
+ <title>eMailChef Jobs</title>
299
+ </emailchef_jobs>
300
+ <emailchef_sync translate="title">
301
+ <title>eMailChef Job Data</title>
302
+ </emailchef_sync>
303
+ <emailchef_log translate="title">
304
+ <title>eMailChef Logs</title>
305
+ </emailchef_log>
306
+ </children>
307
+ </emailchef>
308
+ </children>
309
+ </newsletter>
310
+
311
+ <system>
312
+ <children>
313
+ <config>
314
+ <children>
315
+ <emailchef_newsletter>
316
+ <title>eMailChef Newsletter</title>
317
+ </emailchef_newsletter>
318
+ </children>
319
+ </config>
320
+ </children>
321
+ </system>
322
+
323
+ </children>
324
+ </admin>
325
+ </resources>
326
+ </acl>
327
+ <layout>
328
+ <updates>
329
+ <emailchef>
330
+ <file>emailchef.xml</file>
331
+ </emailchef>
332
+ </updates>
333
+ </layout>
334
+ <translate>
335
+ <modules>
336
+ <emailchef>
337
+ <files>
338
+ <default>EMailChef_EMailChefSync.csv</default>
339
+ </files>
340
+ </emailchef>
341
+ </modules>
342
+ </translate>
343
+ </adminhtml>
344
+ <!-- cron -->
345
+ <crontab>
346
+ <jobs>
347
+ <emailchef_emailchefsync>
348
+ <run><model>emailchef/Cron::run</model></run>
349
+ <schedule>
350
+ <!-- If config setting save, overrides default below -->
351
+ <config_path>crontab/jobs/emailchef_emailchefsync/schedule/cron_expr</config_path>
352
+ <!-- Default to run every 30 minutes -->
353
+ <cron_expr>0,30 * * * *</cron_expr>
354
+ </schedule>
355
+ </emailchef_emailchefsync>
356
+ </jobs>
357
+ </crontab>
358
+ </config>
app/code/community/EMailChef/EMailChefSync/etc/system.xml ADDED
@@ -0,0 +1,458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+
3
+ <config>
4
+ <!-- Top Level Tabs -->
5
+ <tabs>
6
+ <emailchef_tab translate="label" module="emailchef">
7
+ <label>eMailChef</label>
8
+ <class>emailchef-tab-parent</class>
9
+ <sort_order>300</sort_order>
10
+ </emailchef_tab>
11
+ </tabs>
12
+
13
+ <sections>
14
+ <emailchef_newsletter>
15
+ <class>emailchef-tab</class>
16
+ <!--<header_css>internetware-tab</header_css>-->
17
+ <label><![CDATA[Settings & Field Mapping]]></label>
18
+ <tab>emailchef_tab</tab>
19
+ <frontend_type>text</frontend_type>
20
+ <sort_order>99999</sort_order>
21
+ <show_in_default>1</show_in_default>
22
+ <show_in_website>1</show_in_website>
23
+ <show_in_store>1</show_in_store>
24
+
25
+ <groups>
26
+ <!-- main config section -->
27
+ <emailchef translate="label">
28
+ <label>eMailChef Extension Settings</label>
29
+ <frontend_type>text</frontend_type>
30
+ <sort_order>0</sort_order>
31
+ <show_in_default>1</show_in_default>
32
+ <show_in_website>1</show_in_website>
33
+ <show_in_store>1</show_in_store>
34
+ <fields>
35
+ <username_ws translate="label comment">
36
+ <label>Email</label>
37
+ <frontend_type>text</frontend_type>
38
+ <sort_order>20</sort_order>
39
+ <show_in_default>1</show_in_default>
40
+ <show_in_website>1</show_in_website>
41
+ <show_in_store>1</show_in_store>
42
+ <backend_model>emailchef/webserviceusernamevalidator</backend_model>
43
+ </username_ws>
44
+ <password_ws translate="label comment">
45
+ <label>Password</label>
46
+ <frontend_type>password</frontend_type>
47
+ <sort_order>40</sort_order>
48
+ <show_in_default>1</show_in_default>
49
+ <show_in_website>1</show_in_website>
50
+ <show_in_store>1</show_in_store>
51
+ <!--<comment>For assistance visit</comment>-->
52
+ </password_ws>
53
+ <check translate="label">
54
+ <label>Test Connection</label>
55
+ <frontend_type>button</frontend_type>
56
+ <frontend_model>emailchef/adminhtml_system_config_form_testbutton</frontend_model>
57
+ <sort_order>50</sort_order>
58
+ <show_in_default>1</show_in_default>
59
+ <show_in_website>1</show_in_website>
60
+ <show_in_store>1</show_in_store>
61
+ </check>
62
+ <list translate="label">
63
+ <label>List</label>
64
+ <frontend_type>select</frontend_type>
65
+ <source_model>emailchef/source_lists</source_model>
66
+ <sort_order>60</sort_order>
67
+ <show_in_default>1</show_in_default>
68
+ <show_in_website>1</show_in_website>
69
+ <show_in_store>1</show_in_store>
70
+ </list>
71
+ <default_group translate="label comment">
72
+ <label>Default Group</label>
73
+ <frontend_type>select</frontend_type>
74
+ <source_model>emailchef/source_groups</source_model>
75
+ <sort_order>65</sort_order>
76
+ <show_in_default>1</show_in_default>
77
+ <show_in_website>1</show_in_website>
78
+ <show_in_store>1</show_in_store>
79
+ <comment>Used as default group in all subscriptions that do not have a manual group set</comment>
80
+ </default_group>
81
+ <enable_subscribe_in_checkout tranlate="label comment">
82
+ <label>Enable subscription checkbox during checkout</label>
83
+ <frontend_type>select</frontend_type>
84
+ <source_model>adminhtml/system_config_source_yesno</source_model>
85
+ <sort_order>70</sort_order>
86
+ <show_in_default>1</show_in_default>
87
+ <show_in_website>1</show_in_website>
88
+ <show_in_store>1</show_in_store>
89
+ </enable_subscribe_in_checkout>
90
+ <!--<require_subscription_confirmation tranlate="label comment">
91
+ <label>Require Subscription Confirmation</label>
92
+ <frontend_type>select</frontend_type>
93
+ <source_model>adminhtml/system_config_source_yesno</source_model>
94
+ <sort_order>75</sort_order>
95
+ <show_in_default>1</show_in_default>
96
+ <show_in_website>1</show_in_website>
97
+ <show_in_store>1</show_in_store>
98
+ <comment>Defines whether double opt-in is required</comment>
99
+ </require_subscription_confirmation>-->
100
+ <enable_cron_export tranlate="label comment">
101
+ <label>Enable Automatic Data Export to eMailChef</label>
102
+ <frontend_type>select</frontend_type>
103
+ <source_model>adminhtml/system_config_source_yesno</source_model>
104
+ <sort_order>80</sort_order>
105
+ <show_in_default>1</show_in_default>
106
+ <show_in_website>1</show_in_website>
107
+ <show_in_store>1</show_in_store>
108
+ </enable_cron_export>
109
+ <qualifying_order_statuses>
110
+ <label>Order Statuses to Match For Customer Totals</label>
111
+ <frontend_type>multiselect</frontend_type>
112
+ <source_model>adminhtml/system_config_source_order_status</source_model>
113
+ <sort_order>83</sort_order>
114
+ <show_in_default>1</show_in_default>
115
+ <show_in_website>1</show_in_website>
116
+ <show_in_store>1</show_in_store>
117
+ <comment>If none set, those that are complete, closed or processing will be matched</comment>
118
+ </qualifying_order_statuses>
119
+ <server_timezone translate="label comment">
120
+ <label>Server Timezone</label>
121
+ <frontend_type>label</frontend_type>
122
+ <frontend_model>emailchef/adminhtml_system_config_form_field_timezone</frontend_model>
123
+ <sort_order>85</sort_order>
124
+ <show_in_default>1</show_in_default>
125
+ <show_in_website>1</show_in_website>
126
+ <show_in_store>1</show_in_store>
127
+ <frontend_class>disabled</frontend_class>
128
+ </server_timezone>
129
+ <emailchef_cron_frequency translate="label comment">
130
+ <label>Export Frequency</label>
131
+ <frontend_type>select</frontend_type>
132
+ <source_model>emailchef/adminhtml_system_source_cron_frequency</source_model>
133
+ <sort_order>90</sort_order>
134
+ <show_in_default>1</show_in_default>
135
+ <show_in_website>1</show_in_website>
136
+ <show_in_store>1</show_in_store>
137
+ </emailchef_cron_frequency>
138
+ <emailchef_cron_offset translate="label comment">
139
+ <label>Export Offset (in hours)</label>
140
+ <frontend_type>text</frontend_type>
141
+ <validate>validate-digits</validate>
142
+ <sort_order>95</sort_order>
143
+ <show_in_default>1</show_in_default>
144
+ <show_in_website>1</show_in_website>
145
+ <show_in_store>1</show_in_store>
146
+ <comment>e.g. Offset of 2 hours and frequency of each 12 hours will run at 02:00 and 14:00</comment>
147
+ </emailchef_cron_offset>
148
+ <enable_log>
149
+ <label>Enable Module Debugging Log</label>
150
+ <frontend_type>select</frontend_type>
151
+ <source_model>adminhtml/system_config_source_yesno</source_model>
152
+ <sort_order>110</sort_order>
153
+ <show_in_default>1</show_in_default>
154
+ <show_in_website>1</show_in_website>
155
+ <show_in_store>1</show_in_store>
156
+ </enable_log>
157
+ </fields>
158
+ </emailchef>
159
+ <!-- mapping section -->
160
+ <emailchef_mapping translate="label">
161
+ <label>eMailChef Field Mapping</label>
162
+ <frontend_type>text</frontend_type>
163
+ <sort_order>5</sort_order>
164
+ <show_in_default>1</show_in_default>
165
+ <show_in_website>1</show_in_website>
166
+ <show_in_store>1</show_in_store>
167
+ <comment>Matching Magento customer attributes (on the left) with eMailChef attributes (on the right)</comment>
168
+ <fields>
169
+ <Name translate="comment">
170
+ <label>Name</label>
171
+ <frontend_type>select</frontend_type>
172
+ <sort_order>1</sort_order>
173
+ <show_in_default>1</show_in_default>
174
+ <show_in_website>1</show_in_website>
175
+ <show_in_store>1</show_in_store>
176
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
177
+ </Name>
178
+ <Last translate="comment">
179
+ <label>Last</label>
180
+ <frontend_type>select</frontend_type>
181
+ <sort_order>2</sort_order>
182
+ <show_in_default>1</show_in_default>
183
+ <show_in_website>1</show_in_website>
184
+ <show_in_store>1</show_in_store>
185
+ <!--<comment>test..</comment>-->
186
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
187
+ </Last>
188
+ <Email translate="comment">
189
+ <label>Email</label>
190
+ <frontend_type>select</frontend_type>
191
+ <sort_order>3</sort_order>
192
+ <show_in_default>1</show_in_default>
193
+ <show_in_website>1</show_in_website>
194
+ <show_in_store>1</show_in_store>
195
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
196
+ </Email>
197
+ <Company translate="comment">
198
+ <label>Company</label>
199
+ <frontend_type>select</frontend_type>
200
+ <sort_order>4</sort_order>
201
+ <show_in_default>1</show_in_default>
202
+ <show_in_website>1</show_in_website>
203
+ <show_in_store>1</show_in_store>
204
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
205
+ </Company>
206
+ <Address translate="comment">
207
+ <label>Address</label>
208
+ <frontend_type>select</frontend_type>
209
+ <sort_order>5</sort_order>
210
+ <show_in_default>1</show_in_default>
211
+ <show_in_website>1</show_in_website>
212
+ <show_in_store>1</show_in_store>
213
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
214
+ </Address>
215
+ <City translate="comment">
216
+ <label>City</label>
217
+ <frontend_type>select</frontend_type>
218
+ <sort_order>6</sort_order>
219
+ <show_in_default>1</show_in_default>
220
+ <show_in_website>1</show_in_website>
221
+ <show_in_store>1</show_in_store>
222
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
223
+ </City>
224
+ <ZIP translate="comment">
225
+ <label>ZIP</label>
226
+ <frontend_type>select</frontend_type>
227
+ <sort_order>7</sort_order>
228
+ <show_in_default>1</show_in_default>
229
+ <show_in_website>1</show_in_website>
230
+ <show_in_store>1</show_in_store>
231
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
232
+ </ZIP>
233
+ <Province translate="comment">
234
+ <label>Province</label>
235
+ <frontend_type>select</frontend_type>
236
+ <sort_order>8</sort_order>
237
+ <show_in_default>1</show_in_default>
238
+ <show_in_website>1</show_in_website>
239
+ <show_in_store>1</show_in_store>
240
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
241
+ </Province>
242
+ <Region translate="comment">
243
+ <label>Region</label>
244
+ <frontend_type>select</frontend_type>
245
+ <sort_order>9</sort_order>
246
+ <show_in_default>1</show_in_default>
247
+ <show_in_website>1</show_in_website>
248
+ <show_in_store>1</show_in_store>
249
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
250
+ </Region>
251
+ <Country translate="comment">
252
+ <label>Country</label>
253
+ <frontend_type>select</frontend_type>
254
+ <sort_order>10</sort_order>
255
+ <show_in_default>1</show_in_default>
256
+ <show_in_website>1</show_in_website>
257
+ <show_in_store>1</show_in_store>
258
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
259
+ </Country>
260
+ <Gender translate="comment">
261
+ <label>Gender</label>
262
+ <frontend_type>select</frontend_type>
263
+ <sort_order>10</sort_order>
264
+ <show_in_default>1</show_in_default>
265
+ <show_in_website>1</show_in_website>
266
+ <show_in_store>1</show_in_store>
267
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
268
+ </Gender>
269
+ <DateOfBirth translate="comment">
270
+ <label>DateOfBirth</label>
271
+ <frontend_type>select</frontend_type>
272
+ <sort_order>10</sort_order>
273
+ <show_in_default>1</show_in_default>
274
+ <show_in_website>1</show_in_website>
275
+ <show_in_store>1</show_in_store>
276
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
277
+ </DateOfBirth>
278
+ <CustomerID translate="comment">
279
+ <label>CustomerID</label>
280
+ <frontend_type>select</frontend_type>
281
+ <sort_order>10</sort_order>
282
+ <show_in_default>1</show_in_default>
283
+ <show_in_website>1</show_in_website>
284
+ <show_in_store>1</show_in_store>
285
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
286
+ </CustomerID>
287
+ <Phone translate="comment">
288
+ <label>Phone</label>
289
+ <frontend_type>select</frontend_type>
290
+ <sort_order>10</sort_order>
291
+ <show_in_default>1</show_in_default>
292
+ <show_in_website>1</show_in_website>
293
+ <show_in_store>1</show_in_store>
294
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
295
+ </Phone>
296
+ <Fax translate="comment">
297
+ <label>Fax</label>
298
+ <frontend_type>select</frontend_type>
299
+ <sort_order>10</sort_order>
300
+ <show_in_default>1</show_in_default>
301
+ <show_in_website>1</show_in_website>
302
+ <show_in_store>1</show_in_store>
303
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
304
+ </Fax>
305
+ <LatestOrderID translate="comment">
306
+ <label>LatestOrderID</label>
307
+ <frontend_type>select</frontend_type>
308
+ <sort_order>10</sort_order>
309
+ <show_in_default>1</show_in_default>
310
+ <show_in_website>1</show_in_website>
311
+ <show_in_store>1</show_in_store>
312
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
313
+ </LatestOrderID>
314
+ <LatestOrderDate translate="comment">
315
+ <label>LatestOrderDate</label>
316
+ <frontend_type>select</frontend_type>
317
+ <sort_order>10</sort_order>
318
+ <show_in_default>1</show_in_default>
319
+ <show_in_website>1</show_in_website>
320
+ <show_in_store>1</show_in_store>
321
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
322
+ </LatestOrderDate>
323
+ <LatestOrderAmount translate="comment">
324
+ <label>LatestOrderAmount</label>
325
+ <frontend_type>select</frontend_type>
326
+ <sort_order>10</sort_order>
327
+ <show_in_default>1</show_in_default>
328
+ <show_in_website>1</show_in_website>
329
+ <show_in_store>1</show_in_store>
330
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
331
+ </LatestOrderAmount>
332
+ <LatestOrderProductIDs translate="comment">
333
+ <label>LatestOrderProductIDs</label>
334
+ <frontend_type>select</frontend_type>
335
+ <sort_order>10</sort_order>
336
+ <show_in_default>1</show_in_default>
337
+ <show_in_website>1</show_in_website>
338
+ <show_in_store>1</show_in_store>
339
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
340
+ </LatestOrderProductIDs>
341
+ <LatestOrderCategoryIDs translate="comment">
342
+ <label>LatestOrderCategoryIDs</label>
343
+ <frontend_type>select</frontend_type>
344
+ <sort_order>10</sort_order>
345
+ <show_in_default>1</show_in_default>
346
+ <show_in_website>1</show_in_website>
347
+ <show_in_store>1</show_in_store>
348
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
349
+ </LatestOrderCategoryIDs>
350
+ <LatestShippedOrderDate translate="comment">
351
+ <label>LatestShippedOrderDate</label>
352
+ <frontend_type>select</frontend_type>
353
+ <sort_order>10</sort_order>
354
+ <show_in_default>1</show_in_default>
355
+ <show_in_website>1</show_in_website>
356
+ <show_in_store>1</show_in_store>
357
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
358
+ </LatestShippedOrderDate>
359
+ <LatestShippedOrderID translate="comment">
360
+ <label>LatestShippedOrderID</label>
361
+ <frontend_type>select</frontend_type>
362
+ <sort_order>10</sort_order>
363
+ <show_in_default>1</show_in_default>
364
+ <show_in_website>1</show_in_website>
365
+ <show_in_store>1</show_in_store>
366
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
367
+ </LatestShippedOrderID>
368
+ <LatestAbandonedCartDate translate="comment">
369
+ <label>LatestAbandonedCartDate</label>
370
+ <frontend_type>select</frontend_type>
371
+ <sort_order>10</sort_order>
372
+ <show_in_default>1</show_in_default>
373
+ <show_in_website>1</show_in_website>
374
+ <show_in_store>1</show_in_store>
375
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
376
+ </LatestAbandonedCartDate>
377
+ <LatestAbandonedCartTotal translate="comment">
378
+ <label>LatestAbandonedCartTotal</label>
379
+ <frontend_type>select</frontend_type>
380
+ <sort_order>10</sort_order>
381
+ <show_in_default>1</show_in_default>
382
+ <show_in_website>1</show_in_website>
383
+ <show_in_store>1</show_in_store>
384
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
385
+ </LatestAbandonedCartTotal>
386
+ <LatestAbandonedCartID translate="comment">
387
+ <label>LatestAbandonedCartID</label>
388
+ <frontend_type>select</frontend_type>
389
+ <sort_order>10</sort_order>
390
+ <show_in_default>1</show_in_default>
391
+ <show_in_website>1</show_in_website>
392
+ <show_in_store>1</show_in_store>
393
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
394
+ </LatestAbandonedCartID>
395
+ <TotalOrdered translate="comment">
396
+ <label>TotalOrdered</label>
397
+ <frontend_type>select</frontend_type>
398
+ <sort_order>10</sort_order>
399
+ <show_in_default>1</show_in_default>
400
+ <show_in_website>1</show_in_website>
401
+ <show_in_store>1</show_in_store>
402
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
403
+ </TotalOrdered>
404
+ <TotalOrderedLast12m translate="comment">
405
+ <label>TotalOrderedLast12m</label>
406
+ <frontend_type>select</frontend_type>
407
+ <sort_order>10</sort_order>
408
+ <show_in_default>1</show_in_default>
409
+ <show_in_website>1</show_in_website>
410
+ <show_in_store>1</show_in_store>
411
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
412
+ </TotalOrderedLast12m>
413
+ <TotalOrderedLast30d translate="comment">
414
+ <label>TotalOrderedLast30d</label>
415
+ <frontend_type>select</frontend_type>
416
+ <sort_order>10</sort_order>
417
+ <show_in_default>1</show_in_default>
418
+ <show_in_website>1</show_in_website>
419
+ <show_in_store>1</show_in_store>
420
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
421
+ </TotalOrderedLast30d>
422
+ <AllOrderedProductIDs translate="comment">
423
+ <label>AllOrderedProductIDs</label>
424
+ <frontend_type>select</frontend_type>
425
+ <sort_order>10</sort_order>
426
+ <show_in_default>1</show_in_default>
427
+ <show_in_website>1</show_in_website>
428
+ <show_in_store>1</show_in_store>
429
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
430
+ </AllOrderedProductIDs>
431
+ </fields>
432
+ </emailchef_mapping>
433
+ <emailchef_mapping_custom translate="label">
434
+ <label>Custom Customer Attributes</label>
435
+ <frontend_type>text</frontend_type>
436
+ <sort_order>10</sort_order>
437
+ <show_in_default>1</show_in_default>
438
+ <show_in_website>1</show_in_website>
439
+ <show_in_store>1</show_in_store>
440
+ <clone_fields>1</clone_fields>
441
+ <clone_model>emailchef/adminhtml_system_clone_mappings_custom</clone_model>
442
+ <comment>Matching custom Magento customer attributes (on the left) with eMailChef attributes (on the right)</comment>
443
+ <fields>
444
+ <custom_customer_attributes translate="label">
445
+ <label></label>
446
+ <frontend_type>select</frontend_type>
447
+ <source_model>emailchef/adminhtml_system_source_fields</source_model>
448
+ <sort_order>10</sort_order>
449
+ <show_in_default>1</show_in_default>
450
+ <show_in_website>1</show_in_website>
451
+ <show_in_store>1</show_in_store>
452
+ </custom_customer_attributes>
453
+ </fields>
454
+ </emailchef_mapping_custom>
455
+ </groups>
456
+ </emailchef_newsletter>
457
+ </sections>
458
+ </config>
app/code/community/EMailChef/EMailChefSync/lib/emailchef/composer.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "require": {
3
+ "nategood/httpful": "*"
4
+ },
5
+ "autoload": {
6
+ "psr-0": {"": "src/"},
7
+ "psr-4": {
8
+ "EMailChef\\": "src/"
9
+ }
10
+ }
11
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/composer.lock ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "hash": "ce2632f1142f528af40cd4e3847e5d16",
8
+ "packages": [
9
+ {
10
+ "name": "nategood/httpful",
11
+ "version": "0.2.20",
12
+ "source": {
13
+ "type": "git",
14
+ "url": "https://github.com/nategood/httpful.git",
15
+ "reference": "c1cd4d46a4b281229032cf39d4dd852f9887c0f6"
16
+ },
17
+ "dist": {
18
+ "type": "zip",
19
+ "url": "https://api.github.com/repos/nategood/httpful/zipball/c1cd4d46a4b281229032cf39d4dd852f9887c0f6",
20
+ "reference": "c1cd4d46a4b281229032cf39d4dd852f9887c0f6",
21
+ "shasum": ""
22
+ },
23
+ "require": {
24
+ "ext-curl": "*",
25
+ "php": ">=5.3"
26
+ },
27
+ "require-dev": {
28
+ "phpunit/phpunit": "*"
29
+ },
30
+ "type": "library",
31
+ "autoload": {
32
+ "psr-0": {
33
+ "Httpful": "src/"
34
+ }
35
+ },
36
+ "notification-url": "https://packagist.org/downloads/",
37
+ "license": [
38
+ "MIT"
39
+ ],
40
+ "authors": [
41
+ {
42
+ "name": "Nate Good",
43
+ "email": "me@nategood.com",
44
+ "homepage": "http://nategood.com"
45
+ }
46
+ ],
47
+ "description": "A Readable, Chainable, REST friendly, PHP HTTP Client",
48
+ "homepage": "http://github.com/nategood/httpful",
49
+ "keywords": [
50
+ "api",
51
+ "curl",
52
+ "http",
53
+ "requests",
54
+ "rest",
55
+ "restful"
56
+ ],
57
+ "time": "2015-10-26 16:11:30"
58
+ }
59
+ ],
60
+ "packages-dev": [],
61
+ "aliases": [],
62
+ "minimum-stability": "stable",
63
+ "stability-flags": [],
64
+ "prefer-stable": false,
65
+ "prefer-lowest": false,
66
+ "platform": [],
67
+ "platform-dev": []
68
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/AddEmailsToGroupCommand.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class AddEmailsToGroupCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $emails, $listId, $groupId)
15
+ {
16
+ $getSegmentCommand = new GetSegmentCommand();
17
+ $currentSegment = $getSegmentCommand->execute($authKey, $listId, $groupId);
18
+ $updateSegmentCommand = new UpdateSegmentCommand();
19
+ $conditionGroups = array();
20
+ $conditionGroups['logic'] = 'OR';
21
+ $conditionGroups['conditions'] = array();
22
+ if (isset($currentSegment->condition_groups[0]->conditions)) {
23
+ $conditionGroups['conditions'] = $currentSegment->condition_groups[0]->conditions;
24
+ }
25
+ foreach ($emails as $email) {
26
+ $conditionGroups['conditions'][] = array(
27
+ 'field_id' => '-1',
28
+ 'name' => 'email',
29
+ 'comparable_id' => null,
30
+ 'comparator_id' => 1,
31
+ 'value' => $email,
32
+ );
33
+ }
34
+ $conditionGroups = array($conditionGroups);
35
+ $result = $updateSegmentCommand->execute($authKey, $listId, $currentSegment->name, $currentSegment->description, 'OR', $conditionGroups, $groupId);
36
+
37
+ return $result;
38
+ }
39
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/CreateContactCommand.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class CreateContactCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($listId, $email, $authKey)
15
+ {
16
+ $data = array(
17
+ 'instance_in' => array(
18
+ 'list_id' => $listId,
19
+ 'email' => $email,
20
+ 'mode' => 'ADMIN',
21
+ 'firstname' => '',
22
+ 'lastname' => '',
23
+ 'status' => 'ACTIVE',
24
+ 'custom_fields' => array(),
25
+ ),
26
+ );
27
+ $response = $this->apiService->call('post', 'apps/api/v1/contacts', json_encode($data), $authKey);
28
+ if ($response['code'] != '200') {
29
+ throw new \Exception('Unable to create segment');
30
+ } else {
31
+ return $response['body'];
32
+ }
33
+ }
34
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/CreateSegmentCommand.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class CreateSegmentCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $listId, $name, $description, $logic = 'AND', $conditionGroups = array())
15
+ {
16
+ $data = array(
17
+ 'instance_in' => array(
18
+ 'list_id' => $listId,
19
+ 'logic' => $logic,
20
+ 'name' => $name,
21
+ 'condition_groups' => $conditionGroups,
22
+ 'description' => $description,
23
+ ),
24
+ );
25
+ $response = $this->apiService->call('post', 'apps/api/v1/segments?list_id='.$listId, json_encode($data), $authKey);
26
+ if ($response['code'] != '200') {
27
+ throw new \Exception('Unable to create segment');
28
+ } else {
29
+ $group = $response['body'];
30
+ $groupId = $group->id;
31
+
32
+ return $groupId;
33
+ }
34
+ }
35
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/DeleteContactCommand.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class DeleteContactCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($listId, $contactId, $authKey)
15
+ {
16
+ $data = array(
17
+ 'instance_in' => array(
18
+ 'contact_id' => $contactId,
19
+ 'list_id' => $listId,
20
+ 'mode' => 'ADMIN',
21
+ 'remove' => true,
22
+ ),
23
+ );
24
+ $response = $this->apiService->call('delete', 'apps/api/v1/contacts/'.$contactId, $data, $authKey);
25
+ if ($response['code'] != '200') {
26
+ throw new \Exception('Unable to login');
27
+ } else {
28
+ return true;
29
+ }
30
+ }
31
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetAuthenticationTokenCommand.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetAuthenticationTokenCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($username, $password)
15
+ {
16
+ $response = $this->apiService->call('post', 'api/login', json_encode(array('username' => $username, 'password' => $password)));
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Unable to login');
19
+ } else {
20
+ if (ApiService::STAGING) {
21
+ return $response['body']->authkeystaging;
22
+ }
23
+
24
+ return $response['body']->authkey;
25
+ }
26
+ }
27
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetContactFromEmailCommand.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetContactFromEmailCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($listId, $email, $authKey)
15
+ {
16
+ $response = $this->apiService->call('get', 'apps/api/v1/contacts?limit=1000&list_id='.$listId.'&query_string='.urlencode($email), null, $authKey);
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Unable to get contacts');
19
+ } else {
20
+ $body = $response['body'];
21
+ foreach ($body as $c) {
22
+ if ($c->email == $email) {
23
+ return $c;
24
+ }
25
+ }
26
+
27
+ return false;
28
+ }
29
+ }
30
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetListFieldsCommand.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetListFieldsCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($listId, $authKey)
15
+ {
16
+ $response = $this->apiService->call('get', 'apps/api/v1/lists/'.$listId.'/customfields', null, $authKey);
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Unable to get custom fields');
19
+ } else {
20
+ return $response['body'];
21
+ }
22
+ }
23
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetListSegmentsCommand.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetListSegmentsCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($listId, $authKey)
15
+ {
16
+ $response = $this->apiService->call('get', 'apps/api/v1/lists/'.$listId.'/segments?limit=1000', null, $authKey);
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Something wrong');
19
+ } else {
20
+ return $response['body'];
21
+ }
22
+ }
23
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetListsCommand.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetListsCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $fillGroups = true)
15
+ {
16
+ $response = $this->apiService->call('get', 'apps/api/v1/lists?limit=1000', null, $authKey);
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Unable to login');
19
+ } else {
20
+ $lists = $response['body'];
21
+
22
+ if ($fillGroups) {
23
+ $getListSegmentsCommand = new GetListSegmentsCommand();
24
+ foreach ($lists as &$list) {
25
+ $list->groups = $getListSegmentsCommand->execute($list->id, $authKey);
26
+ if (!is_array($list->groups)) {
27
+ $list->groups = array();
28
+ }
29
+ }
30
+ }
31
+
32
+ return $lists;
33
+ }
34
+ }
35
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetPredefinedFieldsCommand.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetPredefinedFieldsCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey)
15
+ {
16
+ $response = $this->apiService->call('get', 'apps/api/v1/predefinedfields ', null, $authKey);
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Unable to get predefined fields');
19
+ } else {
20
+ return $response['body'];
21
+ }
22
+ }
23
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/GetSegmentCommand.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class GetSegmentCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $listId, $segmentId)
15
+ {
16
+ $response = $this->apiService->call('get', 'apps/api/v1/lists/'.$listId.'/segments/'.$segmentId, null, $authKey);
17
+ if ($response['code'] != '200') {
18
+ throw new \Exception('Unable to get segment');
19
+ } else {
20
+ $segment = $response['body'];
21
+
22
+ return $segment;
23
+ }
24
+ }
25
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/ImportContactsCommand.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class ImportContactsCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $contacts, $listId)
15
+ {
16
+ $contactsImport = array();
17
+ foreach ($contacts as $contact) {
18
+ $c = array();
19
+ foreach ($contact as $field => $value) {
20
+ $c[] = array(
21
+ 'placeholder' => $field,
22
+ 'value' => $value,
23
+ );
24
+ }
25
+ $contactsImport[] = $c;
26
+ }
27
+
28
+ $data = array(
29
+ 'instance_in' => array(
30
+ 'contacts' => $contactsImport,
31
+ 'notification_link' => '',
32
+ ),
33
+ );
34
+ $response = $this->apiService->call('post', 'apps/api/v1/lists/'.$listId.'/import', json_encode($data), $authKey);
35
+ if ($response['code'] != '200') {
36
+ throw new \Exception('Unable to import contacts');
37
+ } else {
38
+ //$body = $response['body'];
39
+ return true;
40
+ }
41
+ }
42
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/ImportContactsInGroupCommand.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class ImportContactsInGroupCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $contacts, $listId, $groupId)
15
+ {
16
+ $importContactsCommand = new ImportContactsCommand();
17
+ $importContactsCommand->execute($authKey, $contacts, $listId);
18
+
19
+ $emails = array();
20
+ foreach ($contacts as $contact) {
21
+ $emails[] = $contact['email'];
22
+ }
23
+
24
+ $addEmailsToGroupCommand = new AddEmailsToGroupCommand();
25
+ $addEmailsToGroupCommand->execute($authKey, $emails, $listId, $groupId);
26
+
27
+ return true;
28
+ }
29
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Command/Api/UpdateSegmentCommand.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Command\Api;
4
+
5
+ use EMailChef\Service\ApiService;
6
+
7
+ class UpdateSegmentCommand
8
+ {
9
+ protected $apiService;
10
+ public function __construct($apiService = null)
11
+ {
12
+ $this->apiService = $apiService ?: new ApiService();
13
+ }
14
+ public function execute($authKey, $listId, $name, $description, $logic = 'AND', $conditionGroups, $groupId)
15
+ {
16
+ $data = array(
17
+ 'instance_in' => array(
18
+ 'id' => ''.$groupId,
19
+ 'list_id' => ''.$listId,
20
+ 'logic' => $logic,
21
+ 'name' => $name,
22
+ 'condition_groups' => $conditionGroups,
23
+ 'description' => $description,
24
+ 'tmp_name' => $name,
25
+ 'tmp_description' => $description,
26
+ ),
27
+ );
28
+ $response = $this->apiService->call('put', 'apps/api/v1/segments/'.$groupId.'?list_id='.$listId, json_encode($data), $authKey);
29
+ if ($response['code'] != '200') {
30
+ throw new \Exception('Unable to update segment');
31
+ } else {
32
+ $group = $response['body'];
33
+ $groupId = $group->id;
34
+
35
+ return $groupId;
36
+ }
37
+ }
38
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/src/Service/ApiService.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace EMailChef\Service;
4
+
5
+ class ApiService
6
+ {
7
+ const ENDPOINT = 'https://app.emailchef.com/';
8
+ //const ENDPOINT = 'http://staging.emailchef.com/';
9
+
10
+ const STAGING = false;
11
+
12
+ public function call($method, $path, $data = null, $authKey = null)
13
+ {
14
+ $response = null;
15
+ switch ($method) {
16
+ case 'post':
17
+ $response = \Httpful\Request::post(self::ENDPOINT.$path, $data)->addHeader('Content-Type' , 'application/json')->addHeader(self::STAGING ? 'authkeystaging' : 'authkey', $authKey)->send();
18
+ break;
19
+ case 'delete':
20
+ $response = \Httpful\Request::init(\Httpful\Http::DELETE)->addHeader('Content-Type' , 'application/json')->uri(self::ENDPOINT.$path)->body($data, 'application/json')->addHeader(self::STAGING ? 'authkeystaging' : 'authkey', $authKey)->send();
21
+ break;
22
+ case 'put':
23
+ $response = \Httpful\Request::put(self::ENDPOINT.$path, $data)->addHeader('Content-Type' , 'application/json')->addHeader(self::STAGING ? 'authkeystaging' : 'authkey', $authKey)->send();
24
+ break;
25
+ case 'get':
26
+ default:
27
+ $response = \Httpful\Request::get(self::ENDPOINT.$path)->addHeader('Content-Type' , 'application/json')->addHeader(self::STAGING ? 'authkeystaging' : 'authkey', $authKey)->send();
28
+ break;
29
+ }
30
+
31
+ return array('body' => $response->body, 'code' => $response->code, 'debug' => $response);
32
+ }
33
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/phpunit.xml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <phpunit bootstrap="../vendor/autoload.php">
2
+ <testsuites>
3
+ <testsuite name="main">
4
+ <directory>unit</directory>
5
+ <directory>integration</directory>
6
+ </testsuite>
7
+ </testsuites>
8
+ </phpunit>
app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/AddEmailsToGroupCommandTest.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use EMailChef\Command\Api\AddEmailsToGroupCommand;
4
+
5
+ class AddEmailsToGroupCommandTest extends PHPUnit_Framework_TestCase
6
+ {
7
+ /**
8
+ * @group apicalls
9
+ */
10
+ public function testExecute()
11
+ {
12
+ $c = new AddEmailsToGroupCommand();
13
+ $emails = array('nicolamti@gmail.com', 'nicolam.ti@gmail.com');
14
+ $listId = 1254;
15
+ $groupId = 204;
16
+ $result = $c->execute('850251f2699d2df00a66486739b1c2bf3130b049', $emails, $listId, $groupId);
17
+ $this->assertInternalType('string', $result);
18
+ }
19
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/CreateSegmentCommandTest.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use EMailChef\Command\Api\CreateSegmentCommand;
4
+
5
+ class CreateSegmentCommandTest extends PHPUnit_Framework_TestCase
6
+ {
7
+ /**
8
+ * @group apicalls
9
+ */
10
+ public function testExecute()
11
+ {
12
+ $c = new CreateSegmentCommand();
13
+ $result = $c->execute('850251f2699d2df00a66486739b1c2bf3130b049', 1254, 'newgroup2', 'newgroup desc', 'AND');
14
+ /*$result = $c->execute('3bfb70f683c1c23ba27d89aff468ee02ed1b345f',1254,'newgroup','newgroup desc','AND',array(
15
+ "logic"=>"OR",
16
+ "conditions"=>array(
17
+
18
+ array(
19
+ "field_id"=>"-1",
20
+ "name"=>"email",
21
+ "comparable_id"=>null,
22
+ "comparator_id"=>"3",
23
+ "value"=>"n@n.it"
24
+ )
25
+
26
+ ),
27
+ ));*/
28
+ $this->assertInternalType('string', $result);
29
+ }
30
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/GetAuthenticationTokenCommandTest.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use EMailChef\Command\Api\GetAuthenticationTokenCommand;
4
+
5
+ class GetAuthenticationTokenCommandTest extends PHPUnit_Framework_TestCase
6
+ {
7
+ /**
8
+ * @group apicalls
9
+ */
10
+ public function testExecute()
11
+ {
12
+ $c = new GetAuthenticationTokenCommand();
13
+ $result = $c->execute('info@nicolamoretti.com', 'W9FYihnmgTbU7t2J/');
14
+ $this->assertInternalType('string', $result);
15
+ }
16
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/test/unit/Command/ImportContactsCommandTest.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use EMailChef\Command\Api\ImportContactsCommand;
4
+
5
+ class ImportContactsCommandTest extends PHPUnit_Framework_TestCase
6
+ {
7
+ /**
8
+ * @group apicalls
9
+ */
10
+ public function testExecute()
11
+ {
12
+ $c = new ImportContactsCommand();
13
+ $contacts = array(array(
14
+ 'first_name' => 'nicola',
15
+ 'last_name' => 'm',
16
+ 'email' => 'nicolamti@gmail.com',
17
+ 'company_name' => 'nmtest',
18
+ 'test' => 'ntestm',
19
+ ), array(
20
+ 'first_name' => 'nicola2',
21
+ 'last_name' => 'm2',
22
+ 'email' => 'nicola.mti@gmail.com',
23
+ 'company_name' => 'nmtest2',
24
+ 'test' => 'ntestm2',
25
+ ));
26
+ $listId = 452;
27
+ $result = $c->execute('9fae370a9a0768401a4837b8ab96f43aa7d885d4', $contacts, $listId);
28
+ $this->assertTrue($result);
29
+ }
30
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer' . '/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit07cf5c18a2947bb874182ce6a7f87c4a::getLoader();
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0 class loader
17
+ *
18
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
19
+ *
20
+ * $loader = new \Composer\Autoload\ClassLoader();
21
+ *
22
+ * // register classes with namespaces
23
+ * $loader->add('Symfony\Component', __DIR__.'/component');
24
+ * $loader->add('Symfony', __DIR__.'/framework');
25
+ *
26
+ * // activate the autoloader
27
+ * $loader->register();
28
+ *
29
+ * // to enable searching the include path (eg. for PEAR packages)
30
+ * $loader->setUseIncludePath(true);
31
+ *
32
+ * In this example, if you try to use a class in the Symfony\Component
33
+ * namespace or one of its children (Symfony\Component\Console for instance),
34
+ * the autoloader will first look for the class under the component/
35
+ * directory, and it will then fallback to the framework/ directory if not
36
+ * found before giving up.
37
+ *
38
+ * This class is loosely based on the Symfony UniversalClassLoader.
39
+ *
40
+ * @author Fabien Potencier <fabien@symfony.com>
41
+ * @author Jordi Boggiano <j.boggiano@seld.be>
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+
57
+ private $classMapAuthoritative = false;
58
+
59
+ public function getPrefixes()
60
+ {
61
+ if (!empty($this->prefixesPsr0)) {
62
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
63
+ }
64
+
65
+ return array();
66
+ }
67
+
68
+ public function getPrefixesPsr4()
69
+ {
70
+ return $this->prefixDirsPsr4;
71
+ }
72
+
73
+ public function getFallbackDirs()
74
+ {
75
+ return $this->fallbackDirsPsr0;
76
+ }
77
+
78
+ public function getFallbackDirsPsr4()
79
+ {
80
+ return $this->fallbackDirsPsr4;
81
+ }
82
+
83
+ public function getClassMap()
84
+ {
85
+ return $this->classMap;
86
+ }
87
+
88
+ /**
89
+ * @param array $classMap Class to filename map
90
+ */
91
+ public function addClassMap(array $classMap)
92
+ {
93
+ if ($this->classMap) {
94
+ $this->classMap = array_merge($this->classMap, $classMap);
95
+ } else {
96
+ $this->classMap = $classMap;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Registers a set of PSR-0 directories for a given prefix, either
102
+ * appending or prepending to the ones previously set for this prefix.
103
+ *
104
+ * @param string $prefix The prefix
105
+ * @param array|string $paths The PSR-0 root directories
106
+ * @param bool $prepend Whether to prepend the directories
107
+ */
108
+ public function add($prefix, $paths, $prepend = false)
109
+ {
110
+ if (!$prefix) {
111
+ if ($prepend) {
112
+ $this->fallbackDirsPsr0 = array_merge(
113
+ (array) $paths,
114
+ $this->fallbackDirsPsr0
115
+ );
116
+ } else {
117
+ $this->fallbackDirsPsr0 = array_merge(
118
+ $this->fallbackDirsPsr0,
119
+ (array) $paths
120
+ );
121
+ }
122
+
123
+ return;
124
+ }
125
+
126
+ $first = $prefix[0];
127
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
128
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
129
+
130
+ return;
131
+ }
132
+ if ($prepend) {
133
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
134
+ (array) $paths,
135
+ $this->prefixesPsr0[$first][$prefix]
136
+ );
137
+ } else {
138
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
139
+ $this->prefixesPsr0[$first][$prefix],
140
+ (array) $paths
141
+ );
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Registers a set of PSR-4 directories for a given namespace, either
147
+ * appending or prepending to the ones previously set for this namespace.
148
+ *
149
+ * @param string $prefix The prefix/namespace, with trailing '\\'
150
+ * @param array|string $paths The PSR-0 base directories
151
+ * @param bool $prepend Whether to prepend the directories
152
+ *
153
+ * @throws \InvalidArgumentException
154
+ */
155
+ public function addPsr4($prefix, $paths, $prepend = false)
156
+ {
157
+ if (!$prefix) {
158
+ // Register directories for the root namespace.
159
+ if ($prepend) {
160
+ $this->fallbackDirsPsr4 = array_merge(
161
+ (array) $paths,
162
+ $this->fallbackDirsPsr4
163
+ );
164
+ } else {
165
+ $this->fallbackDirsPsr4 = array_merge(
166
+ $this->fallbackDirsPsr4,
167
+ (array) $paths
168
+ );
169
+ }
170
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
171
+ // Register directories for a new namespace.
172
+ $length = strlen($prefix);
173
+ if ('\\' !== $prefix[$length - 1]) {
174
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
175
+ }
176
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
177
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
178
+ } elseif ($prepend) {
179
+ // Prepend directories for an already registered namespace.
180
+ $this->prefixDirsPsr4[$prefix] = array_merge(
181
+ (array) $paths,
182
+ $this->prefixDirsPsr4[$prefix]
183
+ );
184
+ } else {
185
+ // Append directories for an already registered namespace.
186
+ $this->prefixDirsPsr4[$prefix] = array_merge(
187
+ $this->prefixDirsPsr4[$prefix],
188
+ (array) $paths
189
+ );
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Registers a set of PSR-0 directories for a given prefix,
195
+ * replacing any others previously set for this prefix.
196
+ *
197
+ * @param string $prefix The prefix
198
+ * @param array|string $paths The PSR-0 base directories
199
+ */
200
+ public function set($prefix, $paths)
201
+ {
202
+ if (!$prefix) {
203
+ $this->fallbackDirsPsr0 = (array) $paths;
204
+ } else {
205
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Registers a set of PSR-4 directories for a given namespace,
211
+ * replacing any others previously set for this namespace.
212
+ *
213
+ * @param string $prefix The prefix/namespace, with trailing '\\'
214
+ * @param array|string $paths The PSR-4 base directories
215
+ *
216
+ * @throws \InvalidArgumentException
217
+ */
218
+ public function setPsr4($prefix, $paths)
219
+ {
220
+ if (!$prefix) {
221
+ $this->fallbackDirsPsr4 = (array) $paths;
222
+ } else {
223
+ $length = strlen($prefix);
224
+ if ('\\' !== $prefix[$length - 1]) {
225
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
226
+ }
227
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
228
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Turns on searching the include path for class files.
234
+ *
235
+ * @param bool $useIncludePath
236
+ */
237
+ public function setUseIncludePath($useIncludePath)
238
+ {
239
+ $this->useIncludePath = $useIncludePath;
240
+ }
241
+
242
+ /**
243
+ * Can be used to check if the autoloader uses the include path to check
244
+ * for classes.
245
+ *
246
+ * @return bool
247
+ */
248
+ public function getUseIncludePath()
249
+ {
250
+ return $this->useIncludePath;
251
+ }
252
+
253
+ /**
254
+ * Turns off searching the prefix and fallback directories for classes
255
+ * that have not been registered with the class map.
256
+ *
257
+ * @param bool $classMapAuthoritative
258
+ */
259
+ public function setClassMapAuthoritative($classMapAuthoritative)
260
+ {
261
+ $this->classMapAuthoritative = $classMapAuthoritative;
262
+ }
263
+
264
+ /**
265
+ * Should class lookup fail if not found in the current class map?
266
+ *
267
+ * @return bool
268
+ */
269
+ public function isClassMapAuthoritative()
270
+ {
271
+ return $this->classMapAuthoritative;
272
+ }
273
+
274
+ /**
275
+ * Registers this instance as an autoloader.
276
+ *
277
+ * @param bool $prepend Whether to prepend the autoloader or not
278
+ */
279
+ public function register($prepend = false)
280
+ {
281
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
282
+ }
283
+
284
+ /**
285
+ * Unregisters this instance as an autoloader.
286
+ */
287
+ public function unregister()
288
+ {
289
+ spl_autoload_unregister(array($this, 'loadClass'));
290
+ }
291
+
292
+ /**
293
+ * Loads the given class or interface.
294
+ *
295
+ * @param string $class The name of the class
296
+ * @return bool|null True if loaded, null otherwise
297
+ */
298
+ public function loadClass($class)
299
+ {
300
+ if ($file = $this->findFile($class)) {
301
+ includeFile($file);
302
+
303
+ return true;
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Finds the path to the file where the class is defined.
309
+ *
310
+ * @param string $class The name of the class
311
+ *
312
+ * @return string|false The path if found, false otherwise
313
+ */
314
+ public function findFile($class)
315
+ {
316
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
317
+ if ('\\' == $class[0]) {
318
+ $class = substr($class, 1);
319
+ }
320
+
321
+ // class map lookup
322
+ if (isset($this->classMap[$class])) {
323
+ return $this->classMap[$class];
324
+ }
325
+ if ($this->classMapAuthoritative) {
326
+ return false;
327
+ }
328
+
329
+ $file = $this->findFileWithExtension($class, '.php');
330
+
331
+ // Search for Hack files if we are running on HHVM
332
+ if ($file === null && defined('HHVM_VERSION')) {
333
+ $file = $this->findFileWithExtension($class, '.hh');
334
+ }
335
+
336
+ if ($file === null) {
337
+ // Remember that this class does not exist.
338
+ return $this->classMap[$class] = false;
339
+ }
340
+
341
+ return $file;
342
+ }
343
+
344
+ private function findFileWithExtension($class, $ext)
345
+ {
346
+ // PSR-4 lookup
347
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
348
+
349
+ $first = $class[0];
350
+ if (isset($this->prefixLengthsPsr4[$first])) {
351
+ foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
352
+ if (0 === strpos($class, $prefix)) {
353
+ foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
354
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
355
+ return $file;
356
+ }
357
+ }
358
+ }
359
+ }
360
+ }
361
+
362
+ // PSR-4 fallback dirs
363
+ foreach ($this->fallbackDirsPsr4 as $dir) {
364
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
365
+ return $file;
366
+ }
367
+ }
368
+
369
+ // PSR-0 lookup
370
+ if (false !== $pos = strrpos($class, '\\')) {
371
+ // namespaced class name
372
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
373
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
374
+ } else {
375
+ // PEAR-like class name
376
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
377
+ }
378
+
379
+ if (isset($this->prefixesPsr0[$first])) {
380
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
381
+ if (0 === strpos($class, $prefix)) {
382
+ foreach ($dirs as $dir) {
383
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
384
+ return $file;
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+
391
+ // PSR-0 fallback dirs
392
+ foreach ($this->fallbackDirsPsr0 as $dir) {
393
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
394
+ return $file;
395
+ }
396
+ }
397
+
398
+ // PSR-0 include paths.
399
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
400
+ return $file;
401
+ }
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Scope isolated include.
407
+ *
408
+ * Prevents access to $this/self from included files.
409
+ */
410
+ function includeFile($file)
411
+ {
412
+ include $file;
413
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Httpful' => array($vendorDir . '/nategood/httpful/src'),
10
+ '' => array($baseDir . '/src'),
11
+ );
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'EMailChef\\' => array($baseDir . '/src'),
10
+ );
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit07cf5c18a2947bb874182ce6a7f87c4a
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit07cf5c18a2947bb874182ce6a7f87c4a', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit07cf5c18a2947bb874182ce6a7f87c4a', 'loadClassLoader'));
25
+
26
+ $map = require __DIR__ . '/autoload_namespaces.php';
27
+ foreach ($map as $namespace => $path) {
28
+ $loader->set($namespace, $path);
29
+ }
30
+
31
+ $map = require __DIR__ . '/autoload_psr4.php';
32
+ foreach ($map as $namespace => $path) {
33
+ $loader->setPsr4($namespace, $path);
34
+ }
35
+
36
+ $classMap = require __DIR__ . '/autoload_classmap.php';
37
+ if ($classMap) {
38
+ $loader->addClassMap($classMap);
39
+ }
40
+
41
+ $loader->register(true);
42
+
43
+ return $loader;
44
+ }
45
+ }
46
+
47
+ function composerRequire07cf5c18a2947bb874182ce6a7f87c4a($file)
48
+ {
49
+ require $file;
50
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/composer/installed.json ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "nategood/httpful",
4
+ "version": "0.2.20",
5
+ "version_normalized": "0.2.20.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/nategood/httpful.git",
9
+ "reference": "c1cd4d46a4b281229032cf39d4dd852f9887c0f6"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/nategood/httpful/zipball/c1cd4d46a4b281229032cf39d4dd852f9887c0f6",
14
+ "reference": "c1cd4d46a4b281229032cf39d4dd852f9887c0f6",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "ext-curl": "*",
19
+ "php": ">=5.3"
20
+ },
21
+ "require-dev": {
22
+ "phpunit/phpunit": "*"
23
+ },
24
+ "time": "2015-10-26 16:11:30",
25
+ "type": "library",
26
+ "installation-source": "dist",
27
+ "autoload": {
28
+ "psr-0": {
29
+ "Httpful": "src/"
30
+ }
31
+ },
32
+ "notification-url": "https://packagist.org/downloads/",
33
+ "license": [
34
+ "MIT"
35
+ ],
36
+ "authors": [
37
+ {
38
+ "name": "Nate Good",
39
+ "email": "me@nategood.com",
40
+ "homepage": "http://nategood.com"
41
+ }
42
+ ],
43
+ "description": "A Readable, Chainable, REST friendly, PHP HTTP Client",
44
+ "homepage": "http://github.com/nategood/httpful",
45
+ "keywords": [
46
+ "api",
47
+ "curl",
48
+ "http",
49
+ "requests",
50
+ "rest",
51
+ "restful"
52
+ ]
53
+ }
54
+ ]
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ .DS_Store
2
+ composer.lock
3
+ vendor
4
+ downloads
5
+ .idea/*
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/.travis.yml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ php:
4
+ - 5.3
5
+ - 5.4
6
+ - 5.5
7
+ - 5.6
8
+ - 7.0
9
+ - hhvm
10
+
11
+ matrix:
12
+ fast_finish: true
13
+ allow_failures:
14
+ - php: 7.0
15
+
16
+ script:
17
+ - phpunit -c ./tests/phpunit.xml
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/LICENSE.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ Copyright (c) 2012 Nate Good <me@nategood.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/README.md ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Httpful
2
+
3
+ [![Build Status](https://secure.travis-ci.org/nategood/httpful.png?branch=master)](http://travis-ci.org/nategood/httpful) [![Total Downloads](https://poser.pugx.org/nategood/httpful/downloads.png)](https://packagist.org/packages/nategood/httpful)
4
+
5
+ [Httpful](http://phphttpclient.com) is a simple Http Client library for PHP 5.3+. There is an emphasis of readability, simplicity, and flexibility – basically provide the features and flexibility to get the job done and make those features really easy to use.
6
+
7
+ Features
8
+
9
+ - Readable HTTP Method Support (GET, PUT, POST, DELETE, HEAD, PATCH and OPTIONS)
10
+ - Custom Headers
11
+ - Automatic "Smart" Parsing
12
+ - Automatic Payload Serialization
13
+ - Basic Auth
14
+ - Client Side Certificate Auth
15
+ - Request "Templates"
16
+
17
+ # Sneak Peak
18
+
19
+ Here's something to whet your appetite. Search the twitter API for tweets containing "#PHP". Include a trivial header for the heck of it. Notice that the library automatically interprets the response as JSON (can override this if desired) and parses it as an array of objects.
20
+
21
+ ```php
22
+
23
+ // Make a request to the GitHub API with a custom
24
+ // header of "X-Trvial-Header: Just as a demo".
25
+ $url = "https://api.github.com/users/nategood";
26
+ $response = \Httpful\Request::get($url)
27
+ ->expectsJson()
28
+ ->withXTrivialHeader('Just as a demo')
29
+ ->send();
30
+
31
+ echo "{$response->body->name} joined GitHub on " .
32
+ date('M jS', strtotime($response->body->created_at)) ."\n";
33
+ ```
34
+
35
+ # Installation
36
+
37
+ ## Phar
38
+
39
+ A [PHP Archive](http://php.net/manual/en/book.phar.php) (or .phar) file is available for [downloading](http://phphttpclient.com/httpful.phar). Simply [download](http://phphttpclient.com/httpful.phar) the .phar, drop it into your project, and include it like you would any other php file. _This method is ideal for smaller projects, one off scripts, and quick API hacking_.
40
+
41
+ ```php
42
+ include('httpful.phar');
43
+ $r = \Httpful\Request::get($uri)->sendIt();
44
+ ...
45
+ ```
46
+
47
+ ## Composer
48
+
49
+ Httpful is PSR-0 compliant and can be installed using [composer](http://getcomposer.org/). Simply add `nategood/httpful` to your composer.json file. _Composer is the sane alternative to PEAR. It is excellent for managing dependencies in larger projects_.
50
+
51
+ {
52
+ "require": {
53
+ "nategood/httpful": "*"
54
+ }
55
+ }
56
+
57
+ ## Install from Source
58
+
59
+ Because Httpful is PSR-0 compliant, you can also just clone the Httpful repository and use a PSR-0 compatible autoloader to load the library, like [Symfony's](http://symfony.com/doc/current/components/class_loader.html). Alternatively you can use the PSR-0 compliant autoloader included with the Httpful (simply `require("bootstrap.php")`).
60
+
61
+ ## Build your Phar
62
+
63
+ If you want the build your own [Phar Archive](http://php.net/manual/en/book.phar.php) you can use the `build` script included.
64
+ Make sure that your `php.ini` has the *Off* or 0 value for the `phar.readonly` setting.
65
+ Also you need to create ad empty `downloads` directory in the project root.
66
+
67
+ # Show Me More!
68
+
69
+ You can checkout the [Httpful Landing Page](http://phphttpclient.com) for more info including many examples and [documentation](http://phphttpclient.com/docs).
70
+
71
+ # Contributing
72
+
73
+ Httpful highly encourages sending in pull requests. When submitting a pull request please:
74
+
75
+ - All pull requests should target the `dev` branch (not `master`)
76
+ - Make sure your code follows the [coding conventions](http://pear.php.net/manual/en/standards.php)
77
+ - Please use soft tabs (four spaces) instead of hard tabs
78
+ - Make sure you add appropriate test coverage for your changes
79
+ - Run all unit tests in the test directory via `phpunit ./tests`
80
+ - Include commenting where appropriate and add a descriptive pull request message
81
+
82
+ # Changelog
83
+
84
+ ## 0.2.20
85
+
86
+ - MINOR Move Response building logic into separate function [PR #193](https://github.com/nategood/httpful/pull/193)
87
+
88
+ ## 0.2.19
89
+
90
+ - FEATURE Before send hook [PR #164](https://github.com/nategood/httpful/pull/164)
91
+ - MINOR More descriptive connection exceptions [PR #166](https://github.com/nategood/httpful/pull/166)
92
+
93
+ ## 0.2.18
94
+
95
+ - FIX [PR #149](https://github.com/nategood/httpful/pull/149)
96
+ - FIX [PR #150](https://github.com/nategood/httpful/pull/150)
97
+ - FIX [PR #156](https://github.com/nategood/httpful/pull/156)
98
+
99
+ ## 0.2.17
100
+
101
+ - FEATURE [PR #144](https://github.com/nategood/httpful/pull/144) Adds additional parameter to the Response class to specify additional meta data about the request/response (e.g. number of redirect).
102
+
103
+ ## 0.2.16
104
+
105
+ - FEATURE Added support for whenError to define a custom callback to be fired upon error. Useful for logging or overriding the default error_log behavior.
106
+
107
+ ## 0.2.15
108
+
109
+ - FEATURE [I #131](https://github.com/nategood/httpful/pull/131) Support for SOCKS proxy
110
+
111
+ ## 0.2.14
112
+
113
+ - FEATURE [I #138](https://github.com/nategood/httpful/pull/138) Added alternative option for XML request construction. In the next major release this will likely supplant the older version.
114
+
115
+ ## 0.2.13
116
+
117
+ - REFACTOR [I #121](https://github.com/nategood/httpful/pull/121) Throw more descriptive exception on curl errors
118
+ - REFACTOR [I #122](https://github.com/nategood/httpful/issues/122) Better proxy scrubbing in Request
119
+ - REFACTOR [I #119](https://github.com/nategood/httpful/issues/119) Better document the mimeType param on Request::body
120
+ - Misc code and test cleanup
121
+
122
+ ## 0.2.12
123
+
124
+ - REFACTOR [I #123](https://github.com/nategood/httpful/pull/123) Support new curl file upload method
125
+ - FEATURE [I #118](https://github.com/nategood/httpful/pull/118) 5.4 HTTP Test Server
126
+ - FIX [I #109](https://github.com/nategood/httpful/pull/109) Typo
127
+ - FIX [I #103](https://github.com/nategood/httpful/pull/103) Handle also CURLOPT_SSL_VERIFYHOST for strictSsl mode
128
+
129
+ ## 0.2.11
130
+
131
+ - FIX [I #99](https://github.com/nategood/httpful/pull/99) Prevent hanging on HEAD requests
132
+
133
+ ## 0.2.10
134
+
135
+ - FIX [I #93](https://github.com/nategood/httpful/pull/86) Fixes edge case where content-length would be set incorrectly
136
+
137
+ ## 0.2.9
138
+
139
+ - FEATURE [I #89](https://github.com/nategood/httpful/pull/89) multipart/form-data support (a.k.a. file uploads)! Thanks @dtelaroli!
140
+
141
+ ## 0.2.8
142
+
143
+ - FIX Notice fix for Pull Request 86
144
+
145
+ ## 0.2.7
146
+
147
+ - FIX [I #86](https://github.com/nategood/httpful/pull/86) Remove Connection Established header when using a proxy
148
+
149
+ ## 0.2.6
150
+
151
+ - FIX [I #85](https://github.com/nategood/httpful/issues/85) Empty Content Length issue resolved
152
+
153
+ ## 0.2.5
154
+
155
+ - FEATURE [I #80](https://github.com/nategood/httpful/issues/80) [I #81](https://github.com/nategood/httpful/issues/81) Proxy support added with `useProxy` method.
156
+
157
+ ## 0.2.4
158
+
159
+ - FEATURE [I #77](https://github.com/nategood/httpful/issues/77) Convenience method for setting a timeout (seconds) `$req->timeoutIn(10);`
160
+ - FIX [I #75](https://github.com/nategood/httpful/issues/75) [I #78](https://github.com/nategood/httpful/issues/78) Bug with checking if digest auth is being used.
161
+
162
+ ## 0.2.3
163
+
164
+ - FIX Overriding default Mime Handlers
165
+ - FIX [PR #73](https://github.com/nategood/httpful/pull/73) Parsing http status codes
166
+
167
+ ## 0.2.2
168
+
169
+ - FEATURE Add support for parsing JSON responses as associative arrays instead of objects
170
+ - FEATURE Better support for setting constructor arguments on Mime Handlers
171
+
172
+ ## 0.2.1
173
+
174
+ - FEATURE [PR #72](https://github.com/nategood/httpful/pull/72) Allow support for custom Accept header
175
+
176
+ ## 0.2.0
177
+
178
+ - REFACTOR [PR #49](https://github.com/nategood/httpful/pull/49) Broke headers out into their own class
179
+ - REFACTOR [PR #54](https://github.com/nategood/httpful/pull/54) Added more specific Exceptions
180
+ - FIX [PR #58](https://github.com/nategood/httpful/pull/58) Fixes throwing an error on an empty xml response
181
+ - FEATURE [PR #57](https://github.com/nategood/httpful/pull/57) Adds support for digest authentication
182
+
183
+ ## 0.1.6
184
+
185
+ - Ability to set the number of max redirects via overloading `followRedirects(int max_redirects)`
186
+ - Standards Compliant fix to `Accepts` header
187
+ - Bug fix for bootstrap process when installed via Composer
188
+
189
+ ## 0.1.5
190
+
191
+ - Use `DIRECTORY_SEPARATOR` constant [PR #33](https://github.com/nategood/httpful/pull/32)
192
+ - [PR #35](https://github.com/nategood/httpful/pull/35)
193
+ - Added the raw\_headers property reference to response.
194
+ - Compose request header and added raw\_header to Request object.
195
+ - Fixed response has errors and added more comments for clarity.
196
+ - Fixed header parsing to allow the minimum (status line only) and also cater for the actual CRLF ended headers as per RFC2616.
197
+ - Added the perfect test Accept: header for all Acceptable scenarios see @b78e9e82cd9614fbe137c01bde9439c4e16ca323 for details.
198
+ - Added default User-Agent header
199
+ - `User-Agent: Httpful/0.1.5` + curl version + server software + PHP version
200
+ - To bypass this "default" operation simply add a User-Agent to the request headers even a blank User-Agent is sufficient and more than simple enough to produce me thinks.
201
+ - Completed test units for additions.
202
+ - Added phpunit coverage reporting and helped phpunit auto locate the tests a bit easier.
203
+
204
+ ## 0.1.4
205
+
206
+ - Add support for CSV Handling [PR #32](https://github.com/nategood/httpful/pull/32)
207
+
208
+ ## 0.1.3
209
+
210
+ - Handle empty responses in JsonParser and XmlParser
211
+
212
+ ## 0.1.2
213
+
214
+ - Added support for setting XMLHandler configuration options
215
+ - Added examples for overriding XmlHandler and registering a custom parser
216
+ - Removed the httpful.php download (deprecated in favor of httpful.phar)
217
+
218
+ ## 0.1.1
219
+
220
+ - Bug fix serialization default case and phpunit tests
221
+
222
+ ## 0.1.0
223
+
224
+ - Added Support for Registering Mime Handlers
225
+ - Created AbstractMimeHandler type that all Mime Handlers must extend
226
+ - Pulled out the parsing/serializing logic from the Request/Response classes into their own MimeHandler classes
227
+ - Added ability to register new mime handlers for mime types
228
+
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/bootstrap.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ require(__DIR__ . '/src/Httpful/Bootstrap.php');
4
+ \Httpful\Bootstrap::init();
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/build ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env php
2
+ <?php
3
+
4
+ /**
5
+ * Build the whole library into a single file
6
+ * as an easy drop in solution as opposed to
7
+ * relying on autoloader. Sometimes we just
8
+ * want to hack with an API as a one off thing.
9
+ * Httpful should make this easy.
10
+ */
11
+
12
+ function exit_unless($condition, $msg = null) {
13
+ if ($condition)
14
+ return;
15
+ echo "[FAIL]\n$msg\n";
16
+ exit(1);
17
+ }
18
+
19
+ // Create the Httpful Phar
20
+ echo "Building Phar... ";
21
+ $base_dir = dirname(__FILE__);
22
+ $source_dir = $base_dir . '/src/Httpful/';
23
+ $phar_path = $base_dir . '/downloads/httpful.phar';
24
+ $phar = new Phar($phar_path, 0, 'httpful.phar');
25
+ $stub = <<<HEREDOC
26
+ <?php
27
+ // Phar Stub File
28
+ Phar::mapPhar('httpful.phar');
29
+ include('phar://httpful.phar/Httpful/Bootstrap.php');
30
+ \Httpful\Bootstrap::pharInit();
31
+
32
+ __HALT_COMPILER();
33
+ HEREDOC;
34
+ try {
35
+ $phar->setStub($stub);
36
+ } catch(Exception $e) {
37
+ $phar = false;
38
+ }
39
+ exit_unless($phar, "Unable to create a phar. Make certain you have phar.readonly=0 set in your ini file.");
40
+ $phar->buildFromDirectory(dirname($source_dir));
41
+ echo "[ OK ]\n";
42
+
43
+
44
+
45
+ // Add it to git!
46
+ //echo "Adding httpful.phar to the repo... ";
47
+ //$return_code = 0;
48
+ //passthru("git add $phar_path", $return_code);
49
+ //exit_unless($return_code === 0, "Unable to add download files to git.");
50
+ //echo "[ OK ]\n";
51
+ echo "\nBuild completed successfully.\n\n";
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/composer.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "nategood/httpful",
3
+ "description": "A Readable, Chainable, REST friendly, PHP HTTP Client",
4
+ "homepage": "http://github.com/nategood/httpful",
5
+ "license": "MIT",
6
+ "keywords": ["http", "curl", "rest", "restful", "api", "requests"],
7
+ "version": "0.2.20",
8
+ "authors": [
9
+ {
10
+ "name": "Nate Good",
11
+ "email": "me@nategood.com",
12
+ "homepage": "http://nategood.com"
13
+ }
14
+ ],
15
+ "require": {
16
+ "php": ">=5.3",
17
+ "ext-curl": "*"
18
+ },
19
+ "autoload": {
20
+ "psr-0": {
21
+ "Httpful": "src/"
22
+ }
23
+ },
24
+ "require-dev": {
25
+ "phpunit/phpunit": "*"
26
+ }
27
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/freebase.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Grab some The Dead Weather albums from Freebase
4
+ */
5
+ require(__DIR__ . '/../bootstrap.php');
6
+
7
+ $uri = "https://www.googleapis.com/freebase/v1/mqlread?query=%7B%22type%22:%22/music/artist%22%2C%22name%22:%22The%20Dead%20Weather%22%2C%22album%22:%5B%5D%7D";
8
+ $response = \Httpful\Request::get($uri)
9
+ ->expectsJson()
10
+ ->sendIt();
11
+
12
+ echo 'The Dead Weather has ' . count($response->body->result->album) . " albums.\n";
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/github.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // XML Example from GitHub
3
+ require(__DIR__ . '/../bootstrap.php');
4
+ use \Httpful\Request;
5
+
6
+ $uri = 'https://github.com/api/v2/xml/user/show/nategood';
7
+ $request = Request::get($uri)->send();
8
+
9
+ echo "{$request->body->name} joined GitHub on " . date('M jS', strtotime($request->body->{'created-at'})) ."\n";
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/override.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require(__DIR__ . '/../bootstrap.php');
3
+
4
+ // We can override the default parser configuration options be registering
5
+ // a parser with different configuration options for a particular mime type
6
+
7
+ // Example setting a namespace for the XMLHandler parser
8
+ $conf = array('namespace' => 'http://example.com');
9
+ \Httpful\Httpful::register(\Httpful\Mime::XML, new \Httpful\Handlers\XmlHandler($conf));
10
+
11
+ // We can also add the parsers with our own...
12
+ class SimpleCsvHandler extends \Httpful\Handlers\MimeHandlerAdapter
13
+ {
14
+ /**
15
+ * Takes a response body, and turns it into
16
+ * a two dimensional array.
17
+ *
18
+ * @param string $body
19
+ * @return mixed
20
+ */
21
+ public function parse($body)
22
+ {
23
+ return str_getcsv($body);
24
+ }
25
+
26
+ /**
27
+ * Takes a two dimensional array and turns it
28
+ * into a serialized string to include as the
29
+ * body of a request
30
+ *
31
+ * @param mixed $payload
32
+ * @return string
33
+ */
34
+ public function serialize($payload)
35
+ {
36
+ $serialized = '';
37
+ foreach ($payload as $line) {
38
+ $serialized .= '"' . implode('","', $line) . '"' . "\n";
39
+ }
40
+ return $serialized;
41
+ }
42
+ }
43
+
44
+ \Httpful\Httpful::register('text/csv', new SimpleCsvHandler());
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/examples/showclix.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require(__DIR__ . '/../bootstrap.php');
4
+
5
+ use \Httpful\Request;
6
+
7
+ // Get event details for a public event
8
+ $uri = "http://api.showclix.com/Event/8175";
9
+ $response = Request::get($uri)
10
+ ->expectsType('json')
11
+ ->send();
12
+
13
+ // Print out the event details
14
+ echo "The event {$response->body->event} will take place on {$response->body->event_start}\n";
15
+
16
+ // Example overriding the default JSON handler with one that encodes the response as an array
17
+ \Httpful\Httpful::register(\Httpful\Mime::JSON, new \Httpful\Handlers\JsonHandler(array('decode_as_array' => true)));
18
+
19
+ $response = Request::get($uri)
20
+ ->expectsType('json')
21
+ ->send();
22
+
23
+ // Print out the event details
24
+ echo "The event {$response->body['event']} will take place on {$response->body['event_start']}\n";
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Bootstrap.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful;
4
+
5
+ /**
6
+ * Bootstrap class that facilitates autoloading. A naive
7
+ * PSR-0 autoloader.
8
+ *
9
+ * @author Nate Good <me@nategood.com>
10
+ */
11
+ class Bootstrap
12
+ {
13
+
14
+ const DIR_GLUE = DIRECTORY_SEPARATOR;
15
+ const NS_GLUE = '\\';
16
+
17
+ public static $registered = false;
18
+
19
+ /**
20
+ * Register the autoloader and any other setup needed
21
+ */
22
+ public static function init()
23
+ {
24
+ spl_autoload_register(array('\Httpful\Bootstrap', 'autoload'));
25
+ self::registerHandlers();
26
+ }
27
+
28
+ /**
29
+ * The autoload magic (PSR-0 style)
30
+ *
31
+ * @param string $classname
32
+ */
33
+ public static function autoload($classname)
34
+ {
35
+ self::_autoload(dirname(dirname(__FILE__)), $classname);
36
+ }
37
+
38
+ /**
39
+ * Register the autoloader and any other setup needed
40
+ */
41
+ public static function pharInit()
42
+ {
43
+ spl_autoload_register(array('\Httpful\Bootstrap', 'pharAutoload'));
44
+ self::registerHandlers();
45
+ }
46
+
47
+ /**
48
+ * Phar specific autoloader
49
+ *
50
+ * @param string $classname
51
+ */
52
+ public static function pharAutoload($classname)
53
+ {
54
+ self::_autoload('phar://httpful.phar', $classname);
55
+ }
56
+
57
+ /**
58
+ * @param string $base
59
+ * @param string $classname
60
+ */
61
+ private static function _autoload($base, $classname)
62
+ {
63
+ $parts = explode(self::NS_GLUE, $classname);
64
+ $path = $base . self::DIR_GLUE . implode(self::DIR_GLUE, $parts) . '.php';
65
+
66
+ if (file_exists($path)) {
67
+ require_once($path);
68
+ }
69
+ }
70
+ /**
71
+ * Register default mime handlers. Is idempotent.
72
+ */
73
+ public static function registerHandlers()
74
+ {
75
+ if (self::$registered === true) {
76
+ return;
77
+ }
78
+
79
+ // @todo check a conf file to load from that instead of
80
+ // hardcoding into the library?
81
+ $handlers = array(
82
+ \Httpful\Mime::JSON => new \Httpful\Handlers\JsonHandler(),
83
+ \Httpful\Mime::XML => new \Httpful\Handlers\XmlHandler(),
84
+ \Httpful\Mime::FORM => new \Httpful\Handlers\FormHandler(),
85
+ \Httpful\Mime::CSV => new \Httpful\Handlers\CsvHandler(),
86
+ );
87
+
88
+ foreach ($handlers as $mime => $handler) {
89
+ // Don't overwrite if the handler has already been registered
90
+ if (Httpful::hasParserRegistered($mime))
91
+ continue;
92
+ Httpful::register($mime, $handler);
93
+ }
94
+
95
+ self::$registered = true;
96
+ }
97
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Exception/ConnectionErrorException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful\Exception;
4
+
5
+ class ConnectionErrorException extends \Exception
6
+ {
7
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/CsvHandler.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mime Type: text/csv
4
+ * @author Raja Kapur <rajak@twistedthrottle.com>
5
+ */
6
+
7
+ namespace Httpful\Handlers;
8
+
9
+ class CsvHandler extends MimeHandlerAdapter
10
+ {
11
+ /**
12
+ * @param string $body
13
+ * @return mixed
14
+ * @throws \Exception
15
+ */
16
+ public function parse($body)
17
+ {
18
+ if (empty($body))
19
+ return null;
20
+
21
+ $parsed = array();
22
+ $fp = fopen('data://text/plain;base64,' . base64_encode($body), 'r');
23
+ while (($r = fgetcsv($fp)) !== FALSE) {
24
+ $parsed[] = $r;
25
+ }
26
+
27
+ if (empty($parsed))
28
+ throw new \Exception("Unable to parse response as CSV");
29
+ return $parsed;
30
+ }
31
+
32
+ /**
33
+ * @param mixed $payload
34
+ * @return string
35
+ */
36
+ public function serialize($payload)
37
+ {
38
+ $fp = fopen('php://temp/maxmemory:'. (6*1024*1024), 'r+');
39
+ $i = 0;
40
+ foreach ($payload as $fields) {
41
+ if($i++ == 0) {
42
+ fputcsv($fp, array_keys($fields));
43
+ }
44
+ fputcsv($fp, $fields);
45
+ }
46
+ rewind($fp);
47
+ $data = stream_get_contents($fp);
48
+ fclose($fp);
49
+ return $data;
50
+ }
51
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/FormHandler.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mime Type: application/x-www-urlencoded
4
+ * @author Nathan Good <me@nategood.com>
5
+ */
6
+
7
+ namespace Httpful\Handlers;
8
+
9
+ class FormHandler extends MimeHandlerAdapter
10
+ {
11
+ /**
12
+ * @param string $body
13
+ * @return mixed
14
+ */
15
+ public function parse($body)
16
+ {
17
+ $parsed = array();
18
+ parse_str($body, $parsed);
19
+ return $parsed;
20
+ }
21
+
22
+ /**
23
+ * @param mixed $payload
24
+ * @return string
25
+ */
26
+ public function serialize($payload)
27
+ {
28
+ return http_build_query($payload, null, '&');
29
+ }
30
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/JsonHandler.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mime Type: application/json
4
+ * @author Nathan Good <me@nategood.com>
5
+ */
6
+
7
+ namespace Httpful\Handlers;
8
+
9
+ class JsonHandler extends MimeHandlerAdapter
10
+ {
11
+ private $decode_as_array = false;
12
+
13
+ public function init(array $args)
14
+ {
15
+ $this->decode_as_array = !!(array_key_exists('decode_as_array', $args) ? $args['decode_as_array'] : false);
16
+ }
17
+
18
+ /**
19
+ * @param string $body
20
+ * @return mixed
21
+ * @throws \Exception
22
+ */
23
+ public function parse($body)
24
+ {
25
+ $body = $this->stripBom($body);
26
+ if (empty($body))
27
+ return null;
28
+ $parsed = json_decode($body, $this->decode_as_array);
29
+ if (is_null($parsed) && 'null' !== strtolower($body))
30
+ throw new \Exception("Unable to parse response as JSON");
31
+ return $parsed;
32
+ }
33
+
34
+ /**
35
+ * @param mixed $payload
36
+ * @return string
37
+ */
38
+ public function serialize($payload)
39
+ {
40
+ return json_encode($payload);
41
+ }
42
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/MimeHandlerAdapter.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Handlers are used to parse and serialize payloads for specific
5
+ * mime types. You can register a custom handler via the register
6
+ * method. You can also override a default parser in this way.
7
+ */
8
+
9
+ namespace Httpful\Handlers;
10
+
11
+ class MimeHandlerAdapter
12
+ {
13
+ public function __construct(array $args = array())
14
+ {
15
+ $this->init($args);
16
+ }
17
+
18
+ /**
19
+ * Initial setup of
20
+ * @param array $args
21
+ */
22
+ public function init(array $args)
23
+ {
24
+ }
25
+
26
+ /**
27
+ * @param string $body
28
+ * @return mixed
29
+ */
30
+ public function parse($body)
31
+ {
32
+ return $body;
33
+ }
34
+
35
+ /**
36
+ * @param mixed $payload
37
+ * @return string
38
+ */
39
+ function serialize($payload)
40
+ {
41
+ return (string) $payload;
42
+ }
43
+
44
+ protected function stripBom($body)
45
+ {
46
+ if ( substr($body,0,3) === "\xef\xbb\xbf" ) // UTF-8
47
+ $body = substr($body,3);
48
+ else if ( substr($body,0,4) === "\xff\xfe\x00\x00" || substr($body,0,4) === "\x00\x00\xfe\xff" ) // UTF-32
49
+ $body = substr($body,4);
50
+ else if ( substr($body,0,2) === "\xff\xfe" || substr($body,0,2) === "\xfe\xff" ) // UTF-16
51
+ $body = substr($body,2);
52
+ return $body;
53
+ }
54
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/README.md ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Handlers
2
+
3
+ Handlers are simple classes that are used to parse response bodies and serialize request payloads. All Handlers must extend the `MimeHandlerAdapter` class and implement two methods: `serialize($payload)` and `parse($response)`. Let's build a very basic Handler to register for the `text/csv` mime type.
4
+
5
+ <?php
6
+
7
+ class SimpleCsvHandler extends \Httpful\Handlers\MimeHandlerAdapter
8
+ {
9
+ /**
10
+ * Takes a response body, and turns it into
11
+ * a two dimensional array.
12
+ *
13
+ * @param string $body
14
+ * @return mixed
15
+ */
16
+ public function parse($body)
17
+ {
18
+ return str_getcsv($body);
19
+ }
20
+
21
+ /**
22
+ * Takes a two dimensional array and turns it
23
+ * into a serialized string to include as the
24
+ * body of a request
25
+ *
26
+ * @param mixed $payload
27
+ * @return string
28
+ */
29
+ public function serialize($payload)
30
+ {
31
+ $serialized = '';
32
+ foreach ($payload as $line) {
33
+ $serialized .= '"' . implode('","', $line) . '"' . "\n";
34
+ }
35
+ return $serialized;
36
+ }
37
+ }
38
+
39
+
40
+ Finally, you must register this handler for a particular mime type.
41
+
42
+ Httpful::register('text/csv', new SimpleCsvHandler());
43
+
44
+ After this registering the handler in your source code, by default, any responses with a mime type of text/csv should be parsed by this handler.
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/XHtmlHandler.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mime Type: text/html
4
+ * Mime Type: application/html+xml
5
+ *
6
+ * @author Nathan Good <me@nategood.com>
7
+ */
8
+
9
+ namespace Httpful\Handlers;
10
+
11
+ class XHtmlHandler extends MimeHandlerAdapter
12
+ {
13
+ // @todo add html specific parsing
14
+ // see DomDocument::load http://docs.php.net/manual/en/domdocument.loadhtml.php
15
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Handlers/XmlHandler.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mime Type: application/xml
4
+ *
5
+ * @author Zack Douglas <zack@zackerydouglas.info>
6
+ * @author Nathan Good <me@nategood.com>
7
+ */
8
+
9
+ namespace Httpful\Handlers;
10
+
11
+ class XmlHandler extends MimeHandlerAdapter
12
+ {
13
+ /**
14
+ * @var string $namespace xml namespace to use with simple_load_string
15
+ */
16
+ private $namespace;
17
+
18
+ /**
19
+ * @var int $libxml_opts see http://www.php.net/manual/en/libxml.constants.php
20
+ */
21
+ private $libxml_opts;
22
+
23
+ /**
24
+ * @param array $conf sets configuration options
25
+ */
26
+ public function __construct(array $conf = array())
27
+ {
28
+ $this->namespace = isset($conf['namespace']) ? $conf['namespace'] : '';
29
+ $this->libxml_opts = isset($conf['libxml_opts']) ? $conf['libxml_opts'] : 0;
30
+ }
31
+
32
+ /**
33
+ * @param string $body
34
+ * @return mixed
35
+ * @throws \Exception if unable to parse
36
+ */
37
+ public function parse($body)
38
+ {
39
+ $body = $this->stripBom($body);
40
+ if (empty($body))
41
+ return null;
42
+ $parsed = simplexml_load_string($body, null, $this->libxml_opts, $this->namespace);
43
+ if ($parsed === false)
44
+ throw new \Exception("Unable to parse response as XML");
45
+ return $parsed;
46
+ }
47
+
48
+ /**
49
+ * @param mixed $payload
50
+ * @return string
51
+ * @throws \Exception if unable to serialize
52
+ */
53
+ public function serialize($payload)
54
+ {
55
+ list($_, $dom) = $this->_future_serializeAsXml($payload);
56
+ return $dom->saveXml();
57
+ }
58
+
59
+ /**
60
+ * @param mixed $payload
61
+ * @return string
62
+ * @author Ted Zellers
63
+ */
64
+ public function serialize_clean($payload)
65
+ {
66
+ $xml = new \XMLWriter;
67
+ $xml->openMemory();
68
+ $xml->startDocument('1.0','ISO-8859-1');
69
+ $this->serialize_node($xml, $payload);
70
+ return $xml->outputMemory(true);
71
+ }
72
+
73
+ /**
74
+ * @param \XMLWriter $xmlw
75
+ * @param mixed $node to serialize
76
+ * @author Ted Zellers
77
+ */
78
+ public function serialize_node(&$xmlw, $node){
79
+ if (!is_array($node)){
80
+ $xmlw->text($node);
81
+ } else {
82
+ foreach ($node as $k => $v){
83
+ $xmlw->startElement($k);
84
+ $this->serialize_node($xmlw, $v);
85
+ $xmlw->endElement();
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * @author Zack Douglas <zack@zackerydouglas.info>
92
+ */
93
+ private function _future_serializeAsXml($value, $node = null, $dom = null)
94
+ {
95
+ if (!$dom) {
96
+ $dom = new \DOMDocument;
97
+ }
98
+ if (!$node) {
99
+ if (!is_object($value)) {
100
+ $node = $dom->createElement('response');
101
+ $dom->appendChild($node);
102
+ } else {
103
+ $node = $dom;
104
+ }
105
+ }
106
+ if (is_object($value)) {
107
+ $objNode = $dom->createElement(get_class($value));
108
+ $node->appendChild($objNode);
109
+ $this->_future_serializeObjectAsXml($value, $objNode, $dom);
110
+ } else if (is_array($value)) {
111
+ $arrNode = $dom->createElement('array');
112
+ $node->appendChild($arrNode);
113
+ $this->_future_serializeArrayAsXml($value, $arrNode, $dom);
114
+ } else if (is_bool($value)) {
115
+ $node->appendChild($dom->createTextNode($value?'TRUE':'FALSE'));
116
+ } else {
117
+ $node->appendChild($dom->createTextNode($value));
118
+ }
119
+ return array($node, $dom);
120
+ }
121
+ /**
122
+ * @author Zack Douglas <zack@zackerydouglas.info>
123
+ */
124
+ private function _future_serializeArrayAsXml($value, &$parent, &$dom)
125
+ {
126
+ foreach ($value as $k => &$v) {
127
+ $n = $k;
128
+ if (is_numeric($k)) {
129
+ $n = "child-{$n}";
130
+ }
131
+ $el = $dom->createElement($n);
132
+ $parent->appendChild($el);
133
+ $this->_future_serializeAsXml($v, $el, $dom);
134
+ }
135
+ return array($parent, $dom);
136
+ }
137
+ /**
138
+ * @author Zack Douglas <zack@zackerydouglas.info>
139
+ */
140
+ private function _future_serializeObjectAsXml($value, &$parent, &$dom)
141
+ {
142
+ $refl = new \ReflectionObject($value);
143
+ foreach ($refl->getProperties() as $pr) {
144
+ if (!$pr->isPrivate()) {
145
+ $el = $dom->createElement($pr->getName());
146
+ $parent->appendChild($el);
147
+ $this->_future_serializeAsXml($pr->getValue($value), $el, $dom);
148
+ }
149
+ }
150
+ return array($parent, $dom);
151
+ }
152
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Http.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful;
4
+
5
+ /**
6
+ * @author Nate Good <me@nategood.com>
7
+ */
8
+ class Http
9
+ {
10
+ const HEAD = 'HEAD';
11
+ const GET = 'GET';
12
+ const POST = 'POST';
13
+ const PUT = 'PUT';
14
+ const DELETE = 'DELETE';
15
+ const PATCH = 'PATCH';
16
+ const OPTIONS = 'OPTIONS';
17
+ const TRACE = 'TRACE';
18
+
19
+ /**
20
+ * @return array of HTTP method strings
21
+ */
22
+ public static function safeMethods()
23
+ {
24
+ return array(self::HEAD, self::GET, self::OPTIONS, self::TRACE);
25
+ }
26
+
27
+ /**
28
+ * @param string HTTP method
29
+ * @return bool
30
+ */
31
+ public static function isSafeMethod($method)
32
+ {
33
+ return in_array($method, self::safeMethods());
34
+ }
35
+
36
+ /**
37
+ * @param string HTTP method
38
+ * @return bool
39
+ */
40
+ public static function isUnsafeMethod($method)
41
+ {
42
+ return !in_array($method, self::safeMethods());
43
+ }
44
+
45
+ /**
46
+ * @return array list of (always) idempotent HTTP methods
47
+ */
48
+ public static function idempotentMethods()
49
+ {
50
+ // Though it is possible to be idempotent, POST
51
+ // is not guarunteed to be, and more often than
52
+ // not, it is not.
53
+ return array(self::HEAD, self::GET, self::PUT, self::DELETE, self::OPTIONS, self::TRACE, self::PATCH);
54
+ }
55
+
56
+ /**
57
+ * @param string HTTP method
58
+ * @return bool
59
+ */
60
+ public static function isIdempotent($method)
61
+ {
62
+ return in_array($method, self::safeidempotentMethodsMethods());
63
+ }
64
+
65
+ /**
66
+ * @param string HTTP method
67
+ * @return bool
68
+ */
69
+ public static function isNotIdempotent($method)
70
+ {
71
+ return !in_array($method, self::idempotentMethods());
72
+ }
73
+
74
+ /**
75
+ * @deprecated Technically anything *can* have a body,
76
+ * they just don't have semantic meaning. So say's Roy
77
+ * http://tech.groups.yahoo.com/group/rest-discuss/message/9962
78
+ *
79
+ * @return array of HTTP method strings
80
+ */
81
+ public static function canHaveBody()
82
+ {
83
+ return array(self::POST, self::PUT, self::PATCH, self::OPTIONS);
84
+ }
85
+
86
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Httpful.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful;
4
+
5
+ class Httpful {
6
+ const VERSION = '0.2.20';
7
+
8
+ private static $mimeRegistrar = array();
9
+ private static $default = null;
10
+
11
+ /**
12
+ * @param string $mimeType
13
+ * @param \Httpful\Handlers\MimeHandlerAdapter $handler
14
+ */
15
+ public static function register($mimeType, \Httpful\Handlers\MimeHandlerAdapter $handler)
16
+ {
17
+ self::$mimeRegistrar[$mimeType] = $handler;
18
+ }
19
+
20
+ /**
21
+ * @param string $mimeType defaults to MimeHandlerAdapter
22
+ * @return \Httpful\Handlers\MimeHandlerAdapter
23
+ */
24
+ public static function get($mimeType = null)
25
+ {
26
+ if (isset(self::$mimeRegistrar[$mimeType])) {
27
+ return self::$mimeRegistrar[$mimeType];
28
+ }
29
+
30
+ if (empty(self::$default)) {
31
+ self::$default = new \Httpful\Handlers\MimeHandlerAdapter();
32
+ }
33
+
34
+ return self::$default;
35
+ }
36
+
37
+ /**
38
+ * Does this particular Mime Type have a parser registered
39
+ * for it?
40
+ * @param string $mimeType
41
+ * @return bool
42
+ */
43
+ public static function hasParserRegistered($mimeType)
44
+ {
45
+ return isset(self::$mimeRegistrar[$mimeType]);
46
+ }
47
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Mime.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful;
4
+
5
+ /**
6
+ * Class to organize the Mime stuff a bit more
7
+ * @author Nate Good <me@nategood.com>
8
+ */
9
+ class Mime
10
+ {
11
+ const JSON = 'application/json';
12
+ const XML = 'application/xml';
13
+ const XHTML = 'application/html+xml';
14
+ const FORM = 'application/x-www-form-urlencoded';
15
+ const UPLOAD = 'multipart/form-data';
16
+ const PLAIN = 'text/plain';
17
+ const JS = 'text/javascript';
18
+ const HTML = 'text/html';
19
+ const YAML = 'application/x-yaml';
20
+ const CSV = 'text/csv';
21
+
22
+ /**
23
+ * Map short name for a mime type
24
+ * to a full proper mime type
25
+ */
26
+ public static $mimes = array(
27
+ 'json' => self::JSON,
28
+ 'xml' => self::XML,
29
+ 'form' => self::FORM,
30
+ 'plain' => self::PLAIN,
31
+ 'text' => self::PLAIN,
32
+ 'upload' => self::UPLOAD,
33
+ 'html' => self::HTML,
34
+ 'xhtml' => self::XHTML,
35
+ 'js' => self::JS,
36
+ 'javascript'=> self::JS,
37
+ 'yaml' => self::YAML,
38
+ 'csv' => self::CSV,
39
+ );
40
+
41
+ /**
42
+ * Get the full Mime Type name from a "short name".
43
+ * Returns the short if no mapping was found.
44
+ * @param string $short_name common name for mime type (e.g. json)
45
+ * @return string full mime type (e.g. application/json)
46
+ */
47
+ public static function getFullMime($short_name)
48
+ {
49
+ return array_key_exists($short_name, self::$mimes) ? self::$mimes[$short_name] : $short_name;
50
+ }
51
+
52
+ /**
53
+ * @param string $short_name
54
+ * @return bool
55
+ */
56
+ public static function supportsMimeType($short_name)
57
+ {
58
+ return array_key_exists($short_name, self::$mimes);
59
+ }
60
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Proxy.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Httpful;
3
+
4
+ if (!defined('CURLPROXY_SOCKS4')) {
5
+ define('CURLPROXY_SOCKS4', 4);
6
+ }
7
+
8
+ /**
9
+ * Class to organize the Proxy stuff a bit more
10
+ */
11
+ class Proxy
12
+ {
13
+ const HTTP = CURLPROXY_HTTP;
14
+ const SOCKS4 = CURLPROXY_SOCKS4;
15
+ const SOCKS5 = CURLPROXY_SOCKS5;
16
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Request.php ADDED
@@ -0,0 +1,1186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful;
4
+
5
+ use Httpful\Exception\ConnectionErrorException;
6
+
7
+ /**
8
+ * Clean, simple class for sending HTTP requests
9
+ * in PHP.
10
+ *
11
+ * There is an emphasis of readability without loosing concise
12
+ * syntax. As such, you will notice that the library lends
13
+ * itself very nicely to "chaining". You will see several "alias"
14
+ * methods: more readable method definitions that wrap
15
+ * their more concise counterparts. You will also notice
16
+ * no public constructor. This two adds to the readability
17
+ * and "chainabilty" of the library.
18
+ *
19
+ * @author Nate Good <me@nategood.com>
20
+ */
21
+ class Request
22
+ {
23
+
24
+ // Option constants
25
+ const SERIALIZE_PAYLOAD_NEVER = 0;
26
+ const SERIALIZE_PAYLOAD_ALWAYS = 1;
27
+ const SERIALIZE_PAYLOAD_SMART = 2;
28
+
29
+ const MAX_REDIRECTS_DEFAULT = 25;
30
+
31
+ public $uri,
32
+ $method = Http::GET,
33
+ $headers = array(),
34
+ $raw_headers = '',
35
+ $strict_ssl = false,
36
+ $content_type,
37
+ $expected_type,
38
+ $additional_curl_opts = array(),
39
+ $auto_parse = true,
40
+ $serialize_payload_method = self::SERIALIZE_PAYLOAD_SMART,
41
+ $username,
42
+ $password,
43
+ $serialized_payload,
44
+ $payload,
45
+ $parse_callback,
46
+ $error_callback,
47
+ $send_callback,
48
+ $follow_redirects = false,
49
+ $max_redirects = self::MAX_REDIRECTS_DEFAULT,
50
+ $payload_serializers = array();
51
+
52
+ // Options
53
+ // private $_options = array(
54
+ // 'serialize_payload_method' => self::SERIALIZE_PAYLOAD_SMART
55
+ // 'auto_parse' => true
56
+ // );
57
+
58
+ // Curl Handle
59
+ public $_ch,
60
+ $_debug;
61
+
62
+ // Template Request object
63
+ private static $_template;
64
+
65
+ /**
66
+ * We made the constructor private to force the factory style. This was
67
+ * done to keep the syntax cleaner and better the support the idea of
68
+ * "default templates". Very basic and flexible as it is only intended
69
+ * for internal use.
70
+ * @param array $attrs hash of initial attribute values
71
+ */
72
+ private function __construct($attrs = null)
73
+ {
74
+ if (!is_array($attrs)) return;
75
+ foreach ($attrs as $attr => $value) {
76
+ $this->$attr = $value;
77
+ }
78
+ }
79
+
80
+ // Defaults Management
81
+
82
+ /**
83
+ * Let's you configure default settings for this
84
+ * class from a template Request object. Simply construct a
85
+ * Request object as much as you want to and then pass it to
86
+ * this method. It will then lock in those settings from
87
+ * that template object.
88
+ * The most common of which may be default mime
89
+ * settings or strict ssl settings.
90
+ * Again some slight memory overhead incurred here but in the grand
91
+ * scheme of things as it typically only occurs once
92
+ * @param Request $template
93
+ */
94
+ public static function ini(Request $template)
95
+ {
96
+ self::$_template = clone $template;
97
+ }
98
+
99
+ /**
100
+ * Reset the default template back to the
101
+ * library defaults.
102
+ */
103
+ public static function resetIni()
104
+ {
105
+ self::_initializeDefaults();
106
+ }
107
+
108
+ /**
109
+ * Get default for a value based on the template object
110
+ * @param string|null $attr Name of attribute (e.g. mime, headers)
111
+ * if null just return the whole template object;
112
+ * @return mixed default value
113
+ */
114
+ public static function d($attr)
115
+ {
116
+ return isset($attr) ? self::$_template->$attr : self::$_template;
117
+ }
118
+
119
+ // Accessors
120
+
121
+ /**
122
+ * @return bool does the request have a timeout?
123
+ */
124
+ public function hasTimeout()
125
+ {
126
+ return isset($this->timeout);
127
+ }
128
+
129
+ /**
130
+ * @return bool has the internal curl request been initialized?
131
+ */
132
+ public function hasBeenInitialized()
133
+ {
134
+ return isset($this->_ch);
135
+ }
136
+
137
+ /**
138
+ * @return bool Is this request setup for basic auth?
139
+ */
140
+ public function hasBasicAuth()
141
+ {
142
+ return isset($this->password) && isset($this->username);
143
+ }
144
+
145
+ /**
146
+ * @return bool Is this request setup for digest auth?
147
+ */
148
+ public function hasDigestAuth()
149
+ {
150
+ return isset($this->password) && isset($this->username) && $this->additional_curl_opts[CURLOPT_HTTPAUTH] == CURLAUTH_DIGEST;
151
+ }
152
+
153
+ /**
154
+ * Specify a HTTP timeout
155
+ * @param float|int $timeout seconds to timeout the HTTP call
156
+ * @return Request
157
+ */
158
+ public function timeout($timeout)
159
+ {
160
+ $this->timeout = $timeout;
161
+ return $this;
162
+ }
163
+
164
+ // alias timeout
165
+ public function timeoutIn($seconds)
166
+ {
167
+ return $this->timeout($seconds);
168
+ }
169
+
170
+ /**
171
+ * If the response is a 301 or 302 redirect, automatically
172
+ * send off another request to that location
173
+ * @param bool|int $follow follow or not to follow or maximal number of redirects
174
+ * @return Request
175
+ */
176
+ public function followRedirects($follow = true)
177
+ {
178
+ $this->max_redirects = $follow === true ? self::MAX_REDIRECTS_DEFAULT : max(0, $follow);
179
+ $this->follow_redirects = (bool) $follow;
180
+ return $this;
181
+ }
182
+
183
+ /**
184
+ * @see Request::followRedirects()
185
+ * @return Request
186
+ */
187
+ public function doNotFollowRedirects()
188
+ {
189
+ return $this->followRedirects(false);
190
+ }
191
+
192
+ /**
193
+ * Actually send off the request, and parse the response
194
+ * @return Response with parsed results
195
+ * @throws ConnectionErrorException when unable to parse or communicate w server
196
+ */
197
+ public function send()
198
+ {
199
+ if (!$this->hasBeenInitialized())
200
+ $this->_curlPrep();
201
+
202
+ $result = curl_exec($this->_ch);
203
+
204
+ $response = $this->buildResponse($result);
205
+
206
+ curl_close($this->_ch);
207
+
208
+ return $response;
209
+ }
210
+ public function sendIt()
211
+ {
212
+ return $this->send();
213
+ }
214
+
215
+ // Setters
216
+
217
+ /**
218
+ * @param string $uri
219
+ * @return Request
220
+ */
221
+ public function uri($uri)
222
+ {
223
+ $this->uri = $uri;
224
+ return $this;
225
+ }
226
+
227
+ /**
228
+ * User Basic Auth.
229
+ * Only use when over SSL/TSL/HTTPS.
230
+ * @param string $username
231
+ * @param string $password
232
+ * @return Request
233
+ */
234
+ public function basicAuth($username, $password)
235
+ {
236
+ $this->username = $username;
237
+ $this->password = $password;
238
+ return $this;
239
+ }
240
+ // @alias of basicAuth
241
+ public function authenticateWith($username, $password)
242
+ {
243
+ return $this->basicAuth($username, $password);
244
+ }
245
+ // @alias of basicAuth
246
+ public function authenticateWithBasic($username, $password)
247
+ {
248
+ return $this->basicAuth($username, $password);
249
+ }
250
+
251
+ // @alias of ntlmAuth
252
+ public function authenticateWithNTLM($username, $password)
253
+ {
254
+ return $this->ntlmAuth($username, $password);
255
+ }
256
+
257
+ public function ntlmAuth($username, $password)
258
+ {
259
+ $this->addOnCurlOption(CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
260
+ return $this->basicAuth($username, $password);
261
+ }
262
+
263
+ /**
264
+ * User Digest Auth.
265
+ * @param string $username
266
+ * @param string $password
267
+ * @return Request
268
+ */
269
+ public function digestAuth($username, $password)
270
+ {
271
+ $this->addOnCurlOption(CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
272
+ return $this->basicAuth($username, $password);
273
+ }
274
+
275
+ // @alias of digestAuth
276
+ public function authenticateWithDigest($username, $password)
277
+ {
278
+ return $this->digestAuth($username, $password);
279
+ }
280
+
281
+ /**
282
+ * @return bool is this request setup for client side cert?
283
+ */
284
+ public function hasClientSideCert()
285
+ {
286
+ return isset($this->client_cert) && isset($this->client_key);
287
+ }
288
+
289
+ /**
290
+ * Use Client Side Cert Authentication
291
+ * @param string $key file path to client key
292
+ * @param string $cert file path to client cert
293
+ * @param string $passphrase for client key
294
+ * @param string $encoding default PEM
295
+ * @return Request
296
+ */
297
+ public function clientSideCert($cert, $key, $passphrase = null, $encoding = 'PEM')
298
+ {
299
+ $this->client_cert = $cert;
300
+ $this->client_key = $key;
301
+ $this->client_passphrase = $passphrase;
302
+ $this->client_encoding = $encoding;
303
+
304
+ return $this;
305
+ }
306
+ // @alias of basicAuth
307
+ public function authenticateWithCert($cert, $key, $passphrase = null, $encoding = 'PEM')
308
+ {
309
+ return $this->clientSideCert($cert, $key, $passphrase, $encoding);
310
+ }
311
+
312
+ /**
313
+ * Set the body of the request
314
+ * @param mixed $payload
315
+ * @param string $mimeType currently, sets the sends AND expects mime type although this
316
+ * behavior may change in the next minor release (as it is a potential breaking change).
317
+ * @return Request
318
+ */
319
+ public function body($payload, $mimeType = null)
320
+ {
321
+ $this->mime($mimeType);
322
+ $this->payload = $payload;
323
+ // Iserntentially don't call _serializePayload yet. Wait until
324
+ // we actually send off the request to convert payload to string.
325
+ // At that time, the `serialized_payload` is set accordingly.
326
+ return $this;
327
+ }
328
+
329
+ /**
330
+ * Helper function to set the Content type and Expected as same in
331
+ * one swoop
332
+ * @param string $mime mime type to use for content type and expected return type
333
+ * @return Request
334
+ */
335
+ public function mime($mime)
336
+ {
337
+ if (empty($mime)) return $this;
338
+ $this->content_type = $this->expected_type = Mime::getFullMime($mime);
339
+ if ($this->isUpload()) {
340
+ $this->neverSerializePayload();
341
+ }
342
+ return $this;
343
+ }
344
+ // @alias of mime
345
+ public function sendsAndExpectsType($mime)
346
+ {
347
+ return $this->mime($mime);
348
+ }
349
+ // @alias of mime
350
+ public function sendsAndExpects($mime)
351
+ {
352
+ return $this->mime($mime);
353
+ }
354
+
355
+ /**
356
+ * Set the method. Shouldn't be called often as the preferred syntax
357
+ * for instantiation is the method specific factory methods.
358
+ * @param string $method
359
+ * @return Request
360
+ */
361
+ public function method($method)
362
+ {
363
+ if (empty($method)) return $this;
364
+ $this->method = $method;
365
+ return $this;
366
+ }
367
+
368
+ /**
369
+ * @param string $mime
370
+ * @return Request
371
+ */
372
+ public function expects($mime)
373
+ {
374
+ if (empty($mime)) return $this;
375
+ $this->expected_type = Mime::getFullMime($mime);
376
+ return $this;
377
+ }
378
+ // @alias of expects
379
+ public function expectsType($mime)
380
+ {
381
+ return $this->expects($mime);
382
+ }
383
+
384
+ public function attach($files)
385
+ {
386
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
387
+ foreach ($files as $key => $file) {
388
+ $mimeType = finfo_file($finfo, $file);
389
+ if (function_exists('curl_file_create')) {
390
+ $this->payload[$key] = curl_file_create($file, $mimeType);
391
+ } else {
392
+ $this->payload[$key] = '@' . $file;
393
+ if ($mimeType) {
394
+ $this->payload[$key] .= ';type=' . $mimeType;
395
+ }
396
+ }
397
+ }
398
+ $this->sendsType(Mime::UPLOAD);
399
+ return $this;
400
+ }
401
+
402
+ /**
403
+ * @param string $mime
404
+ * @return Request
405
+ */
406
+ public function contentType($mime)
407
+ {
408
+ if (empty($mime)) return $this;
409
+ $this->content_type = Mime::getFullMime($mime);
410
+ if ($this->isUpload()) {
411
+ $this->neverSerializePayload();
412
+ }
413
+ return $this;
414
+ }
415
+ // @alias of contentType
416
+ public function sends($mime)
417
+ {
418
+ return $this->contentType($mime);
419
+ }
420
+ // @alias of contentType
421
+ public function sendsType($mime)
422
+ {
423
+ return $this->contentType($mime);
424
+ }
425
+
426
+ /**
427
+ * Do we strictly enforce SSL verification?
428
+ * @param bool $strict
429
+ * @return Request
430
+ */
431
+ public function strictSSL($strict)
432
+ {
433
+ $this->strict_ssl = $strict;
434
+ return $this;
435
+ }
436
+ public function withoutStrictSSL()
437
+ {
438
+ return $this->strictSSL(false);
439
+ }
440
+ public function withStrictSSL()
441
+ {
442
+ return $this->strictSSL(true);
443
+ }
444
+
445
+ /**
446
+ * Use proxy configuration
447
+ * @param string $proxy_host Hostname or address of the proxy
448
+ * @param int $proxy_port Port of the proxy. Default 80
449
+ * @param string $auth_type Authentication type or null. Accepted values are CURLAUTH_BASIC, CURLAUTH_NTLM. Default null, no authentication
450
+ * @param string $auth_username Authentication username. Default null
451
+ * @param string $auth_password Authentication password. Default null
452
+ * @return Request
453
+ */
454
+ public function useProxy($proxy_host, $proxy_port = 80, $auth_type = null, $auth_username = null, $auth_password = null, $proxy_type = Proxy::HTTP)
455
+ {
456
+ $this->addOnCurlOption(CURLOPT_PROXY, "{$proxy_host}:{$proxy_port}");
457
+ $this->addOnCurlOption(CURLOPT_PROXYTYPE, $proxy_type);
458
+ if (in_array($auth_type, array(CURLAUTH_BASIC,CURLAUTH_NTLM))) {
459
+ $this->addOnCurlOption(CURLOPT_PROXYAUTH, $auth_type)
460
+ ->addOnCurlOption(CURLOPT_PROXYUSERPWD, "{$auth_username}:{$auth_password}");
461
+ }
462
+ return $this;
463
+ }
464
+
465
+ /**
466
+ * Shortcut for useProxy to configure SOCKS 4 proxy
467
+ * @see Request::useProxy
468
+ * @return Request
469
+ */
470
+ public function useSocks4Proxy($proxy_host, $proxy_port = 80, $auth_type = null, $auth_username = null, $auth_password = null)
471
+ {
472
+ return $this->useProxy($proxy_host, $proxy_port, $auth_type, $auth_username, $auth_password, Proxy::SOCKS4);
473
+ }
474
+
475
+ /**
476
+ * Shortcut for useProxy to configure SOCKS 5 proxy
477
+ * @see Request::useProxy
478
+ * @return Request
479
+ */
480
+ public function useSocks5Proxy($proxy_host, $proxy_port = 80, $auth_type = null, $auth_username = null, $auth_password = null)
481
+ {
482
+ return $this->useProxy($proxy_host, $proxy_port, $auth_type, $auth_username, $auth_password, Proxy::SOCKS5);
483
+ }
484
+
485
+ /**
486
+ * @return bool is this request setup for using proxy?
487
+ */
488
+ public function hasProxy()
489
+ {
490
+ return isset($this->additional_curl_opts[CURLOPT_PROXY]) && is_string($this->additional_curl_opts[CURLOPT_PROXY]);
491
+ }
492
+
493
+ /**
494
+ * Determine how/if we use the built in serialization by
495
+ * setting the serialize_payload_method
496
+ * The default (SERIALIZE_PAYLOAD_SMART) is...
497
+ * - if payload is not a scalar (object/array)
498
+ * use the appropriate serialize method according to
499
+ * the Content-Type of this request.
500
+ * - if the payload IS a scalar (int, float, string, bool)
501
+ * than just return it as is.
502
+ * When this option is set SERIALIZE_PAYLOAD_ALWAYS,
503
+ * it will always use the appropriate
504
+ * serialize option regardless of whether payload is scalar or not
505
+ * When this option is set SERIALIZE_PAYLOAD_NEVER,
506
+ * it will never use any of the serialization methods.
507
+ * Really the only use for this is if you want the serialize methods
508
+ * to handle strings or not (e.g. Blah is not valid JSON, but "Blah"
509
+ * is). Forcing the serialization helps prevent that kind of error from
510
+ * happening.
511
+ * @param int $mode
512
+ * @return Request
513
+ */
514
+ public function serializePayload($mode)
515
+ {
516
+ $this->serialize_payload_method = $mode;
517
+ return $this;
518
+ }
519
+
520
+ /**
521
+ * @see Request::serializePayload()
522
+ * @return Request
523
+ */
524
+ public function neverSerializePayload()
525
+ {
526
+ return $this->serializePayload(self::SERIALIZE_PAYLOAD_NEVER);
527
+ }
528
+
529
+ /**
530
+ * This method is the default behavior
531
+ * @see Request::serializePayload()
532
+ * @return Request
533
+ */
534
+ public function smartSerializePayload()
535
+ {
536
+ return $this->serializePayload(self::SERIALIZE_PAYLOAD_SMART);
537
+ }
538
+
539
+ /**
540
+ * @see Request::serializePayload()
541
+ * @return Request
542
+ */
543
+ public function alwaysSerializePayload()
544
+ {
545
+ return $this->serializePayload(self::SERIALIZE_PAYLOAD_ALWAYS);
546
+ }
547
+
548
+ /**
549
+ * Add an additional header to the request
550
+ * Can also use the cleaner syntax of
551
+ * $Request->withMyHeaderName($my_value);
552
+ * @see Request::__call()
553
+ *
554
+ * @param string $header_name
555
+ * @param string $value
556
+ * @return Request
557
+ */
558
+ public function addHeader($header_name, $value)
559
+ {
560
+ $this->headers[$header_name] = $value;
561
+ return $this;
562
+ }
563
+
564
+ /**
565
+ * Add group of headers all at once. Note: This is
566
+ * here just as a convenience in very specific cases.
567
+ * The preferred "readable" way would be to leverage
568
+ * the support for custom header methods.
569
+ * @param array $headers
570
+ * @return Request
571
+ */
572
+ public function addHeaders(array $headers)
573
+ {
574
+ foreach ($headers as $header => $value) {
575
+ $this->addHeader($header, $value);
576
+ }
577
+ return $this;
578
+ }
579
+
580
+ /**
581
+ * @param bool $auto_parse perform automatic "smart"
582
+ * parsing based on Content-Type or "expectedType"
583
+ * If not auto parsing, Response->body returns the body
584
+ * as a string.
585
+ * @return Request
586
+ */
587
+ public function autoParse($auto_parse = true)
588
+ {
589
+ $this->auto_parse = $auto_parse;
590
+ return $this;
591
+ }
592
+
593
+ /**
594
+ * @see Request::autoParse()
595
+ * @return Request
596
+ */
597
+ public function withoutAutoParsing()
598
+ {
599
+ return $this->autoParse(false);
600
+ }
601
+
602
+ /**
603
+ * @see Request::autoParse()
604
+ * @return Request
605
+ */
606
+ public function withAutoParsing()
607
+ {
608
+ return $this->autoParse(true);
609
+ }
610
+
611
+ /**
612
+ * Use a custom function to parse the response.
613
+ * @param \Closure $callback Takes the raw body of
614
+ * the http response and returns a mixed
615
+ * @return Request
616
+ */
617
+ public function parseWith(\Closure $callback)
618
+ {
619
+ $this->parse_callback = $callback;
620
+ return $this;
621
+ }
622
+
623
+ /**
624
+ * @see Request::parseResponsesWith()
625
+ * @param \Closure $callback
626
+ * @return Request
627
+ */
628
+ public function parseResponsesWith(\Closure $callback)
629
+ {
630
+ return $this->parseWith($callback);
631
+ }
632
+
633
+ /**
634
+ * Callback called to handle HTTP errors. When nothing is set, defaults
635
+ * to logging via `error_log`
636
+ * @param \Closure $callback (string $error)
637
+ * @return Request
638
+ */
639
+ public function whenError(\Closure $callback)
640
+ {
641
+ $this->error_callback = $callback;
642
+ return $this;
643
+ }
644
+
645
+ /**
646
+ * Callback invoked after payload has been serialized but before
647
+ * the request has been built.
648
+ * @param \Closure $callback (Request $request)
649
+ * @return Request
650
+ */
651
+ public function beforeSend(\Closure $callback)
652
+ {
653
+ $this->send_callback = $callback;
654
+ return $this;
655
+ }
656
+
657
+ /**
658
+ * Register a callback that will be used to serialize the payload
659
+ * for a particular mime type. When using "*" for the mime
660
+ * type, it will use that parser for all responses regardless of the mime
661
+ * type. If a custom '*' and 'application/json' exist, the custom
662
+ * 'application/json' would take precedence over the '*' callback.
663
+ *
664
+ * @param string $mime mime type we're registering
665
+ * @param \Closure $callback takes one argument, $payload,
666
+ * which is the payload that we'll be
667
+ * @return Request
668
+ */
669
+ public function registerPayloadSerializer($mime, \Closure $callback)
670
+ {
671
+ $this->payload_serializers[Mime::getFullMime($mime)] = $callback;
672
+ return $this;
673
+ }
674
+
675
+ /**
676
+ * @see Request::registerPayloadSerializer()
677
+ * @param \Closure $callback
678
+ * @return Request
679
+ */
680
+ public function serializePayloadWith(\Closure $callback)
681
+ {
682
+ return $this->registerPayloadSerializer('*', $callback);
683
+ }
684
+
685
+ /**
686
+ * Magic method allows for neatly setting other headers in a
687
+ * similar syntax as the other setters. This method also allows
688
+ * for the sends* syntax.
689
+ * @param string $method "missing" method name called
690
+ * the method name called should be the name of the header that you
691
+ * are trying to set in camel case without dashes e.g. to set a
692
+ * header for Content-Type you would use contentType() or more commonly
693
+ * to add a custom header like X-My-Header, you would use xMyHeader().
694
+ * To promote readability, you can optionally prefix these methods with
695
+ * "with" (e.g. withXMyHeader("blah") instead of xMyHeader("blah")).
696
+ * @param array $args in this case, there should only ever be 1 argument provided
697
+ * and that argument should be a string value of the header we're setting
698
+ * @return Request
699
+ */
700
+ public function __call($method, $args)
701
+ {
702
+ // This method supports the sends* methods
703
+ // like sendsJSON, sendsForm
704
+ //!method_exists($this, $method) &&
705
+ if (substr($method, 0, 5) === 'sends') {
706
+ $mime = strtolower(substr($method, 5));
707
+ if (Mime::supportsMimeType($mime)) {
708
+ $this->sends(Mime::getFullMime($mime));
709
+ return $this;
710
+ }
711
+ // else {
712
+ // throw new \Exception("Unsupported Content-Type $mime");
713
+ // }
714
+ }
715
+ if (substr($method, 0, 7) === 'expects') {
716
+ $mime = strtolower(substr($method, 7));
717
+ if (Mime::supportsMimeType($mime)) {
718
+ $this->expects(Mime::getFullMime($mime));
719
+ return $this;
720
+ }
721
+ // else {
722
+ // throw new \Exception("Unsupported Content-Type $mime");
723
+ // }
724
+ }
725
+
726
+ // This method also adds the custom header support as described in the
727
+ // method comments
728
+ if (count($args) === 0)
729
+ return;
730
+
731
+ // Strip the sugar. If it leads with "with", strip.
732
+ // This is okay because: No defined HTTP headers begin with with,
733
+ // and if you are defining a custom header, the standard is to prefix it
734
+ // with an "X-", so that should take care of any collisions.
735
+ if (substr($method, 0, 4) === 'with')
736
+ $method = substr($method, 4);
737
+
738
+ // Precede upper case letters with dashes, uppercase the first letter of method
739
+ $header = ucwords(implode('-', preg_split('/([A-Z][^A-Z]*)/', $method, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY)));
740
+ $this->addHeader($header, $args[0]);
741
+ return $this;
742
+ }
743
+
744
+ // Internal Functions
745
+
746
+ /**
747
+ * This is the default template to use if no
748
+ * template has been provided. The template
749
+ * tells the class which default values to use.
750
+ * While there is a slight overhead for object
751
+ * creation once per execution (not once per
752
+ * Request instantiation), it promotes readability
753
+ * and flexibility within the class.
754
+ */
755
+ private static function _initializeDefaults()
756
+ {
757
+ // This is the only place you will
758
+ // see this constructor syntax. It
759
+ // is only done here to prevent infinite
760
+ // recusion. Do not use this syntax elsewhere.
761
+ // It goes against the whole readability
762
+ // and transparency idea.
763
+ self::$_template = new Request(array('method' => Http::GET));
764
+
765
+ // This is more like it...
766
+ self::$_template
767
+ ->withoutStrictSSL();
768
+ }
769
+
770
+ /**
771
+ * Set the defaults on a newly instantiated object
772
+ * Doesn't copy variables prefixed with _
773
+ * @return Request
774
+ */
775
+ private function _setDefaults()
776
+ {
777
+ if (!isset(self::$_template))
778
+ self::_initializeDefaults();
779
+ foreach (self::$_template as $k=>$v) {
780
+ if ($k[0] != '_')
781
+ $this->$k = $v;
782
+ }
783
+ return $this;
784
+ }
785
+
786
+ private function _error($error)
787
+ {
788
+ // TODO add in support for various Loggers that follow
789
+ // PSR 3 https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
790
+ if (isset($this->error_callback)) {
791
+ $this->error_callback->__invoke($error);
792
+ } else {
793
+ error_log($error);
794
+ }
795
+ }
796
+
797
+ /**
798
+ * Factory style constructor works nicer for chaining. This
799
+ * should also really only be used internally. The Request::get,
800
+ * Request::post syntax is preferred as it is more readable.
801
+ * @param string $method Http Method
802
+ * @param string $mime Mime Type to Use
803
+ * @return Request
804
+ */
805
+ public static function init($method = null, $mime = null)
806
+ {
807
+ // Setup our handlers, can call it here as it's idempotent
808
+ Bootstrap::init();
809
+
810
+ // Setup the default template if need be
811
+ if (!isset(self::$_template))
812
+ self::_initializeDefaults();
813
+
814
+ $request = new Request();
815
+ return $request
816
+ ->_setDefaults()
817
+ ->method($method)
818
+ ->sendsType($mime)
819
+ ->expectsType($mime);
820
+ }
821
+
822
+ /**
823
+ * Does the heavy lifting. Uses de facto HTTP
824
+ * library cURL to set up the HTTP request.
825
+ * Note: It does NOT actually send the request
826
+ * @return Request
827
+ * @throws \Exception
828
+ */
829
+ public function _curlPrep()
830
+ {
831
+ // Check for required stuff
832
+ if (!isset($this->uri))
833
+ throw new \Exception('Attempting to send a request before defining a URI endpoint.');
834
+
835
+ if (isset($this->payload)) {
836
+ $this->serialized_payload = $this->_serializePayload($this->payload);
837
+ }
838
+
839
+ if (isset($this->send_callback)) {
840
+ call_user_func($this->send_callback, $this);
841
+ }
842
+
843
+ $ch = curl_init($this->uri);
844
+
845
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
846
+ if ($this->method === Http::HEAD) {
847
+ curl_setopt($ch, CURLOPT_NOBODY, true);
848
+ }
849
+
850
+ if ($this->hasBasicAuth()) {
851
+ curl_setopt($ch, CURLOPT_USERPWD, $this->username . ':' . $this->password);
852
+ }
853
+
854
+ if ($this->hasClientSideCert()) {
855
+
856
+ if (!file_exists($this->client_key))
857
+ throw new \Exception('Could not read Client Key');
858
+
859
+ if (!file_exists($this->client_cert))
860
+ throw new \Exception('Could not read Client Certificate');
861
+
862
+ curl_setopt($ch, CURLOPT_SSLCERTTYPE, $this->client_encoding);
863
+ curl_setopt($ch, CURLOPT_SSLKEYTYPE, $this->client_encoding);
864
+ curl_setopt($ch, CURLOPT_SSLCERT, $this->client_cert);
865
+ curl_setopt($ch, CURLOPT_SSLKEY, $this->client_key);
866
+ curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $this->client_passphrase);
867
+ // curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $this->client_cert_passphrase);
868
+ }
869
+
870
+ if ($this->hasTimeout()) {
871
+ if (defined('CURLOPT_TIMEOUT_MS')) {
872
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, $this->timeout * 1000);
873
+ } else {
874
+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
875
+ }
876
+ }
877
+
878
+ if ($this->follow_redirects) {
879
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
880
+ curl_setopt($ch, CURLOPT_MAXREDIRS, $this->max_redirects);
881
+ }
882
+
883
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->strict_ssl);
884
+ // zero is safe for all curl versions
885
+ $verifyValue = $this->strict_ssl + 0;
886
+ //Support for value 1 removed in cURL 7.28.1 value 2 valid in all versions
887
+ if ($verifyValue > 0) $verifyValue++;
888
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, $verifyValue);
889
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
890
+
891
+ // https://github.com/nategood/httpful/issues/84
892
+ // set Content-Length to the size of the payload if present
893
+ if (isset($this->payload)) {
894
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $this->serialized_payload);
895
+ if (!$this->isUpload()) {
896
+ $this->headers['Content-Length'] =
897
+ $this->_determineLength($this->serialized_payload);
898
+ }
899
+ }
900
+
901
+ $headers = array();
902
+ // https://github.com/nategood/httpful/issues/37
903
+ // Except header removes any HTTP 1.1 Continue from response headers
904
+ $headers[] = 'Expect:';
905
+
906
+ if (!isset($this->headers['User-Agent'])) {
907
+ $headers[] = $this->buildUserAgent();
908
+ }
909
+
910
+ $headers[] = "Content-Type: {$this->content_type}";
911
+
912
+ // allow custom Accept header if set
913
+ if (!isset($this->headers['Accept'])) {
914
+ // http://pretty-rfc.herokuapp.com/RFC2616#header.accept
915
+ $accept = 'Accept: */*; q=0.5, text/plain; q=0.8, text/html;level=3;';
916
+
917
+ if (!empty($this->expected_type)) {
918
+ $accept .= "q=0.9, {$this->expected_type}";
919
+ }
920
+
921
+ $headers[] = $accept;
922
+ }
923
+
924
+ // Solve a bug on squid proxy, NONE/411 when miss content length
925
+ if (!isset($this->headers['Content-Length']) && !$this->isUpload()) {
926
+ $this->headers['Content-Length'] = 0;
927
+ }
928
+
929
+ foreach ($this->headers as $header => $value) {
930
+ $headers[] = "$header: $value";
931
+ }
932
+
933
+ $url = \parse_url($this->uri);
934
+ $path = (isset($url['path']) ? $url['path'] : '/').(isset($url['query']) ? '?'.$url['query'] : '');
935
+ $this->raw_headers = "{$this->method} $path HTTP/1.1\r\n";
936
+ $host = (isset($url['host']) ? $url['host'] : 'localhost').(isset($url['port']) ? ':'.$url['port'] : '');
937
+ $this->raw_headers .= "Host: $host\r\n";
938
+ $this->raw_headers .= \implode("\r\n", $headers);
939
+ $this->raw_headers .= "\r\n";
940
+
941
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
942
+
943
+ if ($this->_debug) {
944
+ curl_setopt($ch, CURLOPT_VERBOSE, true);
945
+ }
946
+
947
+ curl_setopt($ch, CURLOPT_HEADER, 1);
948
+
949
+ // If there are some additional curl opts that the user wants
950
+ // to set, we can tack them in here
951
+ foreach ($this->additional_curl_opts as $curlopt => $curlval) {
952
+ curl_setopt($ch, $curlopt, $curlval);
953
+ }
954
+
955
+ $this->_ch = $ch;
956
+
957
+ return $this;
958
+ }
959
+
960
+ /**
961
+ * @param string $str payload
962
+ * @return int length of payload in bytes
963
+ */
964
+ public function _determineLength($str)
965
+ {
966
+ if (function_exists('mb_strlen')) {
967
+ return mb_strlen($str, '8bit');
968
+ } else {
969
+ return strlen($str);
970
+ }
971
+ }
972
+
973
+ /**
974
+ * @return bool
975
+ */
976
+ public function isUpload()
977
+ {
978
+ return Mime::UPLOAD == $this->content_type;
979
+ }
980
+
981
+ /**
982
+ * @return string
983
+ */
984
+ public function buildUserAgent()
985
+ {
986
+ $user_agent = 'User-Agent: Httpful/' . Httpful::VERSION . ' (cURL/';
987
+ $curl = \curl_version();
988
+
989
+ if (isset($curl['version'])) {
990
+ $user_agent .= $curl['version'];
991
+ } else {
992
+ $user_agent .= '?.?.?';
993
+ }
994
+
995
+ $user_agent .= ' PHP/'. PHP_VERSION . ' (' . PHP_OS . ')';
996
+
997
+ if (isset($_SERVER['SERVER_SOFTWARE'])) {
998
+ $user_agent .= ' ' . \preg_replace('~PHP/[\d\.]+~U', '',
999
+ $_SERVER['SERVER_SOFTWARE']);
1000
+ } else {
1001
+ if (isset($_SERVER['TERM_PROGRAM'])) {
1002
+ $user_agent .= " {$_SERVER['TERM_PROGRAM']}";
1003
+ }
1004
+
1005
+ if (isset($_SERVER['TERM_PROGRAM_VERSION'])) {
1006
+ $user_agent .= "/{$_SERVER['TERM_PROGRAM_VERSION']}";
1007
+ }
1008
+ }
1009
+
1010
+ if (isset($_SERVER['HTTP_USER_AGENT'])) {
1011
+ $user_agent .= " {$_SERVER['HTTP_USER_AGENT']}";
1012
+ }
1013
+
1014
+ $user_agent .= ')';
1015
+
1016
+ return $user_agent;
1017
+ }
1018
+
1019
+ /**
1020
+ * Takes a curl result and generates a Response from it
1021
+ * @return Response
1022
+ */
1023
+ public function buildResponse($result) {
1024
+ if ($result === false) {
1025
+ if ($curlErrorNumber = curl_errno($this->_ch)) {
1026
+ $curlErrorString = curl_error($this->_ch);
1027
+ $this->_error($curlErrorString);
1028
+ throw new ConnectionErrorException('Unable to connect to "'.$this->uri.'": ' . $curlErrorNumber . ' ' . $curlErrorString);
1029
+ }
1030
+
1031
+ $this->_error('Unable to connect to "'.$this->uri.'".');
1032
+ throw new ConnectionErrorException('Unable to connect to "'.$this->uri.'".');
1033
+ }
1034
+
1035
+ $info = curl_getinfo($this->_ch);
1036
+
1037
+ // Remove the "HTTP/1.x 200 Connection established" string and any other headers added by proxy
1038
+ $proxy_regex = "/HTTP\/1\.[01] 200 Connection established.*?\r\n\r\n/si";
1039
+ if ($this->hasProxy() && preg_match($proxy_regex, $result)) {
1040
+ $result = preg_replace($proxy_regex, '', $result);
1041
+ }
1042
+
1043
+ $response = explode("\r\n\r\n", $result, 2 + $info['redirect_count']);
1044
+
1045
+ $body = array_pop($response);
1046
+ $headers = array_pop($response);
1047
+
1048
+ return new Response($body, $headers, $this, $info);
1049
+ }
1050
+
1051
+ /**
1052
+ * Semi-reluctantly added this as a way to add in curl opts
1053
+ * that are not otherwise accessible from the rest of the API.
1054
+ * @param string $curlopt
1055
+ * @param mixed $curloptval
1056
+ * @return Request
1057
+ */
1058
+ public function addOnCurlOption($curlopt, $curloptval)
1059
+ {
1060
+ $this->additional_curl_opts[$curlopt] = $curloptval;
1061
+ return $this;
1062
+ }
1063
+
1064
+ /**
1065
+ * Turn payload from structured data into
1066
+ * a string based on the current Mime type.
1067
+ * This uses the auto_serialize option to determine
1068
+ * it's course of action. See serialize method for more.
1069
+ * Renamed from _detectPayload to _serializePayload as of
1070
+ * 2012-02-15.
1071
+ *
1072
+ * Added in support for custom payload serializers.
1073
+ * The serialize_payload_method stuff still holds true though.
1074
+ * @see Request::registerPayloadSerializer()
1075
+ *
1076
+ * @param mixed $payload
1077
+ * @return string
1078
+ */
1079
+ private function _serializePayload($payload)
1080
+ {
1081
+ if (empty($payload) || $this->serialize_payload_method === self::SERIALIZE_PAYLOAD_NEVER)
1082
+ return $payload;
1083
+
1084
+ // When we are in "smart" mode, don't serialize strings/scalars, assume they are already serialized
1085
+ if ($this->serialize_payload_method === self::SERIALIZE_PAYLOAD_SMART && is_scalar($payload))
1086
+ return $payload;
1087
+
1088
+ // Use a custom serializer if one is registered for this mime type
1089
+ if (isset($this->payload_serializers['*']) || isset($this->payload_serializers[$this->content_type])) {
1090
+ $key = isset($this->payload_serializers[$this->content_type]) ? $this->content_type : '*';
1091
+ return call_user_func($this->payload_serializers[$key], $payload);
1092
+ }
1093
+
1094
+ return Httpful::get($this->content_type)->serialize($payload);
1095
+ }
1096
+
1097
+ /**
1098
+ * HTTP Method Get
1099
+ * @param string $uri optional uri to use
1100
+ * @param string $mime expected
1101
+ * @return Request
1102
+ */
1103
+ public static function get($uri, $mime = null)
1104
+ {
1105
+ return self::init(Http::GET)->uri($uri)->mime($mime);
1106
+ }
1107
+
1108
+
1109
+ /**
1110
+ * Like Request:::get, except that it sends off the request as well
1111
+ * returning a response
1112
+ * @param string $uri optional uri to use
1113
+ * @param string $mime expected
1114
+ * @return Response
1115
+ */
1116
+ public static function getQuick($uri, $mime = null)
1117
+ {
1118
+ return self::get($uri, $mime)->send();
1119
+ }
1120
+
1121
+ /**
1122
+ * HTTP Method Post
1123
+ * @param string $uri optional uri to use
1124
+ * @param string $payload data to send in body of request
1125
+ * @param string $mime MIME to use for Content-Type
1126
+ * @return Request
1127
+ */
1128
+ public static function post($uri, $payload = null, $mime = null)
1129
+ {
1130
+ return self::init(Http::POST)->uri($uri)->body($payload, $mime);
1131
+ }
1132
+
1133
+ /**
1134
+ * HTTP Method Put
1135
+ * @param string $uri optional uri to use
1136
+ * @param string $payload data to send in body of request
1137
+ * @param string $mime MIME to use for Content-Type
1138
+ * @return Request
1139
+ */
1140
+ public static function put($uri, $payload = null, $mime = null)
1141
+ {
1142
+ return self::init(Http::PUT)->uri($uri)->body($payload, $mime);
1143
+ }
1144
+
1145
+ /**
1146
+ * HTTP Method Patch
1147
+ * @param string $uri optional uri to use
1148
+ * @param string $payload data to send in body of request
1149
+ * @param string $mime MIME to use for Content-Type
1150
+ * @return Request
1151
+ */
1152
+ public static function patch($uri, $payload = null, $mime = null)
1153
+ {
1154
+ return self::init(Http::PATCH)->uri($uri)->body($payload, $mime);
1155
+ }
1156
+
1157
+ /**
1158
+ * HTTP Method Delete
1159
+ * @param string $uri optional uri to use
1160
+ * @return Request
1161
+ */
1162
+ public static function delete($uri, $mime = null)
1163
+ {
1164
+ return self::init(Http::DELETE)->uri($uri)->mime($mime);
1165
+ }
1166
+
1167
+ /**
1168
+ * HTTP Method Head
1169
+ * @param string $uri optional uri to use
1170
+ * @return Request
1171
+ */
1172
+ public static function head($uri)
1173
+ {
1174
+ return self::init(Http::HEAD)->uri($uri);
1175
+ }
1176
+
1177
+ /**
1178
+ * HTTP Method Options
1179
+ * @param string $uri optional uri to use
1180
+ * @return Request
1181
+ */
1182
+ public static function options($uri)
1183
+ {
1184
+ return self::init(Http::OPTIONS)->uri($uri);
1185
+ }
1186
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Response.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful;
4
+
5
+ /**
6
+ * Models an HTTP response
7
+ *
8
+ * @author Nate Good <me@nategood.com>
9
+ */
10
+ class Response
11
+ {
12
+
13
+ public $body,
14
+ $raw_body,
15
+ $headers,
16
+ $raw_headers,
17
+ $request,
18
+ $code = 0,
19
+ $content_type,
20
+ $parent_type,
21
+ $charset,
22
+ $meta_data,
23
+ $is_mime_vendor_specific = false,
24
+ $is_mime_personal = false;
25
+
26
+ private $parsers;
27
+
28
+ /**
29
+ * @param string $body
30
+ * @param string $headers
31
+ * @param Request $request
32
+ * @param array $meta_data
33
+ */
34
+ public function __construct($body, $headers, Request $request, array $meta_data = array())
35
+ {
36
+ $this->request = $request;
37
+ $this->raw_headers = $headers;
38
+ $this->raw_body = $body;
39
+ $this->meta_data = $meta_data;
40
+
41
+ $this->code = $this->_parseCode($headers);
42
+ $this->headers = Response\Headers::fromString($headers);
43
+
44
+ $this->_interpretHeaders();
45
+
46
+ $this->body = $this->_parse($body);
47
+ }
48
+
49
+ /**
50
+ * Status Code Definitions
51
+ *
52
+ * Informational 1xx
53
+ * Successful 2xx
54
+ * Redirection 3xx
55
+ * Client Error 4xx
56
+ * Server Error 5xx
57
+ *
58
+ * http://pretty-rfc.herokuapp.com/RFC2616#status.codes
59
+ *
60
+ * @return bool Did we receive a 4xx or 5xx?
61
+ */
62
+ public function hasErrors()
63
+ {
64
+ return $this->code >= 400;
65
+ }
66
+
67
+ /**
68
+ * @return bool
69
+ */
70
+ public function hasBody()
71
+ {
72
+ return !empty($this->body);
73
+ }
74
+
75
+ /**
76
+ * Parse the response into a clean data structure
77
+ * (most often an associative array) based on the expected
78
+ * Mime type.
79
+ * @param string Http response body
80
+ * @return array|string|object the response parse accordingly
81
+ */
82
+ public function _parse($body)
83
+ {
84
+ // If the user decided to forgo the automatic
85
+ // smart parsing, short circuit.
86
+ if (!$this->request->auto_parse) {
87
+ return $body;
88
+ }
89
+
90
+ // If provided, use custom parsing callback
91
+ if (isset($this->request->parse_callback)) {
92
+ return call_user_func($this->request->parse_callback, $body);
93
+ }
94
+
95
+ // Decide how to parse the body of the response in the following order
96
+ // 1. If provided, use the mime type specifically set as part of the `Request`
97
+ // 2. If a MimeHandler is registered for the content type, use it
98
+ // 3. If provided, use the "parent type" of the mime type from the response
99
+ // 4. Default to the content-type provided in the response
100
+ $parse_with = $this->request->expected_type;
101
+ if (empty($this->request->expected_type)) {
102
+ $parse_with = Httpful::hasParserRegistered($this->content_type)
103
+ ? $this->content_type
104
+ : $this->parent_type;
105
+ }
106
+
107
+ return Httpful::get($parse_with)->parse($body);
108
+ }
109
+
110
+ /**
111
+ * Parse text headers from response into
112
+ * array of key value pairs
113
+ * @param string $headers raw headers
114
+ * @return array parse headers
115
+ */
116
+ public function _parseHeaders($headers)
117
+ {
118
+ $headers = preg_split("/(\r|\n)+/", $headers, -1, \PREG_SPLIT_NO_EMPTY);
119
+ $parse_headers = array();
120
+ for ($i = 1; $i < count($headers); $i++) {
121
+ list($key, $raw_value) = explode(':', $headers[$i], 2);
122
+ $key = trim($key);
123
+ $value = trim($raw_value);
124
+ if (array_key_exists($key, $parse_headers)) {
125
+ // See HTTP RFC Sec 4.2 Paragraph 5
126
+ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
127
+ // If a header appears more than once, it must also be able to
128
+ // be represented as a single header with a comma-separated
129
+ // list of values. We transform accordingly.
130
+ $parse_headers[$key] .= ',' . $value;
131
+ } else {
132
+ $parse_headers[$key] = $value;
133
+ }
134
+ }
135
+ return $parse_headers;
136
+ }
137
+
138
+ public function _parseCode($headers)
139
+ {
140
+ $end = strpos($headers, "\r\n");
141
+ if ($end === false) $end = strlen($headers);
142
+ $parts = explode(' ', substr($headers, 0, $end));
143
+ if (count($parts) < 2 || !is_numeric($parts[1])) {
144
+ throw new \Exception("Unable to parse response code from HTTP response due to malformed response");
145
+ }
146
+ return intval($parts[1]);
147
+ }
148
+
149
+ /**
150
+ * After we've parse the headers, let's clean things
151
+ * up a bit and treat some headers specially
152
+ */
153
+ public function _interpretHeaders()
154
+ {
155
+ // Parse the Content-Type and charset
156
+ $content_type = isset($this->headers['Content-Type']) ? $this->headers['Content-Type'] : '';
157
+ $content_type = explode(';', $content_type);
158
+
159
+ $this->content_type = $content_type[0];
160
+ if (count($content_type) == 2 && strpos($content_type[1], '=') !== false) {
161
+ list($nill, $this->charset) = explode('=', $content_type[1]);
162
+ }
163
+
164
+ // RFC 2616 states "text/*" Content-Types should have a default
165
+ // charset of ISO-8859-1. "application/*" and other Content-Types
166
+ // are assumed to have UTF-8 unless otherwise specified.
167
+ // http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1
168
+ // http://www.w3.org/International/O-HTTP-charset.en.php
169
+ if (!isset($this->charset)) {
170
+ $this->charset = substr($this->content_type, 5) === 'text/' ? 'iso-8859-1' : 'utf-8';
171
+ }
172
+
173
+ // Is vendor type? Is personal type?
174
+ if (strpos($this->content_type, '/') !== false) {
175
+ list($type, $sub_type) = explode('/', $this->content_type);
176
+ $this->is_mime_vendor_specific = substr($sub_type, 0, 4) === 'vnd.';
177
+ $this->is_mime_personal = substr($sub_type, 0, 4) === 'prs.';
178
+ }
179
+
180
+ // Parent type (e.g. xml for application/vnd.github.message+xml)
181
+ $this->parent_type = $this->content_type;
182
+ if (strpos($this->content_type, '+') !== false) {
183
+ list($vendor, $this->parent_type) = explode('+', $this->content_type, 2);
184
+ $this->parent_type = Mime::getFullMime($this->parent_type);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * @return string
190
+ */
191
+ public function __toString()
192
+ {
193
+ return $this->raw_body;
194
+ }
195
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/src/Httpful/Response/Headers.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Httpful\Response;
4
+
5
+ final class Headers implements \ArrayAccess, \Countable {
6
+
7
+ private $headers;
8
+
9
+ /**
10
+ * @param array $headers
11
+ */
12
+ private function __construct($headers)
13
+ {
14
+ $this->headers = $headers;
15
+ }
16
+
17
+ /**
18
+ * @param string $string
19
+ * @return Headers
20
+ */
21
+ public static function fromString($string)
22
+ {
23
+ $lines = preg_split("/(\r|\n)+/", $string, -1, PREG_SPLIT_NO_EMPTY);
24
+ array_shift($lines); // HTTP HEADER
25
+ $headers = array();
26
+ foreach ($lines as $line) {
27
+ list($name, $value) = explode(':', $line, 2);
28
+ $headers[strtolower(trim($name))] = trim($value);
29
+ }
30
+ return new self($headers);
31
+ }
32
+
33
+ /**
34
+ * @param string $offset
35
+ * @return bool
36
+ */
37
+ public function offsetExists($offset)
38
+ {
39
+ return isset($this->headers[strtolower($offset)]);
40
+ }
41
+
42
+ /**
43
+ * @param string $offset
44
+ * @return mixed
45
+ */
46
+ public function offsetGet($offset)
47
+ {
48
+ if (isset($this->headers[$name = strtolower($offset)])) {
49
+ return $this->headers[$name];
50
+ }
51
+ }
52
+
53
+ /**
54
+ * @param string $offset
55
+ * @param string $value
56
+ * @throws \Exception
57
+ */
58
+ public function offsetSet($offset, $value)
59
+ {
60
+ throw new \Exception("Headers are read-only.");
61
+ }
62
+
63
+ /**
64
+ * @param string $offset
65
+ * @throws \Exception
66
+ */
67
+ public function offsetUnset($offset)
68
+ {
69
+ throw new \Exception("Headers are read-only.");
70
+ }
71
+
72
+ /**
73
+ * @return int
74
+ */
75
+ public function count()
76
+ {
77
+ return count($this->headers);
78
+ }
79
+
80
+ /**
81
+ * @return array
82
+ */
83
+ public function toArray()
84
+ {
85
+ return $this->headers;
86
+ }
87
+
88
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/Httpful/HttpfulTest.php ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Port over the original tests into a more traditional PHPUnit
4
+ * format. Still need to hook into a lightweight HTTP server to
5
+ * better test some things (e.g. obscure cURL settings). I've moved
6
+ * the old tests and node.js server to the tests/.legacy directory.
7
+ *
8
+ * @author Nate Good <me@nategood.com>
9
+ */
10
+ namespace Httpful\Test;
11
+
12
+ require(dirname(dirname(dirname(__FILE__))) . '/bootstrap.php');
13
+ \Httpful\Bootstrap::init();
14
+
15
+ use Httpful\Httpful;
16
+ use Httpful\Request;
17
+ use Httpful\Mime;
18
+ use Httpful\Http;
19
+ use Httpful\Response;
20
+ use Httpful\Handlers\JsonHandler;
21
+
22
+ define('TEST_SERVER', WEB_SERVER_HOST . ':' . WEB_SERVER_PORT);
23
+
24
+ class HttpfulTest extends \PHPUnit_Framework_TestCase
25
+ {
26
+ const TEST_SERVER = TEST_SERVER;
27
+ const TEST_URL = 'http://127.0.0.1:8008';
28
+ const TEST_URL_400 = 'http://127.0.0.1:8008/400';
29
+
30
+ const SAMPLE_JSON_HEADER =
31
+ "HTTP/1.1 200 OK
32
+ Content-Type: application/json
33
+ Connection: keep-alive
34
+ Transfer-Encoding: chunked\r\n";
35
+ const SAMPLE_JSON_RESPONSE = '{"key":"value","object":{"key":"value"},"array":[1,2,3,4]}';
36
+ const SAMPLE_CSV_HEADER =
37
+ "HTTP/1.1 200 OK
38
+ Content-Type: text/csv
39
+ Connection: keep-alive
40
+ Transfer-Encoding: chunked\r\n";
41
+ const SAMPLE_CSV_RESPONSE =
42
+ "Key1,Key2
43
+ Value1,Value2
44
+ \"40.0\",\"Forty\"";
45
+ const SAMPLE_XML_RESPONSE = '<stdClass><arrayProp><array><k1><myClass><intProp>2</intProp></myClass></k1></array></arrayProp><stringProp>a string</stringProp><boolProp>TRUE</boolProp></stdClass>';
46
+ const SAMPLE_XML_HEADER =
47
+ "HTTP/1.1 200 OK
48
+ Content-Type: application/xml
49
+ Connection: keep-alive
50
+ Transfer-Encoding: chunked\r\n";
51
+ const SAMPLE_VENDOR_HEADER =
52
+ "HTTP/1.1 200 OK
53
+ Content-Type: application/vnd.nategood.message+xml
54
+ Connection: keep-alive
55
+ Transfer-Encoding: chunked\r\n";
56
+ const SAMPLE_VENDOR_TYPE = "application/vnd.nategood.message+xml";
57
+ const SAMPLE_MULTI_HEADER =
58
+ "HTTP/1.1 200 OK
59
+ Content-Type: application/json
60
+ Connection: keep-alive
61
+ Transfer-Encoding: chunked
62
+ X-My-Header:Value1
63
+ X-My-Header:Value2\r\n";
64
+
65
+ function testInit()
66
+ {
67
+ $r = Request::init();
68
+ // Did we get a 'Request' object?
69
+ $this->assertEquals('Httpful\Request', get_class($r));
70
+ }
71
+
72
+ function testDetermineLength()
73
+ {
74
+ $r = Request::init();
75
+ $this->assertEquals(1, $r->_determineLength('A'));
76
+ $this->assertEquals(2, $r->_determineLength('À'));
77
+ $this->assertEquals(2, $r->_determineLength('Ab'));
78
+ $this->assertEquals(3, $r->_determineLength('Àb'));
79
+ $this->assertEquals(6, $r->_determineLength('世界'));
80
+ }
81
+
82
+ function testMethods()
83
+ {
84
+ $valid_methods = array('get', 'post', 'delete', 'put', 'options', 'head');
85
+ $url = 'http://example.com/';
86
+ foreach ($valid_methods as $method) {
87
+ $r = call_user_func(array('Httpful\Request', $method), $url);
88
+ $this->assertEquals('Httpful\Request', get_class($r));
89
+ $this->assertEquals(strtoupper($method), $r->method);
90
+ }
91
+ }
92
+
93
+ function testDefaults()
94
+ {
95
+ // Our current defaults are as follows
96
+ $r = Request::init();
97
+ $this->assertEquals(Http::GET, $r->method);
98
+ $this->assertFalse($r->strict_ssl);
99
+ }
100
+
101
+ function testShortMime()
102
+ {
103
+ // Valid short ones
104
+ $this->assertEquals(Mime::JSON, Mime::getFullMime('json'));
105
+ $this->assertEquals(Mime::XML, Mime::getFullMime('xml'));
106
+ $this->assertEquals(Mime::HTML, Mime::getFullMime('html'));
107
+ $this->assertEquals(Mime::CSV, Mime::getFullMime('csv'));
108
+ $this->assertEquals(Mime::UPLOAD, Mime::getFullMime('upload'));
109
+
110
+ // Valid long ones
111
+ $this->assertEquals(Mime::JSON, Mime::getFullMime(Mime::JSON));
112
+ $this->assertEquals(Mime::XML, Mime::getFullMime(Mime::XML));
113
+ $this->assertEquals(Mime::HTML, Mime::getFullMime(Mime::HTML));
114
+ $this->assertEquals(Mime::CSV, Mime::getFullMime(Mime::CSV));
115
+ $this->assertEquals(Mime::UPLOAD, Mime::getFullMime(Mime::UPLOAD));
116
+
117
+ // No false positives
118
+ $this->assertNotEquals(Mime::XML, Mime::getFullMime(Mime::HTML));
119
+ $this->assertNotEquals(Mime::JSON, Mime::getFullMime(Mime::XML));
120
+ $this->assertNotEquals(Mime::HTML, Mime::getFullMime(Mime::JSON));
121
+ $this->assertNotEquals(Mime::XML, Mime::getFullMime(Mime::CSV));
122
+ }
123
+
124
+ function testSettingStrictSsl()
125
+ {
126
+ $r = Request::init()
127
+ ->withStrictSsl();
128
+
129
+ $this->assertTrue($r->strict_ssl);
130
+
131
+ $r = Request::init()
132
+ ->withoutStrictSsl();
133
+
134
+ $this->assertFalse($r->strict_ssl);
135
+ }
136
+
137
+ function testSendsAndExpectsType()
138
+ {
139
+ $r = Request::init()
140
+ ->sendsAndExpectsType(Mime::JSON);
141
+ $this->assertEquals(Mime::JSON, $r->expected_type);
142
+ $this->assertEquals(Mime::JSON, $r->content_type);
143
+
144
+ $r = Request::init()
145
+ ->sendsAndExpectsType('html');
146
+ $this->assertEquals(Mime::HTML, $r->expected_type);
147
+ $this->assertEquals(Mime::HTML, $r->content_type);
148
+
149
+ $r = Request::init()
150
+ ->sendsAndExpectsType('form');
151
+ $this->assertEquals(Mime::FORM, $r->expected_type);
152
+ $this->assertEquals(Mime::FORM, $r->content_type);
153
+
154
+ $r = Request::init()
155
+ ->sendsAndExpectsType('application/x-www-form-urlencoded');
156
+ $this->assertEquals(Mime::FORM, $r->expected_type);
157
+ $this->assertEquals(Mime::FORM, $r->content_type);
158
+
159
+ $r = Request::init()
160
+ ->sendsAndExpectsType(Mime::CSV);
161
+ $this->assertEquals(Mime::CSV, $r->expected_type);
162
+ $this->assertEquals(Mime::CSV, $r->content_type);
163
+ }
164
+
165
+ function testIni()
166
+ {
167
+ // Test setting defaults/templates
168
+
169
+ // Create the template
170
+ $template = Request::init()
171
+ ->method(Http::POST)
172
+ ->withStrictSsl()
173
+ ->expectsType(Mime::HTML)
174
+ ->sendsType(Mime::FORM);
175
+
176
+ Request::ini($template);
177
+
178
+ $r = Request::init();
179
+
180
+ $this->assertTrue($r->strict_ssl);
181
+ $this->assertEquals(Http::POST, $r->method);
182
+ $this->assertEquals(Mime::HTML, $r->expected_type);
183
+ $this->assertEquals(Mime::FORM, $r->content_type);
184
+
185
+ // Test the default accessor as well
186
+ $this->assertTrue(Request::d('strict_ssl'));
187
+ $this->assertEquals(Http::POST, Request::d('method'));
188
+ $this->assertEquals(Mime::HTML, Request::d('expected_type'));
189
+ $this->assertEquals(Mime::FORM, Request::d('content_type'));
190
+
191
+ Request::resetIni();
192
+ }
193
+
194
+ function testAccept()
195
+ {
196
+ $r = Request::get('http://example.com/')
197
+ ->expectsType(Mime::JSON);
198
+
199
+ $this->assertEquals(Mime::JSON, $r->expected_type);
200
+ $r->_curlPrep();
201
+ $this->assertContains('application/json', $r->raw_headers);
202
+ }
203
+
204
+ function testCustomAccept()
205
+ {
206
+ $accept = 'application/api-1.0+json';
207
+ $r = Request::get('http://example.com/')
208
+ ->addHeader('Accept', $accept);
209
+
210
+ $r->_curlPrep();
211
+ $this->assertContains($accept, $r->raw_headers);
212
+ $this->assertEquals($accept, $r->headers['Accept']);
213
+ }
214
+
215
+ function testUserAgent()
216
+ {
217
+ $r = Request::get('http://example.com/')
218
+ ->withUserAgent('ACME/1.2.3');
219
+
220
+ $this->assertArrayHasKey('User-Agent', $r->headers);
221
+ $r->_curlPrep();
222
+ $this->assertContains('User-Agent: ACME/1.2.3', $r->raw_headers);
223
+ $this->assertNotContains('User-Agent: HttpFul/1.0', $r->raw_headers);
224
+
225
+ $r = Request::get('http://example.com/')
226
+ ->withUserAgent('');
227
+
228
+ $this->assertArrayHasKey('User-Agent', $r->headers);
229
+ $r->_curlPrep();
230
+ $this->assertContains('User-Agent:', $r->raw_headers);
231
+ $this->assertNotContains('User-Agent: HttpFul/1.0', $r->raw_headers);
232
+ }
233
+
234
+ function testAuthSetup()
235
+ {
236
+ $username = 'nathan';
237
+ $password = 'opensesame';
238
+
239
+ $r = Request::get('http://example.com/')
240
+ ->authenticateWith($username, $password);
241
+
242
+ $this->assertEquals($username, $r->username);
243
+ $this->assertEquals($password, $r->password);
244
+ $this->assertTrue($r->hasBasicAuth());
245
+ }
246
+
247
+ function testDigestAuthSetup()
248
+ {
249
+ $username = 'nathan';
250
+ $password = 'opensesame';
251
+
252
+ $r = Request::get('http://example.com/')
253
+ ->authenticateWithDigest($username, $password);
254
+
255
+ $this->assertEquals($username, $r->username);
256
+ $this->assertEquals($password, $r->password);
257
+ $this->assertTrue($r->hasDigestAuth());
258
+ }
259
+
260
+ function testJsonResponseParse()
261
+ {
262
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
263
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
264
+
265
+ $this->assertEquals("value", $response->body->key);
266
+ $this->assertEquals("value", $response->body->object->key);
267
+ $this->assertInternalType('array', $response->body->array);
268
+ $this->assertEquals(1, $response->body->array[0]);
269
+ }
270
+
271
+ function testXMLResponseParse()
272
+ {
273
+ $req = Request::init()->sendsAndExpects(Mime::XML);
274
+ $response = new Response(self::SAMPLE_XML_RESPONSE, self::SAMPLE_XML_HEADER, $req);
275
+ $sxe = $response->body;
276
+ $this->assertEquals("object", gettype($sxe));
277
+ $this->assertEquals("SimpleXMLElement", get_class($sxe));
278
+ $bools = $sxe->xpath('/stdClass/boolProp');
279
+ list( , $bool ) = each($bools);
280
+ $this->assertEquals("TRUE", (string) $bool);
281
+ $ints = $sxe->xpath('/stdClass/arrayProp/array/k1/myClass/intProp');
282
+ list( , $int ) = each($ints);
283
+ $this->assertEquals("2", (string) $int);
284
+ $strings = $sxe->xpath('/stdClass/stringProp');
285
+ list( , $string ) = each($strings);
286
+ $this->assertEquals("a string", (string) $string);
287
+ }
288
+
289
+ function testCsvResponseParse()
290
+ {
291
+ $req = Request::init()->sendsAndExpects(Mime::CSV);
292
+ $response = new Response(self::SAMPLE_CSV_RESPONSE, self::SAMPLE_CSV_HEADER, $req);
293
+
294
+ $this->assertEquals("Key1", $response->body[0][0]);
295
+ $this->assertEquals("Value1", $response->body[1][0]);
296
+ $this->assertInternalType('string', $response->body[2][0]);
297
+ $this->assertEquals("40.0", $response->body[2][0]);
298
+ }
299
+
300
+ function testParsingContentTypeCharset()
301
+ {
302
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
303
+ // $response = new Response(SAMPLE_JSON_RESPONSE, "", $req);
304
+ // // Check default content type of iso-8859-1
305
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, "HTTP/1.1 200 OK
306
+ Content-Type: text/plain; charset=utf-8\r\n", $req);
307
+ $this->assertInstanceOf('Httpful\Response\Headers', $response->headers);
308
+ $this->assertEquals($response->headers['Content-Type'], 'text/plain; charset=utf-8');
309
+ $this->assertEquals($response->content_type, 'text/plain');
310
+ $this->assertEquals($response->charset, 'utf-8');
311
+ }
312
+
313
+ function testParsingContentTypeUpload()
314
+ {
315
+ $req = Request::init();
316
+
317
+ $req->sendsType(Mime::UPLOAD);
318
+ // $response = new Response(SAMPLE_JSON_RESPONSE, "", $req);
319
+ // // Check default content type of iso-8859-1
320
+ $this->assertEquals($req->content_type, 'multipart/form-data');
321
+ }
322
+
323
+ function testAttach() {
324
+ $req = Request::init();
325
+ $testsPath = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..');
326
+ $filename = $testsPath . DIRECTORY_SEPARATOR . 'test_image.jpg';
327
+ $req->attach(array('index' => $filename));
328
+ $payload = $req->payload['index'];
329
+ // PHP 5.5 + will take advantage of CURLFile while previous
330
+ // versions just use the string syntax
331
+ if (is_string($payload)) {
332
+ $this->assertEquals($payload, '@' . $filename . ';type=image/jpeg');
333
+ } else {
334
+ $this->assertInstanceOf('CURLFile', $payload);
335
+ }
336
+
337
+ $this->assertEquals($req->content_type, Mime::UPLOAD);
338
+ $this->assertEquals($req->serialize_payload_method, Request::SERIALIZE_PAYLOAD_NEVER);
339
+ }
340
+
341
+ function testIsUpload() {
342
+ $req = Request::init();
343
+
344
+ $req->sendsType(Mime::UPLOAD);
345
+
346
+ $this->assertTrue($req->isUpload());
347
+ }
348
+
349
+ function testEmptyResponseParse()
350
+ {
351
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
352
+ $response = new Response("", self::SAMPLE_JSON_HEADER, $req);
353
+ $this->assertEquals(null, $response->body);
354
+
355
+ $reqXml = Request::init()->sendsAndExpects(Mime::XML);
356
+ $responseXml = new Response("", self::SAMPLE_XML_HEADER, $reqXml);
357
+ $this->assertEquals(null, $responseXml->body);
358
+ }
359
+
360
+ function testNoAutoParse()
361
+ {
362
+ $req = Request::init()->sendsAndExpects(Mime::JSON)->withoutAutoParsing();
363
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
364
+ $this->assertInternalType('string', $response->body);
365
+ $req = Request::init()->sendsAndExpects(Mime::JSON)->withAutoParsing();
366
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
367
+ $this->assertInternalType('object', $response->body);
368
+ }
369
+
370
+ function testParseHeaders()
371
+ {
372
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
373
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
374
+ $this->assertEquals('application/json', $response->headers['Content-Type']);
375
+ }
376
+
377
+ function testRawHeaders()
378
+ {
379
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
380
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
381
+ $this->assertContains('Content-Type: application/json', $response->raw_headers);
382
+ }
383
+
384
+ function testHasErrors()
385
+ {
386
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
387
+ $response = new Response('', "HTTP/1.1 100 Continue\r\n", $req);
388
+ $this->assertFalse($response->hasErrors());
389
+ $response = new Response('', "HTTP/1.1 200 OK\r\n", $req);
390
+ $this->assertFalse($response->hasErrors());
391
+ $response = new Response('', "HTTP/1.1 300 Multiple Choices\r\n", $req);
392
+ $this->assertFalse($response->hasErrors());
393
+ $response = new Response('', "HTTP/1.1 400 Bad Request\r\n", $req);
394
+ $this->assertTrue($response->hasErrors());
395
+ $response = new Response('', "HTTP/1.1 500 Internal Server Error\r\n", $req);
396
+ $this->assertTrue($response->hasErrors());
397
+ }
398
+
399
+ function testWhenError() {
400
+ $caught = false;
401
+
402
+ try {
403
+ Request::get('malformed:url')
404
+ ->whenError(function($error) use(&$caught) {
405
+ $caught = true;
406
+ })
407
+ ->timeoutIn(0.1)
408
+ ->send();
409
+ } catch (\Httpful\Exception\ConnectionErrorException $e) {}
410
+
411
+ $this->assertTrue($caught);
412
+ }
413
+
414
+ function testBeforeSend() {
415
+ $invoked = false;
416
+ $changed = false;
417
+ $self = $this;
418
+
419
+ try {
420
+ Request::get('malformed://url')
421
+ ->beforeSend(function($request) use(&$invoked,$self) {
422
+ $self->assertEquals('malformed://url', $request->uri);
423
+ $self->assertEquals('A payload', $request->serialized_payload);
424
+ $request->uri('malformed2://url');
425
+ $invoked = true;
426
+ })
427
+ ->whenError(function($error) { /* Be silent */ })
428
+ ->body('A payload')
429
+ ->send();
430
+ } catch (\Httpful\Exception\ConnectionErrorException $e) {
431
+ $this->assertTrue(strpos($e->getMessage(), 'malformed2') !== false);
432
+ $changed = true;
433
+ }
434
+
435
+ $this->assertTrue($invoked);
436
+ $this->assertTrue($changed);
437
+ }
438
+
439
+ function test_parseCode()
440
+ {
441
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
442
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
443
+ $code = $response->_parseCode("HTTP/1.1 406 Not Acceptable\r\n");
444
+ $this->assertEquals(406, $code);
445
+ }
446
+
447
+ function testToString()
448
+ {
449
+ $req = Request::init()->sendsAndExpects(Mime::JSON);
450
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
451
+ $this->assertEquals(self::SAMPLE_JSON_RESPONSE, (string)$response);
452
+ }
453
+
454
+ function test_parseHeaders()
455
+ {
456
+ $parse_headers = Response\Headers::fromString(self::SAMPLE_JSON_HEADER);
457
+ $this->assertCount(3, $parse_headers);
458
+ $this->assertEquals('application/json', $parse_headers['Content-Type']);
459
+ $this->assertTrue(isset($parse_headers['Connection']));
460
+ }
461
+
462
+ function testMultiHeaders()
463
+ {
464
+ $req = Request::init();
465
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_MULTI_HEADER, $req);
466
+ $parse_headers = $response->_parseHeaders(self::SAMPLE_MULTI_HEADER);
467
+ $this->assertEquals('Value1,Value2', $parse_headers['X-My-Header']);
468
+ }
469
+
470
+ function testDetectContentType()
471
+ {
472
+ $req = Request::init();
473
+ $response = new Response(self::SAMPLE_JSON_RESPONSE, self::SAMPLE_JSON_HEADER, $req);
474
+ $this->assertEquals('application/json', $response->headers['Content-Type']);
475
+ }
476
+
477
+ function testMissingBodyContentType()
478
+ {
479
+ $body = 'A string';
480
+ $request = Request::post(HttpfulTest::TEST_URL, $body)->_curlPrep();
481
+ $this->assertEquals($body, $request->serialized_payload);
482
+ }
483
+
484
+ function testParentType()
485
+ {
486
+ // Parent type
487
+ $request = Request::init()->sendsAndExpects(Mime::XML);
488
+ $response = new Response('<xml><name>Nathan</name></xml>', self::SAMPLE_VENDOR_HEADER, $request);
489
+
490
+ $this->assertEquals("application/xml", $response->parent_type);
491
+ $this->assertEquals(self::SAMPLE_VENDOR_TYPE, $response->content_type);
492
+ $this->assertTrue($response->is_mime_vendor_specific);
493
+
494
+ // Make sure we still parsed as if it were plain old XML
495
+ $this->assertEquals("Nathan", $response->body->name->__toString());
496
+ }
497
+
498
+ function testMissingContentType()
499
+ {
500
+ // Parent type
501
+ $request = Request::init()->sendsAndExpects(Mime::XML);
502
+ $response = new Response('<xml><name>Nathan</name></xml>',
503
+ "HTTP/1.1 200 OK
504
+ Connection: keep-alive
505
+ Transfer-Encoding: chunked\r\n", $request);
506
+
507
+ $this->assertEquals("", $response->content_type);
508
+ }
509
+
510
+ function testCustomMimeRegistering()
511
+ {
512
+ // Register new mime type handler for "application/vnd.nategood.message+xml"
513
+ Httpful::register(self::SAMPLE_VENDOR_TYPE, new DemoMimeHandler());
514
+
515
+ $this->assertTrue(Httpful::hasParserRegistered(self::SAMPLE_VENDOR_TYPE));
516
+
517
+ $request = Request::init();
518
+ $response = new Response('<xml><name>Nathan</name></xml>', self::SAMPLE_VENDOR_HEADER, $request);
519
+
520
+ $this->assertEquals(self::SAMPLE_VENDOR_TYPE, $response->content_type);
521
+ $this->assertEquals('custom parse', $response->body);
522
+ }
523
+
524
+ public function testShorthandMimeDefinition()
525
+ {
526
+ $r = Request::init()->expects('json');
527
+ $this->assertEquals(Mime::JSON, $r->expected_type);
528
+
529
+ $r = Request::init()->expectsJson();
530
+ $this->assertEquals(Mime::JSON, $r->expected_type);
531
+ }
532
+
533
+ public function testOverrideXmlHandler()
534
+ {
535
+ // Lazy test...
536
+ $prev = \Httpful\Httpful::get(\Httpful\Mime::XML);
537
+ $this->assertEquals($prev, new \Httpful\Handlers\XmlHandler());
538
+ $conf = array('namespace' => 'http://example.com');
539
+ \Httpful\Httpful::register(\Httpful\Mime::XML, new \Httpful\Handlers\XmlHandler($conf));
540
+ $new = \Httpful\Httpful::get(\Httpful\Mime::XML);
541
+ $this->assertNotEquals($prev, $new);
542
+ }
543
+
544
+ public function testHasProxyWithoutProxy()
545
+ {
546
+ $r = Request::get('someUrl');
547
+ $this->assertFalse($r->hasProxy());
548
+ }
549
+
550
+ public function testHasProxyWithProxy()
551
+ {
552
+ $r = Request::get('some_other_url');
553
+ $r->useProxy('proxy.com');
554
+ $this->assertTrue($r->hasProxy());
555
+ }
556
+
557
+ public function testParseJSON()
558
+ {
559
+ $handler = new JsonHandler();
560
+
561
+ $bodies = array(
562
+ 'foo',
563
+ array(),
564
+ array('foo', 'bar'),
565
+ null
566
+ );
567
+ foreach ($bodies as $body) {
568
+ $this->assertEquals($body, $handler->parse(json_encode($body)));
569
+ }
570
+
571
+ try {
572
+ $result = $handler->parse('invalid{json');
573
+ } catch(\Exception $e) {
574
+ $this->assertEquals('Unable to parse response as JSON', $e->getMessage());
575
+ return;
576
+ }
577
+ $this->fail('Expected an exception to be thrown due to invalid json');
578
+ }
579
+
580
+ // /**
581
+ // * Skeleton for testing against the 5.4 baked in server
582
+ // */
583
+ // public function testLocalServer()
584
+ // {
585
+ // if (!defined('WITHOUT_SERVER') || (defined('WITHOUT_SERVER') && !WITHOUT_SERVER)) {
586
+ // // PHP test server seems to always set content type to application/octet-stream
587
+ // // so force parsing as JSON here
588
+ // Httpful::register('application/octet-stream', new \Httpful\Handlers\JsonHandler());
589
+ // $response = Request::get(TEST_SERVER . '/test.json')
590
+ // ->sendsAndExpects(MIME::JSON);
591
+ // $response->send();
592
+ // $this->assertTrue(...);
593
+ // }
594
+ // }
595
+ }
596
+
597
+ class DemoMimeHandler extends \Httpful\Handlers\MimeHandlerAdapter
598
+ {
599
+ public function parse($body)
600
+ {
601
+ return 'custom parse';
602
+ }
603
+ }
604
+
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/Httpful/requestTest.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @author nick fox <quixand gmail com>
4
+ */
5
+ namespace Httpful\Test;
6
+
7
+ class requestTest extends \PHPUnit_Framework_TestCase
8
+ {
9
+
10
+ /**
11
+ * @author Nick Fox
12
+ * @expectedException Httpful\Exception\ConnectionErrorException
13
+ * @expectedExceptionMessage Unable to connect
14
+ */
15
+ public function testGet_InvalidURL()
16
+ {
17
+ // Silence the default logger via whenError override
18
+ \Httpful\Request::get('unavailable.url')->whenError(function($error) {})->send();
19
+ }
20
+
21
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/bootstrap-server.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $php_version = phpversion();
4
+ $php_major = floatval(substr($php_version, 0, 3));
5
+
6
+ // Define SIGKILL if pcntl is not found
7
+ if (!function_exists('pcntl_signal')) {
8
+ define('SIGKILL', 9);
9
+ }
10
+
11
+ if ($php_major < 5.4) {
12
+ define('WITHOUT_SERVER', true);
13
+ } else {
14
+ // Command that starts the built-in web server
15
+ $command = sprintf('php -S %s:%d -t %s >./server.log 2>&1 & echo $!', WEB_SERVER_HOST, WEB_SERVER_PORT, WEB_SERVER_DOCROOT);
16
+
17
+ // Execute the command and store the process ID
18
+ $output = array();
19
+ exec($command, $output, $exit_code);
20
+
21
+ // sleep for a second to let server come up
22
+ sleep(1);
23
+ $pid = (int) $output[0];
24
+
25
+ // check server.log to see if it failed to start
26
+ $server_logs = file_get_contents("./server.log");
27
+ if (strpos($server_logs, "Fail") !== false) {
28
+ // server failed to start for some reason
29
+ print "Failed to start server! Logs:" . PHP_EOL . PHP_EOL;
30
+ print_r($server_logs);
31
+ exit(1);
32
+ }
33
+
34
+ echo sprintf('%s - Web server started on %s:%d with PID %d', date('r'), WEB_SERVER_HOST, WEB_SERVER_PORT, $pid) . PHP_EOL;
35
+
36
+ register_shutdown_function(function() {
37
+ // cleanup after ourselves -- remove log file, shut down server
38
+ global $pid;
39
+ unlink("./server.log");
40
+ posix_kill($pid, SIGKILL);
41
+ });
42
+ }
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/phpunit.xml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <phpunit bootstrap="./bootstrap-server.php">
2
+ <testsuites>
3
+ <testsuite name="Httpful">
4
+ <directory>.</directory>
5
+ </testsuite>
6
+ </testsuites>
7
+ <php>
8
+ <const name="WEB_SERVER_HOST" value="localhost" />
9
+ <const name="WEB_SERVER_PORT" value="1349" />
10
+ <const name="WEB_SERVER_DOCROOT" value="./static" />
11
+ </php>
12
+ <logging>
13
+ <log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
14
+ </logging>
15
+ </phpunit>
16
+
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/static/test.json ADDED
@@ -0,0 +1 @@
 
1
+ {"foo": "bar", "baz": false}
app/code/community/EMailChef/EMailChefSync/lib/emailchef/vendor/nategood/httpful/tests/test_image.jpg ADDED
Binary file
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-install-0.1.0.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ //do not remove this line
4
+
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-install-2.3.0.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Install.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ $installer->run('CREATE TABLE IF NOT EXISTS `emailchef_filter_hints` (
9
+ `filter_name` varchar(255) collate utf8_unicode_ci NOT NULL,
10
+ `hints` varchar(255) collate utf8_unicode_ci NOT NULL,
11
+ PRIMARY KEY (`filter_name`)
12
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
13
+
14
+ $installer->run("DROP TABLE IF EXISTS {$installer->getTable('emailchef/sync')};
15
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/sync')} (
16
+ `store_id` int(11) DEFAULT NULL,
17
+ `customer_id` int(11) NOT NULL,
18
+ `entity` varchar(100) NOT NULL,
19
+ `job_id` int(11) NOT NULL,
20
+ `needs_sync` tinyint(1) DEFAULT 1,
21
+ `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
22
+ `last_sync` datetime NULL,
23
+ PRIMARY KEY (`customer_id`, `entity`, `job_id`)
24
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
25
+
26
+ $installer->run("
27
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/job')};
28
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/job')} (
29
+ `id` int(11) NOT NULL AUTO_INCREMENT,
30
+ `store_id` int(11) DEFAULT NULL,
31
+ `emailchefgroupid` int(11) NOT NULL,
32
+ `status` varchar(20) NOT NULL,
33
+ `queue_datetime` datetime NOT NULL,
34
+ `start_datetime` datetime,
35
+ `finish_datetime` datetime,
36
+ PRIMARY KEY (`id`)
37
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
38
+
39
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-install-2.4.0.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Install.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ $installer->run('
9
+ CREATE TABLE IF NOT EXISTS `emailchef_filter_hints` (
10
+ `filter_name` varchar(255) collate utf8_unicode_ci NOT NULL,
11
+ `hints` varchar(255) collate utf8_unicode_ci NOT NULL,
12
+ PRIMARY KEY (`filter_name`)
13
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
14
+ /*
15
+ * Install jobs Table
16
+ */
17
+ $installer->run("
18
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/job')};
19
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/job')} (
20
+ `id` int(11) NOT NULL AUTO_INCREMENT,
21
+ `store_id` int(11) DEFAULT NULL,
22
+ `emailchefgroupid` int(11) DEFAULT NULL,
23
+ `list_id` int(11) DEFAULT NULL,
24
+ `list_guid` varchar(255) DEFAULT NULL,
25
+ `status` varchar(20) NOT NULL,
26
+ `process_id` INT UNSIGNED DEFAULT NULL,
27
+ `tries` INT UNSIGNED DEFAULT 0,
28
+ `type` INT UNSIGNED DEFAULT 0,
29
+ `queue_datetime` datetime NOT NULL,
30
+ `start_datetime` datetime,
31
+ `finish_datetime` datetime,
32
+ PRIMARY KEY (`id`)
33
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;");
34
+ /*
35
+ * Install Job Sync Tasks
36
+ */
37
+ $installer->run("
38
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/sync')};
39
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/sync')} (
40
+ `id` int (11) NOT NULL AUTO_INCREMENT,
41
+ `store_id` int(11) DEFAULT NULL,
42
+ `customer_id` int(11) NOT NULL,
43
+ `entity` varchar(100) NOT NULL,
44
+ `job_id` int(11) NOT NULL,
45
+ `needs_sync` tinyint(1) DEFAULT 1,
46
+ `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
47
+ `last_sync` datetime NULL,
48
+ PRIMARY KEY (`id`),
49
+ UNIQUE KEY uniq_key (`customer_id`,`entity`,`job_id`, `store_id`)
50
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
51
+ /*
52
+ * Install Log Table
53
+ */
54
+ $this->run("
55
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/log')};
56
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/log')} (
57
+ `id` int(11) NOT NULL AUTO_INCREMENT,
58
+ `store_id` int(11) DEFAULT NULL,
59
+ `job_id` int(11) DEFAULT NULL,
60
+ `type` varchar(20) NOT NULL,
61
+ `status` varchar(20) NOT NULL,
62
+ `data` TEXT DEFAULT NULL,
63
+ `event_time` datetime NOT NULL,
64
+ PRIMARY KEY (`id`)
65
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
66
+
67
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-0.1.0-1.0.0.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+
3
+ //do not remove this line
4
+
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-0.3.0-1.0.0.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+
5
+ $this->run('CREATE TABLE IF NOT EXISTS `emailchef_filter_hints` (
6
+ `filter_name` varchar(255) collate utf8_unicode_ci NOT NULL,
7
+ `hints` varchar(255) collate utf8_unicode_ci NOT NULL,
8
+ PRIMARY KEY (`filter_name`)
9
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
10
+
11
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-1.0.0-1.5.2.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+
5
+ $this->run('CREATE TABLE IF NOT EXISTS `emailchef_fields_mapping` (
6
+ `magento_field_name` varchar(255) collate utf8_unicode_ci NOT NULL,
7
+ `emailchef_field_id` int(11) NOT NULL,
8
+ PRIMARY KEY (`magento_field_name`, `emailchef_field_id`)
9
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
10
+
11
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.1.3-2.2.0.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+
5
+ $this->run('CREATE TABLE IF NOT EXISTS `emailchef_sync` (
6
+ `customer_id` int(11) NOT NULL,
7
+ `entity` varchar(100) NOT NULL,
8
+ `job_id` int(11) NOT NULL,
9
+ `needs_sync` tinyint(1) NOT NULL,
10
+ `last_sync` datetime NULL,
11
+ PRIMARY KEY (`customer_id`,`entity`,`job_id`)
12
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
13
+
14
+ $this->run('CREATE TABLE IF NOT EXISTS `emailchef_sync_jobs` (
15
+ `id` int(11) NOT NULL AUTO_INCREMENT,
16
+ `emailchefgroupid` int(11) NOT NULL,
17
+ `status` varchar(20) NOT NULL,
18
+ `queue_datetime` datetime NOT NULL,
19
+ `start_datetime` datetime,
20
+ `finish_datetime` datetime,
21
+ PRIMARY KEY (`id`)
22
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;');
23
+
24
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.2.0-2.3.0.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+
5
+ /*$this->run("
6
+ ALTER TABLE emailchef_sync_jobs
7
+ ADD `store_id` INT UNSIGNED DEFAULT NULL;
8
+ ");
9
+
10
+ $this->run("
11
+ ALTER TABLE emailchef_sync
12
+ ADD `store_id` INT UNSIGNED DEFAULT NULL;
13
+ ");*/
14
+
15
+ $this->run('DROP TABLE IF EXISTS emailchef_filter_hints;
16
+ CREATE TABLE IF NOT EXISTS `emailchef_filter_hints` (
17
+ `filter_name` varchar(255) collate utf8_unicode_ci NOT NULL,
18
+ `hints` varchar(255) collate utf8_unicode_ci NOT NULL,
19
+ PRIMARY KEY (`filter_name`)
20
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
21
+
22
+ $this->run('DROP TABLE IF EXISTS emailchef_sync;
23
+ CREATE TABLE IF NOT EXISTS `emailchef_sync` (
24
+ `store_id` int(11) DEFAULT NULL,
25
+ `customer_id` int(11) NOT NULL,
26
+ `entity` varchar(100) NOT NULL,
27
+ `job_id` int(11) NOT NULL,
28
+ `needs_sync` tinyint(1) NOT NULL,
29
+ `last_sync` datetime NULL,
30
+ PRIMARY KEY (`customer_id`,`entity`,`job_id`)
31
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
32
+
33
+ $this->run('
34
+ DROP TABLE IF EXISTS emailchef_sync_jobs;
35
+ CREATE TABLE IF NOT EXISTS `emailchef_sync_jobs` (
36
+ `id` int(11) NOT NULL AUTO_INCREMENT,
37
+ `store_id` int(11) DEFAULT NULL,
38
+ `emailchefgroupid` int(11) NOT NULL,
39
+ `status` varchar(20) NOT NULL,
40
+ `queue_datetime` datetime NOT NULL,
41
+ `start_datetime` datetime,
42
+ `finish_datetime` datetime,
43
+ PRIMARY KEY (`id`)
44
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;');
45
+
46
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.2.1-2.3.0.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+
5
+ /*$this->run("
6
+ ALTER TABLE emailchef_sync_jobs
7
+ ADD `store_id` INT UNSIGNED DEFAULT NULL;
8
+ ");
9
+
10
+ $this->run("
11
+ ALTER TABLE emailchef_sync
12
+ ADD `store_id` INT UNSIGNED DEFAULT NULL;
13
+ ");*/
14
+
15
+ $this->run('DROP TABLE IF EXISTS emailchef_filter_hints;
16
+ CREATE TABLE IF NOT EXISTS `emailchef_filter_hints` (
17
+ `filter_name` varchar(255) collate utf8_unicode_ci NOT NULL,
18
+ `hints` varchar(255) collate utf8_unicode_ci NOT NULL,
19
+ PRIMARY KEY (`filter_name`)
20
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
21
+
22
+ $this->run('DROP TABLE IF EXISTS emailchef_sync;
23
+ CREATE TABLE IF NOT EXISTS `emailchef_sync` (
24
+ `store_id` int(11) DEFAULT NULL,
25
+ `customer_id` int(11) NOT NULL,
26
+ `entity` varchar(100) NOT NULL,
27
+ `job_id` int(11) NOT NULL,
28
+ `needs_sync` tinyint(1) NOT NULL,
29
+ `last_sync` datetime NULL,
30
+ PRIMARY KEY (`customer_id`,`entity`,`job_id`)
31
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
32
+
33
+ $this->run('
34
+ DROP TABLE IF EXISTS emailchef_sync_jobs;
35
+ CREATE TABLE IF NOT EXISTS `emailchef_sync_jobs` (
36
+ `id` int(11) NOT NULL AUTO_INCREMENT,
37
+ `store_id` int(11) DEFAULT NULL,
38
+ `emailchefgroupid` int(11) NOT NULL,
39
+ `status` varchar(20) NOT NULL,
40
+ `queue_datetime` datetime NOT NULL,
41
+ `start_datetime` datetime,
42
+ `finish_datetime` datetime,
43
+ PRIMARY KEY (`id`)
44
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;');
45
+
46
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.3.0-2.3.1.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+ $installer = $this;
5
+ /*
6
+ * We want to record the process id, and the number of attempts we've made at
7
+ * processing the job!
8
+ */
9
+ $this->run("
10
+ ALTER TABLE {$installer->getTable('emailchef/job')}
11
+ ADD `process_id` INT UNSIGNED DEFAULT NULL,
12
+ ADD `tries` INT UNSIGNED DEFAULT 0;
13
+ ");
14
+
15
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.3.1-2.3.2.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $this->startSetup();
4
+ $installer = $this;
5
+
6
+ /*
7
+ * Add Job Type
8
+ */
9
+ $this->run("
10
+ ALTER TABLE {$installer->getTable('emailchef/job')}
11
+ ADD `type` INT UNSIGNED DEFAULT 0;
12
+ ");
13
+ /*
14
+ * Need a Simple Key to allow us to utilise the grid.
15
+ */
16
+ $this->run("
17
+ ALTER TABLE {$installer->getTable('emailchef/sync')}
18
+ ADD column id int (11) NOT NULL AUTO_INCREMENT,
19
+ DROP PRIMARY KEY,
20
+ ADD PRIMARY KEY (id),
21
+ ADD UNIQUE KEY uniq_key (`customer_id`,`entity`,`job_id`, `store_id`);
22
+ ");
23
+ /*
24
+ * Install Log Table
25
+ */
26
+ $this->run("
27
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/log')};
28
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/log')} (
29
+ `id` int(11) NOT NULL AUTO_INCREMENT,
30
+ `store_id` int(11) DEFAULT NULL,
31
+ `job_id` int(11) DEFAULT NULL,
32
+ `type` varchar(20) NOT NULL,
33
+ `status` varchar(20) NOT NULL,
34
+ `data` TEXT DEFAULT NULL,
35
+ `event_time` datetime NOT NULL,
36
+ PRIMARY KEY (`id`)
37
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
38
+
39
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.3.2-2.4.0.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Install.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ $installer->run('
9
+ CREATE TABLE IF NOT EXISTS `emailchef_filter_hints` (
10
+ `filter_name` varchar(255) collate utf8_unicode_ci NOT NULL,
11
+ `hints` varchar(255) collate utf8_unicode_ci NOT NULL,
12
+ PRIMARY KEY (`filter_name`)
13
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;');
14
+ /*
15
+ * Install jobs Table
16
+ */
17
+ $installer->run("
18
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/job')};
19
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/job')} (
20
+ `id` int(11) NOT NULL AUTO_INCREMENT,
21
+ `store_id` int(11) DEFAULT NULL,
22
+ `emailchefgroupid` int(11) DEFAULT NULL,
23
+ `list_id` int(11) DEFAULT NULL,
24
+ `list_guid` varchar(255) DEFAULT NULL,
25
+ `status` varchar(20) NOT NULL,
26
+ `process_id` INT UNSIGNED DEFAULT NULL,
27
+ `tries` INT UNSIGNED DEFAULT 0,
28
+ `type` INT UNSIGNED DEFAULT 0,
29
+ `queue_datetime` datetime NOT NULL,
30
+ `start_datetime` datetime,
31
+ `finish_datetime` datetime,
32
+ PRIMARY KEY (`id`)
33
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;");
34
+ /*
35
+ * Install Job Sync Tasks
36
+ */
37
+ $installer->run("
38
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/sync')};
39
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/sync')} (
40
+ `id` int (11) NOT NULL AUTO_INCREMENT,
41
+ `store_id` int(11) DEFAULT NULL,
42
+ `customer_id` int(11) NOT NULL,
43
+ `entity` varchar(100) NOT NULL,
44
+ `job_id` int(11) NOT NULL,
45
+ `needs_sync` tinyint(1) DEFAULT 1,
46
+ `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
47
+ `last_sync` datetime NULL,
48
+ PRIMARY KEY (`id`),
49
+ UNIQUE KEY uniq_key (`customer_id`,`entity`,`job_id`, `store_id`)
50
+ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
51
+ /*
52
+ * Install Log Table
53
+ */
54
+ $this->run("
55
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/log')};
56
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/log')} (
57
+ `id` int(11) NOT NULL AUTO_INCREMENT,
58
+ `store_id` int(11) DEFAULT NULL,
59
+ `job_id` int(11) DEFAULT NULL,
60
+ `type` varchar(20) NOT NULL,
61
+ `status` varchar(20) NOT NULL,
62
+ `data` TEXT DEFAULT NULL,
63
+ `event_time` datetime NOT NULL,
64
+ PRIMARY KEY (`id`)
65
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
66
+
67
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.4.0-2.4.1.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Install.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ /*
9
+ * Install Job Sync Tasks
10
+ *
11
+ * Change to InnoDB, and add in Foreign Key
12
+ */
13
+ $installer->run("
14
+ DROP TABLE IF EXISTS {$installer->getTable('emailchef/sync')};
15
+ CREATE TABLE IF NOT EXISTS {$installer->getTable('emailchef/sync')} (
16
+ `id` int (11) NOT NULL AUTO_INCREMENT,
17
+ `store_id` int(11) DEFAULT NULL,
18
+ `customer_id` int(11) NOT NULL,
19
+ `entity` varchar(100) NOT NULL,
20
+ `job_id` int(11) NOT NULL,
21
+ `needs_sync` tinyint(1) DEFAULT 1,
22
+ `created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
23
+ `last_sync` datetime NULL,
24
+ PRIMARY KEY (`id`),
25
+ UNIQUE KEY uniq_key (`customer_id`,`entity`,`job_id`, `store_id`),
26
+ INDEX `fk_jobs_idx` (`job_id` ASC),
27
+ CONSTRAINT `fk_jobs`
28
+ FOREIGN KEY (`job_id`)
29
+ REFERENCES {$installer->getTable('emailchef/job')} (`id`)
30
+ ON DELETE CASCADE
31
+ ON UPDATE NO ACTION
32
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;");
33
+
34
+ $this->endSetup();
app/code/community/EMailChef/EMailChefSync/sql/emailchef_setup/mysql4-upgrade-2.6.1-2.7.0.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Install.
4
+ */
5
+ $installer = $this;
6
+ $this->startSetup();
7
+
8
+ $this->endSetup();
app/design/adminhtml/default/default/layout/emailchef.xml ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+
4
+ <emailchef_adminhtml_emailchefbackend_index>
5
+ <reference name="content">
6
+ <!-- <block type="emailchef/adminhtml_emailchefbackend" name="emailchefbackend" template="emailchef/emailchefbackend.phtml"/>-->
7
+
8
+ <block type="emailchef/adminhtml_emailchefbackend" name="emailchefbackend" />
9
+ </reference>
10
+ </emailchef_adminhtml_emailchefbackend_index>
11
+
12
+ <emailchef_adminhtml_sync_index>
13
+ <reference name="content">
14
+ <block type="emailchef/adminhtml_sync" name="sync" />
15
+ </reference>
16
+ </emailchef_adminhtml_sync_index>
17
+
18
+ <emailchef_adminhtml_log_index>
19
+ <reference name="content">
20
+ <block type="emailchef/adminhtml_log" name="emailchef_log" />
21
+ </reference>
22
+ </emailchef_adminhtml_log_index>
23
+
24
+ <emailchef_adminhtml_filter_index>
25
+ <update handle="emailchef_adminhtml_index"/>
26
+ <reference name="content">
27
+ <block type="emailchef/filters" name="filter" template="emailchef/emailchefsync/filter.phtml"/>
28
+ </reference>
29
+ <reference name="head">
30
+ <action method="addCss"><stylesheet>emailchef/emailchefsync/emailchef.css</stylesheet></action>
31
+ </reference>
32
+ </emailchef_adminhtml_filter_index>
33
+
34
+ <emailchef_adminhtml_filter_confirm>
35
+ <update handle="emailchef_adminhtml_confirm"/>
36
+ <reference name="content">
37
+ <block type="adminhtml/template" name="filter" template="emailchef/emailchefsync/confirm.phtml"/>
38
+ </reference>
39
+ <reference name="head">
40
+ <action method="addCss"><stylesheet>emailchef/emailchefsync/emailchef.css</stylesheet></action>
41
+ </reference>
42
+ </emailchef_adminhtml_filter_confirm>
43
+
44
+ <emailchef_adminhtml_fieldsmapping_index>
45
+ <update handle="emailchef_adminhtml_index" />
46
+ <reference name="content">
47
+ <block type="adminhtml/template" name="fieldsmapping" template="emailchef/emailchefsync/fieldsmapping.phtml" />
48
+ </reference>
49
+ <reference name="head">
50
+ <action method="addCss"><stylesheet>emailchef/emailchefsync/emailchef.css</stylesheet></action>
51
+ </reference>
52
+ </emailchef_adminhtml_fieldsmapping_index>
53
+
54
+ <emailchef_adminhtml_viewdatatransferlog_index>
55
+ <update handle="emailchef_adminhtml_index" />
56
+ <reference name="content">
57
+ <block type="adminhtml/template" name="viewdatatransferlog" template="emailchef/emailchefsync/viewdatatransferlog.phtml" />
58
+ </reference>
59
+ <reference name="head">
60
+ <action method="addCss"><stylesheet>emailchef/emailchefsync/emailchef.css</stylesheet></action>
61
+ </reference>
62
+ </emailchef_adminhtml_viewdatatransferlog_index>
63
+
64
+ <emailchef_adminhtml_viewdatatransferlog_search>
65
+ <update handle="emailchef_adminhtml_index" />
66
+ <reference name="content">
67
+ <block type="adminhtml/template" name="viewdatatransferlog" template="emailchef/emailchefsync/viewdatatransferlog.phtml" />
68
+ </reference>
69
+ <reference name="head">
70
+ <action method="addCss"><stylesheet>emailchef/emailchefsync/emailchef.css</stylesheet></action>
71
+ </reference>
72
+ </emailchef_adminhtml_viewdatatransferlog_search>
73
+
74
+ <adminhtml_system_config_edit>
75
+ <reference name="head">
76
+ <action method="addJs"><stylesheet>emailchef/admin.js</stylesheet></action>
77
+ </reference>
78
+ <reference name="content">
79
+ <block type="adminhtml/template" name="emailchefsysconfigjavascript" template="emailchef/emailchefsync/sysconfigjavascript.phtml" />
80
+ </reference>
81
+ </adminhtml_system_config_edit>
82
+
83
+
84
+ <!-- works but need a better image.. -->
85
+ <!--<default>
86
+ <reference name="head">
87
+ <action method="addCss"><stylesheet>emailchef/emailchefsync/emailchef.css</stylesheet></action>
88
+ </reference>
89
+ </default>-->
90
+
91
+ </layout>
app/design/adminhtml/default/default/template/emailchef/emailchefsync/confirm.phtml ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * confirm.phtml
4
+ */
5
+ $storeId = $this->getRequest()->getParam('store_id');
6
+ if(empty($storeId)) {
7
+ $storeId = NULL; //Mage::app()->getDefaultStoreView()->getStoreId();
8
+ }
9
+
10
+ $wsSend = new EMailChefWsSend($storeId); /** @todo add in storeID, use session.. not needed really here... **/
11
+ $accessKey = $wsSend->loginFromId();
12
+
13
+ //ottengo l'elenco delle liste e dei gruppi da emailchef
14
+ $wsImport = new EMailChefWsImport($storeId);
15
+
16
+ $customersFiltered = $wsImport->getCustomersFiltered($this, $storeId);
17
+
18
+ $lists = $wsImport->GetNlList($accessKey,true);
19
+ ?>
20
+
21
+ <?php //creo il form nascosto per passare i parametri al tasto back ?>
22
+ <form id="back_form" name="back_form" method="post" action="<?php echo $this->getUrl('*/*/'); ?>">
23
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
24
+ <input type="hidden" name="store_id" value="<?php echo $this->getRequest()->getParam('store_id'); ?>" />
25
+ <input type="hidden" name="emailchefCustomers" value="<?php echo $this->getRequest()->getParam('emailchefCustomers'); ?>" />
26
+ <input type="hidden" name="emailchefProductSku" value="<?php echo $this->getRequest()->getParam('emailchefProductSku'); ?>" />
27
+ <input type="hidden" name="emailchefCategoryId" value="<?php echo $this->getRequest()->getParam('emailchefCategoryId'); ?>" />
28
+ <input type="hidden" name="emailchefCustomerGroupId" value="<?php echo $this->getRequest()->getParam('emailchefCustomerGroupId'); ?>" />
29
+ <input type="hidden" name="emailchefCountry" value="<?php echo $this->getRequest()->getParam('emailchefCountry'); ?>" />
30
+ <input type="hidden" name="emailchefPostCode" value="<?php echo $this->getRequest()->getParam('emailchefPostCode'); ?>" />
31
+ <input type="hidden" name="emailchefCustomerStartDate" value="<?php echo $this->getRequest()->getParam('emailchefCustomerStartDate'); ?>" />
32
+ <input type="hidden" name="emailchefCustomerEndDate" value="<?php echo $this->getRequest()->getParam('emailchefCustomerEndDate'); ?>" />
33
+ <input type="hidden" name="emailchefTotalAmountCond" value="<?php echo $this->getRequest()->getParam('emailchefTotalAmountCond'); ?>" />
34
+ <input type="hidden" name="emailchefTotalAmountValue" value="<?php echo $this->getRequest()->getParam('emailchefTotalAmountValue'); ?>" />
35
+ <input type="hidden" name="emailchefOrderStartDate" value="<?php echo $this->getRequest()->getParam('emailchefOrderStartDate'); ?>" />
36
+ <input type="hidden" name="emailchefOrderEndDate" value="<?php echo $this->getRequest()->getParam('emailchefOrderEndDate'); ?>" />
37
+ <input type="hidden" name="emailchefOrderYesNo" value="<?php echo $this->getRequest()->getParam('emailchefOrderYesNo'); ?>" />
38
+ <input type="hidden" name="emailchefSubscribed" value="<?php echo $this->getRequest()->getParam('emailchefSubscribed'); ?>" />
39
+ </form>
40
+
41
+ <form id="csv_form" name="csv_form" method="post" action="<?php echo $this->getUrl('*/*/csv'); ?>">
42
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
43
+ <input type="hidden" name="store_id" value="<?php echo $this->getRequest()->getParam('store_id'); ?>" />
44
+ <?php
45
+ $countPost = 0;
46
+ $textArea = '';
47
+ $formParams = '';
48
+ $emailchefCustomerIds = array();
49
+ //mi passo gli id di tutti i clienti filtrati
50
+ foreach ($customersFiltered as $i=>$customer) {
51
+ if ($i++ < 25) $textArea .= $customer['email'] . "\n";
52
+ $emailchefCustomerIds[$countPost] = $customer['entity_id'];
53
+ $countPost++;
54
+ }
55
+ //salvo l'array nella sessione
56
+ if ($countPost > 0) {
57
+ Mage::getSingleton('core/session')->setEMailChefCustomerIds($emailchefCustomerIds);
58
+ }
59
+ ?>
60
+ <input name="countPost" type="hidden" value="<?php echo $countPost; ?>" />
61
+ </form>
62
+ <div class="content-header">
63
+ <table cellspacing="0" class="grid-header">
64
+ <tr>
65
+ <td><h3><?php echo $this->__('eMailChef')?></h3></td>
66
+ <td class="a-right">
67
+ <div id="emailchefloading" class="emailchefloading"><?php echo $this->__("Please wait for the next step to load") ?></div>
68
+ <button id="emailchefback" onclick="back_form.submit()" class="scalable back" type="button"><span><?php echo $this->__('Reset filters')?></span></button>
69
+ <button onclick="if (!editForm.validate()){return false;} $$('.content-header-floating').invoke('setStyle', {visibility:'hidden'});document.getElementById('emailchefsend').style.display='none';document.getElementById('emailchefback').style.display='none';document.getElementById('emailchefloading').style.display='block';editForm.submit()"
70
+ class="scalable save" type="button" id="emailchefsend">
71
+ <span><?php echo $this->__('Send to eMailChef')?></span>
72
+ </button>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </div>
77
+ <div class="entry-edit">
78
+ <?php foreach($lists as $list) : ?>
79
+ <?php /* @var $list SimpleXMLElement */ ?>
80
+ <?php $listId = (string) $list->id ?>
81
+ <?php if($listId == Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $storeId)): ?>
82
+ <?php $listName = (string) $list->name ?>
83
+ <?php $idList = (string) $listId ?>
84
+ <?php $listGUID = (string) $listId ?>
85
+ <?php endif ?>
86
+ <?php endforeach ?>
87
+ <?php if (!isset($idList)): ?>
88
+ <h4><?php echo $this->__('There is no list selected in eMailChef config. Please select one.')?></h4>
89
+ <?php else: ?>
90
+ <form id="edit_form" name="edit_form" method="post" action="<?php echo $this->getUrl('*/*/post')?>">
91
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
92
+ <input type="hidden" name="store_id" value="<?php echo $this->getRequest()->getParam('store_id'); ?>" />
93
+ <input name="emailchefIdList" type="hidden" value="<?php echo $idList; ?>" />
94
+ <input name="emailchefListGUID" type="hidden" value="<?php echo $listGUID; ?>" />
95
+
96
+ <h4><span id="spantitle3"><?php echo $this->__('Confirm filtered customers and select eMailChef group')?></span></h4>
97
+ <fieldset id="my-fieldset">
98
+ <table cellspacing="0" class="form-list">
99
+ <tr>
100
+ <td colspan="2"><h4><?php echo $this->__('Were found')?> <strong><?php echo $countPost; ?></strong> <?php echo $this->__('records')?></h4></td>
101
+ </tr>
102
+ <tr>
103
+ <td><?php echo $this->__('Filtered customers preview')?>:</td>
104
+ </tr>
105
+ <tr>
106
+ <td>
107
+ <textarea name="emailchefCustomerFilteredView" rows="5" cols="50" disabled="disabled" class="txtar1"><?php echo $textArea ?></textarea>
108
+ </td>
109
+ </tr>
110
+ <tr>
111
+ <td colspan="2">
112
+ <?php echo $this->__('Selected list')?>: <strong>
113
+ <?php echo $listName; ?><br /><br /><br />
114
+ </strong></td>
115
+ </tr>
116
+ </table>
117
+
118
+ <table>
119
+ <tr>
120
+ <td>
121
+ <h4><?php echo $this->__('Next step')?></h4>
122
+ </td>
123
+ </tr>
124
+ <tr>
125
+ <td class="label">
126
+ <p class="slgrp1"><?php echo $this->__('Select group')?> <input type="radio" name="emailchefNewGroup" value="0" checked="checked" /></p>
127
+ </td>
128
+ </tr>
129
+ <tr>
130
+ <td class="input-ele">
131
+ <p class="istrz1"><?php echo $this->__('Select an existing group')?>:</p>
132
+ <select class="required-entry slctpg1" name="emailchefGroupId">
133
+ <?php
134
+ $groups = array();
135
+ foreach($lists as $list) {
136
+ if ($list->id == Mage::getStoreConfig('emailchef_newsletter/emailchef/list', $storeId)){
137
+ foreach($list->groups as $group) {
138
+ $groups[(string)$group->id] = (string)$group->name;
139
+ }
140
+ }
141
+ }
142
+ @asort($groups);
143
+ $defaultGroupId = Mage::getStoreConfig('emailchef_newsletter/emailchef/default_group');
144
+ foreach ($groups as $tmpid=>$tmpname) {
145
+ echo '<option value="'.$tmpid.'"';
146
+ // If there is a default group set in config, pre-select this
147
+ if ($tmpid == $defaultGroupId) {
148
+ echo ' selected="selected"';
149
+ }
150
+ echo '>'.htmlspecialchars($tmpname).'</option>';
151
+ }
152
+ ?>
153
+ </select>
154
+ <br /><br />
155
+ </td>
156
+ </tr>
157
+ <tr>
158
+ <td>
159
+ <p class="istrz2"><?php echo $this->__('or')?></p>
160
+ </td>
161
+ </tr>
162
+ <tr>
163
+ <td class="label">
164
+ <p class="slgrp1"><?php echo $this->__('Create new customer group')?> <input type="radio" name="emailchefNewGroup" value="1" /></p>
165
+ </td>
166
+ </tr>
167
+ <tr>
168
+ <td>
169
+ <p class="istrz1"><?php echo $this->__('Group name')?>:</p>
170
+ </td>
171
+ </tr>
172
+ <tr>
173
+ <td>
174
+ <input type="text" name="emailchefNewGroupName" size="60" class="inptptx2" />
175
+ </td>
176
+ </tr>
177
+ </table>
178
+
179
+ </fieldset>
180
+ </form>
181
+ <?php endif; ?>
182
+
183
+ </div>
184
+ <script type="text/javascript">
185
+ var editForm = new varienForm('edit_form');
186
+ </script>
app/design/adminhtml/default/default/template/emailchef/emailchefsync/fieldsmapping.phtml ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @depreciated
4
+ */
5
+ $allmagentofields = array(
6
+ "Name", "Last", "Email", "Company", "Address", "City", "ZIP", "Province", "Region", "Country", "Gender", "DateOfBirth", "CustomerID",
7
+ "Phone", "Fax", "LatestOrderID", "LatestOrderDate", "LatestOrderAmount", "LatestOrderProductIDs", "LatestOrderCategoryIDs",
8
+ "LatestShippedOrderDate", "LatestShippedOrderID", "LatestAbandonedCartDate", "LatestAbandonedCartTotal",
9
+ "LatestAbandonedCartID", "TotalOrdered", "TotalOrderedLast12m", "TotalOrderedLast30d", "AllOrderedProductIDs"
10
+ );
11
+ $wsSend = new EMailChefWsSend();
12
+ $accessKey = $wsSend->loginFromId();
13
+
14
+ if ($accessKey === false) {
15
+ echo $this->__('WARNING: before proceeding you must correctly configure the settings of eMailChef access in System->Configuration->Newsletter->eMailChef');
16
+ } else {
17
+ $wsImport = new EMailChefWsImport();
18
+
19
+ $wsSend = new EMailChefWsSend();
20
+ // campi che arrivano da emailchef
21
+ $wsFields = $wsSend->getFields($accessKey);
22
+ //carico i mapping salvati
23
+ $fields = $wsImport->getFieldsMapping();
24
+ ?>
25
+ <div class="content-header">
26
+ <table cellspacing="0" class="grid-header">
27
+ <tr>
28
+ <td>
29
+ <h3><?php echo $this->__('Fields mapping')?></h3>
30
+ </td>
31
+ <td class="a-right">
32
+ <button onclick="document.forms.saveFieldsMappingForm.submit()" class="scalable save" type="button"><span><?php echo $this->__('Save configuration')?></span></button>
33
+ </td>
34
+ </tr>
35
+ </table>
36
+ </div>
37
+ <p><?php echo $this->__('Associate all Magento fields with eMailChef ones') ?></p>
38
+ <p>&nbsp;</p>
39
+ <div style="font-weight:bold">
40
+ <div style="display:block;float:left;width:180px"><?php echo $this->__("Magento fields") ?></div>
41
+ <div><?php echo $this->__("eMailChef fields") ?></div>
42
+ </div>
43
+ <form name="saveFieldsMappingForm" method="post" action="<?php echo $this->getUrl('*/*/save')?>">
44
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
45
+ <?php foreach ($allmagentofields as $magentofield): ?>
46
+ <div>
47
+ <label for="sl_<?php echo $magentofield ?>" style="display:block;float:left;width:180px;"><?php echo $magentofield ?></label>
48
+ <select name="<?php echo $magentofield ?>" id="sl_<?php echo $magentofield ?>">
49
+ <option value=""></option>
50
+ <?php
51
+ foreach ($wsFields as $nome=>$id) {
52
+ $selected = ($id == $fields[$magentofield]) ? "selected='selected'" : "";
53
+ $nome = htmlspecialchars($nome);
54
+ echo "<option value='$id' $selected>$nome</option>";
55
+ }
56
+ echo '</select>';
57
+ ?>
58
+ </div>
59
+ <?php endforeach; ?>
60
+ </form>
61
+ <?php } ?>
app/design/adminhtml/default/default/template/emailchef/emailchefsync/filter.phtml ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * filter.phtml
4
+ */
5
+ $storeId = $this->getRequest()->getParam('store_id');
6
+ if(empty($storeId)) {
7
+ $storeId = NULL; //Mage::app()->getDefaultStoreView()->getStoreId();
8
+ }
9
+
10
+ $wsSend = new EMailChefWsSend($storeId); /** @todo add in storeID, use session.. not needed really here... **/
11
+ $accessKey = $wsSend->loginFromId();
12
+
13
+ if ($accessKey === false || strlen(Mage::getStoreConfig('emailchef_newsletter/emailchef/list')) < 1) {
14
+ echo $this->__('WARNING: before proceeding you must correctly configure the settings of eMailChef access in System->Configuration->Newsletter->eMailChef');
15
+ } else {
16
+ //controllo se la lista e' stata selezionata correttamente
17
+ $wsImport = new EMailChefWsImport($storeId);
18
+ $emailchefLists = $wsImport->GetNlList($accessKey);
19
+
20
+ //carico i filtri salvati
21
+ $filterHints = $wsImport->getFilterHints();
22
+
23
+ //TODO: sembra inutilizzata
24
+ //chiamata attivazione web services su EMailChef
25
+ //$urlWSActivation = 'http://'.Mage::getStoreConfig('newsletter/emailchef/url_console').'/frontend/WSActivation.aspx?usr='.Mage::getStoreConfig('newsletter/emailchef/user').'&pwd='.Mage::getStoreConfig('newsletter/emailchef/password').'&nl_url='.Mage::getStoreConfig('newsletter/emailchef/url_console').'&ws_name=WSEMailChefImport';
26
+ //fopen($urlWSActivation, 'r');
27
+
28
+ //salvo i parametri in variabili
29
+ $emailchefCustomers = $this->getRequest()->getParam('emailchefCustomers');
30
+ $emailchefProductSku = $this->getRequest()->getParam('emailchefProductSku');
31
+ $emailchefCategoryId = $this->getRequest()->getParam('emailchefCategoryId');
32
+ $emailchefCustomerGroupId = $this->getRequest()->getParam('emailchefCustomerGroupId');
33
+ $emailchefCountry = $this->getRequest()->getParam('emailchefCountry');
34
+ $emailchefPostCode = $this->getRequest()->getParam('emailchefPostCode');
35
+ $emailchefCustomerStartDate = $this->getRequest()->getParam('emailchefCustomerStartDate');
36
+ $emailchefCustomerEndDate = $this->getRequest()->getParam('emailchefCustomerEndDate');
37
+ $emailchefTotalAmountCond = $this->getRequest()->getParam('emailchefTotalAmountCond');
38
+ $emailchefTotalAmountValue = $this->getRequest()->getParam('emailchefTotalAmountValue');
39
+ $emailchefOrderStartDate = $this->getRequest()->getParam('emailchefOrderStartDate');
40
+ $emailchefOrderEndDate = $this->getRequest()->getParam('emailchefOrderEndDate');
41
+ $emailchefOrderYesNo = $this->getRequest()->getParam('emailchefOrderYesNo');
42
+ $emailchefSubscribed = $this->getRequest()->getParam('emailchefSubscribed');
43
+
44
+
45
+ function print_category($category)
46
+ {
47
+ if (is_numeric($category)) {
48
+ $category = Mage::getModel("catalog/category")->load($category);
49
+ }
50
+
51
+ echo '<option value="'.$category->getData('entity_id').'">'.str_repeat("-", $category->getData("level")-2) . htmlspecialchars($category->getData('name')).'</option>';
52
+ $children = $category->getChildren();
53
+ if (!$children) return;
54
+
55
+ $children = explode(",", $children);
56
+ foreach($children as $child) {
57
+ print_category($child);
58
+ }
59
+ }
60
+ ?>
61
+
62
+ <div class="content-header">
63
+ <table cellspacing="0" class="grid-header">
64
+ <tr>
65
+ <td>
66
+ <h3><?php echo $this->__('Filters')?></h3>
67
+ </td>
68
+ <td class="a-right">
69
+ <div id="emailchefloading" class="emailchefloading"><?php echo $this->__("Please wait for the next step to load") ?></div>
70
+ <button onclick="$$('.content-header-floating').invoke('setStyle', {visibility:'hidden'});document.getElementById('emailchefsend').style.display='none';document.getElementById('emailchefloading').style.display='block';editForm.submit();" class="scalable save" type="button" id="emailchefsend">
71
+ <div class="emailchefloading"></div><span><?php echo $this->__('Apply filter')?></span>
72
+ </button>
73
+ </td>
74
+ </tr>
75
+ </table>
76
+ </div>
77
+
78
+ <div class="entry-edit">
79
+ <form id="edit_form" name="edit_form" method="post" action="<?php echo $this->getUrl('*/*/confirm')?>">
80
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
81
+
82
+ <input name="filter_name" id="filter_name" type="hidden" value="" />
83
+
84
+ <p id="spansugger"><a href="#ottsugg"><?php echo $this->__('Get hints')?> &rArr;</a></p>
85
+ <fieldset id="my-fieldset">
86
+ <table cellspacing="0" class="form-list">
87
+ <tr>
88
+ <td colspan="3"><?php echo $this->__('By this plugin you can import contacts registered in your eCommerce in the eMailChef platform.')?></td>
89
+ </tr>
90
+ </tr>
91
+ <tr>
92
+ <td colspan="3">&nbsp;</td>
93
+ </tr>
94
+ <tr>
95
+ <td>
96
+ <strong><?php echo $this->__('Store')?></strong>
97
+ </td>
98
+ <td colspan="2">
99
+ <select name="store_id">
100
+ <?php foreach($this->_getStoresArray() as $store): ?>
101
+ <option value="<?php echo $store['id'] ?>">
102
+ <?php echo $store['name'] ?>
103
+ </option>
104
+ <?php endforeach ?>
105
+ </select>
106
+ </td>
107
+ </tr>
108
+ <tr>
109
+ <td colspan="3">&nbsp;</td>
110
+ </tr>
111
+ <tr>
112
+ <td colspan="3">
113
+ <strong><?php echo $this->__('Sold products')?></strong>
114
+ </td>
115
+ </tr>
116
+ <?php // Customer filter : 0 = all , 1 = who bought , 2 = who have never purchased ?>
117
+ <tr>
118
+ <td class="input-ele spdnpg1">
119
+ <input type="radio" name="emailchefCustomers" id="emailchefCustomersAll" value="0" <?php if (!isset($emailchefCustomers) || (isset($emailchefCustomers) && $emailchefCustomers == 0)) { echo 'checked="checked"'; } ?>
120
+ onclick="customerDependentFilters(false);" />&nbsp;<label for="emailchefCustomersAll"><?php echo $this->__('All customers')?></label>
121
+ </td>
122
+
123
+ <td class="input-ele spdnpg1">
124
+ <input type="radio" name="emailchefCustomers" id="emailchefCustomersWhoHaveBought" value="1" <?php if (isset($emailchefCustomers) && $emailchefCustomers == 1) { echo 'checked="checked"'; } ?>
125
+ onclick="customerDependentFilters(false);" />&nbsp;<label for="emailchefCustomersWhoHaveBought"><?php echo $this->__('Customers who have purchased')?></label>
126
+ </td>
127
+
128
+ <td class="input-ele spdnpg1">
129
+ <input type="radio" name="emailchefCustomers" id="emailchefCustomersWhoHaventBought" value="2" <?php if (isset($emailchefCustomers) && $emailchefCustomers == 2) { echo 'checked="checked"'; } ?>
130
+ onclick="customerDependentFilters(true);" />&nbsp;<label for="emailchefCustomersWhoHaventBought"><?php echo $this->__("Customers who have not purchased")?></label>
131
+ </td>
132
+ </tr>
133
+ <tr>
134
+ <td colspan="3">
135
+ <strong><?php echo $this->__('Opt-in Status')?></strong>
136
+ </td>
137
+ </tr>
138
+ <tr>
139
+ <td>
140
+ <input type="radio" name="emailchefSubscribed" id="emailchefSubscribedAllCustomers"
141
+ value="0" <?php if (!isset($emailchefSubscribed) || (isset($emailchefSubscribed) && $emailchefSubscribed == 0)) { echo 'checked="checked"'; } ?> />&nbsp;<label for="emailchefSubscribedAllCustomers"><?php echo $this->__("All customers")?></label>
142
+ </td>
143
+ <td>
144
+ <input type="radio" name="emailchefSubscribed" id="emailchefSubscribedOptIn"
145
+ value="1" <?php if (isset($emailchefSubscribed) && $emailchefSubscribed == 1) { echo 'checked="checked"'; } ?> />&nbsp;<label for="emailchefSubscribedOptIn"><?php echo $this->__("Opted-in Only"); ?></label>
146
+ </td>
147
+ <td>
148
+ <input type="radio" name="emailchefSubscribed" id="emailchefSubscribedNonOptIn"
149
+ value="2" <?php if (isset($emailchefSubscribed) && $emailchefSubscribed == 2) { echo 'checked="checked"'; } ?> />&nbsp;<label for="emailchefSubscribedNonOptIn"><?php echo $this->__("Non Opted-in Only"); ?></label>
150
+ </td>
151
+ </tr>
152
+ </table>
153
+
154
+ <br /><br />
155
+
156
+ <table cellspacing="0" class="form-list">
157
+ <tr>
158
+ <td colspan="2">
159
+ <strong><?php echo $this->__('Groups')?></strong>
160
+ </td>
161
+ </tr>
162
+ <tr>
163
+ <td class="labelpg1"><?php echo $this->__('Select customer group')?></td>
164
+ <td class="input-ele">
165
+ <select name="emailchefCustomerGroupId" class="slctpg1">
166
+ <?php
167
+ $customerGroups = Mage::helper('customer')->getGroups()->toOptionArray();
168
+
169
+ if ($emailchefCustomerGroupId) {
170
+ foreach ($customerGroups as $customerGroup) {
171
+ if ($emailchefCustomerGroupId == $customerGroup['value']) {
172
+ echo '<option value="'.$customerGroup['value'].'">'.$customerGroup['label'].'</option>';
173
+ }
174
+ }
175
+ }
176
+ ?>
177
+
178
+ <option value="0">-- <?php echo $this->__('Any')?> --</option>
179
+
180
+ <?php
181
+ foreach ($customerGroups as $customerGroup) {
182
+ echo '<option value="'.$customerGroup['value'].'">'.$customerGroup['label'].'</option>';
183
+ }
184
+ ?>
185
+ </select>
186
+ </td>
187
+ </tr>
188
+
189
+ <tr>
190
+ <td colspan="2">
191
+ <br /><br /><strong><?php echo $this->__('Location')?></strong>
192
+ </td>
193
+ </tr>
194
+ <tr>
195
+ <td class="labelpg1"><?php echo $this->__('Select country')?></td>
196
+ <td class="input-ele">
197
+ <select name="emailchefCountry" class="slctpg1">
198
+ <?php
199
+ $countries = Mage::getResourceModel('directory/country_collection')
200
+ ->loadData()
201
+ ->toOptionArray(false);
202
+
203
+ if ($emailchefCountry) {
204
+ foreach ($countries as $country){
205
+ if ($country['value'] == $emailchefCountry)
206
+ echo '<option value="'.$country['value'].'">'.$country['label'].'</option>';
207
+ }
208
+ }
209
+ ?>
210
+
211
+ <option value="0">-- <?php echo $this->__('Any')?> --</option>
212
+
213
+ <?php
214
+ foreach ($countries as $country) {
215
+ echo '<option value="'.$country['value'].'">'.$country['label'].'</option>';
216
+ }
217
+ ?>
218
+ </select>
219
+ </td>
220
+ </tr>
221
+ <tr>
222
+ <td class="labelpg1"><?php echo $this->__('Zip code')?></td>
223
+ <td class="input-ele">
224
+ <input type="text" class="inptptx1" name="emailchefPostCode" size="10" value="<?php echo $emailchefPostCode; ?>" /> <span class="tip">(<?php echo $this->__('e.g.')?> 12345)</span>
225
+ </td>
226
+ </tr>
227
+ </table>
228
+
229
+ <table cellspacing="0" class="form-list" id="customerDependentContainer">
230
+ <tr>
231
+ <td colspan="2">
232
+ <br /><br /><strong><?php echo $this->__('Products and categories')?></strong>
233
+ </td>
234
+ </tr>
235
+
236
+ <?php //select con tutti i prodotti ?>
237
+ <tr>
238
+ <td class="labelpg1"><?php echo $this->__('Insert product SKU')?></td>
239
+ <td class="input-ele">
240
+ <input type="text" class="inptptx1 customerDependent" name="emailchefProductSku" size="20" value="<?php echo $emailchefProductSku; ?>" /> <span class="tip">(<?php echo $this->__('e.g.')?> MYSKU123)</span>
241
+ </td>
242
+ </tr>
243
+ <?php //select con tutte le categorie ?>
244
+ <tr>
245
+ <td class="labelpg1"><?php echo $this->__('Select category')?></td>
246
+ <td class="input-ele">
247
+ <?php
248
+ $categoriesCollection = Mage::getModel('catalog/category')->getCollection();
249
+ $categoriesCollection->addAttributeToSelect('name');
250
+ $categoriesCollection->addAttributeToSelect('entity_id');
251
+ ?>
252
+ <select id="emailchefCategoryId" name="emailchefCategoryId" class="slctpg1 customerDependent">
253
+ <?php
254
+ if ($emailchefCategoryId) {
255
+ $category = Mage::getModel('catalog/category')->load($emailchefCategoryId);
256
+ echo '<option value="'.$emailchefCategoryId.'">'.$category->getData('name').'</option>';
257
+ }
258
+ ?>
259
+
260
+ <option value="0">-- <?php echo $this->__('Any')?> --</option>
261
+
262
+ <?php
263
+ foreach ($categoriesCollection as $category) {
264
+ if ($category->getLevel() == 2) {
265
+ print_category($category);
266
+ }
267
+ }
268
+ ?>
269
+ </select>
270
+ </td>
271
+ </tr>
272
+
273
+ <tr>
274
+ <td colspan="2">
275
+ <br /><br /><strong><?php echo $this->__('Subscription date')?></strong>
276
+ </td>
277
+ </tr>
278
+ <tr>
279
+ <td class="labelpg1"><?php echo $this->__('From')?></td>
280
+ <td class="input-ele">
281
+ <input type="text" class="inptptx1 customerDependent" name="emailchefCustomerStartDate" id="emailchefCustomerStartDate" size="20" value="<?php echo $emailchefCustomerStartDate; ?>" />
282
+ <img id="emailchefCustomerStartDateTrig" class="v-middle" alt="" src="<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN) ?>/adminhtml/default/default/images/grid-cal.gif"> <span class="tip">(<?php echo Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>)</span>
283
+ <script type="text/javascript">
284
+ Calendar.setup({
285
+ inputField: "emailchefCustomerStartDate",
286
+ ifFormat: "<?php echo Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>",
287
+ showsTime: false,
288
+ button: "emailchefCustomerStartDateTrig",
289
+ align: "Bl",
290
+ singleClick : true
291
+ });
292
+ </script>
293
+ </td>
294
+ </tr>
295
+ <tr>
296
+ <td class="labelpg1"><?php echo $this->__('To')?></td>
297
+ <td class="input-ele">
298
+ <input type="text" class="inptptx1 customerDependent" name="emailchefCustomerEndDate" id="emailchefCustomerEndDate" size="20" value="<?php echo $emailchefCustomerEndDate; ?>" />
299
+ <img id="emailchefCustomerEndDateTrig" class="v-middle" alt="" src="<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN) ?>/adminhtml/default/default/images/grid-cal.gif"> <span class="tip">(<?php echo Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>)</span>
300
+ <script type="text/javascript">
301
+ Calendar.setup({
302
+ inputField: "emailchefCustomerEndDate",
303
+ ifFormat: "<?php echo Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>",
304
+ showsTime: false,
305
+ button: "emailchefCustomerEndDateTrig",
306
+ align: "Bl",
307
+ singleClick : true
308
+ });
309
+ </script>
310
+ </td>
311
+ </tr>
312
+ <tr>
313
+ <td colspan="2">
314
+ <br /><br /><strong><?php echo $this->__('Total purchased amount')?></strong>
315
+ </td>
316
+ </tr>
317
+ <tr>
318
+ <td class="labelpg1"><?php echo $this->__('Order total')?></td>
319
+ <td class="input-ele">
320
+ <select id="emailchefTotalAmountCond" name="emailchefTotalAmountCond" class="slctpg2 customerDependent">
321
+ <?php
322
+ if ($emailchefTotalAmountCond && $emailchefTotalAmountCond != 'gt') {
323
+ if ($emailchefTotalAmountCond == 'lt') {
324
+ echo '<option value="lt"> '.$this->__('less than').' </option>';
325
+ } elseif ($emailchefTotalAmountCond == 'eq') {
326
+ echo '<option value="eq"> '.$this->__('same as').' </option>';
327
+ }
328
+ }
329
+ ?>
330
+ <option value="gt"> <?php echo $this->__('more than')?> </option>
331
+ <option value="lt"> <?php echo $this->__('less than')?> </option>
332
+ <option value="eq"> <?php echo $this->__('same as')?> </option>
333
+ </select>
334
+
335
+ <!--label for="emailchefTotalAmountValue" class="lbl1"><?php echo $this->__('Specify amount')?></label-->&nbsp;
336
+ <input type="text" class="inptptx1 customerDependent" id="emailchefTotalAmountValue" name="emailchefTotalAmountValue" size="20" value="<?php echo $emailchefTotalAmountValue; ?>" /> <span class="tip">(<?php echo $this->__('e.g.')?> 50)</span>
337
+ </td>
338
+ </tr>
339
+
340
+ <tr>
341
+ <td colspan="2">
342
+ <br /><br /><strong><?php echo $this->__('Date of purchase')?></strong>
343
+ </td>
344
+ </tr>
345
+
346
+ <tr>
347
+ <td><?php echo $this->__('Show customers who'); ?></td>
348
+ <td>
349
+ <select name="emailchefOrderYesNo" class="slctpg2 customerDependent">
350
+ <?php
351
+ if ($emailchefOrderYesNo == 'no') {
352
+ echo '<option value="no">'.$this->__("Haven't purchased").'</option>';
353
+ }
354
+ ?>
355
+ <option value="yes"> <?php echo $this->__('Have purchased'); ?> </option>
356
+ <option value="no"> <?php echo $this->__("Haven't purchased"); ?> </option>
357
+ </select>
358
+ </td>
359
+ </tr>
360
+
361
+ <tr>
362
+ <td class="labelpg1"><?php echo $this->__('From')?></td>
363
+ <td class="input-ele">
364
+ <input type="text" class="inptptx1 customerDependent" name="emailchefOrderStartDate" id="emailchefOrderStartDate" size="20" value="<?php echo $emailchefOrderStartDate; ?>" /><img id="emailchefOrderStartDateTrig" class="v-middle" alt="" src="/skin/adminhtml/default/default/images/grid-cal.gif"> <span class="tip">(<?php echo Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>)</span>
365
+ <script type="text/javascript">
366
+ Calendar.setup({
367
+ inputField: "emailchefOrderStartDate",
368
+ ifFormat: "<?php echo Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>",
369
+ showsTime: false,
370
+ button: "emailchefOrderStartDateTrig",
371
+ align: "Bl",
372
+ singleClick : true
373
+ });
374
+ </script>
375
+ </td>
376
+ </tr>
377
+ <tr>
378
+ <td class="labelpg1"><?php echo $this->__('To')?></td>
379
+ <td class="input-ele">
380
+ <input type="text" class="inptptx1 customerDependent" name="emailchefOrderEndDate" id="emailchefOrderEndDate" size="20" value="<?php echo $emailchefOrderEndDate; ?>" /><img id="emailchefOrderEndDateTrig" class="v-middle" alt="" src="/skin/adminhtml/default/default/images/grid-cal.gif"> <span class="tip">(<?php echo Mage::app()->getLocale()->getDateFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>)</span>
381
+ <script type="text/javascript">
382
+ Calendar.setup({
383
+ inputField: "emailchefOrderEndDate",
384
+ ifFormat: "<?php echo Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>",
385
+ showsTime: false,
386
+ button: "emailchefOrderEndDateTrig",
387
+ align: "Bl",
388
+ singleClick : true
389
+ });
390
+ </script>
391
+ </td>
392
+ </tr>
393
+ </table>
394
+ </fieldset>
395
+ </form>
396
+
397
+ <h4><span id="spantitle3"><a name="saveFilter"><?php echo $this->__('Save current filters as hint')?></a></span></h4>
398
+ <fieldset id="my-fieldset3">
399
+ <table>
400
+ <tr>
401
+ <td>
402
+ <input name="filter_name_text" id="filter_name_text" type="text" value="" maxlength="100" size="50" />
403
+ <input class="form-button" type="submit" onclick="saveFilterHint();return false;" value="<?php echo $this->__('Save hint')?>" />
404
+ </td>
405
+ </tr>
406
+ </table>
407
+ </fieldset>
408
+
409
+ <h4><span id="spantitle1"><a name="ottsugg"><?php echo $this->__('Filter hints')?></a></span></h4>
410
+ <fieldset id="my-fieldset2">
411
+ <table cellspacing="0" class="form-list">
412
+ <tr>
413
+ <td><?php echo $this->__('Set and customize one of the following filters:')?></td>
414
+ </tr>
415
+ <tr>
416
+ <td>
417
+ <form action="*/*/" id="filtro1" name="filtro1" method="post">
418
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
419
+ <input name="emailchefCustomers" type="hidden" value="2" />
420
+ <input name="emailchefCustomerGroupId" type="hidden" value="2" />
421
+ <p class="parscefil"><?php echo $this->__("All wholesale customers who haven't purchased yet")?> &raquo;</p>
422
+ <input class="form-button" type="submit" value="<?php echo $this->__('Set hint')?>" />
423
+ </form>
424
+ </td>
425
+ </tr>
426
+ <tr>
427
+ <td>
428
+ <form action="*/*/" id="filtro2" name="filtro2" method="post">
429
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
430
+ <input name="emailchefCustomers" type="hidden" value="1" />
431
+ <input name="emailchefTotalAmountCond" type="hidden" value="gt" />
432
+ <input name="emailchefTotalAmountValue" type="hidden" value="50" />
433
+ <p class="parscefil"><?php echo $this->__('More than 50 Euros orders')?> &raquo;</p>
434
+ <input class="form-button" type="submit" value="<?php echo $this->__('Set hint')?>" />
435
+ </form>
436
+ </td>
437
+ </tr>
438
+ <tr>
439
+ <td>
440
+ <form action="*/*/" id="filtro3" name="filtro3" method="post">
441
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
442
+ <input name="emailchefCustomers" type="hidden" value="0" />
443
+ <input name="emailchefOrderYesNo" type="hidden" value="no" />
444
+ <input name="emailchefOrderStartDate" type="hidden" value="01/01/<?php echo date('Y'); ?>" />
445
+ <p class="parscefil"><?php echo $this->__('Members with no purchase in')?> <?php echo date('Y'); ?> &raquo;</p>
446
+ <input class="form-button" type="submit" value="<?php echo $this->__('Set hint')?>" />
447
+ </form>
448
+
449
+ </td>
450
+ </tr>
451
+
452
+ <?php if(!empty($filterHints)): ?>
453
+ <tr>
454
+ <td>&nbsp;</td>
455
+ </tr>
456
+ <tr>
457
+ <td><?php echo $this->__('Or choose one of those you saved:')?></td>
458
+ </tr>
459
+ <?php endif ?>
460
+
461
+ <?php
462
+ foreach ($filterHints as $fh) {
463
+ $filter_name = $fh['filter_name'];
464
+ echo '<tr><td>';
465
+ echo '<form action="*/*/" id="'.$filter_name.'" name="'.$filter_name.'" method="post">';
466
+ echo '<input name="form_key" type="hidden" value="'. Mage::getSingleton('core/session')->getFormKey() .'" />';
467
+ $hints = explode('|', $fh['hints']);
468
+ foreach ($hints as $h) {
469
+ $array = explode('=', $h);
470
+ echo '<input name="'.$array[0].'" type="hidden" value="'.$array[1].'" />';
471
+ }
472
+ echo '<p class="parscefil">'.$filter_name.' &raquo;</p>';
473
+ echo '<input class="form-button" type="submit" value="'.$this->__('Set hint').'" />';
474
+ echo '</form>';
475
+ echo '&nbsp;';
476
+ echo '<form name="deleteForm_'.$filter_name.'" action="'.$this->getUrl('*/*/deleteFilterHint').'" method="post">';
477
+ echo '<input name="form_key" type="hidden" value="'. Mage::getSingleton('core/session')->getFormKey() .'" />';
478
+ echo '<input name="filter_name" type="hidden" value="'. $filter_name .'" />';
479
+ echo '<input class="form-button" type="submit" name="delete" onclick="if(confirm(\''.$this->__('Do you really want to delete this filter hint?').'\')==true){this.submit();}return false;" value="'.$this->__('Delete hint').'" />';
480
+ echo '</form>';
481
+ echo '</td></tr>';
482
+ } ?>
483
+
484
+ </table>
485
+ </fieldset>
486
+
487
+ <!--<a href="<?php echo $this->getUrl('*/*/testCron')?>">TEST CRON</a>
488
+ <a href="<?php echo $this->getUrl('*/*/testFields')?>">TEST GETFIELDS</a>-->
489
+ </div>
490
+ <script type="text/javascript">
491
+ var editForm = new varienForm('edit_form');
492
+
493
+ document.getElementsByClassName = function(className) {
494
+ var retnode = [];
495
+ var myclass = new RegExp('\\b'+className+'\\b');
496
+ var elements = this.getElementsByTagName('*');
497
+ var elementsLength = elements.length;
498
+ var element = null;
499
+ for (var i = 0; i < elementsLength; i++) {
500
+ element = elements[i];
501
+ if (myclass.test(element.className)) {
502
+ retnode.push(element);
503
+ }
504
+ }
505
+ return retnode;
506
+ };
507
+
508
+ function customerDependentFilters(isDisabled) {
509
+ document.getElementById('customerDependentContainer').style.display = (isDisabled) ? 'none' : 'block';
510
+
511
+ var elements = document.getElementsByClassName('customerDependent');
512
+
513
+ var elementsLength = elements.length;
514
+ for (var i=0; i < elementsLength; i++) {
515
+ elements[i].disabled = isDisabled;
516
+ }
517
+ }
518
+
519
+ function saveFilterHint() {
520
+ if (document.getElementById('filter_name_text').value=='') {
521
+ alert('<?php echo $this->__('Please, give your new hint a name.')?>');
522
+ } else {
523
+ document.getElementById('filter_name').value = document.getElementById('filter_name_text').value;
524
+ document.getElementById('edit_form').action = '<?php echo $this->getUrl('*/*/saveFilterHint')?>';
525
+ document.getElementById('edit_form').submit();
526
+ }
527
+ return false;
528
+ }
529
+
530
+ window.onload = function() {
531
+ var isDisabled = document.getElementById('emailchefCustomersWhoHaventBought').checked;
532
+ customerDependentFilters(isDisabled);
533
+ }
534
+ </script>
535
+ <?php } ?>
app/design/adminhtml/default/default/template/emailchef/emailchefsync/sysconfigjavascript.phtml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is solely to instantiate the javascript in system config with values that can only be generated via php
4
+ */
5
+ ?>
6
+ <script language="JavaScript">
7
+ // Initialise observer so that when list is changed, groups are reloaded
8
+ urlList = '<?php echo Mage::getModel('adminhtml/url')->getUrl("emailchef/adminhtml_configuration/getgroups"); ?>';
9
+ document.observe("dom:loaded", function() {
10
+ initListObserver(urlList);
11
+ });
12
+ // Initialise observer to run self-test
13
+ urlTest = '<?php echo Mage::getModel('adminhtml/url')->getUrl("emailchef/adminhtml_configuration/testconnection"); ?>';
14
+ document.observe("dom:loaded", function() {
15
+ initSelfTestObserver(urlTest);
16
+ });
17
+ </script>
app/design/adminhtml/default/default/template/emailchef/emailchefsync/viewdatatransferlog.phtml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form name="viewdatatransferlog_form" action="<?php echo $this->getUrl('*/*/search') ?>" method="post">
2
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
3
+ <div class="content-header">
4
+ <table cellspacing="0" class="grid-header">
5
+ <tr>
6
+ <td style="width:50%">
7
+ <h3><?php echo $this->__("View data transfer log") ?></h3>
8
+ </td>
9
+ <td class="form-buttons">
10
+ <button onclick="searchForm.submit()"><?php echo $this->__("Search") ?></button>
11
+ </td>
12
+ </tr>
13
+ </table>
14
+ </div>
15
+ <div class="grid">
16
+ <div class="hor-scroll">
17
+ <table class="data" cellspacing="0">
18
+ <thead>
19
+ <tr class="headings">
20
+ <th><span class="nobr"><?php echo $this->__("Date/time") ?></span></th>
21
+ <th><span class="nobr"><?php echo $this->__("Type") ?></span></th>
22
+ <th><span class="nobr"><?php echo $this->__("Result") ?></span></th>
23
+ <th class="last"><span class="nobr"><?php echo $this->__("N. updated records") ?></span></th>
24
+ </tr>
25
+ <tr class="filter">
26
+ <th><div class="range"><div class="range-line date">
27
+ <span class="label"><?php echo $this->__("From") ?>:</span>
28
+ <input type="text" class="input-text no-changes" value="" id="sales_order_grid_filter_created_at1354009617.6284_from" name="date_from">
29
+ <img title="" id="sales_order_grid_filter_created_at1354009617.6284_from_trig" class="v-middle" alt="" src="<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN) ?>/adminhtml/default/default/images/grid-cal.gif">
30
+ </div><div class="range-line date">
31
+ <span class="label"><?php echo $this->__("To") ?>:</span>
32
+ <input type="text" class="input-text no-changes" value="" id="sales_order_grid_filter_created_at1354009617.6284_to" name="date_to">
33
+ <img title="" id="sales_order_grid_filter_created_at1354009617.6284_to_trig" class="v-middle" alt="" src="<?php echo Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN) ?>/adminhtml/default/default/images/grid-cal.gif">
34
+ </div></div><input type="hidden" value="it_IT" name="created_at[locale]"><script type="text/javascript">
35
+ Calendar.setup({
36
+ inputField : "sales_order_grid_filter_created_at1354009617.6284_from",
37
+ ifFormat : "<?php echo Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>",
38
+ button : "sales_order_grid_filter_created_at1354009617.6284_from_trig",
39
+ showsTime: false,
40
+ align : "Bl",
41
+ singleClick : true
42
+ });
43
+ Calendar.setup({
44
+ inputField : "sales_order_grid_filter_created_at1354009617.6284_to",
45
+ ifFormat : "<?php echo Mage::app()->getLocale()->getDateStrFormat(Mage_Core_Model_Locale::FORMAT_TYPE_SHORT) ?>",
46
+ button : "sales_order_grid_filter_created_at1354009617.6284_to_trig",
47
+ showsTime: false,
48
+ align : "Bl",
49
+ singleClick : true
50
+ });
51
+ </script></th>
52
+ <th><select name="type">
53
+ <option selected="selected" value=""></option>
54
+ <option value="automatic"><?php echo $this->__("Automatic") ?></option>
55
+ <option value="manual"><?php echo $this->__("Manual") ?></option>
56
+ </select></th>
57
+ <th><select name="result">
58
+ <option selected="selected" value=""></option>
59
+ <option value="completed"><?php echo $this->__("Completed") ?></option>
60
+ <option value="partial"><?php echo $this->__("Partial") ?></option>
61
+ <option value="failed"><?php echo $this->__("Failed") ?></option>
62
+ </select></th>
63
+ <th class="last">&nbsp;</th>
64
+ </tr>
65
+ </thead>
66
+ </table>
67
+ </div>
68
+ </div>
69
+ </form>
70
+ <script type="text/javascript">
71
+ var searchForm = new varienForm('viewdatatransferlog_form');
72
+ </script>
app/design/frontend/base/default/layout/emailchef.xml ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <checkout_onepage_review>
4
+ <reference name="checkout.onepage.review.info.items.after">
5
+ <block type="emailchef/checkout_subscribe" name="emailchef.subscribe" template="emailchef/subscribe.phtml" />
6
+ </reference>
7
+ </checkout_onepage_review>
8
+
9
+ <emailchef_index_index>
10
+ <reference name="root">
11
+ <action method="setTemplate">
12
+ <template>page/1column.phtml</template>
13
+ </action>
14
+ </reference>
15
+ <reference name="content">
16
+ <block type="emailchef/index" name="emailchef_index" template="emailchef/index.phtml"/>
17
+ </reference>
18
+ </emailchef_index_index>
19
+
20
+ <customer_account_index>
21
+ <reference name="customer_account_dashboard_info">
22
+ <action method="setTemplate">
23
+ <template>emailchef/customer/account/dashboard/info.phtml</template>
24
+ </action>
25
+ </reference>
26
+ </customer_account_index>
27
+ </layout>
app/design/frontend/base/default/template/emailchef/customer/account/dashboard/info.phtml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="col2-set">
2
+ <div class="col-1">
3
+ <div class="box">
4
+ <div class="box-title">
5
+ <h3><?php echo $this->__('Contact Information') ?></h3>
6
+ <a href="<?php echo $this->getUrl('customer/account/edit') ?>"><?php echo $this->__('Edit') ?></a>
7
+ </div>
8
+ <div class="box-content">
9
+ <p>
10
+ <?php echo $this->escapeHtml($this->getCustomer()->getName()) ?><br />
11
+ <?php echo $this->escapeHtml($this->getCustomer()->getEmail()) ?><br />
12
+ <a href="<?php echo $this->getChangePasswordUrl() ?>"><?php echo $this->__('Change Password') ?></a>
13
+ </p>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ <?php if( $this->isNewsletterEnabled() ): ?>
18
+ <div class="col-2">
19
+ <div class="box">
20
+ <div class="box-title">
21
+ <h3><?php echo $this->__('Newsletters') ?></h3>
22
+ <a href="<?php echo $this->getUrl('newsletter/manage') ?>"><?php echo $this->__('Edit') ?></a>
23
+ </div>
24
+ <div class="box-content">
25
+ <p>
26
+ <?php /** @modification: Checks for subscription status, not just whether subscribed */
27
+ switch( $this->getSubscriptionObject()->getStatus() ) {
28
+ case Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED:
29
+ echo $this->__('You are currently subscribed to "General Subscription"'); break;
30
+ case Mage_Newsletter_Model_Subscriber::STATUS_UNCONFIRMED:
31
+ echo Mage::helper("emailchef")->__('Check your email to confirm your subscription to our newsletter.'); break;
32
+ default:
33
+ echo $this->__('You are currently not subscribed to any newsletter.');
34
+ }
35
+ ?>
36
+ </p>
37
+ </div>
38
+ </div>
39
+ <?php /* Extensions placeholder */ ?>
40
+ <?php echo $this->getChildHtml('customer.account.dashboard.info.extra')?>
41
+ </div>
42
+ <?php endif; ?>
43
+ </div>
app/design/frontend/base/default/template/emailchef/index.phtml ADDED
File without changes
app/design/frontend/base/default/template/emailchef/subscribe.phtml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $storeId = Mage::app()->getStore()->getStoreId();
3
+ $display_checkbox = false;
4
+ if (Mage::getStoreConfig("emailchef_newsletter/emailchef/enable_subscribe_in_checkout", $storeId) == 1) {
5
+ if (Mage::helper('customer')->isLoggedIn()) {
6
+ $email = Mage::helper('customer')->getCustomer()->getEmail();
7
+ $newsletter_subscriber_model = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
8
+ if ($newsletter_subscriber_model->getSubscriberStatus() != 1) {
9
+ $display_checkbox = true;
10
+ }
11
+ } else {
12
+ $display_checkbox = true;
13
+ }
14
+ }
15
+ ?>
16
+
17
+ <?php if ($display_checkbox): ?>
18
+ <div class="buttons-set">
19
+ <label>
20
+ <input type="checkbox" onchange="emailchefModifyPost()" name="emailchef_subscribe" id="emailchef_subscribe" value="1" title="<?php echo $this->htmlEscape($this->__('Sign Up for Newsletter')) ?>" checked="checked" />
21
+ <?php echo $this->htmlEscape($this->__('Sign Up for Newsletter')) ?>
22
+ </label>
23
+ </div>
24
+ <script type="text/javascript">
25
+ emailchefModifyPost = function () {
26
+ if ($('emailchef_subscribe2')) $('emailchef_subscribe2').remove();
27
+ if ($('emailchef_subscribe').checked) {
28
+ var newinput = new Element("input", {name: "emailchef_subscribe2", id: "emailchef_subscribe2", value: "1", type: "hidden"});
29
+ try {
30
+ Element.insert(Form.findFirstElement(payment.form), newinput);
31
+ } catch (e) {
32
+ $("co-payment-form").insert(newinput);
33
+ }
34
+ }
35
+ }
36
+ emailchefModifyPost();
37
+ </script>
38
+ <?php endif; ?>
app/design/frontend/enterprise/default/layout/emailchef.xml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <checkout_onepage_review>
4
+ <reference name="checkout.onepage.review.info.items.after">
5
+ <block type="emailchef/checkout_subscribe" name="emailchef.subscribe" template="emailchef/subscribe.phtml" />
6
+ </reference>
7
+ </checkout_onepage_review>
8
+
9
+ <customer_account_index>
10
+ <reference name="customer_account_dashboard_info">
11
+ <action method="setTemplate">
12
+ <template>emailchef/customer/account/dashboard/info.phtml</template>
13
+ </action>
14
+ </reference>
15
+ </customer_account_index>
16
+ </layout>
app/etc/modules/EMailChef_EMailChefSync.xml ADDED
@@ -0,0 +1 @@
 
0
  <modules>
1
  <EMailChef_EMailChefSync>
2
  <active>true</active>
3
  <codePool>community</codePool>
4
  <depends>
5
  <Mage_Newsletter />
6
  </depends>
7
  </EMailChef_EMailChefSync>
8
  </modules>
1
+ <?xml version="1.0"?>
2
  <modules>
3
  <EMailChef_EMailChefSync>
4
  <active>true</active>
5
  <codePool>community</codePool>
6
  <depends>
7
  <Mage_Newsletter />
8
  </depends>
9
  </EMailChef_EMailChefSync>
10
  </modules>
app/locale/en_US/EMailChef_EMailChefSync.csv ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Members have not been sent correctly,Customers have not been sent correctly
2
+ Warning: no member has been selected,Warning: no customer has been selected
3
+ WARNING: before proceeding you must correctly configure the settings of eMailChef access in System->Configuration->Newsletter->eMailChef,WARNING: before proceeding you must correctly configure the eMailChef extension settings under System->Configuration->Newsletter->eMailChef
4
+ Apply filter,Apply filter
5
+ Get hints,View saved filters
6
+ Sold products,Purchase History
7
+ All customers,All customers
8
+ Customers who have purchased,Customers who have purchased
9
+ Customers who have not purchased,Customers who have not purchased
10
+ Select product,Select product
11
+ Any,Any
12
+ Select category,Products that belong to this category...
13
+ Groups,Groups
14
+ Select customer group,Select customer group
15
+ Location,Location
16
+ Select country,Select country
17
+ Zip code,Zip code
18
+ From,Between
19
+ To,And
20
+ Total purchased amount,Total purchased amount
21
+ Order total,Customers who have ordered
22
+ less than,less than
23
+ same as,exactly
24
+ more than,more than
25
+ Specify amount,Specify amount
26
+ Date of purchase,Purchase timeframe
27
+ Show customers who,Show customers who
28
+ Haven't purchased,did not purchase
29
+ Have purchased,purchased
30
+ In this period,In this period
31
+ Filter hints,Saved filters
32
+ All wholesale customers who haven't purchased yet,All wholesale customers who haven't purchased yet
33
+ Set filter,Set filter
34
+ More than 50 Euros orders,Customer who purchased over $50
35
+ Members with no purchase in,Members with no purchase in
36
+ Reset filters,Reset filters
37
+ Export to CSV,Export to CSV
38
+ Send to eMailChef,Send to eMailChef
39
+ Confirm filtered customers and select eMailChef group,Confirm filtered customers and select eMailChef group
40
+ Were found,Were found
41
+ records,records
42
+ Filtered customers,Filtered customers
43
+ Selected list,Selected list
44
+ Next step,Next step
45
+ Select group,Select group
46
+ Select an existing group,Select an existing group
47
+ or,or
48
+ Create new customer group,Create new customer group
49
+ Group name,Group name
50
+ Add a new e-mail address or select adresses to be removed from list,Add new email addresses or select addresses to be removed from list
51
+ Change members list: please add one email adress per row,Edit customers list: add one email address per row
52
+ Save changes,Save changes
53
+ Set and customize one of the following filters:,Set and customize one of the following filters:
54
+ Filter customers,Filter customers
55
+ You can find it on your browser url bar (e.g. g4a0.s03.it),Shown in your browser address field when you use eMailChef (e.g. g4a0.s03.it)
56
+ "If you haven't yet, we suggest you to create a DEM list directly from your emailchef console","If you haven't yet, we suggest you to create an 'ecommerce' (or similar) list in your eMailChef account"
57
+ Insert product SKU,Products whose SKU contains...
58
+ Enable Cron Export,Enable Cron Export
59
+ Subscription date,Subscription date
60
+ Save hint,Save filter
61
+ Delete hint,Delete
62
+ Set hint,Use this filter
63
+ Or choose one of those you saved:,Or choose one of those you saved:
64
+ Do you really want to delete this hint?,Do you really want to delete this filter?
65
+ "Please, give your new hint a name.",Please provide a name for the filter.
66
+ Save current filters as hint,Save this filter
67
+ Opted-in Only,Opted-in Only
68
+ All customers,All customers
69
+ Products and categories,Products and categories
70
+ dd/mm/yyyy,dd/mm/yyyy
71
+ e.g.,e.g.
72
+ Opt-in Status,Opt-in Status
73
+ "Magento fields","Magento fields"
74
+ "eMailChef fields","eMailChef fields"
75
+ "Fields mapping","Map Fields"
76
+ Filters,"Sync/segment Customers"
77
+ "By this plugin you can import contacts registered in your eCommerce in the eMailChef platform.","Create custom segments using the filters below and easily transfer them to a new or existing Group in your eMailChef account."
78
+ "Web service username is not in the right format","Web service username is not in the right format, it should be the a letter followed by some numbers (eg: a12345)"
79
+ "Please fill the admin console URL","Please fill the admin console URL"
80
+ "Admin console URL is not in the right format","Admin console URL is not in the right format, a valid URL example is abc123.s00.it"
81
+ "Unable to connect to eMailChef console","Unable to connect to your eMailChef account"
82
+ "Your subscription is waiting for confirmation","Your subscription to the newsletter is waiting for confirmation, please check your email and click the confirmation link"
83
+ "eMailChef configuration is not complete", "eMailChef configuration is not complete, please <a href=''>click here</a> to fill the missing information"
84
+ "eMailChef fields mapping is not complete","eMailChef fields mapping is not complete, please <a href=''>click here</a> to fill the missing information"
85
+ "Filtered customers preview","Filtered customers preview (max 25)"
86
+ "Members have been sent correctly","Customers segmented successfully. The data export to eMailChef will start within 5 minutes. The duration of the export process depends on the total amount of data being transferred."
87
+ "A eMailChef import process is schedules and will be executed soon.","A eMailChef import process is scheduled and will be executed soon."
88
+ "Check your email to confirm your subscription to our newsletter.","Check your email to confirm your subscription to our newsletter."
89
+ "Default Group","Default Group"
90
+ "Used as default group in all subscriptions that do not have a manual group set","Used as default group in all subscriptions that do not have a manual group set"
91
+ "Config warning: mysql.connect_timeout is %d which is a bit low. This may cause intermittent issues when connecting with eMailChef. Please contact your Web host to discuss an increase in the timeout setting.'","Config warning: mysql.connect_timeout is %d which is a bit low. This may cause intermittent issues when connecting with eMailChef. Please contact your Web host to discuss an increase in the timeout setting.'"
app/locale/it_IT/EMailChef_EMailChefSync.csv ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Yes","Sì"
2
+ "No","No"
3
+ "Members have been sent correctly","Segmentazione completata con successo. L'esportazione verso eMailChef verra' attivata nei prossimi 5 minuti. La durata totale dell'esportazione dipende dal volume dei dati trasferiti."
4
+ "Warning: no member has been selected","Attenzione: non hai inviato nessun iscritto"
5
+ "WARNING: before proceeding you must correctly configure the settings of eMailChef access in System->Configuration->Newsletter->eMailChef","ATTENZIONE: prima di procedere devi configurare correttamente i parametri per accedere a eMailChef in Sistema->Configurazione->Newsletter->eMailChef"
6
+ "Apply filter","Applica filtro"
7
+ "Get hints","Ottieni suggerimenti"
8
+ "Sold products","Prodotti venduti"
9
+ "All customers","Tutti i clienti"
10
+ "Customers who have purchased","I clienti che hanno acquistato"
11
+ "Customers who have not purchased","I clienti che non hanno mai acquistato"
12
+ "Select product","Seleziona un prodotto"
13
+ "Any","Qualsiasi"
14
+ "Select category","Seleziona una categoria"
15
+ "Groups","Tipo di cliente"
16
+ "Select customer group","Seleziona gruppo di clienti"
17
+ "Location","Provenienza cliente"
18
+ "Select country","Seleziona paese"
19
+ "Zip code","CAP"
20
+ "From","Data inizio"
21
+ "To","Data fine"
22
+ "Total purchased amount","Somma totale ordinata"
23
+ "Order total","Totale ordinato"
24
+ "less than","minore di"
25
+ "same as","uguale a"
26
+ "more than","maggiore di"
27
+ "Specify amount","Inserisci il valore"
28
+ "Date of purchase","Data ordini"
29
+ "Show customers who","Seleziona utenti che"
30
+ "Haven't purchased","Non hanno effettuato un ordine"
31
+ "Have purchased","Hanno effettuato un ordine"
32
+ "In this period","Nel periodo"
33
+ "Filter hints","Filtri salvati"
34
+ "All wholesale customers who haven't purchased yet","Tutti i clienti all'ingrosso che non hanno mai acquistato"
35
+ "Set filter","imposta filtro"
36
+ "More than 50 Euros orders","Tutti i clienti che hanno acquistato per oltre 50 Euro"
37
+ "Members with no purchase in","Tutti i clienti che non hanno acquistato nel"
38
+ "Reset filters","Reimposta i filtri"
39
+ "Export to CSV","Esporta in CSV"
40
+ "Send to eMailChef","Invia a eMailChef"
41
+ "Confirm filtered customers and select eMailChef group","Conferma i clienti filtrati e scegli gruppo di eMailChef"
42
+ "Were found","Sono stati trovati"
43
+ "records","clienti corrispondenti ai criteri di ricerca"
44
+ "Filtered customers","Clienti filtrati"
45
+ "Selected list","Lista selezionata"
46
+ "Next step","Prossimo Step"
47
+ "Select group","Seleziona gruppo"
48
+ "Select an existing group","Scegli tra i gruppi gi&agrave; presenti su eMailChef"
49
+ "or","oppure"
50
+ "Create new customer group","Crea nuovo gruppo"
51
+ "Group name","Inserisci il nome del nuovo gruppo"
52
+ "Add a new e-mail address or select adresses to be removed from list","Aggiungi o rimuovi manualmente gli indirizzi email dalla lista"
53
+ "Change members list: please add one email adress per row","Modifica manualmente l'elenco degli iscritti, scrivere un solo indirizzo email per ogni riga"
54
+ "Save changes","Applica modifiche"
55
+ "Set and customize one of the following filters:","Imposta e personalizza uno dei seguenti filtri:"
56
+ "Filter customers","Filtra i clienti"
57
+ "You can find it on your browser url bar (e.g. g4a0.s03.it)","Si trova nella barra degli indirizzi del tuo browser (es. g4a0.s03.it)"
58
+ "If you haven't yet, we suggest you to create a DEM list directly from your emailchef console","Se non &egrave; stato ancora fatto &egrave; consigliabile creare una lista dedicata alle DEM direttamente dalla console di eMailChef"
59
+ "Insert product SKU","Inserisci lo SKU del prodotto"
60
+ "Enable Cron Export","Abilita Export Automatico"
61
+ "Subscription date","Data di iscrizione"
62
+ "Save hint","Salva il suggerimento"
63
+ "Delete hint","Cancella il suggerimento"
64
+ "Set hint","Applica il suggerimento"
65
+ "Or choose one of those you saved:","O scegline uno tra quelli che hai salvato:"
66
+ "Do you really want to delete this hint?","Vuoi davvero cancellare questo suggerimento?"
67
+ "Please, give your new hint a name.","Per favore, dai un nome al tuo nuovo suggerimento."
68
+ "Save current filters as hint","Salva i filtri correnti come suggerimento"
69
+ "Opted-in Only","Clienti iscritti alla newsletter"
70
+ "All customers","Tutti i clienti"
71
+ "Products and categories","Prodotti e categorie"
72
+ "dd/mm/yyyy","gg/mm/aaaa"
73
+ "e.g.","es."
74
+ "Opt-in Status","Iscrizione alla newsletter"
75
+ "Associate all Magento fields with eMailChef ones","Associa i campi Magento con quelli eMailChef"
76
+ "Fields mapping","Mappa campi"
77
+ "Filters","Sincronizza/segmenta clienti"
78
+ "Export Frequency","Frequenza di esportazione"
79
+ "Enable Automatic Data Export to eMailChef","Abilita l'export automatico dei dati verso eMailChef"
80
+ "Admin Console URL","URL della console di amministrazione"
81
+ "Web Service Username","Username dei web service"
82
+ "Web Service Password","Password dei web service"
83
+ "You can set it in your console (Manage->Web Services), then type it here","Puoi impostarla dalla tua console (Gestione->Web service)"
84
+ "Allow Guest Subscription","Permetti l'iscrizione di utenti ospiti"
85
+ "Error: unable to save current filter","Errore: impossibile salvare il filtro corrente"
86
+ "Error: unable to delete the filter","Errore: impossibile eliminare il filtro selezionato"
87
+ "Magento fields","Campi Magento"
88
+ "eMailChef fields","Campi eMailChef"
89
+ "By this plugin you can import contacts registered in your eCommerce in the eMailChef platform.","Crea segmenti personalizzati usando i filtri sottostanti e trasferiscili facilmente in un gruppo esistente (o nuovo) del tuo account eMailChef."
90
+ "Please fill the web service username","Compila il campo Username dei web service"
91
+ "Web service username is not in the right format","Il campo Username dei web service non è nel formato corretto, dovrebbe essere formato dalla lettera a seguita da alcuni numeri (es: a12345)"
92
+ "Please fill the admin console URL","Compila il campo URL della console di amministrazione"
93
+ "Admin console URL is not in the right format","Il campo URL della console di amministrazione non è nel formato corretto, un esempio di URL valida è abc123.s00.it"
94
+ "Unable to connect to eMailChef console","Impossibile connettersi alla console di eMailChef"
95
+ "Your subscription is waiting for confirmation","La tua iscrizione alla newsletter è in attesa di conferma, controlla la tua casella email e clicca sul link inviatoti"
96
+ "eMailChef configuration is not complete", "La configurazione di eMailChef non è completa, <a href=''>clicca qui</a> per digitare le informazioni mancanti"
97
+ "eMailChef fields mapping is not complete","La mappatura dei campi eMailChef non è completa, <a href=''>clicca qui</a> per digitare le informazioni mancanti"
98
+ "Connect to eMailChef","Connetti a eMailChef"
99
+ "For assistance visit help.emailchef.com and search for ""API credentials""","Per assistenza visita help.emailchef.com e cerca ""credenziali API"""
100
+ "View data transfer log","Log di trasferimento dati"
101
+ "Enable subscription checkbox during checkout","Abilita la checkbox di iscrizione alla newsletter in fase di checkout"
102
+ "Next step","Prossimo passo"
103
+ "Filtered customers preview","Anteprima dei clienti filtrati (max 25)"
104
+ "A eMailChef import process is running.","L'importazione verso eMailChef è in esecuzione."
105
+ "A eMailChef import process is schedules and will be executed soon.","L'importazione verso eMailChef è schedulata e inizierà a breve."
106
+ "Please wait for the next step to load","Attendere il caricamento della prossima schermata"
107
+ "Check your email to confirm your subscription to our newsletter.","Controlla la posta elettronica e conferma l'iscrizione alla newsletter."
108
+ "Default Group","Gruppo default"
109
+ "Used as default group in all subscriptions that do not have a manual group set","Usato come gruppo predefinito nelle iscrizioni per le quali non e' stato specificato un gruppo."
110
+ "View eMailChef Tasks","Visualizza Task eMailChef"
111
+ "View Task Data","Informazioni sul Task"
112
+ "View Logs","Visualizza Log"
113
+ "eMailChef Scheduled Tasks","Task Schedulati eMailChef"
114
+ "Settings & Field Mapping","Impostazioni & Mappatura Campi"
115
+ "Test Connection","Test Connessione"
116
+ "For assistance visit","Per assistenza visitare"
117
+ "Please fill in eMailChef Email and Password before testing","Inserire l'Email e la Password di eMailChef prima di continuare"
118
+ "Success! Connection established with eMailChef with given details","Dati corretti! Connessione stabilita correttamente con eMailChef"
119
+ "Error in email / password","Email / password errati"
120
+ "Config warning: mysql.connect_timeout is %d which is a bit low. This may cause intermittent issues when connecting with eMailChef", "Attenzione: l'impostazione mysql.connect_timeout è impostata a %d. Questo valore è basso e potrebbe causare errori durante la sincronizzazione con eMailChef"
121
+ "List","Lista"
122
+ "Require Subscription Confirmation","Richiedi Conferma Iscrizione"
123
+ "Defines whether double opt-in is required","Opt-in richiesto"
124
+ "Server Timezone","Fuso orario server"
125
+ "Export Offset (in hours)","Differenza di fuso orario nell'esportazione (in ore)"
126
+ "Enable Module Debugging Log","Abilita Debug del Modulo"
127
+ "Disable Newsletter Subscription Notification","Disabilita Notifica Iscrizione Newsletter"
128
+ "Disables the default notification sent by Magento","Disabilita notifica di default inviata da Magento"
129
+ "Order Statuses to Match For Customer Totals","Stati Ordine per il calcolo dei Totali Clienti"
130
+ "If none set, those that are complete, closed or processing will be matched","Se non selezionati verranno abbinati gli ordini completati, chiusi o in elaborazione"
131
+ "Hourly","Ogni ora"
132
+ "Daily","Ogni giorno"
133
+ "Every %d hours","Ogni %d ore"
134
+ "Matching Magento customer attributes (on the left) with eMailChef attributes (on the right)","Mappatura attributi clienti Magento (colonna sinistra) con attributi emailChef (colonna destra)"
135
+ "Matching custom Magento customer attributes (on the left) with eMailChef attributes (on the right)","Mappature attributi personalizzati clienti Magento (colonna sinistra) con attributi eMailChef (colonna destra)"
136
+ "eMailChef Field Mapping","Mappatura Campi eMailChef"
137
+ "Custom Customer Attributes","Attributi Cliente Personalizzati"
138
+ "Message ID (optional)","ID Messaggio (opzionale)"
139
+ "See the documentation for details","Si veda la documentazione per maggiori dettagli"
js/emailchef/admin.js ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * EMailChef admin javascript
3
+ *
4
+ * Javascript to be run on admin pages
5
+ */
6
+
7
+ /**
8
+ * Setup Ajax in system config for loading groups
9
+ */
10
+ function initListObserver(url) {
11
+ $('emailchef_newsletter_emailchef_list').observe('change', function (event) {
12
+ var currentGroupSelected = $('emailchef_newsletter_emailchef_default_group').value;
13
+ var updater = new Ajax.Updater('emailchef_newsletter_emailchef_default_group', url, {
14
+ method: 'get',
15
+ onSuccess: function () {
16
+ $('emailchef_newsletter_emailchef_default_group').value = currentGroupSelected;
17
+ },
18
+ parameters: {list: $('emailchef_newsletter_emailchef_list').value}
19
+ });
20
+ }); // End of emailchef list change
21
+ }
22
+
23
+ function initSelfTestObserver(url) {
24
+ $('emailchef_selftest_button').observe('click', function (event) {
25
+ var request = new Ajax.Request(url, {
26
+ method: 'get',
27
+ onFailure: function(transport) {$('messages').update('<ul class="messages"><li class="error-msg"><ul><li>Error checking connection details</li></ul></li></ul>')},
28
+ onComplete: function(transport) {
29
+ $('messages').update(transport.responseText);
30
+ Element.hide('loading-mask');
31
+ },
32
+ parameters: {
33
+ username_ws: $('emailchef_newsletter_emailchef_username_ws').value,
34
+ password_ws: $('emailchef_newsletter_emailchef_password_ws').value
35
+ }
36
+ });
37
+ }); // End of emailchef selftest button click change
38
+ }
package.xml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>eMailChef_Email_Marketing</name>
4
+ <version>2.7.5</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.opensource.org/licenses/academic.php">Academic Free License (AFL)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Easily send targeted emails to your clients. Segment and synchronize customers and orders with your eMailChef account.</summary>
10
+ <description>eMailChef is the perfect marketing tool to add an intuitive and solid eMail campaign solution to your Magento eCommerce.&#xD;
11
+ &#xD;
12
+ The extension allows you to:&#xD;
13
+ * transfer customers and orders relevant information to eMailChef dashboard&#xD;
14
+ * segment customers based on orders, abandoned carts, subscription date, etc.&#xD;
15
+ * synchronize Magento an eMailChef subscription status&#xD;
16
+ * Increase sales with automated messages to reward loyal customers, recover abandoned carts, repeat purchases, engage inactive customers.&#xD;
17
+ &#xD;
18
+ It supports custom customer fields synchronization, multiple stores and a scalable structure to support a big or growing eCommerce.</description>
19
+ <notes>First community release</notes>
20
+ <authors><author><name>eMailChef</name><user>emailchef</user><email>info@emailchef.com</email></author></authors>
21
+ <date>2016-03-13</date>
22
+ <time>21:11:02</time>
23
+ <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="emailchef"><dir name="emailchefsync"><file name="confirm.phtml" hash="4cc51eec964f9adc861d2adeeab2e159"/><file name="fieldsmapping.phtml" hash="f081cbcc9505dd2a751e3c371dfd66d4"/><file name="filter.phtml" hash="ee871c5ecf502ce490e124c79749f04c"/><file name="sysconfigjavascript.phtml" hash="54b6b0eede87cea5623ce4c53d3bb19a"/><file name="viewdatatransferlog.phtml" hash="fcc13d34146e22630d1a170888b2cc73"/></dir></dir></dir><dir name="layout"><file name="emailchef.xml" hash="483a27e7658ed30eabbf4ccb6c49e32d"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="emailchef.xml" hash="ae1a0ff16778698b944b0bc47022a3da"/></dir><dir name="template"><dir name="emailchef"><dir name="customer"><dir name="account"><dir name="dashboard"><file name="info.phtml" hash="460c819142337968742c0d3f3ea2d70b"/></dir></dir></dir><file name="index.phtml" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="subscribe.phtml" hash="c1120655930feee69a36eb17d06cd28c"/></dir></dir></dir></dir><dir name="enterprise"><dir name="default"><dir name="layout"><file name="emailchef.xml" hash="a05826432214fdfa4a504ccb97ed30f0"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="EMailChef_EMailChefSync.xml" hash="d168206ac099f1f2820bc482dc41fd32"/></dir></target><target name="magelocale"><dir name="en_US"><file name="EMailChef_EMailChefSync.csv" hash="2c2af98653250a10f19f8800ce653a5f"/></dir><dir name="it_IT"><file name="EMailChef_EMailChefSync.csv" hash="4c26494d0f811fe272b8d96f5296ec2f"/></dir></target><target name="mageweb"><dir name="js"><dir name="emailchef"><file name="admin.js" hash="3dec32e3f22caaf2b08550b25d329137"/></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="emailchef"><dir name="emailchefsync"><file name="emailchef.css" hash="f4677eafd94f55b21f692f1a1a4418a4"/><dir name="images"><file name="EMailChef_300_200_transparent_small.png" hash="b77c12541d578e3837fd8dd84287472d"/></dir></dir></dir><dir name="images"><file name="EMailChef_300_200_transparent_small.png" hash="b77c12541d578e3837fd8dd84287472d"/></dir></dir></dir></dir></target><target name="magecommunity"><dir name="EMailChef"><dir name="EMailChefSync"><dir name="Block"><dir name="Adminhtml"><dir name="Emailchef"><file name="Grid.php" hash="d2a3345bc696652e530fda1af2fbaa53"/></dir><file name="Emailchefbackend.php" hash="ec91007a6241138036eaef8e17d231bd"/><dir name="Log"><file name="Grid.php" hash="0db1b79afaecb26a1dc24e8907fe27a0"/></dir><file name="Log.php" hash="207af70ed0f43aa8ffd3781b422301cf"/><dir name="Sync"><file name="Grid.php" hash="0c260fe778a4ea90370ae69ee515c3e2"/></dir><file name="Sync.php" hash="671f148a9f202022373c72b13b539ba6"/><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Timezone.php" hash="93b1bcd9a90a5f2bf41f61573b2ca05c"/></dir><file name="Testbutton.php" hash="589cc7c54e89119c04df0694ff480449"/></dir></dir></dir></dir><dir name="Checkout"><file name="Subscribe.php" hash="9210cae9ac928334172ac320739f9909"/></dir><file name="Filters.php" hash="5e2d11f5745b29ace6ffd2391cbd0725"/><file name="Index.php" hash="f81f4560e001904fe932e37779f596b3"/></dir><dir name="Helper"><file name="Customer.php" hash="2536e068e34da684d04292fe316443c5"/><file name="Data.php" hash="dc99faa205fcca3fca09f7be639bc524"/><file name="Order.php" hash="1accc4d002bd35a600cfc1ca44ffcc74"/></dir><dir name="Model"><dir name="Adminhtml"><dir name="System"><dir name="Clone"><dir name="Mappings"><file name="Custom.php" hash="0078206fe6c6bd081d8428ff6476e59c"/></dir></dir><dir name="Source"><dir name="Cron"><file name="Frequency.php" hash="37df5528600d8341da41d0cc10b11a07"/><file name="Hours.php" hash="d40324183409e7f2d930670ff6dacc61"/></dir><file name="Fields.php" hash="4a19370ad6fc4ecbfc386fb09a73cc1e"/></dir><file name=".DS_Store" hash="699eb0995de74828d9f23655e826e581"/></dir><file name=".DS_Store" hash="173bd8294aed6b0b02e19ffb8e68cbd5"/></dir><file name="Config.php" hash="1673a5bc70d5d0d9f34a0c56a8e8cd15"/><file name="Cron.php" hash="1acdd3e8b566a071abc441bf8918d838"/><file name="EMailChef.php" hash="437dad8c72017bc16f3de697aea36d93"/><file name="EMailChefWsImport.php" hash="10451b9a5947d45c3314e2054bdc195a"/><file name="Job.php" hash="dfe36405177326d15e1bebdb08874b21"/><file name="Log.php" hash="58e8e6cb86330d3c59069fb296b9b4fd"/><dir name="Mysql14"><dir name="EMailChef"><file name="Collection.php" hash="cb68241cd01ebd90d8ddbc9dcdb715c3"/></dir><file name="EMailChef.php" hash="a497d4b9997f3d151b5a51b3d6998f2a"/></dir><dir name="Mysql4"><dir name="Job"><file name="Collection.php" hash="ba1292353eef4e045d8c72de5e7769d6"/></dir><file name="Job.php" hash="384997974ab3e9de8d7ba1211b15c443"/><dir name="Log"><file name="Collection.php" hash="ceeb26d021f95e99880682b3b7af817b"/></dir><file name="Log.php" hash="ea770e1528045a8ccdb9bd4e59871be3"/><dir name="Sync"><file name="Collection.php" hash="5bfde1db8cac1f77f3ac4c625f4345c6"/></dir><file name="Sync.php" hash="759298c97fc80f1e66972ffb78f7ff5a"/></dir><file name="Observer.php" hash="26d4dd4c7a3455b316189df408cc9012"/><dir name="Source"><file name="Groups.php" hash="0154ecf02a3270accf04447ac1674801"/><file name="Lists.php" hash="7ba86d3afb767b4e79a994a376ccf7fb"/><file name="Store.php" hash="80599650cd05006e2dd40c9b628cd545"/></dir><file name="Subscriber.php" hash="781b551a91122a2b9bc6bbeecfeacff5"/><file name="Sync.php" hash="0f977fd0c8b31275a257831048119194"/><file name="Webserviceusernamevalidator.php" hash="f63b53fe27fda5577d93d523afb41c5a"/><file name="Wssend.php" hash="6a1852323adbe3f356081a2215bd2e9a"/><file name=".DS_Store" hash="6f2c4920df9dd2405271ef9b6495cacc"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="ConfigurationController.php" hash="d8b83bc8d3ce26065fb02478e608de6c"/><file name="EmailchefbackendController.php" hash="da7805443770f5237f414e6d4b671606"/><file name="FieldsmappingController.php" hash="2179ea6b4af996119da131e16b98a6b1"/><file name="FilterController.php" hash="bb7a37a13bc7806940869fff0d0e32cd"/><file name="LogController.php" hash="3dd0493229d5a72e6107d7a5b3c40daf"/><file name="SyncController.php" hash="36b329636bb36b53255515a2aa008b71"/><file name="ViewdatatransferlogController.php" hash="9c365252d2f19dc083a1e37f08d3d459"/></dir><file name="IndexController.php" hash="496e64c0017cad1e4ca3054fc7bec8b2"/><file name="TestController.php" hash="3f33f416a780c73ca084209e0b15733e"/></dir><dir name="data"><dir name="emailchef_setup"><file name="data-upgrade-2.6.1-2.7.0.php" hash="8d5d8d7d0bc17a1713f3d3e4e2f5a152"/><file name="data-upgrade-2.7.0-2.7.1.php" hash="ee4db9ad27329df5ff266c5743034bf1"/></dir></dir><dir name="etc"><file name="config.xml" hash="ffa53e7bc300fe10757810c1b61c4194"/><file name="system.xml" hash="fc9d505c9ae6411c31b276992e43e548"/></dir><dir name="lib"><dir name="emailchef"><file name="composer.json" hash="ce2632f1142f528af40cd4e3847e5d16"/><file name="composer.lock" hash="77160029c175c981c1c211ef1a633e31"/><dir name="src"><dir name="Command"><dir name="Api"><file name="AddEmailsToGroupCommand.php" hash="6a9c5cbfdeb309460614c37fbb59b51e"/><file name="CreateContactCommand.php" hash="fd4f1b6031cbb9553bc162c0a4c8c982"/><file name="CreateSegmentCommand.php" hash="713fc967af2ea10e8f1812f41050d56f"/><file name="DeleteContactCommand.php" hash="3695d465e99b6b0043f2b9d62ccb591a"/><file name="GetAuthenticationTokenCommand.php" hash="638082e753ae3b1513ad41c355cf5919"/><file name="GetContactFromEmailCommand.php" hash="f8ae9b6c2f3ad30c49f420b19153319c"/><file name="GetListFieldsCommand.php" hash="eb20042dc648ce5346c5b3cbd399d1e2"/><file name="GetListSegmentsCommand.php" hash="4ba2286ffaf027101330a1253b3cddb4"/><file name="GetListsCommand.php" hash="e701c5994c365453b027fbdfdcc7a8ec"/><file name="GetPredefinedFieldsCommand.php" hash="79bda491223b61ec7dad630eb60c3cf4"/><file name="GetSegmentCommand.php" hash="8a59af05a57584d9c8fb32afb3fba379"/><file name="ImportContactsCommand.php" hash="17c3dd74132c36d73929b73b07e3b184"/><file name="ImportContactsInGroupCommand.php" hash="3ad7291d5fe56642984a4276d3ef5ab5"/><file name="UpdateSegmentCommand.php" hash="9488cbd85eb973f7d48433c32e24af44"/></dir></dir><dir name="Service"><file name="ApiService.php" hash="7824c933c44a8491fe9334338b0fafcb"/></dir></dir><dir name="test"><file name="phpunit.xml" hash="829f0c39f029c0d0ab092c5c6fd8d301"/><dir name="unit"><dir name="Command"><file name="AddEmailsToGroupCommandTest.php" hash="75a8404f94d8e309f02bb9b64e9c2120"/><file name="CreateSegmentCommandTest.php" hash="7ef3ceb2ffa4469fe950ba4f25dd903a"/><file name="GetAuthenticationTokenCommandTest.php" hash="12d673b9fbc583df9d45f3481ebd44ec"/><file name="ImportContactsCommandTest.php" hash="e6ea4e1e5df69ba52d0c0c96e3e101ce"/></dir></dir></dir><dir name="vendor"><file name="autoload.php" hash="83838c2118adc16023a8ef43073033c8"/><dir name="composer"><file name="ClassLoader.php" hash="9c1e7fe1a9eb1693e07ee4420ca5361e"/><file name="autoload_classmap.php" hash="8645d3a4e3ad87e7cf4d88a46717aab4"/><file name="autoload_namespaces.php" hash="cc14160111f4c826b2d2f7d3607cd929"/><file name="autoload_psr4.php" hash="8101210abd86efa0c6c2b176feb02eb2"/><file name="autoload_real.php" hash="7367f6c0c32fe6e2143fb8035b968a3a"/><file name="installed.json" hash="c11b9c8f89ab3517257f24de51cd98e9"/></dir><dir name="nategood"><dir name="httpful"><file name="LICENSE.txt" hash="7ca5638737732644abff32e3692d3f08"/><file name="README.md" hash="a66bf378ff0e33997f001b1f8914f113"/><file name="bootstrap.php" hash="43403ece6b45e45b41226f492bd26a00"/><file name="build" hash="60d32512c85fd00edaa34ffa661a2673"/><file name="composer.json" hash="f4d44577667e084ce4caf4c59ac23eb0"/><dir name="examples"><file name="freebase.php" hash="be0393bad689907ef0bca220c782b2e9"/><file name="github.php" hash="cf5b514b4dbcb52d4b82a33dab26e26e"/><file name="override.php" hash="1d6a4995a66732da8663f4b918fc7f70"/><file name="showclix.php" hash="fd7d0d44c75d63cfbcbcc194b8f69f9f"/></dir><dir name="src"><dir name="Httpful"><file name="Bootstrap.php" hash="51d17ae72a57c65546486b435776c2bd"/><dir name="Exception"><file name="ConnectionErrorException.php" hash="a49ab01edd81689362a97e02295f7a0e"/></dir><dir name="Handlers"><file name="CsvHandler.php" hash="269db178b45c9e6e1a16cf2c4440ddb1"/><file name="FormHandler.php" hash="e675ecb22f91e30d57ca35fe3c6374f6"/><file name="JsonHandler.php" hash="d5461f6a8b86da134b029b4916594590"/><file name="MimeHandlerAdapter.php" hash="34010b71fb36f33b9e448b74e2e39e0f"/><file name="README.md" hash="fcad8bf687507c77de6f4f7806707726"/><file name="XHtmlHandler.php" hash="9a9a41aea61b8704a9a98e727a4ca27e"/><file name="XmlHandler.php" hash="c25296058b3954baafe034d2e464ae2c"/></dir><file name="Http.php" hash="dfdca2d11fb4dea5c1abd054cb6be852"/><file name="Httpful.php" hash="eb04ecd891d3c48927a5897e3449d0a4"/><file name="Mime.php" hash="77faccc1070d3d2dbafbb3cfc77ad1a9"/><file name="Proxy.php" hash="d45089ad4c29a84ad65a1a381e7327bc"/><file name="Request.php" hash="897337705e2fa79d2b983af47dd19061"/><dir name="Response"><file name="Headers.php" hash="6a6267acdca14d6ec7e0dd5c2785a738"/></dir><file name="Response.php" hash="ab18c330d7b0044c315704954fae0e54"/></dir></dir><dir name="tests"><dir name="Httpful"><file name="HttpfulTest.php" hash="404bb70a04fc9ad548f41d5fe8ba28f5"/><file name="requestTest.php" hash="4febb97fefe75e79330526b4d47e1de7"/></dir><file name="bootstrap-server.php" hash="5c4cd2603d8936d6b5c1c38d698113ad"/><file name="phpunit.xml" hash="f36b3a0ba9fc6db70b4e32ba87883b39"/><dir name="static"><file name="test.json" hash="01d6c8b6c785adff197ff820909740e7"/></dir><file name="test_image.jpg" hash="255d85184ea945fc9d6bd6366a23a145"/></dir><file name=".gitignore" hash="6bd5c19cb1b9adb0223f58c272e2bfd8"/><file name=".travis.yml" hash="db6c7675e766a565e94040ffa06801bd"/></dir></dir></dir></dir></dir><dir name="sql"><dir name="emailchef_setup"><file name="mysql4-install-0.1.0.php" hash="2c503698e89eb5ca27feef563455c334"/><file name="mysql4-install-2.3.0.php" hash="6015f9a0aa56c874333bda358ce36c50"/><file name="mysql4-install-2.4.0.php" hash="68c15d5830e59c6a2840d9c1096c3918"/><file name="mysql4-upgrade-0.1.0-1.0.0.php" hash="2c503698e89eb5ca27feef563455c334"/><file name="mysql4-upgrade-0.3.0-1.0.0.php" hash="7f4813a164c9d75e47a4ce0bb15a1511"/><file name="mysql4-upgrade-1.0.0-1.5.2.php" hash="a25dc5c3193164b9c460193ee28daf0d"/><file name="mysql4-upgrade-2.1.3-2.2.0.php" hash="6a160864837daf1bb1dd6955f1cf9b59"/><file name="mysql4-upgrade-2.2.0-2.3.0.php" hash="c9e5bf6ac04871b071fc22e010d7b3a4"/><file name="mysql4-upgrade-2.2.1-2.3.0.php" hash="c9e5bf6ac04871b071fc22e010d7b3a4"/><file name="mysql4-upgrade-2.3.0-2.3.1.php" hash="dffc26ae01d24236673bda7075cf4747"/><file name="mysql4-upgrade-2.3.1-2.3.2.php" hash="2bbeaa910873c9f47875275e1a11979e"/><file name="mysql4-upgrade-2.3.2-2.4.0.php" hash="68c15d5830e59c6a2840d9c1096c3918"/><file name="mysql4-upgrade-2.4.0-2.4.1.php" hash="acda14236900c30b1cb71be8e6a34329"/><file name="mysql4-upgrade-2.6.1-2.7.0.php" hash="f85d104d7350403fdd8dd8e53c8ed8c1"/></dir></dir></dir></dir></target></contents>
24
+ <compatible/>
25
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
26
+ </package>
skin/adminhtml/default/default/emailchef/emailchefsync/emailchef.css ADDED
@@ -0,0 +1 @@
 
0
  background: url(./images/EMailChef_300_200_transparent_small.png) 10px 0 no-repeat;
1
  text-indent: -9999px;
2
  overflow: hidden;
1
+ h4 { font-size: 1.05em; margin-bottom: 0.6em; overflow: hidden; }
2
  background: url(./images/EMailChef_300_200_transparent_small.png) 10px 0 no-repeat;
3
  text-indent: -9999px;
4
  overflow: hidden;
skin/adminhtml/default/default/emailchef/emailchefsync/images/EMailChef_300_200_transparent_small.png ADDED
Binary file
skin/adminhtml/default/default/images/EMailChef_300_200_transparent_small.png ADDED
Binary file