Copernica_MarketingSoftware - Version 1.2.4

Version Notes

Improvements:
- Deleted an unnecessary SOAP call.

Bugs:

- Fixed, when deleting a customer from the backoffice an error occured.

Download this release

Release Info

Developer Cream
Extension Copernica_MarketingSoftware
Version 1.2.4
Comparing to
See all releases


Version 1.2.4

Files changed (75) hide show
  1. app/code/community/Copernica/MarketingSoftware/Block/Adminhtml/Marketingsoftware/Export.php +26 -0
  2. app/code/community/Copernica/MarketingSoftware/Block/Adminhtml/Marketingsoftware/Link.php +26 -0
  3. app/code/community/Copernica/MarketingSoftware/Block/Adminhtml/Marketingsoftware/Settings.php +26 -0
  4. app/code/community/Copernica/MarketingSoftware/Helper/Api.php +1092 -0
  5. app/code/community/Copernica/MarketingSoftware/Helper/Config.php +559 -0
  6. app/code/community/Copernica/MarketingSoftware/Helper/Data.php +333 -0
  7. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Address.php +327 -0
  8. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Attributes.php +113 -0
  9. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Customer.php +256 -0
  10. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Name.php +120 -0
  11. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Order.php +385 -0
  12. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Order/Item.php +199 -0
  13. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Order/Item/Options.php +138 -0
  14. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Price.php +237 -0
  15. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Product.php +411 -0
  16. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Quote.php +359 -0
  17. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Quote/Item.php +199 -0
  18. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Quote/Item/Options.php +143 -0
  19. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Storeview.php +182 -0
  20. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Subscription.php +163 -0
  21. app/code/community/Copernica/MarketingSoftware/Model/Abstraction/readme.txt +7 -0
  22. app/code/community/Copernica/MarketingSoftware/Model/AsyncPomSoapClient.php +295 -0
  23. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Abstract.php +121 -0
  24. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Address/Subprofile.php +77 -0
  25. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Cartitem/Subprofile.php +108 -0
  26. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Order/Subprofile.php +89 -0
  27. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Orderitem/Subprofile.php +92 -0
  28. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profile.php +33 -0
  29. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profilecustomer.php +47 -0
  30. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profileorder.php +59 -0
  31. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profilequote.php +59 -0
  32. app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profilesubscription.php +38 -0
  33. app/code/community/Copernica/MarketingSoftware/Model/Error.php +115 -0
  34. app/code/community/Copernica/MarketingSoftware/Model/Marketingsoftware.php +34 -0
  35. app/code/community/Copernica/MarketingSoftware/Model/Mysql4/Queue.php +11 -0
  36. app/code/community/Copernica/MarketingSoftware/Model/Mysql4/Queue/Collection.php +39 -0
  37. app/code/community/Copernica/MarketingSoftware/Model/Observer.php +345 -0
  38. app/code/community/Copernica/MarketingSoftware/Model/PomSoapClient.php +280 -0
  39. app/code/community/Copernica/MarketingSoftware/Model/Queue.php +56 -0
  40. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/Abstract.php +79 -0
  41. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerAdd.php +39 -0
  42. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerFull.php +97 -0
  43. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerModify.php +27 -0
  44. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerRemove.php +52 -0
  45. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/OrderAdd.php +10 -0
  46. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/OrderModify.php +82 -0
  47. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItem.php +53 -0
  48. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItemAdd.php +15 -0
  49. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItemModify.php +16 -0
  50. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItemRemove.php +16 -0
  51. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteModify.php +57 -0
  52. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/StartSync.php +239 -0
  53. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/SubscriptionAdd.php +10 -0
  54. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/SubscriptionModify.php +62 -0
  55. app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/SubscriptionRemove.php +10 -0
  56. app/code/community/Copernica/MarketingSoftware/controllers/Adminhtml/Marketingsoftware/ExportController.php +115 -0
  57. app/code/community/Copernica/MarketingSoftware/controllers/Adminhtml/Marketingsoftware/LinkController.php +159 -0
  58. app/code/community/Copernica/MarketingSoftware/controllers/Adminhtml/Marketingsoftware/SettingsController.php +127 -0
  59. app/code/community/Copernica/MarketingSoftware/controllers/ProductController.php +159 -0
  60. app/code/community/Copernica/MarketingSoftware/controllers/UnsubscribeController.php +41 -0
  61. app/code/community/Copernica/MarketingSoftware/etc/adminhtml.xml +48 -0
  62. app/code/community/Copernica/MarketingSoftware/etc/config.xml +161 -0
  63. app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-install-1.2.0.php +20 -0
  64. app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.5-1.1.6.php +21 -0
  65. app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.6-1.1.7.php +18 -0
  66. app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.7-1.1.8.php +25 -0
  67. app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.8-1.2.0.php +86 -0
  68. app/design/adminhtml/default/default/template/marketingsoftware/export.phtml +174 -0
  69. app/design/adminhtml/default/default/template/marketingsoftware/link.phtml +666 -0
  70. app/design/adminhtml/default/default/template/marketingsoftware/settings.phtml +223 -0
  71. app/etc/modules/Copernica_MarketingSoftware.xml +16 -0
  72. js/copernica/marketingsoftware/collection.js +304 -0
  73. js/copernica/marketingsoftware/database.js +395 -0
  74. js/copernica/marketingsoftware/field.js +275 -0
  75. package.xml +23 -0
app/code/community/Copernica/MarketingSoftware/Block/Adminhtml/Marketingsoftware/Export.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Export Block
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ class Copernica_MarketingSoftware_Block_Adminhtml_Marketingsoftware_Export extends Mage_Core_Block_Template
9
+ {
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setTemplate('marketingsoftware/export.phtml');
14
+ }
15
+
16
+ public function getIframeUrl()
17
+ {
18
+ return $this->getUrl('*/*/progress', array('_secure' => true));
19
+ }
20
+
21
+ public function getPostUrl()
22
+ {
23
+ return $this->getUrl('*/*/get', array('_secure' => true));
24
+ }
25
+ }
26
+ ?>
app/code/community/Copernica/MarketingSoftware/Block/Adminhtml/Marketingsoftware/Link.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings Block
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ class Copernica_MarketingSoftware_Block_Adminhtml_Marketingsoftware_Link extends Mage_Core_Block_Template
9
+ {
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setTemplate('marketingsoftware/link.phtml');
14
+ }
15
+
16
+ public function getAjaxUrl()
17
+ {
18
+ return $this->getUrl('*/*/checkajax', array('_secure' => true));
19
+ }
20
+
21
+ public function getPostUrl()
22
+ {
23
+ return $this->getUrl('*/*/saveProfilesAndCollections', array('_secure' => true));
24
+ }
25
+ }
26
+ ?>
app/code/community/Copernica/MarketingSoftware/Block/Adminhtml/Marketingsoftware/Settings.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings Block
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ class Copernica_MarketingSoftware_Block_Adminhtml_Marketingsoftware_Settings extends Mage_Core_Block_Template
9
+ {
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setTemplate('marketingsoftware/settings.phtml');
14
+ }
15
+
16
+ public function getCheckSettingsUrl()
17
+ {
18
+ return $this->getUrl('*/*/checker', array('_secure' => true));
19
+ }
20
+
21
+ public function getPostUrl()
22
+ {
23
+ return $this->getUrl('*/*/send', array('_secure' => true));
24
+ }
25
+ }
26
+ ?>
app/code/community/Copernica/MarketingSoftware/Helper/Api.php ADDED
@@ -0,0 +1,1092 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copernica_MarketingSoftware_Helper_Api
4
+ * This file holds the class that is used to communicate with Copernica
5
+ * Copernica Marketing Software v 1.2.0
6
+ * March 2011
7
+ * http://www.copernica.com/
8
+ */
9
+
10
+ /** Require some additional file for exceptions */
11
+ require_once(dirname(__FILE__).'/../Model/Error.php');
12
+
13
+ /**
14
+ * CopernicaAPI class
15
+ * Class with methods to communicate with the Copernica API
16
+ */
17
+ class Copernica_MarketingSoftware_Helper_Api extends Mage_Core_Helper_Abstract
18
+ {
19
+ /**
20
+ * The main SOAPAPI object that will be used for all calls
21
+ * @var SoapClient
22
+ */
23
+ public $soapclient;
24
+
25
+ /**
26
+ * The Copernica account name that is sent with the constructor
27
+ * @var string
28
+ */
29
+ private $account;
30
+
31
+ /**
32
+ * Store the id of the database
33
+ * @var integer
34
+ */
35
+ private $databaseID = false;
36
+
37
+ /**
38
+ * Store the id of the collection
39
+ * @var integer
40
+ */
41
+ private $collectionID = array();
42
+
43
+ /**
44
+ * Checks the connection settings and initializes the soap client
45
+ * @param string URL of the copernica API
46
+ * @param string Account name
47
+ * @param string User name
48
+ * @param string Password
49
+ */
50
+ public function init($url, $username, $accountname, $password)
51
+ {
52
+ $helper = Mage::helper('marketingsoftware');
53
+
54
+ // store error information
55
+ $this->account = $accountname;
56
+
57
+ try {
58
+ // construct SOAPAPI object
59
+ $this->soapclient = Mage::getModel('marketingsoftware/asyncPomSoapClient', array(
60
+ 'url' => $url,
61
+ 'login' => $username,
62
+ 'account' => $accountname,
63
+ 'password' => $password
64
+ ));
65
+ } catch (Exception $e) {
66
+
67
+ // there is no connection
68
+ $this->soapclient = false;
69
+
70
+ if ($e instanceOf CopernicaError) {
71
+ throw $e;
72
+ } else {
73
+ // throw an error
74
+ throw new CopernicaError(COPERNICAERROR_UNREACHABLE);
75
+ }
76
+ }
77
+ return $this;
78
+ }
79
+
80
+ /**
81
+ * Is this API instance valid?
82
+ * @param boolean also validate the configuration
83
+ * @throws Exception
84
+ * @return boolean
85
+ */
86
+ public function check($extensive = false)
87
+ {
88
+ // if no soapclient object exists, there is a problem with the connection
89
+ if (!is_object($this->soapclient)) throw new CopernicaError(COPERNICAERROR_UNREACHABLE);
90
+
91
+ // check for invalid login
92
+ $objarray = get_object_vars($this->soapclient);
93
+
94
+ // return API Error
95
+ if (isset($objarray['__soap_fault'])) throw new CopernicaError(COPERNICAERROR_LOGINFAILURE);
96
+
97
+ // If we should not do an extensive check, return now
98
+ if (!$extensive) return true;
99
+
100
+ // Get the config
101
+ $config = Mage::helper('marketingsoftware/config');
102
+
103
+ // check the database and collection names, might throw an exception
104
+ $this->getDatabaseId();
105
+ $this->getCollectionId($config->getCartItemsCollectionName());
106
+ $this->getCollectionId($config->getOrdersCollectionName());
107
+ $this->getCollectionId($config->getOrderItemsCollectionName());
108
+ $this->getCollectionId($config->getAddressesCollectionName());
109
+
110
+ // else we have a valid login
111
+ return true;
112
+ }
113
+
114
+ /**
115
+ * Get the database id
116
+ * @param string
117
+ * @return integer
118
+ */
119
+ protected function getDatabaseId($databaseName = false)
120
+ {
121
+ // Did we already have this id, return it
122
+ if ($this->databaseID !== false) return $this->databaseID;
123
+
124
+ // Get the database name
125
+ $identifier = ($databaseName === false) ? Mage::helper('marketingsoftware/config')->getDatabaseName() : $databaseName;
126
+
127
+ // Get the database object
128
+ $request = $this->soapclient->Account_Database(array('identifier' => $identifier));
129
+
130
+ // Get the response object from the request
131
+ $object = $this->soapclient->result($request);
132
+
133
+ // If it not an object, throw an error
134
+ if (!is_object($object)) throw (new CopernicaError(COPERNICAERROR_NODATABASE));
135
+
136
+ // if no databasename was given, store it
137
+ if ($databaseName === false) $this->databaseID = $object->id;
138
+
139
+ // store and return the object
140
+ return $object->id;
141
+ }
142
+
143
+ /**
144
+ * Get the collection id
145
+ * @param string
146
+ * @return integer
147
+ */
148
+ protected function getCollectionId($name, $databaseName = '')
149
+ {
150
+ // Did we already have this id, return it
151
+ if (isset($this->collectionID[$databaseName.$name])) return $this->collectionID[$databaseName.$name];
152
+
153
+ // Get the soap collection object
154
+ $request = $this->soapclient->Database_Collection(array(
155
+ 'id' => $this->getDatabaseId($databaseName ? $databaseName : false),
156
+ 'identifier' => $name
157
+ ));
158
+
159
+ // Get the response object from the request
160
+ $object = $this->soapclient->result($request);
161
+
162
+ // no object is returned
163
+ if (!is_object($object)) throw (new CopernicaError(COPERNICAERROR_NOCOLLECTION));
164
+
165
+ // store and return the object
166
+ return $this->collectionID[$databaseName.$name] = $object->id;
167
+ }
168
+
169
+ /**
170
+ * Get the Copernica profiles from the api, which match a certain identifier
171
+ * @param identifier
172
+ */
173
+ public function searchProfiles($identifier)
174
+ {
175
+ // Search the profiles
176
+ return $this->soapclient->result(
177
+ $this->soapclient->Database_SearchProfiles(array(
178
+ 'id' => $this->getDatabaseId(),
179
+ 'requirements' => array(
180
+ $this->soapclient->toObject(array(
181
+ 'fieldname' => 'customer_id',
182
+ 'value' => $identifier,
183
+ 'operator' => '='
184
+ ))
185
+ )
186
+ ))
187
+ );
188
+ }
189
+
190
+ /**
191
+ * Merge the given array of profiles
192
+ * @param array
193
+ * @return array
194
+ */
195
+ public function mergeProfiles($profiles)
196
+ {
197
+ // Get the first item
198
+ $first = $profiles[0];
199
+
200
+ // iterate over the rest of the items
201
+ for ($i = 1; $i < count($profiles); $i++)
202
+ {
203
+ $this->soapclient->Profile_Move(array(
204
+ 'id' => $first->id,
205
+ 'profile' => $this->soapclient->toObject(array(
206
+ 'id' => $profiles[$i]->id
207
+ )),
208
+ ));
209
+ }
210
+ }
211
+ /**
212
+ * Update the profiles given a customer and return the found profiles
213
+ * @param Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer
214
+ * @param String optional identifier for this update action
215
+ * @return array
216
+ */
217
+ public function updateProfiles($data, $identifier = false)
218
+ {
219
+ // Do we have valid identifier
220
+ if ($identifier !== false)
221
+ {
222
+ // search for a profile
223
+ $response = $this->searchProfiles($identifier);
224
+
225
+ // no match found, use the normal identifier instead
226
+ if ($response->length == 0) $identifier = false;
227
+ }
228
+
229
+ // if we are calling this function with an incorrect profile, just
230
+ // return because we will damage too much
231
+ if ($data->id() == false)
232
+ {
233
+ // Log the profile identifier that is given
234
+ Mage::log("Identifier has type: ".gettype($data->id()) ." and value ".$data->id() ? 'true':'false');
235
+ Mage::log("Data is of type: ".get_class($data));
236
+ Mage::log("Data: ".print_r($data->toArray(), true));
237
+ foreach (debug_backtrace() as $tr) Mage::log(" ".$tr['file'].''.$tr['line']);
238
+
239
+ // and get lost
240
+ return;
241
+ }
242
+
243
+ // Update the profiles and wait for the result because, we want to search for it
244
+ $this->soapclient->result($this->soapclient->Database_updateProfiles(array(
245
+ 'id' => $this->getDatabaseId(),
246
+ 'requirements' => array(
247
+ $this->soapclient->toObject(array(
248
+ 'fieldname' => 'customer_id',
249
+ 'value' => $identifier == false ? $data->id() : $identifier,
250
+ 'operator' => '='
251
+ ))
252
+ ),
253
+ 'create' => true,
254
+ 'fields' => $data->toArray()
255
+ )));
256
+ }
257
+
258
+ /**
259
+ * Remove the profile
260
+ *
261
+ * @param Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer $data
262
+ * @return void
263
+ */
264
+ public function removeProfiles($data)
265
+ {
266
+ $profileIds = array();
267
+ $profiles = $this->searchProfiles($data->id());
268
+
269
+ foreach($profiles->items as $item) {
270
+ $profileIds[] = $item->id;
271
+ }
272
+
273
+ $this->soapclient->Database_removeProfiles(array(
274
+ 'id' => $this->getDatabaseId(),
275
+ 'ids' => $profileIds
276
+ ));
277
+ }
278
+
279
+ /**
280
+ * Update the subprofiles given, the profile identifier
281
+ * the collection name and the data
282
+ * @param string customer identifier
283
+ * @param Copernica_MarketingSoftware_Model_Copernica_Subprofile
284
+ */
285
+ public function updateCartItemSubProfiles($profileID, $data)
286
+ {
287
+ // The collection name and id are determined
288
+ $collectionName = Mage::helper('marketingsoftware/config')->getCartItemsCollectionName();
289
+ $collectionId = $this->getCollectionId($collectionName);
290
+
291
+ // Update the subprofiles
292
+ $this->soapclient->Profile_updateSubProfiles(array(
293
+ 'id' => $profileID,
294
+ 'requirements' => array(
295
+ $this->soapclient->toObject(array(
296
+ 'fieldname' => 'item_id',
297
+ 'value' => $data->id(),
298
+ 'operator' => '='
299
+ ))
300
+ ),
301
+ 'collection' => $this->soapclient->toObject(array('id' => $collectionId)),
302
+ 'create' => true,
303
+ 'fields' => $data->toArray(),
304
+ ));
305
+ }
306
+
307
+ /**
308
+ * Remove the cart items which have been purchased
309
+ * @param string customer identifier
310
+ * @param integer quote item id
311
+ */
312
+ public function removeOldCartItems($profileID, $quoteId)
313
+ {
314
+ // The collection name and id are determined
315
+ $collectionName = Mage::helper('marketingsoftware/config')->getCartItemsCollectionName();
316
+ $collectionId = $this->getCollectionId($collectionName);
317
+
318
+ // find the subprofiles
319
+ $subprofiles = $this->soapclient->result($this->soapclient->Profile_searchSubProfiles(array(
320
+ 'id' => $profileID,
321
+ 'requirements' => array(
322
+ $this->soapclient->toObject(array(
323
+ 'fieldname' => 'quote_id',
324
+ 'value' => $quoteId,
325
+ 'operator' => '='
326
+ )),
327
+ $this->soapclient->toObject(array(
328
+ 'fieldname' => 'status',
329
+ 'value' => 'deleted',
330
+ 'operator' => '!='
331
+ ))
332
+ ),
333
+ 'collection' => $this->soapclient->toObject(array('id' => $collectionId)),
334
+ )));
335
+
336
+ // Build an array of ids
337
+ $ids = array();
338
+ foreach ($subprofiles->items as $subprofile) $ids[] = $subprofile->id;
339
+
340
+ // Remove the subprofiles
341
+ $this->soapclient->Collection_removeSubProfiles(array(
342
+ 'id' => $collectionId,
343
+ 'ids' => $ids
344
+ ));
345
+ }
346
+
347
+ /**
348
+ * Update the subprofiles given, the profile identifier
349
+ * the collection name and the data
350
+ * @param string customer identifier
351
+ * @param Copernica_MarketingSoftware_Model_Copernica_Subprofile
352
+ */
353
+ public function updateOrderSubProfile($profileID, $data)
354
+ {
355
+ // The collection name and id are determined
356
+ $collectionName = Mage::helper('marketingsoftware/config')->getOrdersCollectionName();
357
+ $collectionId = $this->getCollectionId($collectionName);
358
+
359
+ // Update the subprofiles
360
+ $this->soapclient->Profile_updateSubProfiles(array(
361
+ 'id' => $profileID,
362
+ 'requirements' => array(
363
+ $this->soapclient->toObject(array(
364
+ 'fieldname' => 'order_id',
365
+ 'value' => $data->id(),
366
+ 'operator' => '='
367
+ ))
368
+ ),
369
+ 'collection' => $this->soapclient->toObject(array('id' => $collectionId)),
370
+ 'create' => true,
371
+ 'fields' => $data->toArray(),
372
+ ));
373
+ }
374
+
375
+ /**
376
+ * Update the subprofiles given, the profile identifier
377
+ * the collection name and the data
378
+ * @param string customer identifier
379
+ * @param Copernica_MarketingSoftware_Model_Copernica_Subprofile
380
+ */
381
+ public function updateOrderItemSubProfiles($profileID, $data)
382
+ {
383
+ // The collection name and id are determined
384
+ $collectionName = Mage::helper('marketingsoftware/config')->getOrderItemsCollectionName();
385
+ $collectionId = $this->getCollectionId($collectionName);
386
+
387
+ // Update the subprofiles
388
+ $this->soapclient->Profile_updateSubProfiles(array(
389
+ 'id' => $profileID,
390
+ 'requirements' => array(
391
+ $this->soapclient->toObject(array(
392
+ 'fieldname' => 'item_id',
393
+ 'value' => $data->id(),
394
+ 'operator' => '='
395
+ ))
396
+ ),
397
+ 'collection' => $this->soapclient->toObject(array('id' => $collectionId)),
398
+ 'create' => true,
399
+ 'fields' => $data->toArray(),
400
+ ));
401
+ }
402
+
403
+ /**
404
+ * Update the subprofiles given, the profile identifier
405
+ * the collection name and the data
406
+ * @param string customer identifier
407
+ * @param Copernica_MarketingSoftware_Model_Copernica_Subprofile
408
+ */
409
+ public function updateAddressSubProfiles($profileID, $data)
410
+ {
411
+ // The collection name and id are determined
412
+ $collectionName = Mage::helper('marketingsoftware/config')->getAddressesCollectionName();
413
+ $collectionId = $this->getCollectionId($collectionName);
414
+
415
+ // Update the subprofiles
416
+ $this->soapclient->Profile_updateSubProfiles(array(
417
+ 'id' => $profileID,
418
+ 'requirements' => array(
419
+ $this->soapclient->toObject(array(
420
+ 'fieldname' => 'address_id',
421
+ 'value' => $data->id(),
422
+ 'operator' => '='
423
+ ))
424
+ ),
425
+ 'collection' => $this->soapclient->toObject(array('id' => $collectionId)),
426
+ 'create' => true,
427
+ 'fields' => $data->toArray(),
428
+ ));
429
+ }
430
+
431
+ /**
432
+ * Does a database with the given name exist?
433
+ * @param string
434
+ * @return boolean
435
+ */
436
+ public function databaseExist($databaseName)
437
+ {
438
+ // We have a valid id
439
+ try
440
+ {
441
+ return $this->getDatabaseId($databaseName) > 0;
442
+ }
443
+ catch (Exception $e)
444
+ {
445
+ return false;
446
+ }
447
+ }
448
+
449
+ /**
450
+ * Is the database with the given name valid?
451
+ * @param string
452
+ * @return string 'ok', 'notexists', 'notvalid'
453
+ */
454
+ public function validateDatabase($databaseName)
455
+ {
456
+ try
457
+ {
458
+ // Get the database id
459
+ $id = $this->getDatabaseId($databaseName);
460
+ }
461
+ catch (Exception $e)
462
+ {
463
+ // the database does not exist?
464
+ return 'notexists';
465
+ }
466
+
467
+ // we should check whether this database has the crucial field: customer_id
468
+ $response = $this->soapclient->result($this->soapclient->Database_field(array(
469
+ 'id' => $id,
470
+ 'identifier' => 'customer_id'
471
+ )));
472
+
473
+ // is there are respone object?
474
+ if (!is_object($response) || $response->id == 0) return 'notvalid';
475
+
476
+ // everything seems ok
477
+ return 'ok';
478
+ }
479
+
480
+ /**
481
+ * Repair the database with the given name valid?
482
+ * @param string
483
+ * @return string 'ok', 'notexists', 'notvalid'
484
+ */
485
+ public function repairDatabase($databaseName)
486
+ {
487
+ try
488
+ {
489
+ // Get the database id
490
+ $id = $this->getDatabaseId($databaseName);
491
+ }
492
+ catch (Exception $e)
493
+ {
494
+ // create the database
495
+ $response = $this->soapclient->result($this->soapclient->Account_createDatabase(array('name' => $databaseName)));
496
+
497
+ // Get the database id
498
+ $id = $response->id;
499
+ }
500
+
501
+ // create the field customer id
502
+ $this->soapclient->Database_createField(array(
503
+ 'id' => $id,
504
+ 'name' => 'customer_id',
505
+ 'type' => 'text'
506
+ ));
507
+
508
+ // everything seems ok
509
+ return $this->validateDatabase($databaseName);
510
+ }
511
+
512
+ /**
513
+ * Is the collection in the given database, with the given type
514
+ * and name valid?
515
+ * @param string $databaseName name of the database
516
+ * @param string $collectionType 'cartproducts', 'orders', 'orderproducts', 'addresses'
517
+ * @param string $collectionName name of the collection
518
+ * @return string 'ok', 'notexists', 'notvalid'
519
+ */
520
+ public function validateCollection($databaseName, $collectionType, $collectionName)
521
+ {
522
+ // Get the database id
523
+ try
524
+ {
525
+ $collectionId = $this->getCollectionId($collectionName, $databaseName);
526
+ }
527
+ catch (Exception $e)
528
+ {
529
+ // does the collection exist?
530
+ return 'notexists';
531
+ }
532
+
533
+ // there are some required fields, check if they exist
534
+ $requiredFields = array(
535
+ 'cartproducts' => array('item_id', 'quote_id', 'status'),
536
+ 'orders' => array('order_id', 'quote_id'),
537
+ 'orderproducts' => array('item_id', 'order_id'),
538
+ 'addresses' => array('address_id'),
539
+ );
540
+
541
+ // is this a known collection type
542
+ if (!isset($requiredFields[$collectionType])) return 'impossible';
543
+
544
+ // initialize the request array
545
+ $requests = array();
546
+
547
+ foreach($requiredFields[$collectionType] as $field)
548
+ {
549
+ // we should check whether this collection has the crucial fields
550
+ $requests[] = $this->soapclient->Collection_field(array(
551
+ 'id' => $collectionId,
552
+ 'identifier' => $field
553
+ ));
554
+ }
555
+
556
+ // iterate over the requests
557
+ foreach ($requests as $request)
558
+ {
559
+ // Get the response
560
+ $response = $this->soapclient->result($request);
561
+
562
+ // is there a respone object?
563
+ if (!is_object($response) || $response->id == 0) return 'notvalid';
564
+ }
565
+
566
+ // everything seems ok
567
+ return 'ok';
568
+ }
569
+
570
+ /**
571
+ * Repair the collection in the given database, with the given type
572
+ * and name
573
+ * @param string $databaseName name of the database
574
+ * @param string $collectionType 'cartproducts', 'orders', 'orderproducts', 'addresses'
575
+ * @param string $collectionName name of the collection
576
+ * @return string 'ok', 'notexists', 'notvalid'
577
+ */
578
+ public function repairCollection($databaseName, $collectionType, $collectionName)
579
+ {
580
+ try
581
+ {
582
+ // Get the collection id
583
+ $collectionId = $this->getCollectionId($collectionName, $databaseName);
584
+ }
585
+ catch (Exception $e)
586
+ {
587
+ // Get the Database id
588
+ $id = $this->getDatabaseId($databaseName);
589
+
590
+ // The collection should be created
591
+ $response = $this->soapclient->result($this->soapclient->Database_createCollection(array(
592
+ 'id' => $id,
593
+ 'name' => $collectionName
594
+ )));
595
+
596
+ // Get the collection id
597
+ $collectionId = $response->id;
598
+ }
599
+
600
+ // there are some required fields, check if they exist
601
+ $requiredFields = array(
602
+ 'cartproducts' => array('item_id', 'quote_id', 'status'),
603
+ 'orders' => array('order_id', 'quote_id'),
604
+ 'orderproducts' => array('item_id', 'order_id'),
605
+ 'addresses' => array('address_id'),
606
+ );
607
+
608
+ // is this a known collection type
609
+ if (!isset($requiredFields[$collectionType])) return 'impossible';
610
+
611
+ // iterate over the required fields and them if needed
612
+ foreach($requiredFields[$collectionType] as $field)
613
+ {
614
+ // we should check whether this collection has the crucial fields
615
+ $this->soapclient->Collection_createField(array(
616
+ 'id' => $collectionId,
617
+ 'name' => $field,
618
+ 'type' => 'text',
619
+ ));
620
+ }
621
+
622
+ // everything seems ok
623
+ return 'ok';
624
+ }
625
+
626
+ /**
627
+ * Validate the field, given the collection name.
628
+ * When the collection name is empty the check is performed for the database
629
+ * @param String fieldname in our Magento plug-in
630
+ * @param String fieldname in the customers Copernica environment
631
+ * @param String name of the database in the customers Copernica environment
632
+ * @param String collection name (bool)false, 'cartproducts', 'orders', 'orderproducts', 'addresses'
633
+ * @param String name of the collection in the customers Copernica environment
634
+ * @return 'ok', 'notexists', 'notvalid'
635
+ */
636
+ public function validateField($magentoFieldName, $copernicaFieldName, $database, $collection = false, $collectionName = false)
637
+ {
638
+ switch($collection)
639
+ {
640
+ case "cartproducts": return $this->validateCartProductsField($database, $collectionName, $magentoFieldName, $copernicaFieldName);
641
+ case "orders": return $this->validateOrdersField($database, $collectionName, $magentoFieldName, $copernicaFieldName);
642
+ case "orderproducts": return $this->validateOrderProductsField($database, $collectionName, $magentoFieldName, $copernicaFieldName);
643
+ case "addresses": return $this->validateAddressesField($database, $collectionName, $magentoFieldName, $copernicaFieldName);
644
+
645
+ // no collection given use database
646
+ default: return $this->validateDatabaseField($database, $magentoFieldName, $copernicaFieldName);
647
+ }
648
+ }
649
+
650
+ /**
651
+ * Validate the field from the database
652
+ * @param String name of the database in the customers Copernica environment
653
+ * @param String name of the field in our Magento plug-in
654
+ * @param String fieldname in the customers Copernica environment
655
+ * @return 'ok', 'notexists', 'notvalid'
656
+ */
657
+ private function validateDatabaseField($databaseName, $magentoFieldName, $copernicaFieldName)
658
+ {
659
+ // Get the database id
660
+ $id = $this->getDatabaseId($databaseName);
661
+
662
+ // Get the response
663
+ $response = $this->soapclient->result($this->soapclient->Database_field(array(
664
+ 'id' => $id,
665
+ 'identifier' => $copernicaFieldName
666
+ )));
667
+
668
+ // does the field exist
669
+ if (!is_object($response) || $response->id == 0) return 'notexists';
670
+
671
+ // any extra checks base on which field we are checking
672
+ switch($magentoFieldName)
673
+ {
674
+ case "email": return ($response->type != 'email') ? 'notvalid' : 'ok';
675
+ case "newsletter":
676
+ $retrieveDatabaseCall = $this->soapclient->Database_retrieve(array('id' => $id));
677
+ $unsubscribeValuesCall = $this->soapclient->Database_unsubscribeValues(array('id' => $id));
678
+ $databaseCallbacksCall = $this->soapclient->Database_callbacks(array('id' => $id));
679
+
680
+ // is the unsubscribe behaviour set?
681
+ $database = $this->soapclient->result($retrieveDatabaseCall);
682
+
683
+ // unsubscribe behaviour should be update
684
+ if ($database->unsubscribebehavior != 'update') return 'notvalid';
685
+
686
+ // get the the unsubscribe values
687
+ $unsubscribeValues = $this->soapclient->result($unsubscribeValuesCall);
688
+
689
+ // by default the right field is not found
690
+ $found = false;
691
+
692
+ // iterate over the fields
693
+ foreach ($unsubscribeValues as $field => $newValue)
694
+ {
695
+ // ignore all other fields
696
+ if ($field != $copernicaFieldName) continue;
697
+
698
+ // we found it
699
+ $found = true;
700
+
701
+ // The new value should be 'unsubscribed_copernica'
702
+ if ($newValue != 'unsubscribed_copernica') return 'notvalid';
703
+ }
704
+
705
+ // the correct unsubscribe field should be found
706
+ if (!$found) return 'notvalid';
707
+
708
+ // are the callbacks installed?
709
+ $callbacks = $this->soapclient->result($databaseCallbacksCall);
710
+
711
+ // No valid result is returned, it is not valid
712
+ if (!isset($callbacks->items)) return 'notvalid';
713
+
714
+ // Get the url for the callback
715
+ $callbackUrl = Mage::helper('marketingsoftware')->unsubscribeCallbackUrl();
716
+
717
+ // We assume the callback is not there
718
+ $found = false;
719
+
720
+ // check all returned callbacks
721
+ foreach ($callbacks->items as $callback)
722
+ {
723
+ if (
724
+ $callback->url == $callbackUrl &&
725
+ $callback->method == 'json' &&
726
+ $callback->expression == "profile.$copernicaFieldName == 'unsubscribed_copernica';"
727
+ ) $found = true;
728
+ }
729
+
730
+ // did we find the correct thingy
731
+ return $found ? 'ok' :'notvalid';
732
+ }
733
+
734
+ // everyhing seems to be ok
735
+ return 'ok';
736
+ }
737
+
738
+ /**
739
+ * Get the field object from a certain collection with a certain name
740
+ * @param String name of the database in the customers Copernica environment
741
+ * @param String name of the collection in the customers Copernica environment
742
+ * @param String fieldname in the customers Copernica environment
743
+ * @return object SOAP object
744
+ */
745
+ private function collectionFieldData($database, $collectionName, $fieldName)
746
+ {
747
+ // Get the id of this collection
748
+ $id = $this->getCollectionId($collectionName, $database);
749
+
750
+ // return the response
751
+ return $this->soapclient->result($this->soapclient->Collection_field(array(
752
+ 'id' => $id,
753
+ 'identifier' => $fieldName
754
+ )));
755
+ }
756
+
757
+ /**
758
+ * Validate the field from the cart items collection
759
+ * @param String name of the database in the customers Copernica environment
760
+ * @param String name of the collection in the customers Copernica environment
761
+ * @param String name of the field in our Magento plug-in
762
+ * @param String fieldname in the customers Copernica environment
763
+ * @return 'ok', 'notexists', 'notvalid'
764
+ */
765
+ private function validateCartProductsField($database, $collectionName, $magentoFieldName, $copernicaFieldName)
766
+ {
767
+ // Get the id of this collection
768
+ $object = $this->collectionFieldData($database, $collectionName, $copernicaFieldName);
769
+
770
+ // does the field exist
771
+ if (!is_object($object) || $object->id == 0) return 'notexists';
772
+
773
+ // some special cases
774
+ switch($magentoFieldName)
775
+ {
776
+ case 'timestamp': return (in_array($object->type, array('empty_datetime', 'datetime'))) ? 'ok' : 'notvalid';
777
+ case 'url':
778
+ case 'image': return ($object->length > 100) ? 'ok' : 'notvalid';
779
+ case 'categories':
780
+ case 'options':
781
+ case 'attributes': return (($object->length > 150 || $object->big) && isset($object->lines) && $object->lines > 1) ? 'ok' : 'notvalid';
782
+ }
783
+
784
+ // default it is okay
785
+ return 'ok';
786
+ }
787
+
788
+ /**
789
+ * Validate the field from the orders collection
790
+ * @param String name of the database in the customers Copernica environment
791
+ * @param String name of the collection in the customers Copernica environment
792
+ * @param String name of the field in our Magento plug-in
793
+ * @param String fieldname in the customers Copernica environment
794
+ * @return 'ok', 'notexists', 'notvalid'
795
+ */
796
+ private function validateOrdersField($database, $collectionName, $magentoFieldName, $copernicaFieldName)
797
+ {
798
+ // Get the id of this collection
799
+ $object = $this->collectionFieldData($database, $collectionName, $copernicaFieldName);
800
+
801
+ // does the field exist
802
+ if (!is_object($object) || $object->id == 0) return 'notexists';
803
+
804
+ // some special cases
805
+ switch($magentoFieldName)
806
+ {
807
+ case 'timestamp': return (in_array($object->type, array('empty_datetime', 'datetime'))) ? 'ok' : 'notvalid';
808
+ }
809
+
810
+ // default it is okay
811
+ return 'ok';
812
+ }
813
+
814
+ /**
815
+ * Validate the field from the order items collection
816
+ * @param String name of the database in the customers Copernica environment
817
+ * @param String name of the collection in the customers Copernica environment
818
+ * @param String name of the field in our Magento plug-in
819
+ * @param String fieldname in the customers Copernica environment
820
+ * @return 'ok', 'notexists', 'notvalid'
821
+ */
822
+ private function validateOrderProductsField($database, $collectionName, $magentoFieldName, $copernicaFieldName)
823
+ {
824
+ // Get the id of this collection
825
+ $object = $this->collectionFieldData($database, $collectionName, $copernicaFieldName);
826
+
827
+ // does the field exist
828
+ if (!is_object($object) || $object->id == 0) return 'notexists';
829
+
830
+ // some special cases
831
+ switch($magentoFieldName)
832
+ {
833
+ case 'timestamp': return (in_array($object->type, array('empty_datetime', 'datetime'))) ? 'ok' : 'notvalid';
834
+ case 'url':
835
+ case 'image': return ($object->length > 100) ? 'ok' : 'notvalid';
836
+ case 'categories':
837
+ case 'options':
838
+ case 'attributes': return (($object->length > 150 || $object->big) && $object->lines > 1) ? 'ok' : 'notvalid';
839
+ }
840
+
841
+ // default it is okay
842
+ return 'ok';
843
+ }
844
+
845
+ /**
846
+ * Validate the field from the addresses collection
847
+ * @param String name of the database in the customers Copernica environment
848
+ * @param String name of the collection in the customers Copernica environment
849
+ * @param String name of the field in our Magento plug-in
850
+ * @param String fieldname in the customers Copernica environment
851
+ * @return 'ok', 'notexists', 'notvalid'
852
+ */
853
+ private function validateAddressesField($database, $collectionName, $magentoFieldName, $copernicaFieldName)
854
+ {
855
+ // Get the id of this collection
856
+ $object = $this->collectionFieldData($database, $collectionName, $copernicaFieldName);
857
+
858
+ // does the field exist
859
+ if (!is_object($object) || $object->id == 0) return 'notexists';
860
+
861
+ // some special cases
862
+ switch($magentoFieldName)
863
+ {
864
+ case "email": return ($object->type != 'email') ? 'notvalid' : 'ok';
865
+ case "telephone": return ($object->type != 'phone_gsm') ? 'notvalid' : 'ok';
866
+ case "fax": return ($object->type != 'phone_fax') ? 'notvalid' : 'ok';
867
+ }
868
+
869
+ // default it is okay
870
+ return 'ok';
871
+ }
872
+
873
+ /**
874
+ * Repair the field, given the collection name.
875
+ * When the collection name is empty the check is performed for the database
876
+ * @param String fieldname in our Magento plug-in
877
+ * @param String fieldname in the customers Copernica environment
878
+ * @param String collection name (bool)false, 'cartproducts', 'orders', 'orderproducts', 'addresses'
879
+ * @param String name of the collection in the customers Copernica environment
880
+ * @return 'ok', 'notexists', 'notvalid'
881
+ */
882
+ public function repairField($magentoFieldName, $copernicaFieldName, $database, $collection = false, $containerName = false)
883
+ {
884
+ if ($collection == false) return $this->repairDatabaseField($database, $magentoFieldName, $copernicaFieldName);
885
+ else return $this->repairCollectionField($database, $containerName, $collection, $magentoFieldName, $copernicaFieldName);
886
+ }
887
+
888
+ /**
889
+ * Repair the field from the cart items collection
890
+ * @param String name of the collection in the customers Copernica environment
891
+ * @param String name of the field in our Magento plug-in
892
+ * @param String fieldname in the customers Copernica environment
893
+ * @return 'ok', 'notexists', 'notvalid'
894
+ */
895
+ private function repairDatabaseField($databaseName, $magentoFieldName, $copernicaFieldName)
896
+ {
897
+ $id = $this->getDatabaseId($databaseName);
898
+
899
+ // Get the field object
900
+ $object = $this->soapclient->result($this->soapclient->Database_field(array(
901
+ 'id' => $id,
902
+ 'identifier' => $copernicaFieldName
903
+ )));
904
+
905
+ // does the field exist
906
+ if (!is_object($object) || $object->id == 0)
907
+ {
908
+ // we have to create this field
909
+ $definition = array(
910
+ 'id' => $id,
911
+ 'name' => $copernicaFieldName,
912
+ 'display'=> '1',
913
+ 'type' => 'text',
914
+ );
915
+ }
916
+ else
917
+ {
918
+ // we have to create this field
919
+ $definition = array('id' => $object->id);
920
+ }
921
+
922
+ // What field is this?
923
+ switch($magentoFieldName)
924
+ {
925
+ case "email": $definition['type'] = 'email'; break;
926
+ case "newsletter":
927
+ // is the unsubscribe behaviour set?
928
+ $database = $this->soapclient->result($this->soapclient->Database_retrieve(array('id' => $id)));
929
+
930
+ // unsubscribe behaviour should be update
931
+ if ($database->unsubscribebehavior != 'update')
932
+ {
933
+ $this->soapclient->Database_update(array(
934
+ 'id' => $id,
935
+ 'unsubscribebehavior' => 'update'
936
+ ));
937
+ }
938
+
939
+ // get the the unsubscribe values
940
+ $unsubscribeValues = $this->soapclient->result($this->soapclient->Database_unsubscribeValues(array('id' => $id)));
941
+
942
+ // the correct unsubscribe field should be added
943
+ $unsubscribeValues[$copernicaFieldName] = 'unsubscribed_copernica';
944
+
945
+ // store these values
946
+ $this->soapclient->Database_setUnsubscribeValues(array('id' => $id, 'fields' => $unsubscribeValues));
947
+
948
+ // are the callbacks installed?
949
+ $callbacks = $this->soapclient->result($this->soapclient->Database_callbacks(array('id' => $id)));
950
+
951
+ // Get the url for the callback
952
+ $callbackUrl = Mage::helper('marketingsoftware')->unsubscribeCallbackUrl();
953
+
954
+ // We assume the callback is not there
955
+ $found = false;
956
+
957
+ // did we receive callbacks?
958
+ if (isset($callbacks->items))
959
+ {
960
+ // check all returned callbacks
961
+ foreach ($callbacks->items as $callback)
962
+ {
963
+ if (
964
+ $callback->url == $callbackUrl &&
965
+ $callback->method == 'json' &&
966
+ $callback->expression == "profile.$copernicaFieldName == 'unsubscribed_copernica';"
967
+ ) $found = true;
968
+ }
969
+ }
970
+
971
+ // there is no valid callback found
972
+ if (!$found)
973
+ {
974
+ // create the callback
975
+ $this->soapclient->Database_createCallback(array(
976
+ 'id' => $id,
977
+ 'url' => $callbackUrl,
978
+ 'method' => 'json',
979
+ 'expression' => "profile.$copernicaFieldName == 'unsubscribed_copernica';",
980
+ ));
981
+ }
982
+
983
+ break;
984
+ }
985
+
986
+ // create the field or update the existing field
987
+ if (!is_object($object) || $object->id == 0) $result = $this->soapclient->Database_createField($definition);
988
+ elseif (count($definition) > 1) $result = $this->soapclient->Field_update($definition);
989
+
990
+ // wait for the field update / creation to be finished
991
+ if (isset($result)) $this->soapclient->result($result);
992
+
993
+ // recheck the field
994
+ return $this->validateField($magentoFieldName, $copernicaFieldName, $databaseName);
995
+ }
996
+
997
+ /**
998
+ * Repair the field from the cart items collection
999
+ * @param String name of the collection in the customers Copernica environment
1000
+ * @param String collection name 'cartproducts', 'orders', 'orderproducts', 'addresses'
1001
+ * @param String name of the field in our Magento plug-in
1002
+ * @param String fieldname in the customers Copernica environment
1003
+ * @return 'ok', 'notexists', 'notvalid'
1004
+ */
1005
+ private function repairCollectionField($database, $collectionName, $collection, $magentoFieldName, $copernicaFieldName)
1006
+ {
1007
+ // Get the id of this collection
1008
+ $object = $this->collectionFieldData($database, $collectionName, $copernicaFieldName);
1009
+
1010
+ // does the field exist
1011
+ if (!is_object($object) || $object->id == 0)
1012
+ {
1013
+ // we have to create this field
1014
+ $definition = array(
1015
+ 'id' => $this->getCollectionId($collectionName, $database),
1016
+ 'name' => $copernicaFieldName,
1017
+ 'display'=> '1',
1018
+ 'type' => 'text',
1019
+ );
1020
+ }
1021
+ else
1022
+ {
1023
+ // we have to create this field
1024
+ $definition = array('id' => $object->id);
1025
+ }
1026
+
1027
+ // enrich the definition, given the collection
1028
+ $definition = $this->getFieldDefinition($collection, $magentoFieldName, $definition);
1029
+
1030
+ // create the field or update the existing field
1031
+ if (!is_object($object) || $object->id == 0) $this->soapclient->Collection_createField($definition);
1032
+ elseif (count($definition) > 1) $this->soapclient->CollectionField_update($definition);
1033
+
1034
+ // Assume the field exists now
1035
+ return 'ok';
1036
+ }
1037
+
1038
+ /**
1039
+ * Enrich the field collection
1040
+ * @param String collection name 'cartproducts', 'orders', 'orderproducts', 'addresses'
1041
+ * @param String name of the field in our Magento plug-in
1042
+ * @param array definition
1043
+ * @return array with enriched definition
1044
+ */
1045
+ private function getFieldDefinition($collection, $fieldName, $definition)
1046
+ {
1047
+ if ($collection == 'cartproducts' || $collection == 'orderproducts')
1048
+ {
1049
+ // some special cases, for the cart / order products
1050
+ switch($fieldName)
1051
+ {
1052
+ case 'timestamp': $definition['type'] = 'datetime'; break;
1053
+ case 'url':
1054
+ case 'image': $definition['length'] = 155; break;
1055
+ case 'categories': case 'options': case 'attributes':
1056
+ $definition['length'] = 255;
1057
+
1058
+ // both are needed for the current version
1059
+ $definition['textlines'] = $definition['lines'] = 4;
1060
+ break;
1061
+ }
1062
+ }
1063
+ elseif ($collection == 'orders' && $fieldName == 'timestamp')
1064
+ {
1065
+ $definition['type'] = 'datetime';
1066
+ }
1067
+ elseif ($collection == 'addresses')
1068
+ {
1069
+ switch($fieldName)
1070
+ {
1071
+ case "email": $definition['type'] = 'email'; break;
1072
+ case "telephone": $definition['type'] = 'phone_gsm'; break;
1073
+ case "fax": $definition['type'] = 'phone_fax'; break;
1074
+ }
1075
+ }
1076
+
1077
+ // return the definition
1078
+ return $definition;
1079
+ }
1080
+
1081
+ /**
1082
+ * Method that handles the calls to the API
1083
+ * @param string Name of the method
1084
+ * @param array Associative array of parameters
1085
+ * @return mixed
1086
+ */
1087
+ public function __call($methodname, $params)
1088
+ {
1089
+ // Call the soap client directly
1090
+ return $this->soapclient->__call($methodname, $params);
1091
+ }
1092
+ }
app/code/community/Copernica/MarketingSoftware/Helper/Config.php ADDED
@@ -0,0 +1,559 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_Helper_Config extends Mage_Core_Helper_Abstract
3
+ {
4
+ /**
5
+ * Define a prefix used for the config
6
+ * @name CONFIG_BASE a prefix
7
+ */
8
+ const CONFIG_BASE = 'marketingsoftware/';
9
+
10
+ /**
11
+ * Get the config item from the basic magento component
12
+ * @param string $name Name of the config parameter
13
+ */
14
+ private function _getConfig($name)
15
+ {
16
+ // scope is added to the beginning of the path
17
+ return (string)Mage::getConfig()->getNode(self::CONFIG_BASE . $name, 'default', 0);
18
+ }
19
+
20
+ /**
21
+ * Set the config item from the basic magento component
22
+ * @param string $name Name of the config parameter
23
+ * @param string $value Value that should be stored in the config
24
+ */
25
+ private function _setConfig($name, $value)
26
+ {
27
+ // is this value new the same as the existing value
28
+ if ($value === $this->_getConfig($name)) return;
29
+
30
+ // Store the value in the config
31
+ Mage::getConfig()->saveConfig(self::CONFIG_BASE . $name, $value);
32
+
33
+ // We changed something in the settings, clean the cache
34
+ Mage::getConfig()->cleanCache();
35
+
36
+ // some config items are not that interesting
37
+ if (in_array($name, array(
38
+ 'customer_progress_status',
39
+ 'order_progress_status',
40
+ 'subscription_progress_status',
41
+ 'cronjob_starttime',
42
+ 'cronjob_endtime',
43
+ 'cronjob_processedtasks',
44
+ ))) return;
45
+
46
+ // We have to reset the progress status
47
+ $this->setCustomerProgressStatus('0');
48
+ $this->setOrderProgressStatus('0');
49
+ $this->setSubscriptionProgressStatus('0');
50
+ }
51
+
52
+ /**
53
+ * Get the hostname from the config
54
+ * @return String
55
+ */
56
+ public function getHostname()
57
+ {
58
+ return $this->_getConfig('hostname');
59
+ }
60
+
61
+ /**
62
+ * Set the hostname from the config
63
+ * @return String
64
+ * @return Copernica_MarketingSoftware_Helper_Config
65
+ */
66
+ public function setHostname($value)
67
+ {
68
+ $this->_setConfig('hostname', $value);
69
+ return $this;
70
+ }
71
+
72
+ /**
73
+ * Get the username from the config
74
+ * @return String
75
+ */
76
+ public function getUsername()
77
+ {
78
+ return $this->_getConfig('username');
79
+ }
80
+
81
+ /**
82
+ * Set the username to the config
83
+ * @param String
84
+ * @return Copernica_MarketingSoftware_Helper_Config
85
+ */
86
+ public function setUsername($value)
87
+ {
88
+ $this->_setConfig('username', $value);
89
+ return $this;
90
+ }
91
+
92
+ /**
93
+ * Get the accountname from the config
94
+ * @return String
95
+ */
96
+ public function getAccount()
97
+ {
98
+ return $this->_getConfig('account');
99
+ }
100
+
101
+ /**
102
+ * Store the accountname in the config
103
+ * @param String
104
+ * @return Copernica_MarketingSoftware_Helper_Config
105
+ */
106
+ public function setAccount($value)
107
+ {
108
+ $this->_setConfig('account', $value);
109
+ return $this;
110
+ }
111
+
112
+ /**
113
+ * Get the password from the config
114
+ * @return String
115
+ */
116
+ public function getPassword()
117
+ {
118
+ return $this->_getConfig('password');
119
+ }
120
+
121
+ /**
122
+ * Set the password in the config
123
+ * @param String
124
+ */
125
+ public function setPassword($value)
126
+ {
127
+ $this->_setConfig('password', $value);
128
+ return $this;
129
+ }
130
+
131
+ /**
132
+ * Get the name of the database
133
+ * @return String
134
+ */
135
+ public function getDatabaseName()
136
+ {
137
+ return $this->_getConfig('database');
138
+ }
139
+
140
+ /**
141
+ * Set the name of the database
142
+ * @param String
143
+ * @return Copernica_MarketingSoftware_Helper_Config
144
+ */
145
+ public function setDatabaseName($value)
146
+ {
147
+ $this->_setConfig('database', $value);
148
+ return $this;
149
+ }
150
+
151
+ /**
152
+ * Get the linked customer fields
153
+ * @return array assoc array of fields which have been linked
154
+ */
155
+ public function getLinkedCustomerFields()
156
+ {
157
+ // Get the value
158
+ $value = $this->_getConfig('linked_customer_fields');
159
+
160
+ // What value is found?
161
+ $value = empty($value) ? array() : json_decode($value, true);
162
+
163
+ // is this an old data entry (prior to 1.2.0)
164
+ if (!isset($value['customer_email'])) return $value;
165
+
166
+ // yes this is old data... time for a small conversion
167
+ $oldValues = $value;
168
+ $newValues = array();
169
+
170
+ // iterate over the data
171
+ foreach ($oldValues as $key => $value)
172
+ {
173
+ $key = str_replace('customer_', '', $key);
174
+ $newValues[$key] = $value;
175
+ }
176
+
177
+ // store the converted values
178
+ $this->setLinkedCustomerFields($newValues);
179
+
180
+ // return the new Values
181
+ return $newValues;
182
+ }
183
+
184
+ /**
185
+ * Set the linked customer fields
186
+ * @param array assoc array of fields which have been linked
187
+ * @return Copernica_MarketingSoftware_Helper_Config
188
+ */
189
+ public function setLinkedCustomerFields($value)
190
+ {
191
+ $this->_setConfig('linked_customer_fields', json_encode($value));
192
+ return $this;
193
+ }
194
+
195
+ /**
196
+ * Get the name of the not-ordered products collection
197
+ * @return string
198
+ */
199
+ public function getCartItemsCollectionName()
200
+ {
201
+ return $this->_getConfig('cart_items_collection_name');
202
+ }
203
+
204
+ /**
205
+ * Set the name of the not-ordered products collection
206
+ * @param String
207
+ * @return Copernica_MarketingSoftware_Helper_Config
208
+ */
209
+ public function setCartItemsCollectionName($value)
210
+ {
211
+ $this->_setConfig('cart_items_collection_name', $value);
212
+ return $this;
213
+ }
214
+
215
+ /**
216
+ * Get the linked customer fields
217
+ * @return array assoc array of fields which have been linked
218
+ */
219
+ public function getLinkedCartItemFields()
220
+ {
221
+ $value = $this->_getConfig('linked_cart_item_fields');
222
+
223
+ // What value is found?
224
+ if (empty($value)) return array();
225
+ else return json_decode($value, true);
226
+ }
227
+
228
+ /**
229
+ * Get the linked customer fields
230
+ * @param array assoc array of fields which have been linked
231
+ * @return Copernica_MarketingSoftware_Helper_Config
232
+ */
233
+ public function setLinkedCartItemFields($value)
234
+ {
235
+ $this->_setConfig('linked_cart_item_fields', json_encode($value));
236
+ return $this;
237
+ }
238
+
239
+ /**
240
+ * Get the name of the orders collection
241
+ * @return String
242
+ */
243
+ public function getOrdersCollectionName()
244
+ {
245
+ return $this->_getConfig('orders_collection_name');
246
+ }
247
+
248
+ /**
249
+ * Set the name of the orders collection
250
+ * @param String
251
+ * @return Copernica_MarketingSoftware_Helper_Config
252
+ */
253
+ public function setOrdersCollectionName($value)
254
+ {
255
+ $this->_setConfig('orders_collection_name', $value);
256
+ return $this;
257
+ }
258
+
259
+ /**
260
+ * Get the linked order fields
261
+ * @return array assoc array of fields which have been linked
262
+ */
263
+ public function getLinkedOrderFields()
264
+ {
265
+ // Get the value
266
+ $value = $this->_getConfig('linked_order_fields');
267
+
268
+ // What value is found?
269
+ $value = empty($value) ? array() : json_decode($value, true);
270
+
271
+ // is this an old data entry (prior to 1.2.0)
272
+ if (!isset($value['order_timestamp'])) return $value;
273
+
274
+ // yes this is old data... time for a small conversion
275
+ $oldValues = $value;
276
+ $newValues = array();
277
+
278
+ // iterate over the data
279
+ foreach ($oldValues as $key => $value)
280
+ {
281
+ // remove the order prefix and rename the qty field
282
+ $key = ($key == 'order_qty') ? 'quantity' : str_replace('order_', '', $key);
283
+ $newValues[$key] = $value;
284
+ }
285
+
286
+ // store the converted values
287
+ $this->setLinkedOrderFields($newValues);
288
+
289
+ // return the new Values
290
+ return $newValues;
291
+ }
292
+
293
+ /**
294
+ * Set the linked order fields
295
+ * @param array assoc array of fields which have been linked
296
+ * @return Copernica_MarketingSoftware_Helper_Config
297
+ */
298
+ public function setLinkedOrderFields($value)
299
+ {
300
+ $this->_setConfig('linked_order_fields', json_encode($value));
301
+ return $this;
302
+ }
303
+
304
+ /**
305
+ * Get the name of the collection were all the orders are stored
306
+ * @return String
307
+ * @return Copernica_MarketingSoftware_Helper_Config
308
+ */
309
+ public function getOrderItemsCollectionName()
310
+ {
311
+ return $this->_getConfig('order_items_collection_name');
312
+ }
313
+
314
+ /**
315
+ * Get the name of the collection were all the orders are stored
316
+ * @param String
317
+ */
318
+ public function setOrderItemsCollectionName($value)
319
+ {
320
+ $this->_setConfig('order_items_collection_name', $value);
321
+ return $this;
322
+ }
323
+
324
+ /**
325
+ * Get the linked order item fields
326
+ * @return array assoc array of fields which have been linked
327
+ */
328
+ public function getLinkedOrderItemFields()
329
+ {
330
+ $value = $this->_getConfig('linked_order_item_fields');
331
+
332
+ // What value is found?
333
+ $value = empty($value) ? array() : json_decode($value, true);
334
+
335
+ // is this an old data entry (prior to 1.2.0)
336
+ if (!isset($value['product_internal_id'])) return $value;
337
+
338
+ // yes this is old data... time for a small conversion
339
+ $oldValues = $value;
340
+ $newValues = array();
341
+
342
+ // iterate over the data
343
+ foreach ($oldValues as $key => $value)
344
+ {
345
+ // remove the order prefix and rename the qty field
346
+ if ($key == 'product_qty') $key = 'quantity';
347
+ elseif ($key == 'product_base_row_total') $key = 'total_price';
348
+ else $key = str_replace('product_', '', $key);
349
+
350
+ // assign it to the new values
351
+ $newValues[$key] = $value;
352
+ }
353
+
354
+ // store the converted values
355
+ $this->setLinkedOrderItemFields($newValues);
356
+
357
+ // return the new Values
358
+ return $newValues;
359
+ }
360
+
361
+ /**
362
+ * Set the linked order item fields
363
+ * @param array assoc array of fields which have been linked
364
+ * @return Copernica_MarketingSoftware_Helper_Config
365
+ */
366
+ public function setLinkedOrderItemFields($value)
367
+ {
368
+ $this->_setConfig('linked_order_item_fields', json_encode($value));
369
+ return $this;
370
+ }
371
+
372
+ /**
373
+ * Get the address collection name
374
+ * @return String
375
+ */
376
+ public function getAddressesCollectionName()
377
+ {
378
+ return $this->_getConfig('address_collection_name');
379
+ }
380
+
381
+ /**
382
+ * Set the name of the collection with addresses
383
+ */
384
+ public function setAddressesCollectionName($value)
385
+ {
386
+ $this->_setConfig('address_collection_name', $value);
387
+ return $this;
388
+ }
389
+
390
+ /**
391
+ * Get the linked address fields
392
+ * @return array assoc array of fields which have been linked
393
+ */
394
+ public function getLinkedAddressFields()
395
+ {
396
+ $value = $this->_getConfig('linked_address_fields');
397
+
398
+ // What value is found?
399
+ $value = empty($value) ? array() : json_decode($value, true);
400
+
401
+ // is this an old data entry (prior to 1.2.0)
402
+ if (!isset($value['address_firstname'])) return $value;
403
+
404
+ // yes this is old data... time for a small conversion
405
+ $oldValues = $value;
406
+ $newValues = array();
407
+
408
+ // iterate over the data
409
+ foreach ($oldValues as $key => $value)
410
+ {
411
+ // remove the order prefix and rename the qty field
412
+ $key = str_replace('address_', '', $key);
413
+ $newValues[$key] = $value;
414
+ }
415
+
416
+ // store the converted values
417
+ $this->setLinkedAddressFields($newValues);
418
+
419
+ // return the new Values
420
+ return $newValues;
421
+ }
422
+
423
+ /**
424
+ * set the linked address fields
425
+ * @param array assoc array of fields which have been linked
426
+ * @return Copernica_MarketingSoftware_Helper_Config
427
+ */
428
+ public function setLinkedAddressFields($value)
429
+ {
430
+ $this->_setConfig('linked_address_fields', json_encode($value));
431
+ return $this;
432
+ }
433
+
434
+ /**
435
+ * Get the progress status for customers
436
+ * This is the created timestamp of the most recent customer which has
437
+ * been queued for synchronisation
438
+ * @return datetime
439
+ */
440
+ public function getCustomerProgressStatus()
441
+ {
442
+ return $this->_getConfig('customer_progress_status');
443
+ }
444
+
445
+ /**
446
+ * Set the progress status for customers
447
+ * This is the created timestamp of the most recent customer which has
448
+ * been queued for synchronisation
449
+ * @param datetime
450
+ */
451
+ public function setCustomerProgressStatus($value)
452
+ {
453
+ $this->_setConfig('customer_progress_status', $value);
454
+ return $this;
455
+ }
456
+
457
+ /**
458
+ * Get the progress status for orders
459
+ * This is the created timestamp of the most recent order which has
460
+ * been queued for synchronisation
461
+ * @return datetime
462
+ */
463
+ public function getOrderProgressStatus()
464
+ {
465
+ return $this->_getConfig('order_progress_status');
466
+ }
467
+
468
+ /**
469
+ * Set the progress status for orders
470
+ * This is the created timestamp of the most recent order which has
471
+ * been queued for synchronisation
472
+ * @param datetime
473
+ */
474
+ public function setOrderProgressStatus($value)
475
+ {
476
+ $this->_setConfig('order_progress_status', $value);
477
+ return $this;
478
+ }
479
+
480
+ /**
481
+ * Get the progress status for subscriptions
482
+ * This is the created timestamp of the most recent subscription which has
483
+ * been queued for synchronisation
484
+ * @return datetime
485
+ */
486
+ public function getSubscriptionProgressStatus()
487
+ {
488
+ return $this->_getConfig('subscription_progress_status');
489
+ }
490
+
491
+ /**
492
+ * Set the progress status for subscriptions
493
+ * This is the created timestamp of the most recent subscription which has
494
+ * been queued for synchronisation
495
+ * @param datetime
496
+ */
497
+ public function setSubscriptionProgressStatus($value)
498
+ {
499
+ $this->_setConfig('subscription_progress_status', $value);
500
+ return $this;
501
+ }
502
+
503
+ /**
504
+ * Get the last start time of the cronjob.
505
+ * @return datetime
506
+ */
507
+ public function getLastStartTimeCronjob()
508
+ {
509
+ return $this->_getConfig('cronjob_starttime');
510
+ }
511
+
512
+ /**
513
+ * Set the last start time of the cronjob.
514
+ * @param datetime
515
+ */
516
+ public function setLastStartTimeCronjob($value)
517
+ {
518
+ $this->_setConfig('cronjob_starttime', $value);
519
+ return $this;
520
+ }
521
+
522
+ /**
523
+ * Get the last end time of the cronjob.
524
+ * @return datetime
525
+ */
526
+ public function getLastEndTimeCronjob()
527
+ {
528
+ return $this->_getConfig('cronjob_endtime');
529
+ }
530
+
531
+ /**
532
+ * Set the last end time of the cronjob.
533
+ * @param datetime
534
+ */
535
+ public function setLastEndTimeCronjob($value)
536
+ {
537
+ $this->_setConfig('cronjob_endtime', $value);
538
+ return $this;
539
+ }
540
+
541
+ /**
542
+ * Get the number of processed records of the last cronjob run.
543
+ * @return integer
544
+ */
545
+ public function getLastCronjobProcessedTasks()
546
+ {
547
+ return (int)$this->_getConfig('cronjob_processedtasks');
548
+ }
549
+
550
+ /**
551
+ * Set the last end time of the cronjob.
552
+ * @param integer
553
+ */
554
+ public function setLastCronjobProcessedTasks($value)
555
+ {
556
+ $this->_setConfig('cronjob_processedtasks', $value);
557
+ return $this;
558
+ }
559
+ }
app/code/community/Copernica/MarketingSoftware/Helper/Data.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /** The CopernicaError is required **/
3
+ require_once(dirname(__FILE__).'/../Model/Error.php');
4
+
5
+ /**
6
+ * The base helper for the Copernica Marketingsoftware plug-in
7
+ */
8
+ class Copernica_MarketingSoftware_Helper_Data extends Mage_Core_Helper_Abstract
9
+ {
10
+ /**
11
+ * Helper method returns all supported customer fields
12
+ * @return array
13
+ */
14
+ public function supportedCustomerFields()
15
+ {
16
+ return array(
17
+ 'firstname' => 'Firstname',
18
+ 'middlename' => 'Middlename',
19
+ 'lastname' => 'Lastname',
20
+ 'email' => 'E-mail',
21
+ 'group' => 'Customer group',
22
+ 'newsletter' => 'Newsletter',
23
+ 'store_view' => 'Store view',
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Helper method returns all supported fields for
29
+ * the cart item collection
30
+ * @return array
31
+ */
32
+ public function supportedCartItemFields()
33
+ {
34
+ return array(
35
+ 'product_id' => 'product id',
36
+ 'name' => 'Product name',
37
+ 'sku' => 'SKU',
38
+ 'weight' => 'Weight',
39
+ 'quantity' => 'Quantity',
40
+ 'price' => 'Price',
41
+ 'timestamp' => 'Modified',
42
+ 'store_view' => 'Store view',
43
+ 'total_price' => 'Total price',
44
+ 'url' => 'Details URL',
45
+ 'image' => 'Image URL',
46
+ 'categories' => 'Categories',
47
+ 'options' => 'Product options',
48
+ 'attributes' => 'Product Attributes',
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Helper method returns all supported fields for
54
+ * the order collection
55
+ * @return array
56
+ */
57
+ public function supportedOrderFields()
58
+ {
59
+ return array(
60
+ 'increment_id' => 'Increment id',
61
+ 'timestamp' => 'Timestamp',
62
+ 'quantity' => 'Quantity',
63
+ //'subtotal' => 'Subtotal',
64
+ 'shipping' => 'Shipping costs',
65
+ 'total' => 'Order total',
66
+ 'weight' => 'Total weight',
67
+ 'currency' => 'Currency',
68
+ 'status' => 'Order status',
69
+ 'store_view' => 'Store view',
70
+ 'remote_ip' => 'Order ip address',
71
+ 'shipping_description' => 'Shipping description',
72
+ 'payment_description' => 'Payment description',
73
+ 'shipping_address_id' => 'Shipping Address id',
74
+ 'billing_address_id' => 'Billing Address id',
75
+ );
76
+ }
77
+
78
+ /**
79
+ * Helper method returns all supported fields for
80
+ * the cart item collection
81
+ * @return array
82
+ */
83
+ public function supportedOrderItemFields()
84
+ {
85
+ return array(
86
+ 'product_id' => 'product id',
87
+ 'increment_id' => 'Increment id',
88
+ 'name' => 'Product name',
89
+ 'sku' => 'SKU',
90
+ 'weight' => 'Weight',
91
+ 'quantity' => 'Quantity',
92
+ 'price' => 'Price',
93
+ 'timestamp' => 'Modified',
94
+ 'store_view' => 'Store view',
95
+ 'total_price' => 'Total price',
96
+ 'url' => 'Details URL',
97
+ 'image' => 'Image URL',
98
+ 'categories' => 'Categories',
99
+ 'options' => 'Product options',
100
+ 'attributes' => 'Product Attributes',
101
+ );
102
+ }
103
+
104
+ /**
105
+ * Helper method returns all supported fields for
106
+ * the address collection
107
+ * @return array
108
+ */
109
+ public function supportedAddressFields()
110
+ {
111
+ return array(
112
+ 'firstname' => 'Firstname',
113
+ 'middlename' => 'Middlename',
114
+ 'prefix' => 'Prefix',
115
+ 'lastname' => 'Lastname',
116
+ 'email' => 'E-mail',
117
+ 'company' => 'Company',
118
+ 'street' => 'Street',
119
+ 'city' => 'City',
120
+ 'state' => 'State',
121
+ 'zipcode' => 'Zip code',
122
+ 'country_id' => 'Country',
123
+ 'telephone' => 'Telephone number',
124
+ 'fax' => 'Fax number',
125
+ );
126
+ }
127
+
128
+ /**
129
+ * Get the version of this extension
130
+ * @return string version number
131
+ */
132
+ public function getExtensionVersion()
133
+ {
134
+ // Get the config and return the version from the config
135
+ $config = Mage::getConfig()->getModuleConfig('Copernica_MarketingSoftware')->asArray();
136
+ return $config['version'];
137
+ }
138
+
139
+ /**
140
+ * Check if there is a new version of the extension.
141
+ * @return boolean|Strubg Either false or the version number
142
+ */
143
+ public function checkNewVersion()
144
+ {
145
+ // if we cannot access remote URLs, don't return anything. A notice for this will already be shown
146
+ if (!$this->checkURL()) return false;
147
+
148
+ // version URL
149
+ $url = 'http://www.copernica.com/magento_extension_version.txt';
150
+
151
+ // get the version information from the URL
152
+ if (ini_get('allow_url_fopen') == '1') $data = @file_get_contents($url);
153
+ else
154
+ {
155
+ $ch = curl_init($url);
156
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5);
157
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
158
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
159
+ $data = curl_exec($ch);
160
+ curl_close($ch);
161
+ }
162
+
163
+ // trim the retrieved version
164
+ $data = trim($data);
165
+
166
+ // if the official version is smaller or equal to the current version, then we are ok
167
+ if (version_compare($data, $this->getExtensionVersion()) <= 0) return false;
168
+
169
+ // else, return the new available version for further processing
170
+ return $data;
171
+ }
172
+
173
+ /**
174
+ * Check if the connection URL does exists
175
+ * and if it does exists, check to see if it's SOAP
176
+ * @param string Connection URL (optional)
177
+ * @return boolean
178
+ */
179
+ public function checkConnectionURL($connectionURL = null)
180
+ {
181
+ // construct the full SOAP url, based on the default url setting or a custom one
182
+ if ($connectionURL) $url = $connectionURL."?SOAPAPI=WSDL";
183
+ else $url = Mage::helper('marketingsoftware/config')->getHostname()."?SOAPAPI=WSDL";
184
+
185
+ // validate the url either with file_get_contents and get_headers if it's available
186
+ if (ini_get('allow_url_fopen') == '1')
187
+ {
188
+ // check to see if it's alive
189
+ $checkURL = @file_get_contents($url, NULL, NULL, 0, 1);
190
+
191
+ // check to see if it's SOAP
192
+ if ($checkURL)
193
+ {
194
+ $contents = get_headers($url, 1);
195
+ if($contents['Content-Type'] == 'text/xml') return true;
196
+ else return false;
197
+ }
198
+ else return false;
199
+ }
200
+
201
+ // or validate via CURL
202
+ else
203
+ {
204
+ // let CURL process our data
205
+ $ch = curl_init($url);
206
+ curl_setopt($ch, CURLOPT_TIMEOUT, 5);
207
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
208
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
209
+ $data = curl_exec($ch);
210
+ $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
211
+ $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
212
+ curl_close($ch);
213
+
214
+ // check to see if it's SOAP
215
+ if($httpCode >= 200 && $httpCode < 300 && $contentType == 'text/xml') return true;
216
+ else return false;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Get the url for the unsubscribe callback
222
+ * @return String
223
+ */
224
+ public function unsubscribeCallbackUrl()
225
+ {
226
+ return Mage::getModel('core/url')->getUrl('copernica/unsubscribe/process', array());
227
+ }
228
+
229
+ /**
230
+ * Check if SOAP is enabled
231
+ * @return boolean|CopernicaError
232
+ */
233
+ public function checkSoap()
234
+ {
235
+ if (!extension_loaded('soap')) throw new CopernicaError(COPERNICAERROR_SOAPNOTENABLED);
236
+ else return true;
237
+ }
238
+
239
+ /**
240
+ * Check if we can use CURL or FOPEN
241
+ * @return boolean|CopernicaError
242
+ */
243
+ public function checkURL()
244
+ {
245
+ if (!function_exists('curl_version') && !ini_get('allow_url_fopen')) throw new CopernicaError(COPERNICAERROR_CURLNOTENABLED);
246
+ else return true;
247
+ }
248
+
249
+ /**
250
+ * Does the queue contain the magic token, which indicates that the synchronisation
251
+ * should be started?
252
+ * @return boolean
253
+ */
254
+ public function isSynchronisationStartScheduled()
255
+ {
256
+ // Construct a new resource for this because caching fucks it all up
257
+ $count = Mage::getResourceModel('marketingsoftware/queue_collection')
258
+ ->addFieldToFilter('action', 'start_sync')
259
+ ->getSize();
260
+
261
+ // Reset the count
262
+ return ($count > 0);
263
+ }
264
+
265
+ /**
266
+ * Is the Copernica module enabled?
267
+ * @return boolean
268
+ */
269
+ public function enabled()
270
+ {
271
+ // Get the setting from 'advanced/modules_disable_output/Copernica_MarketingSoftware'
272
+ return (Mage::getConfig()->getNode('advanced/modules_disable_output/Copernica_MarketingSoftware', 'default', 0) == 0);
273
+ }
274
+
275
+ /**
276
+ * Perform some default check to validate that the plug-in is configured correctly and working
277
+ * like it should be working.
278
+ * Note: this plug-in does not return anything but adds messages to the adminhtml session
279
+ */
280
+ public function validatePluginBehaviour()
281
+ {
282
+ // A new version is available
283
+ if ($version = $this->checkNewVersion()) Mage::getSingleton('adminhtml/session')->addNotice("A new version ($version) of the Magento-Copernica extension is available. Click <a href='http://www.copernica.com/download/Copernica_MarketingSoftware-$version.tar.gz'>here</a> to download it.");
284
+
285
+ // Perform the checks, an exception might be thrown, not that in in this way we can show only one error
286
+ try
287
+ {
288
+ $this->checkSoap();
289
+ $this->checkUrl();
290
+ }
291
+ catch (Exception $e)
292
+ {
293
+ // Add the exception to the session
294
+ Mage::getSingleton('adminhtml/session')->addException($e, (string)$e);
295
+ }
296
+
297
+ // Check the queue length and the oldest record to have an idea of the performance of the plug-in
298
+ $collection = Mage::getResourceModel('marketingsoftware/queue_collection');
299
+ $length = $collection->getSize();
300
+ $oldestTimestamp = $collection->getQueueStartTime();
301
+ $printableTime = Mage::helper('core')->formatDate($oldestTimestamp, 'short', true);
302
+ $oldestRecordAge = is_null($oldestTimestamp) ? 0 : time() - strtotime($oldestTimestamp);
303
+
304
+ // Is the queue length too big or are there old records
305
+ if ($length > 100 || $oldestRecordAge > 60*60*24)
306
+ {
307
+ // A basic message should be added
308
+ $message = "Note: Your Copernica database is not up-to-date at this moment.";
309
+
310
+ // Is the length bigger or the oldest record in the queue of a long time
311
+ if ($length > 100) $message .= " There is queue of $length local modifications waiting to be processed.";
312
+ if ($oldestRecordAge > 60*60*24) $message .= " There is still a modification of $printableTime that is not synchronized with Copernica.";
313
+
314
+ // A warning should be added because one of the two problems is the case
315
+ Mage::getSingleton('adminhtml/session')->addWarning($message);
316
+
317
+ // Is this problem caused by the copernica being unreachable, or the login being invalid
318
+ try
319
+ {
320
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
321
+ $result = $api->check(true);
322
+ }
323
+ catch(Exception $e)
324
+ {
325
+ // No valid result has been retrieved
326
+ $result = false;
327
+
328
+ // An exception is found add it to the session
329
+ Mage::getSingleton('adminhtml/session')->addException($e,(string)$e);
330
+ }
331
+ }
332
+ }
333
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Address.php ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an Address
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Address implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Order_Address|Mage_Sales_Model_Quote_Address|Mage_Customer_Model_Address
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $type;
18
+ private $name;
19
+ private $email;
20
+ private $street;
21
+ private $city;
22
+ private $zipcode;
23
+ private $state;
24
+ private $countryCode;
25
+ private $telephone;
26
+ private $fax;
27
+ private $company;
28
+ private $customerId;
29
+
30
+ /**
31
+ * Sets the original model
32
+ * @param Mage_Sales_Model_Order_Address|Mage_Sales_Model_Quote_Address|Mage_Customer_Model_Address $original
33
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Address
34
+ */
35
+ public function setOriginal($original)
36
+ {
37
+ $this->original = $original;
38
+ return $this;
39
+ }
40
+
41
+ /**
42
+ * Returns the original model
43
+ * @return Mage_Sales_Model_Order_Address|Mage_Sales_Model_Quote_Address|Mage_Customer_Model_Address
44
+ */
45
+ protected function original()
46
+ {
47
+ return $this->original;
48
+ }
49
+
50
+ /**
51
+ * Return the type of this address
52
+ * @return array {0-2} (billing|shipping)
53
+ */
54
+ public function type()
55
+ {
56
+ // Is this object still present?
57
+ if (is_object($this->original))
58
+ {
59
+ if ($type = $this->original->getAddressType()) {
60
+ return array($type);
61
+ } else {
62
+ $types = array();
63
+ if ($customer = $this->original->getCustomer()) {
64
+ $id = $this->original->getId();
65
+ if ($customer->getData('default_billing') == $id) {
66
+ $types[] = 'billing';
67
+ }
68
+ if ($customer->getData('default_shipping') == $id) {
69
+ $types[] = 'shipping';
70
+ }
71
+ }
72
+ return $types;
73
+ }
74
+ return Mage::getModel('marketingsoftware/abstraction_name')->setOriginal($this->original);
75
+ }
76
+ else return $this->type;
77
+ }
78
+
79
+ /**
80
+ * The customer may return null
81
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Customer
82
+ */
83
+ public function customer()
84
+ {
85
+ // Is this object still present?
86
+ if (is_object($this->original))
87
+ {
88
+ //the order quote address model only returns a customer if it exists
89
+ if ($customerId = $this->original->getCustomerId())
90
+ {
91
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($customerId);
92
+ }
93
+ elseif ($customer = $this->original->getCustomer())
94
+ {
95
+ return Mage::getModel('marketingsoftware/abstraction_customer')->setOriginal($customer);
96
+ }
97
+ else return null;
98
+ }
99
+ elseif ($this->customerId)
100
+ {
101
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($this->customerId);
102
+ }
103
+ else return null;
104
+ }
105
+
106
+ /**
107
+ * We want to return a unique id, but to do this we need to append
108
+ * a prefix based on the type of address
109
+ * @return string
110
+ */
111
+ public function id()
112
+ {
113
+ // Is this object still present?
114
+ if (is_object($this->original))
115
+ {
116
+ // Get the normal identifier
117
+ $id = $this->original->getId();
118
+
119
+ // switch depending on the type
120
+ switch(get_class($this->original))
121
+ {
122
+ case "Mage_Sales_Model_Order_Address":
123
+ if ($cid = $this->original->getCustomerAddressId()) return 'ca_'.$cid;
124
+ return 'oa_'.$id;
125
+ case "Mage_Sales_Model_Quote_Address":
126
+ if ($cid = $this->original->getCustomerAddressId()) return 'ca_'.$cid;
127
+ return 'qa_'.$id;
128
+ case "Mage_Customer_Model_Address": return 'ca_'.$id;
129
+ default: return $id;
130
+ }
131
+ }
132
+ else return $this->id;
133
+ }
134
+
135
+ /**
136
+ * Return the name belonging to this address
137
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Name
138
+ */
139
+ public function name()
140
+ {
141
+ // Is this object still present?
142
+ if (is_object($this->original))
143
+ {
144
+ return Mage::getModel('marketingsoftware/abstraction_name')->setOriginal($this->original);
145
+ }
146
+ else return $this->name;
147
+ }
148
+
149
+ /**
150
+ * Return the e-mail address of this address
151
+ * @return string
152
+ */
153
+ public function email()
154
+ {
155
+ // Is this object still present?
156
+ if (is_object($this->original))
157
+ {
158
+ if ($email = $this->original->getEmail()) return $email;
159
+ elseif (is_object($order = $this->original->getOrder())
160
+ && $customerEmail = $order->getCustomerEmail()) return $customerEmail;
161
+ elseif (is_object($quote = $this->original->getQuote())
162
+ && $customerEmail = $quote->getCustomerEmail()) return $customerEmail;
163
+ }
164
+ else return $this->email;
165
+ }
166
+
167
+ /**
168
+ * Return the street of this addresses
169
+ * @return string
170
+ */
171
+ public function street()
172
+ {
173
+ // Is this object still present?
174
+ if (is_object($this->original))
175
+ {
176
+ return $this->original->getStreetFull();
177
+ }
178
+ else return $this->street;
179
+ }
180
+
181
+ /**
182
+ * Get the city of this addresses
183
+ * @return string
184
+ */
185
+ public function city()
186
+ {
187
+ // Is this object still present?
188
+ if (is_object($this->original))
189
+ {
190
+ return $this->original->getCity();
191
+ }
192
+ else return $this->city;
193
+ }
194
+
195
+ /**
196
+ * Get the zipcode of this addresses
197
+ * @return string
198
+ */
199
+ public function zipcode()
200
+ {
201
+ // Is this object still present?
202
+ if (is_object($this->original))
203
+ {
204
+ return $this->original->getPostcode();
205
+ }
206
+ else return $this->zipcode;
207
+ }
208
+
209
+ /**
210
+ * Get the state of this addresses
211
+ * @return string
212
+ */
213
+ public function state()
214
+ {
215
+ // Is this object still present?
216
+ if (is_object($this->original))
217
+ {
218
+ return $this->original->getRegion();
219
+ }
220
+ else return $this->state;
221
+ }
222
+
223
+ /**
224
+ * Get the countrycode of this addresses
225
+ * @return string
226
+ */
227
+ public function countryCode()
228
+ {
229
+ // Is this object still present?
230
+ if (is_object($this->original))
231
+ {
232
+ return $this->original->getCountryId();
233
+ }
234
+ else return $this->countryCode;
235
+ }
236
+
237
+ /**
238
+ * Get the telephone number of this addresses
239
+ * @return string
240
+ */
241
+ public function telephone()
242
+ {
243
+ // Is this object still present?
244
+ if (is_object($this->original))
245
+ {
246
+ return $this->original->getTelephone();
247
+ }
248
+ else return $this->telephone;
249
+ }
250
+
251
+ /**
252
+ * Get the fax number of this addresses
253
+ * @return string
254
+ */
255
+ public function fax()
256
+ {
257
+ // Is this object still present?
258
+ if (is_object($this->original))
259
+ {
260
+ return $this->original->getFax();
261
+ }
262
+ else return $this->fax;
263
+ }
264
+
265
+ /**
266
+ * Get the company of this address
267
+ * @return string
268
+ */
269
+ public function company()
270
+ {
271
+ // Is this object still present?
272
+ if (is_object($this->original))
273
+ {
274
+ return $this->original->getCompany();
275
+ }
276
+ else return $this->company;
277
+ }
278
+
279
+ /**
280
+ * Serialize the object
281
+ * @return string
282
+ */
283
+ public function serialize()
284
+ {
285
+ // serialize the data
286
+ return serialize(array(
287
+ $this->id(),
288
+ $this->type(),
289
+ $this->name(),
290
+ $this->email(),
291
+ $this->street(),
292
+ $this->city(),
293
+ $this->zipcode(),
294
+ $this->state(),
295
+ $this->countryCode(),
296
+ $this->telephone(),
297
+ $this->fax(),
298
+ $this->company(),
299
+ is_object($customer = $this->customer()) ? $customer->id() : null,
300
+ ));
301
+ }
302
+
303
+ /**
304
+ * Unserialize the object
305
+ * @param string
306
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Address
307
+ */
308
+ public function unserialize($string)
309
+ {
310
+ list(
311
+ $this->id,
312
+ $this->type,
313
+ $this->name,
314
+ $this->email,
315
+ $this->street,
316
+ $this->city,
317
+ $this->zipcode,
318
+ $this->state,
319
+ $this->countryCode,
320
+ $this->telephone,
321
+ $this->fax,
322
+ $this->company,
323
+ $this->customerId
324
+ ) = unserialize($string);
325
+ return $this;
326
+ }
327
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Attributes.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around attributes
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Attributes implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Catalog_Model_Product
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $name;
17
+ private $attributes;
18
+
19
+ /**
20
+ * Sets the original model
21
+ * @param Mage_Catalog_Model_Product $original
22
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Attributes
23
+ */
24
+ public function setOriginal(Mage_Catalog_Model_Product $original)
25
+ {
26
+ $this->original = $original;
27
+ return $this;
28
+ }
29
+
30
+ /**
31
+ * The name of this product
32
+ * @return integer
33
+ */
34
+ public function name()
35
+ {
36
+ // Is this object still present?
37
+ if (is_object($this->original))
38
+ {
39
+ if ($attributeSet = Mage::getModel('eav/entity_attribute_set')->load($this->original->getAttributeSetId())) {
40
+ return $attributeSet->getAttributeSetName();
41
+ }
42
+ }
43
+ else return $this->name;
44
+ }
45
+
46
+ /**
47
+ * Return an assoc array with attributes
48
+ * @return array
49
+ */
50
+ public function attributes()
51
+ {
52
+ // Is this object still present?
53
+ if (is_object($this->original))
54
+ {
55
+ $data = array();
56
+ $attributes = $this->original->getAttributes();
57
+
58
+ foreach ($attributes as $attribute) {
59
+ if (
60
+ $attribute->getIsUserDefined() &&
61
+ in_array($attribute->getFrontendInput(), array('text', 'select', 'multiline', 'textarea', 'price', 'date', 'multiselect')) &&
62
+ ($label = $attribute->getFrontendLabel()) &&
63
+ ($value = $attribute->getFrontend()->getValue($this->original))
64
+ ) {
65
+ // is this an object which is not serializable
66
+
67
+ // add the value to the array of data
68
+ $data[$label] = $value;
69
+ }
70
+ }
71
+ return $data;
72
+ }
73
+ else return $this->attributes;
74
+ }
75
+
76
+ /**
77
+ * Return a string representation
78
+ */
79
+ public function __toString()
80
+ {
81
+ $options = "";
82
+ foreach ($this->attributes() as $key => $value) $options .= "$key: $value\n";
83
+ return $options;
84
+ }
85
+
86
+ /**
87
+ * Serialize the object
88
+ * @return string
89
+ */
90
+ public function serialize()
91
+ {
92
+ // serialize the data
93
+ return serialize(array(
94
+ $this->name(),
95
+ $this->attributes(),
96
+ ));
97
+ }
98
+
99
+ /**
100
+ * Unserialize the object
101
+ * @param string
102
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Attributes
103
+ */
104
+ public function unserialize($string)
105
+ {
106
+ list(
107
+ $this->name,
108
+ $this->attributes
109
+ ) = unserialize($string);
110
+ return $this;
111
+ }
112
+ }
113
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Customer.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a magento Customer
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Customer implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Customer_Model_Customer
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $name;
18
+ private $email;
19
+ private $subscription;
20
+ private $group;
21
+ private $addresses;
22
+ private $storeview;
23
+
24
+
25
+ /**
26
+ * Sets the original model
27
+ * @param Mage_Customer_Model_Customer $original
28
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Customer
29
+ */
30
+ public function setOriginal(Mage_Customer_Model_Customer $original)
31
+ {
32
+ $this->original = $original;
33
+ return $this;
34
+ }
35
+
36
+ /**
37
+ * Returns the original model
38
+ * @return Mage_Customer_Model_Customer
39
+ */
40
+ protected function original()
41
+ {
42
+ return $this->original;
43
+ }
44
+
45
+ /**
46
+ * Loads a customer model
47
+ * @param integer $customerId
48
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
49
+ */
50
+ public function loadCustomer($customerId)
51
+ {
52
+ $customer = Mage::getModel('customer/customer')->load($customerId);
53
+ if ($customer->getId()) {
54
+ //set the original model if the customer exists
55
+ $this->original = $customer;
56
+ }
57
+ else
58
+ {
59
+ // We did load a customer to make sure that it works more
60
+ // or less, we assign the customer id here
61
+ $this->id = $customerId;
62
+ }
63
+ return $this;
64
+ }
65
+
66
+ /**
67
+ * Return the id of the customer
68
+ * @return string
69
+ */
70
+ public function id()
71
+ {
72
+ // Is this object still present?
73
+ if (is_object($this->original))
74
+ {
75
+ return $this->original->getId();
76
+ }
77
+ else return $this->id;
78
+ }
79
+
80
+ /**
81
+ * Return the name of this customer
82
+ * Note that null may also be returned to indicate that the name is not known
83
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Name
84
+ */
85
+ public function name()
86
+ {
87
+ // Is this object still present?
88
+ if (is_object($this->original))
89
+ {
90
+ return Mage::getModel('marketingsoftware/abstraction_name')->setOriginal($this->original);
91
+ }
92
+ else return $this->name;
93
+ }
94
+
95
+ /**
96
+ * Return the e-mail address of the customer
97
+ * @return string
98
+ */
99
+ public function email()
100
+ {
101
+ // Is this object still present?
102
+ if (is_object($this->original))
103
+ {
104
+ return $this->original->getEmail();
105
+ }
106
+ else return $this->email;
107
+ }
108
+
109
+ /**
110
+ * Return the subscription of the customer
111
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Subscription
112
+ */
113
+ public function subscription()
114
+ {
115
+ // Is this object still present?
116
+ if (is_object($this->original))
117
+ {
118
+ $subscriber = Mage::getModel('newsletter/subscriber');
119
+ if (
120
+ $subscriber->loadByCustomer($this->original)->getId() ||
121
+ $subscriber->loadByEmail($this->email())->getId()
122
+ ) {
123
+ return Mage::getModel('marketingsoftware/abstraction_subscription')->setOriginal($subscriber);
124
+ }
125
+ }
126
+ else return $this->subscription;
127
+ }
128
+
129
+ /**
130
+ * Return the group to which this customer belongs
131
+ * @return string
132
+ */
133
+ public function group()
134
+ {
135
+ // Is this object still present?
136
+ if (is_object($this->original))
137
+ {
138
+ return Mage::getModel('customer/group')->load($this->original->getGroupId())->getCode();
139
+ }
140
+ else return $this->group;
141
+ }
142
+
143
+ /**
144
+ * Get the quotes for this customer
145
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Quote
146
+ */
147
+ public function quotes()
148
+ {
149
+ $data = array();
150
+
151
+ //retrieve this customer's quote ids
152
+ $quoteIDS = Mage::getResourceModel('sales/quote_collection')
153
+ ->addFieldToFilter('customer_id', $this->id())->getAllIds();
154
+
155
+ foreach ($quoteIDS as $id) {
156
+ $data[] = Mage::getModel('marketingsoftware/abstraction_quote')->loadQuote($id);
157
+ }
158
+ return $data;
159
+ }
160
+
161
+ /**
162
+ * Get the orders for this customer
163
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Order
164
+ */
165
+ public function orders()
166
+ {
167
+ $data = array();
168
+
169
+ //retrieve this customer's order ids
170
+ $orderIDS = Mage::getResourceModel('sales/order_collection')
171
+ ->addAttributeToFilter('customer_id', $this->id())->getAllIds();
172
+
173
+ foreach ($orderIDS as $id) {
174
+ $data[] = Mage::getModel('marketingsoftware/abstraction_order')->loadOrder($id);
175
+ }
176
+ return $data;
177
+ }
178
+
179
+ /**
180
+ * Get the addresses for this customer
181
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Address
182
+ */
183
+ public function addresses()
184
+ {
185
+ // Is this object still present?
186
+ if (is_object($this->original))
187
+ {
188
+ $data = array();
189
+ //retrieve this customer's addresses
190
+ $addresses = $this->original->getAddressesCollection();
191
+ foreach ($addresses as $address) {
192
+ $data[] = Mage::getModel('marketingsoftware/abstraction_address')->setOriginal($address);
193
+ }
194
+ return $data;
195
+ }
196
+ else return $this->addresses;
197
+ }
198
+
199
+ /**
200
+ * To what storeview does this order belong
201
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
202
+ */
203
+ public function storeview()
204
+ {
205
+ // Is this object still present?
206
+ if (is_object($this->original))
207
+ {
208
+ return Mage::getModel('marketingsoftware/abstraction_storeview')->setOriginal($this->original->getStore());
209
+ }
210
+ else return $this->storeview;
211
+ }
212
+
213
+ /**
214
+ * Serialize the object
215
+ * @return string
216
+ */
217
+ public function serialize()
218
+ {
219
+ // serialize the data
220
+ return serialize(array(
221
+ $this->id(),
222
+ $this->name(),
223
+ $this->email(),
224
+ $this->subscription(),
225
+ $this->group(),
226
+ $this->addresses(),
227
+ $this->storeview(),
228
+ ));
229
+ }
230
+
231
+ /**
232
+ * Unserialize the object
233
+ * @param string
234
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Customer
235
+ */
236
+ public function unserialize($string)
237
+ {
238
+ // Get the data into an array
239
+ $data = unserialize($string);
240
+
241
+ // assign the data to the internal vars
242
+ list(
243
+ $this->id,
244
+ $this->name,
245
+ $this->email,
246
+ $this->subscription,
247
+ $this->group,
248
+ $this->addresses
249
+ ) = $data;
250
+
251
+ // do we have a storeview available?
252
+ if (isset($data[6])) $this->storeview = $data[6];
253
+
254
+ return $this;
255
+ }
256
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Name.php ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a name, note this is not an Magento object
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Name implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Customer_Model_Customer|Mage_Sales_Model_Order_Address|Mage_Sales_Model_Quote_Address|Mage_Customer_Model_Address
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $firstname;
17
+ private $prefix;
18
+ private $middlename;
19
+ private $lastname;
20
+
21
+ /**
22
+ * Sets the original model
23
+ * @param Mage_Customer_Model_Customer|Mage_Customer_Model_Customer_Address|Mage_Sales_Model_Order_Address|Mage_Sales_Model_Quote_Address|Mage_Customer_Model_Address
24
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Name
25
+ */
26
+ public function setOriginal($original)
27
+ {
28
+ $this->original = $original;
29
+ return $this;
30
+ }
31
+
32
+ /**
33
+ * Return the firstname of the customer
34
+ * @return string
35
+ */
36
+ public function firstname()
37
+ {
38
+ // Is this object still present?
39
+ if (is_object($this->original))
40
+ {
41
+ return $this->original->getFirstname();
42
+ }
43
+ else return $this->firstname;
44
+ }
45
+
46
+ /**
47
+ * Return the prefix of the customer
48
+ * NOTE: the prefix field is not displayed by default
49
+ * @return string
50
+ */
51
+ public function prefix()
52
+ {
53
+ // Is this object still present?
54
+ if (is_object($this->original))
55
+ {
56
+ return $this->original->getPrefix();
57
+ }
58
+ else return $this->prefix;
59
+ }
60
+
61
+ /**
62
+ * Return the middlename of the customer
63
+ * NOTE: the middlename field is not displayed by default
64
+ * @return string
65
+ */
66
+ public function middlename()
67
+ {
68
+ // Is this object still present?
69
+ if (is_object($this->original))
70
+ {
71
+ return $this->original->getMiddlename();
72
+ }
73
+ else return $this->middlename;
74
+ }
75
+
76
+ /**
77
+ * Return the lastname of the customer
78
+ * @return string
79
+ */
80
+ public function lastname()
81
+ {
82
+ // Is this object still present?
83
+ if (is_object($this->original))
84
+ {
85
+ return $this->original->getLastname();
86
+ }
87
+ else return $this->lastname;
88
+ }
89
+
90
+ /**
91
+ * Serialize the object
92
+ * @return string
93
+ */
94
+ public function serialize()
95
+ {
96
+ // serialize the data
97
+ return serialize(array(
98
+ $this->firstname(),
99
+ $this->prefix(),
100
+ $this->middlename(),
101
+ $this->lastname(),
102
+ ));
103
+ }
104
+
105
+ /**
106
+ * Unserialize the object
107
+ * @param string
108
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Name
109
+ */
110
+ public function unserialize($string)
111
+ {
112
+ list(
113
+ $this->firstname,
114
+ $this->prefix,
115
+ $this->middlename,
116
+ $this->lastname
117
+ ) = unserialize($string);
118
+ }
119
+ }
120
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Order.php ADDED
@@ -0,0 +1,385 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an Order
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Order implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Order
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $incrementId;
18
+ private $quoteId;
19
+ private $quantity;
20
+ private $currency;
21
+ private $timestamp;
22
+ private $customerIP;
23
+ private $items;
24
+ private $storeview;
25
+ private $customerId;
26
+ private $addresses;
27
+ private $price;
28
+ private $weight;
29
+ private $state;
30
+ private $status;
31
+ private $shippingDescription;
32
+ private $paymentDescription;
33
+
34
+
35
+ /**
36
+ * Sets the original model
37
+ * @param Mage_Sales_Model_Order $original
38
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order
39
+ */
40
+ public function setOriginal(Mage_Sales_Model_Order $original)
41
+ {
42
+ $this->original = $original;
43
+ return $this;
44
+ }
45
+
46
+ /**
47
+ * Loads an order model
48
+ * @param integer $orderId
49
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order
50
+ */
51
+ public function loadOrder($orderId)
52
+ {
53
+ $order = Mage::getModel('sales/order')->load($orderId);
54
+ if ($order->getId()) {
55
+ //set the original model if the quote exists
56
+ $this->original = $order;
57
+ }
58
+ return $this;
59
+ }
60
+
61
+ /**
62
+ * The id of this order object
63
+ * @return integer
64
+ */
65
+ public function id()
66
+ {
67
+ // Is this object still present?
68
+ if (is_object($this->original))
69
+ {
70
+ return $this->original->getId();
71
+ }
72
+ else return $this->id;
73
+ }
74
+
75
+ /**
76
+ * The increment (longer) id of this order object
77
+ * @return integer
78
+ */
79
+ public function incrementId()
80
+ {
81
+ // Is this object still present?
82
+ if (is_object($this->original))
83
+ {
84
+ return $this->original->getIncrementId();
85
+ }
86
+ else return $this->incrementId;
87
+ }
88
+
89
+ /**
90
+ * The quote id of this order object
91
+ * @return integer
92
+ */
93
+ public function quoteId()
94
+ {
95
+ // Is this object still present?
96
+ if (is_object($this->original))
97
+ {
98
+ return $this->original->getQuoteId();
99
+ }
100
+ else return $this->quoteId;
101
+ }
102
+
103
+ /**
104
+ * The state of this order
105
+ * @return string
106
+ */
107
+ public function state()
108
+ {
109
+ // Is this object still present?
110
+ if (is_object($this->original))
111
+ {
112
+ return $this->original->getState();
113
+ }
114
+ else return $this->state;
115
+ }
116
+
117
+ /**
118
+ * The status of this order
119
+ * @return string
120
+ */
121
+ public function status()
122
+ {
123
+ // Is this object still present?
124
+ if (is_object($this->original))
125
+ {
126
+ return $this->original->getStatus();
127
+ }
128
+ else return $this->status;
129
+ }
130
+
131
+ /**
132
+ * The number of items present in this order
133
+ * @return integer
134
+ */
135
+ public function quantity()
136
+ {
137
+ // Is this object still present?
138
+ if (is_object($this->original))
139
+ {
140
+ return $this->original->getTotalQtyOrdered();
141
+ }
142
+ else return $this->quantity;
143
+ }
144
+
145
+ /**
146
+ * The number of items present in this order
147
+ * @return integer
148
+ */
149
+ public function currency()
150
+ {
151
+ // Is this object still present?
152
+ if (is_object($this->original))
153
+ {
154
+ return $this->original->getOrderCurrencyCode();
155
+ }
156
+ else return $this->currency;
157
+ }
158
+
159
+ /**
160
+ * The price
161
+ * Note that an object is returned, which may consist of multiple components
162
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Price
163
+ */
164
+ public function price()
165
+ {
166
+ // Is this object still present?
167
+ if (is_object($this->original))
168
+ {
169
+ // Note that the price may consist of multiple elements
170
+ return Mage::getModel('marketingsoftware/abstraction_price')->setOriginal($this->original);
171
+ }
172
+ else return $this->price;
173
+ }
174
+
175
+ /**
176
+ * The weight
177
+ * @return float
178
+ */
179
+ public function weight()
180
+ {
181
+ // Is this object still present?
182
+ if (is_object($this->original))
183
+ {
184
+ return $this->original->getWeight();
185
+ }
186
+ else return $this->weight;
187
+ }
188
+
189
+ /**
190
+ * To what storeview does this order belong
191
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
192
+ */
193
+ public function storeview()
194
+ {
195
+ // Is this object still present?
196
+ if (is_object($this->original))
197
+ {
198
+ return Mage::getModel('marketingsoftware/abstraction_storeview')->setOriginal($this->original->getStore());
199
+ }
200
+ else return $this->storeview;
201
+ }
202
+
203
+ /**
204
+ * Get the items from the order
205
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Quote_Item
206
+ */
207
+ public function items()
208
+ {
209
+ // Is this object still present?
210
+ if (is_object($this->original))
211
+ {
212
+ $data = array();
213
+ $items = $this->original->getAllVisibleItems();
214
+ foreach ($items as $item) {
215
+ $data[] = Mage::getModel('marketingsoftware/abstraction_order_item')->setOriginal($item);
216
+ }
217
+ return $data;
218
+ }
219
+ else return $this->items;
220
+ }
221
+
222
+ /**
223
+ * The timestamp at which this order was modified
224
+ * @return string
225
+ */
226
+ public function timestamp()
227
+ {
228
+ // Is this object still present?
229
+ if (is_object($this->original))
230
+ {
231
+ return $this->original->getUpdatedAt();
232
+ }
233
+ else return $this->timestamp;
234
+ }
235
+
236
+ /**
237
+ * The customer may return null
238
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Customer
239
+ */
240
+ public function customer()
241
+ {
242
+ // Is this object still present?
243
+ if (is_object($this->original))
244
+ {
245
+ //the order model only returns a customer if it exists
246
+ if ($customerId = $this->original->getCustomerId()) {
247
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($customerId);
248
+ } else {
249
+ return null;
250
+ }
251
+ }
252
+ elseif ($this->customerId)
253
+ {
254
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($this->customerId);
255
+ }
256
+ else return null;
257
+ }
258
+
259
+ /**
260
+ * The addresses of the order
261
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Address
262
+ */
263
+ public function addresses()
264
+ {
265
+ // Is this object still present?
266
+ if (is_object($this->original))
267
+ {
268
+ $data = array();
269
+ //retrieve this quote's addresses
270
+ $addresses = $this->original->getAddressesCollection();
271
+ foreach ($addresses as $address) {
272
+ $data[] = Mage::getModel('marketingsoftware/abstraction_address')->setOriginal($address);
273
+ }
274
+ return $data;
275
+ }
276
+ else return $this->addresses;
277
+ }
278
+
279
+ /**
280
+ * The shipping method of the order
281
+ * @return string
282
+ */
283
+ public function shippingDescription()
284
+ {
285
+ // Is this object still present?
286
+ if (is_object($this->original))
287
+ {
288
+ return $this->original->getShippingDescription();
289
+ }
290
+ else return $this->shippingDescription;
291
+ }
292
+
293
+ /**
294
+ * The payment method of the order
295
+ * @return string
296
+ */
297
+ public function paymentDescription()
298
+ {
299
+ // Is this object still present?
300
+ if (is_object($this->original))
301
+ {
302
+ if ($payment = $this->original->getPayment()) {
303
+ try {
304
+ return $payment->getMethodInstance()->getTitle();
305
+ } catch (Mage_Core_Exception $exception) {
306
+ return null;
307
+ }
308
+ }
309
+ return null;
310
+ }
311
+ else return $this->paymentDescription;
312
+ }
313
+
314
+ /**
315
+ * The IP from which this order was constructed
316
+ * @return string
317
+ */
318
+ public function customerIP()
319
+ {
320
+ // Is this object still present?
321
+ if (is_object($this->original))
322
+ {
323
+ return $this->original->getRemoteIp();
324
+ }
325
+ else return $this->customerIP;
326
+ }
327
+
328
+ /**
329
+ * Serialize the object
330
+ * @return string
331
+ */
332
+ public function serialize()
333
+ {
334
+ // serialize the data
335
+ return serialize(array(
336
+ $this->id(),
337
+ $this->incrementId(),
338
+ $this->quoteId(),
339
+ $this->quantity(),
340
+ $this->currency(),
341
+ $this->timestamp(),
342
+ $this->customerIP(),
343
+ $this->items(),
344
+ $this->storeview(),
345
+ is_object($customer = $this->customer()) ? $customer->id() : null,
346
+ $this->addresses(),
347
+ $this->price(),
348
+ $this->weight(),
349
+ $this->state(),
350
+ $this->status(),
351
+ $this->shippingDescription(),
352
+ $this->paymentDescription()
353
+ ));
354
+ }
355
+
356
+ /**
357
+ * Unserialize the object
358
+ * @param string
359
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order
360
+ */
361
+ public function unserialize($string)
362
+ {
363
+ list(
364
+ $this->id,
365
+ $this->incrementId,
366
+ $this->quoteId,
367
+ $this->quantity,
368
+ $this->currency,
369
+ $this->timestamp,
370
+ $this->customerIP,
371
+ $this->items,
372
+ $this->storeview,
373
+ $this->customerId,
374
+ $this->addresses,
375
+ $this->price,
376
+ $this->weight,
377
+ $this->state,
378
+ $this->status,
379
+ $this->shippingDescription,
380
+ $this->paymentDescription
381
+ ) = unserialize($string);
382
+ return $this;
383
+ }
384
+ }
385
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Order/Item.php ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an Order Item
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Order_Item implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Order_Item
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $orderId;
18
+ private $quantity;
19
+ private $price;
20
+ private $weight;
21
+ private $timestamp;
22
+ private $options;
23
+ private $product;
24
+
25
+ /**
26
+ * Sets the original model
27
+ * @param Mage_Sales_Model_Order_Item $original
28
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order_Item
29
+ */
30
+ public function setOriginal(Mage_Sales_Model_Order_Item $original)
31
+ {
32
+ $this->original = $original;
33
+ return $this;
34
+ }
35
+
36
+ /**
37
+ * The id of this order item object
38
+ * @return integer
39
+ */
40
+ public function id()
41
+ {
42
+ // Is this object still present?
43
+ if (is_object($this->original))
44
+ {
45
+ return $this->original->getId();
46
+ }
47
+ else return $this->id;
48
+ }
49
+
50
+ /**
51
+ * Get the order to which this item belongs
52
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order
53
+ */
54
+ public function order()
55
+ {
56
+ // Is this object still present?
57
+ if (is_object($this->original))
58
+ {
59
+ if ($order = $this->original->getOrder()) {
60
+ return Mage::getModel('marketingsoftware/abstraction_order')->setOriginal($order);
61
+ } else {
62
+ return null;
63
+ }
64
+ }
65
+ else return Mage::getModel('marketingsoftware/abstraction_order')->loadOrder($this->orderId);
66
+ }
67
+
68
+ /**
69
+ * The amount of this order item
70
+ * @return integer
71
+ */
72
+ public function quantity()
73
+ {
74
+ // Is this object still present?
75
+ if (is_object($this->original))
76
+ {
77
+ return $this->original->getQtyOrdered();
78
+ }
79
+ else return $this->quantity;
80
+ }
81
+
82
+ /**
83
+ * The price
84
+ * Note that an object is returned, which may consist of multiple components
85
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Price
86
+ */
87
+ public function price()
88
+ {
89
+ // Is this object still present?
90
+ if (is_object($this->original))
91
+ {
92
+ // Note that the price may consist of multiple elements
93
+ return Mage::getModel('marketingsoftware/abstraction_price')->setOriginal($this->original);
94
+ }
95
+ else return $this->price;
96
+ }
97
+
98
+ /**
99
+ * The weight
100
+ * @return float
101
+ */
102
+ public function weight()
103
+ {
104
+ // Is this object still present?
105
+ if (is_object($this->original))
106
+ {
107
+ return $this->original->getWeight();
108
+ }
109
+ else return $this->weight;
110
+ }
111
+
112
+ /**
113
+ * The timestamp at which this order was modified
114
+ * @return string
115
+ */
116
+ public function timestamp()
117
+ {
118
+ // Is this object still present?
119
+ if (is_object($this->original))
120
+ {
121
+ return $this->original->getUpdatedAt();
122
+ }
123
+ else return $this->timestamp;
124
+ }
125
+
126
+ /**
127
+ * Get the options of this order item
128
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order_Item_Options
129
+ */
130
+ public function options()
131
+ {
132
+ // Is this object still present?
133
+ if (is_object($this->original))
134
+ {
135
+ $options = Mage::getModel('marketingsoftware/abstraction_order_item_options')->setOriginal($this->original);
136
+ if ($options->attributes()) {
137
+ //only return option object if it this order actually has options
138
+ return $options;
139
+ } else {
140
+ return null;
141
+ }
142
+ }
143
+ else return $this->options;
144
+ }
145
+
146
+ /**
147
+ * Get the product which belongs to this item
148
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Product
149
+ */
150
+ public function product()
151
+ {
152
+ // Is this object still present?
153
+ if (is_object($this->original))
154
+ {
155
+ return Mage::getModel('marketingsoftware/abstraction_product')->setOriginal($this->original);
156
+ }
157
+ else return $this->product;
158
+ }
159
+
160
+ /**
161
+ * Serialize the object
162
+ * @return string
163
+ */
164
+ public function serialize()
165
+ {
166
+ // serialize the data
167
+ return serialize(array(
168
+ $this->id(),
169
+ is_object($order = $this->order()) ? $order->id() : null,
170
+ $this->quantity(),
171
+ $this->price(),
172
+ $this->weight(),
173
+ $this->timestamp(),
174
+ $this->options(),
175
+ $this->product(),
176
+ ));
177
+ }
178
+
179
+ /**
180
+ * Unserialize the object
181
+ * @param string
182
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order_Item
183
+ */
184
+ public function unserialize($string)
185
+ {
186
+ list(
187
+ $this->id,
188
+ $this->orderId,
189
+ $this->quantity,
190
+ $this->price,
191
+ $this->weight,
192
+ $this->timestamp,
193
+ $this->options,
194
+ $this->product
195
+ ) = unserialize($string);
196
+ return $this;
197
+ }
198
+ }
199
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Order/Item/Options.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around order item options
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Order_Item_Options implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Order_Item
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $name;
17
+ private $attributes;
18
+
19
+
20
+ /**
21
+ * Sets the original model
22
+ * @param Mage_Sales_Model_Order_Item $original
23
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order_Item_Options
24
+ */
25
+ public function setOriginal(Mage_Sales_Model_Order_Item $original)
26
+ {
27
+ $this->original = $original;
28
+ return $this;
29
+ }
30
+
31
+ /**
32
+ * The name of this order item
33
+ * @return integer
34
+ */
35
+ public function name()
36
+ {
37
+ // Is this object still present?
38
+ if (is_object($this->original))
39
+ {
40
+ return $this->original->getName();
41
+ }
42
+ else return $this->name;
43
+ }
44
+
45
+ /**
46
+ * Return an assoc array with attributes
47
+ * @return array
48
+ */
49
+ public function attributes()
50
+ {
51
+ // Is this object still present?
52
+ if (is_object($this->original))
53
+ {
54
+ $data = array();
55
+ $options = $this->original->getProductOptions();
56
+ $attributes = array();
57
+ if (isset($options['attributes_info'])) {
58
+ //configurable products
59
+ $attributes = $options['attributes_info'];
60
+ } elseif (isset($options['bundle_options'])) {
61
+ //bundle products
62
+ $attributes = $options['bundle_options'];
63
+ } elseif (isset($options['options'])) {
64
+ //generic products
65
+ $attributes = $options['options'];
66
+ }
67
+ if ($attributes) {
68
+ foreach ($attributes as $attribute) {
69
+ $data[$attribute['label']] = $attribute['value'];
70
+ }
71
+ return $data;
72
+ }
73
+ return null;
74
+ }
75
+ else return $this->attributes;
76
+ }
77
+
78
+ /**
79
+ * Return a string representation
80
+ * @return String
81
+ */
82
+ public function __toString()
83
+ {
84
+ return $this->arrayToString($this->attributes());
85
+ }
86
+
87
+ /**
88
+ * Return a string representation of an array
89
+ * @param array
90
+ * @return String
91
+ */
92
+ private function arrayToString($value, $prefix = '')
93
+ {
94
+ $string = "";
95
+ foreach ($value as $key => $value)
96
+ {
97
+ // is the value an array
98
+ if (is_array($value))
99
+ {
100
+ // if there is only one subvalue, use that instead
101
+ if (isset($value[0]) && count($value) == 1) $value = $value[0];
102
+
103
+ // compose the string
104
+ $string .= $prefix.$key.":\n".$this->arrayToString($value, $prefix.' ');
105
+ }
106
+ else $string.= $prefix.$key.": $value\n";
107
+ }
108
+ return $string;
109
+ }
110
+
111
+ /**
112
+ * Serialize the object
113
+ * @return string
114
+ */
115
+ public function serialize()
116
+ {
117
+ // serialize the data
118
+ return serialize(array(
119
+ $this->name(),
120
+ $this->attributes(),
121
+ ));
122
+ }
123
+
124
+ /**
125
+ * Unserialize the object
126
+ * @param string
127
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Order_Item_Options
128
+ */
129
+ public function unserialize($string)
130
+ {
131
+ list(
132
+ $this->name,
133
+ $this->attributes
134
+ ) = unserialize($string);
135
+ return $this;
136
+ }
137
+ }
138
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Price.php ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a price
4
+ * This is not representing a magento object
5
+ * Note that the price can consist of a lot of components:
6
+ * - price
7
+ * - shippingcost
8
+ * - discount
9
+ * - additional_fees (is a list of custom configurable fees)
10
+ * - tax
11
+ * - total_price
12
+ */
13
+ class Copernica_MarketingSoftware_Model_Abstraction_Price implements Serializable
14
+ {
15
+ /**
16
+ * The original object
17
+ * @param Mage_Sales_Model_Quote|Mage_Sales_Model_Order|Mage_Sales_Model_Quote_Item|Mage_Sales_Model_Order_Item
18
+ */
19
+ private $original;
20
+
21
+ /**
22
+ * Predefine the internal fields
23
+ */
24
+ private $total;
25
+ private $costs;
26
+ private $itemPrice;
27
+ private $originalPrice;
28
+ private $discount;
29
+ private $tax;
30
+ private $shipping;
31
+ private $currency;
32
+
33
+ /**
34
+ * Sets the original model
35
+ * @param Mage_Sales_Model_Quote|Mage_Sales_Model_Order|Mage_Sales_Model_Quote_Item|Mage_Sales_Model_Order_Item $original
36
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Price
37
+ */
38
+ public function setOriginal($original)
39
+ {
40
+ $this->original = $original;
41
+ return $this;
42
+ }
43
+
44
+ /**
45
+ * Return the total price
46
+ * @return float
47
+ */
48
+ public function total()
49
+ {
50
+ // Is this object still present?
51
+ if (is_object($this->original))
52
+ {
53
+ // Used for quotes and orders
54
+ if ($grandTotal = $this->original->getGrandTotal()) return $grandTotal;
55
+
56
+ // Used for quote items and order items
57
+ elseif ($rowTotalInclTax = $this->original->getRowTotalInclTax()) return $rowTotalInclTax;
58
+
59
+ // Used for quote items and order items (when no tax is configured)
60
+ elseif ($baseRowTotal = $this->original->getBaseRowTotal()) return $baseRowTotal;
61
+ }
62
+ else return $this->total;
63
+ }
64
+
65
+ /**
66
+ * Return the price for the individual item
67
+ * @return float
68
+ */
69
+ public function costs()
70
+ {
71
+ // Is this object still present?
72
+ if (is_object($this->original))
73
+ {
74
+ // Used for quotes and orders
75
+ if ($this->original instanceOf Mage_Sales_Model_Quote || $this->original instanceOf Mage_Sales_Model_Order)
76
+ {
77
+ $costs = 0;
78
+
79
+ // iterate over all visisble items
80
+ foreach ($this->original->getAllVisibleItems() as $item)
81
+ {
82
+ $costs += $item->getBaseCost();
83
+ }
84
+
85
+ // return the costs
86
+ return $costs;
87
+ }
88
+
89
+ // Used for quote items and order items
90
+ elseif ($baseCost = $this->original->getBaseCost()) return $baseCost;
91
+ }
92
+ else return $this->costs;
93
+ }
94
+
95
+ /**
96
+ * Return the price for the individual item
97
+ * @return float
98
+ */
99
+ public function itemPrice()
100
+ {
101
+ // Is this object still present?
102
+ if (is_object($this->original))
103
+ {
104
+ // no price for an individual item
105
+ if ($this->original instanceOf Mage_Sales_Model_Quote || $this->original instanceOf Mage_Sales_Model_Order) return 0;
106
+
107
+ // Used for quote items and order items
108
+ elseif ($price = $this->original->getPrice()) return $price;
109
+ }
110
+ else return $this->itemPrice;
111
+ }
112
+
113
+ /**
114
+ * Return the original price for the individual item
115
+ * @return float
116
+ */
117
+ public function originalPrice()
118
+ {
119
+ // Is this object still present?
120
+ if (is_object($this->original))
121
+ {
122
+ // no price for an individual item
123
+ if ($this->original instanceOf Mage_Sales_Model_Quote || $this->original instanceOf Mage_Sales_Model_Order) return 0;
124
+
125
+ // Used for quote items and order items
126
+ elseif ($originalPrice = $this->original->getOriginalPrice()) return $originalPrice;
127
+ }
128
+ else return $this->originalPrice;
129
+ }
130
+
131
+ /**
132
+ * Return the discount which was given
133
+ * @return float
134
+ */
135
+ public function discount()
136
+ {
137
+ // Is this object still present?
138
+ if (is_object($this->original))
139
+ {
140
+ // Used for all items
141
+ if ($discountAmount = $this->original->getDiscountAmount()) return $discountAmount;
142
+ }
143
+ else return $this->discount;
144
+ }
145
+
146
+ /**
147
+ * Return the tax which was paid
148
+ * @return float
149
+ */
150
+ public function tax()
151
+ {
152
+ // Is this object still present?
153
+ if (is_object($this->original))
154
+ {
155
+ // Used for all items
156
+ if ($taxAmount = $this->original->getTaxAmount()) return $taxAmount;
157
+ }
158
+ else return $this->tax;
159
+ }
160
+
161
+ /**
162
+ * Return the shipping costs
163
+ * @return float
164
+ */
165
+ public function shipping()
166
+ {
167
+ // Is this object still present?
168
+ if (is_object($this->original))
169
+ {
170
+ // Shipping is only available for quotes and orders, but not for items
171
+ if ($this->original instanceOf Mage_Sales_Model_Quote || $this->original instanceOf Mage_Sales_Model_Order)
172
+ {
173
+ // Get the shipping amount
174
+ if ($shippingAmount = $this->original->getShippingAmount()) return $shippingAmount;
175
+ }
176
+ else return 0;
177
+ }
178
+ else return $this->shipping;
179
+ }
180
+
181
+ /**
182
+ * Return the currency code
183
+ * @return float
184
+ */
185
+ public function currency()
186
+ {
187
+ // Is this object still present?
188
+ if (is_object($this->original))
189
+ {
190
+ if ($currency = $this->original->getOrderCurrencyCode()) return $currency;
191
+ elseif ($currency = $this->original->getQuoteCurrencyCode()) return $currency;
192
+ elseif (($order = $this->original->getOrder()) && ($currency = $order->getOrderCurrencyCode())) return $currency;
193
+ elseif (($quote = $this->original->getQuote()) && ($currency = $quote->getQuoteCurrencyCode())) return $currency;
194
+ else return '';
195
+ }
196
+ else return $this->currency;
197
+ }
198
+
199
+ /**
200
+ * Serialize the object
201
+ * @return string
202
+ */
203
+ public function serialize()
204
+ {
205
+ // serialize the data
206
+ return serialize(array(
207
+ $this->total(),
208
+ $this->costs(),
209
+ $this->itemPrice(),
210
+ $this->originalPrice(),
211
+ $this->discount(),
212
+ $this->tax(),
213
+ $this->shipping(),
214
+ $this->currency(),
215
+ ));
216
+ }
217
+
218
+ /**
219
+ * Unserialize the object
220
+ * @param string
221
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Price
222
+ */
223
+ public function unserialize($string)
224
+ {
225
+ list(
226
+ $this->total,
227
+ $this->costs,
228
+ $this->itemPrice,
229
+ $this->originalPrice,
230
+ $this->discount,
231
+ $this->tax,
232
+ $this->shipping,
233
+ $this->currency
234
+ ) = unserialize($string);
235
+ }
236
+ }
237
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Product.php ADDED
@@ -0,0 +1,411 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a magento Product
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Product implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Catalog_Model_Product
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $sku;
18
+ private $name;
19
+ private $description;
20
+ private $productUrl;
21
+ private $imagePath;
22
+ private $weight;
23
+ private $categories = array();
24
+ private $isNew;
25
+ private $price;
26
+ private $created;
27
+ private $modified;
28
+ private $attributes;
29
+
30
+ /**
31
+ * Sets the original model
32
+ * @param Mage_Catalog_Model_Product|Mage_Sales_Model_Quote_Item|Mage_Sales_Model_Order_Item $original
33
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Product
34
+ */
35
+ public function setOriginal($original)
36
+ {
37
+ if ($original instanceof Mage_Catalog_Model_Product) {
38
+ //this is the original product
39
+ $this->original = $original;
40
+
41
+ return $this;
42
+ }
43
+ else
44
+ {
45
+ //the quote item or order item has a product id
46
+ $product = Mage::getModel('catalog/product')->load($original->getProductId());
47
+ if ($product->getId())
48
+ {
49
+ //the product exists
50
+ $this->original = $product;
51
+ }
52
+ else
53
+ {
54
+ // unfortunately we do not have the product any more, but we have the information
55
+ // so we can fill a lot of fields, so the functions still work
56
+ $this->id = $original->getProductId();
57
+ $this->sku = $original->getSKU();
58
+ $this->name = $original->getName();
59
+ $this->description = $original->getDescription();
60
+ $this->productUrl = '';
61
+ $this->imagePath = '';
62
+ $this->weight = $original->getWeight();
63
+ $this->categories = array();
64
+ $this->isNew = false;
65
+ $this->price = $original->getPrice();
66
+ $this->created = '';
67
+ $this->modified = '';
68
+ $this->attributes = '';
69
+ }
70
+
71
+ return $this;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Loads a product model
77
+ * @param integer $productId
78
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Product
79
+ */
80
+ public function loadProduct($productId)
81
+ {
82
+ $product = Mage::getModel('catalog/product')->load($productId);
83
+ if ($product->getId()) {
84
+ //set the original model if the product exists
85
+ $this->original = $product;
86
+ }
87
+ else
88
+ {
89
+ $this->id = $productId;
90
+ }
91
+ return $this;
92
+ }
93
+
94
+ /**
95
+ * Return the identifier for this object
96
+ * @return integer
97
+ */
98
+ public function id()
99
+ {
100
+ // Is this object still present?
101
+ if (is_object($this->original))
102
+ {
103
+ return $this->original->getId();
104
+ }
105
+ else return $this->id;
106
+ }
107
+
108
+ /**
109
+ * Return the sku (stock keeping unit), which is an unique identifier
110
+ * for a magento product
111
+ * @return string
112
+ */
113
+ public function sku()
114
+ {
115
+ // Is this object still present?
116
+ if (is_object($this->original))
117
+ {
118
+ return $this->original->getSku();
119
+ }
120
+ else return $this->sku;
121
+ }
122
+
123
+ /**
124
+ * Return the name of this magento product
125
+ * @return string
126
+ */
127
+ public function name()
128
+ {
129
+ // Is this object still present?
130
+ if (is_object($this->original))
131
+ {
132
+ return $this->original->getName();
133
+ }
134
+ else return $this->name;
135
+ }
136
+
137
+ /**
138
+ * Return the description of this magento product
139
+ * @return string
140
+ */
141
+ public function description()
142
+ {
143
+ // Is this object still present?
144
+ if (is_object($this->original))
145
+ {
146
+ return $this->original->getShortDescription();
147
+ }
148
+ else return $this->description;
149
+ }
150
+
151
+ /**
152
+ * Return the price of this magento product
153
+ * @return string
154
+ */
155
+ public function price()
156
+ {
157
+ // Is this object still present?
158
+ if (is_object($this->original))
159
+ {
160
+ return $this->original->getPrice();
161
+ }
162
+ else return $this->price;
163
+ }
164
+
165
+ /**
166
+ * Return the creation date of this magento product
167
+ * @return string
168
+ */
169
+ public function created()
170
+ {
171
+ // Is this object still present?
172
+ if (is_object($this->original))
173
+ {
174
+ return $this->original->getCreatedAt();
175
+ }
176
+ else return $this->created;
177
+ }
178
+
179
+ /**
180
+ * Return the modification date of this magento product
181
+ * @return string
182
+ */
183
+ public function modified()
184
+ {
185
+ // Is this object still present?
186
+ if (is_object($this->original))
187
+ {
188
+ return $this->original->getUpdatedAt();
189
+ }
190
+ else return $this->modified;
191
+ }
192
+
193
+ /**
194
+ * Return the product url of this magento product
195
+ * @param integer optional store id
196
+ * @return string
197
+ */
198
+ public function productUrl($storeId = null)
199
+ {
200
+ // If the object is not present and there is no store id
201
+ // than we fallback to the `cached item`
202
+ if (!is_object($this->original) && $storeId === null)
203
+ {
204
+ return $this->productUrl;
205
+ }
206
+ else
207
+ {
208
+ // Get the product
209
+ $product = is_object($this->original) ? $this->original : Mage::getModel('catalog/product')->load($this->id);
210
+
211
+ // Could not load the product, return an empty string
212
+ if (!$product->getId()) return '';
213
+
214
+ // Retrieve the requested store, null returns the default store
215
+ $store = Mage::app()->getStore($storeId);
216
+
217
+ // We have a valid product now
218
+ $href = Mage::getModel('core/url_rewrite')->loadByIdPath('product/' . $product->getId())->getRequestPath();
219
+ if ($href && is_object($store))
220
+ {
221
+ // Get the url from the store
222
+ $url = $store->getUrl('', array('_direct' => $href));
223
+
224
+ // Should we use the SEO rewrites
225
+ if (Mage::getStoreConfig('web/seo/use_rewrites')) {
226
+ return str_replace('index.php/', '', $url);
227
+ } else {
228
+ return $url;
229
+ }
230
+ }
231
+ // or use the default if it doesn't exist
232
+ else return $product->getProductUrl();
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Return the image url of this magento product
238
+ * @param integer|boolean optional store id, if false is given only the path is returned
239
+ * @return string
240
+ */
241
+ public function imageUrl($storeId = null)
242
+ {
243
+ // Is this object still present?
244
+ if (is_object($this->original))
245
+ {
246
+ $path = 'catalog' . DS . 'product' . $this->original->getImage();
247
+ }
248
+ else $path = $this->imagePath;
249
+
250
+ // most likely store `false` is supplied to the function, if the path
251
+ // is empty it is also not very usefull to prepend a string to it
252
+ if ($storeId === false || empty($path)) return $path;
253
+
254
+ // Retrieve the requested store, null returns the default store
255
+ $store = Mage::app()->getStore($storeId);
256
+
257
+ // We did retrieve a store, but was it an object?
258
+ if (!is_object($store)) return $path;
259
+
260
+ // add a prefix for the store here
261
+ return $store->getBaseUrl('media') . $path;
262
+ }
263
+
264
+ /**
265
+ * Return the weight of this magento product
266
+ * @return float
267
+ */
268
+ public function weight()
269
+ {
270
+ // Is this object still present?
271
+ if (is_object($this->original))
272
+ {
273
+ return $this->original->getWeight();
274
+ }
275
+ else return $this->weight;
276
+ }
277
+
278
+ /**
279
+ * Return the categories of this product
280
+ * @return array of category ids to category names in a path from the root
281
+ */
282
+ public function categories()
283
+ {
284
+ // Is this object still present?
285
+ if (is_object($this->original))
286
+ {
287
+ $data = array();
288
+ $categoryIds = $this->original->getCategoryIds();
289
+ foreach ($categoryIds as $categoryId) {
290
+ $category = Mage::getModel('catalog/category')->load($categoryId);
291
+ $data[] = $this->_getFullCategoryName($category);
292
+ }
293
+ return $data;
294
+ }
295
+ else return $this->categories;
296
+ }
297
+
298
+ /**
299
+ * Return the flattened tree of the given category
300
+ * @param Mage_Catalog_Model_Category $category
301
+ * @return array
302
+ */
303
+ private function _getFullCategoryName(Mage_Catalog_Model_Category $category)
304
+ {
305
+ // is there a parent?
306
+ if ($category->getParentId() > 1)
307
+ {
308
+ // get the parent
309
+ $parent = $category->getParentCategory();
310
+ $data = $this->_getFullCategoryName($parent);
311
+ } else {
312
+ $data = array();
313
+ }
314
+
315
+ // append the current name
316
+ $data[$category->getId()] = $category->getName();
317
+
318
+ // return the data
319
+ return $data;
320
+ }
321
+
322
+ /**
323
+ * Return whether this product is new
324
+ * @return boolean
325
+ */
326
+ public function isNew()
327
+ {
328
+ // Is this object still present?
329
+ if (is_object($this->original))
330
+ {
331
+ $from = $this->original->getNewsFromDate() ? Mage::app()->getLocale()->date($this->original->getNewsFromDate()) : null;
332
+ $to = $this->original->getNewsToDate() ? Mage::app()->getLocale()->date($this->original->getNewsToDate()) : null;
333
+ if ($from || $to) {
334
+ $new = true;
335
+ $now = Zend_Date::now();
336
+ if ($from) {
337
+ $new = $new && $from->isEarlier($now);
338
+ }
339
+ if ($to) {
340
+ $new = $new && $to->isLater($now);
341
+ }
342
+ return $new;
343
+ }
344
+ return false;
345
+ }
346
+ else return $this->isNew;
347
+ }
348
+
349
+ /**
350
+ * Return the attributes for this product
351
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Attributes
352
+ */
353
+ public function attributes()
354
+ {
355
+ // Is this object still present?
356
+ if (is_object($this->original))
357
+ {
358
+ return Mage::getModel('marketingsoftware/abstraction_attributes')->setOriginal($this->original);
359
+ }
360
+ else return $this->attributes;
361
+ }
362
+
363
+ /**
364
+ * Serialize the object
365
+ * @return string
366
+ */
367
+ public function serialize()
368
+ {
369
+ // serialize the data
370
+ return serialize(array(
371
+ $this->id(),
372
+ $this->sku(),
373
+ $this->name(),
374
+ $this->description(),
375
+ $this->productUrl(),
376
+ $this->imageUrl(false), // gets the image path if store 'false' is supplied
377
+ $this->weight(),
378
+ $this->categories(),
379
+ $this->isNew(),
380
+ $this->price(),
381
+ $this->created(),
382
+ $this->modified(),
383
+ $this->attributes(),
384
+ ));
385
+ }
386
+
387
+ /**
388
+ * Unserialize the object
389
+ * @param string
390
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Product
391
+ */
392
+ public function unserialize($string)
393
+ {
394
+ list(
395
+ $this->id,
396
+ $this->sku,
397
+ $this->name,
398
+ $this->description,
399
+ $this->productUrl,
400
+ $this->imagePath,
401
+ $this->weight,
402
+ $this->categories,
403
+ $this->isNew,
404
+ $this->price,
405
+ $this->created,
406
+ $this->modified,
407
+ $this->attributes
408
+ ) = unserialize($string);
409
+ return $this;
410
+ }
411
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Quote.php ADDED
@@ -0,0 +1,359 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a Quote
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Quote implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Quote
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $quoteId;
17
+ private $quantity;
18
+ private $currency;
19
+ private $timestamp;
20
+ private $customerIP;
21
+ private $items;
22
+ private $storeview;
23
+ private $customerId;
24
+ private $addresses;
25
+ private $price;
26
+ private $weight;
27
+ private $active;
28
+ private $shippingDescription;
29
+ private $paymentDescription;
30
+
31
+ /**
32
+ * Sets the original model
33
+ * @param Mage_Sales_Model_Quote $original
34
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote
35
+ */
36
+ public function setOriginal(Mage_Sales_Model_Quote $original)
37
+ {
38
+ $this->original = $original;
39
+ return $this;
40
+ }
41
+
42
+ /**
43
+ * Loads a quote model
44
+ * @param integer $quoteId
45
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote
46
+ */
47
+ public function loadQuote($quoteId)
48
+ {
49
+ // Get the model
50
+ $quote = Mage::getModel('sales/quote');
51
+
52
+ // Difference between Magento 1.4 / 1.5
53
+ if (!is_callable($quote, 'loadByIdWithoutStore'))
54
+ {
55
+ // construct an array with store ids
56
+ $storeIDs = array();
57
+ foreach (Mage::app()->getStores() as $id => $store) $storeIDs[] = $id;
58
+
59
+ // The store ids are used for loading the quote, independant of the store
60
+ $quote->setSharedStoreIds($storeIDs);
61
+ $quote->load($quoteId);
62
+ }
63
+ else $quote->loadByIdWithoutStore($quoteId);
64
+
65
+ // we did load a valid quote, set the original model
66
+ if ($quote->getId()) $this->original = $quote;
67
+ else $this->quoteId = $quoteId;
68
+
69
+ // return this
70
+ return $this;
71
+ }
72
+
73
+ /**
74
+ * The quote id of this quote object
75
+ * @return integer
76
+ */
77
+ public function id()
78
+ {
79
+ // Is this object still present?
80
+ if (is_object($this->original))
81
+ {
82
+ return $this->original->getId();
83
+ }
84
+ else return $this->quoteId;
85
+ }
86
+
87
+ /**
88
+ * Is this quote still active
89
+ * @return boolean
90
+ */
91
+ public function active()
92
+ {
93
+ // Is this object still present?
94
+ if (is_object($this->original))
95
+ {
96
+ return (bool)$this->original->getIsActive();
97
+ }
98
+ else return $this->active;
99
+ }
100
+
101
+ /**
102
+ * The number of items present in this quote
103
+ * @return integer
104
+ */
105
+ public function quantity()
106
+ {
107
+ // Is this object still present?
108
+ if (is_object($this->original))
109
+ {
110
+ return $this->original->getItemsQty();
111
+ }
112
+ else return $this->quantity;
113
+ }
114
+
115
+ /**
116
+ * The payment currency of this quote
117
+ * @return string
118
+ */
119
+ public function currency()
120
+ {
121
+ // Is this object still present?
122
+ if (is_object($this->original))
123
+ {
124
+ return $this->original->getQuoteCurrencyCode();
125
+ }
126
+ else return $this->currency;
127
+ }
128
+
129
+ /**
130
+ * The price
131
+ * Note that an object is returned, which may consist of multiple components
132
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Price
133
+ */
134
+ public function price()
135
+ {
136
+ // Is this object still present?
137
+ if (is_object($this->original))
138
+ {
139
+ // Note that the price may consist of multiple elements
140
+ return Mage::getModel('marketingsoftware/abstraction_price')->setOriginal($this->original);
141
+ }
142
+ else return $this->price;
143
+ }
144
+
145
+ /**
146
+ * The weight
147
+ * @return float
148
+ */
149
+ public function weight()
150
+ {
151
+ // Is this object still present?
152
+ if (is_object($this->original))
153
+ {
154
+ if ($address = $this->original->getShippingAddress()) {
155
+ return $address->getWeight();
156
+ } else {
157
+ return null;
158
+ }
159
+ }
160
+ else return $this->price;
161
+ }
162
+
163
+ /**
164
+ * To what storeview does this quote belong
165
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
166
+ */
167
+ public function storeview()
168
+ {
169
+ // Is this object still present?
170
+ if (is_object($this->original))
171
+ {
172
+ return Mage::getModel('marketingsoftware/abstraction_storeview')->setOriginal($this->original->getStore());
173
+ }
174
+ else return $this->storeview;
175
+ }
176
+
177
+ /**
178
+ * Get the items from the quote
179
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Quote_Item
180
+ */
181
+ public function items()
182
+ {
183
+ // Is this object still present?
184
+ if (is_object($this->original))
185
+ {
186
+ $data = array();
187
+ $items = $this->original->getAllVisibleItems();
188
+ foreach ($items as $item) {
189
+ $data[] = Mage::getModel('marketingsoftware/abstraction_quote_item')->setOriginal($item);
190
+ }
191
+ return $data;
192
+ }
193
+ else return $this->items;
194
+ }
195
+
196
+ /**
197
+ * The timestamp at which this quote was modified
198
+ * @return string
199
+ */
200
+ public function timestamp()
201
+ {
202
+ // Is this object still present?
203
+ if (is_object($this->original))
204
+ {
205
+ return $this->original->getUpdatedAt();
206
+ }
207
+ else return $this->timestamp;
208
+ }
209
+
210
+ /**
211
+ * The customer may return null
212
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Customer
213
+ */
214
+ public function customer()
215
+ {
216
+ // Is this object still present?
217
+ if (is_object($this->original))
218
+ {
219
+ // The quote model only returns a customer if it exists
220
+ if ($customerId = $this->original->getCustomerId())
221
+ {
222
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($customerId);
223
+ }
224
+ }
225
+ elseif ($this->customerId)
226
+ {
227
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($this->customerId);
228
+ }
229
+
230
+ // default fallback
231
+ return null;
232
+ }
233
+
234
+ /**
235
+ * The addresses of this quote
236
+ * @return array of Copernica_MarketingSoftware_Model_Abstraction_Address
237
+ */
238
+ public function addresses()
239
+ {
240
+ // Is this object still present?
241
+ if (is_object($this->original))
242
+ {
243
+ $data = array();
244
+ //retrieve this quote's addresses
245
+ //Note: this may return empty addresses, since quotes always have address records. Check the email field of the address.
246
+ $addresses = $this->original->getAddressesCollection();
247
+ foreach ($addresses as $address) {
248
+ $data[] = Mage::getModel('marketingsoftware/abstraction_address')->setOriginal($address);
249
+ }
250
+ return $data;
251
+ }
252
+ else return $this->addresses;
253
+ }
254
+
255
+ /**
256
+ * The IP from which this quote was constructed
257
+ * @return string
258
+ */
259
+ public function customerIP()
260
+ {
261
+ // Is this object still present?
262
+ if (is_object($this->original))
263
+ {
264
+ return $this->original->getRemoteIp();
265
+ }
266
+ else return $this->customerIP;
267
+ }
268
+
269
+ /**
270
+ * The shipping method of this quote
271
+ * @return string
272
+ */
273
+ public function shippingDescription()
274
+ {
275
+ // Is this object still present?
276
+ if (is_object($this->original))
277
+ {
278
+ if ($address = $this->original->getShippingAddress()) {
279
+ return $address->getShippingDescription();
280
+ } else {
281
+ return null;
282
+ }
283
+ }
284
+ else return $this->shippingDescription;
285
+ }
286
+
287
+ /**
288
+ * The payment method of this quote
289
+ * @return string
290
+ */
291
+ public function paymentDescription()
292
+ {
293
+ // Is this object still present?
294
+ if (is_object($this->original))
295
+ {
296
+ if ($payment = $this->original->getPayment()) {
297
+ //this try/catch is needed because getMethodInstance throws an exception instead of returning null
298
+ try {
299
+ return $payment->getMethodInstance()->getTitle();
300
+ } catch (Mage_Core_Exception $exception) {
301
+ return null;
302
+ }
303
+ }
304
+ return null;
305
+ }
306
+ else return $this->paymentDescription;
307
+ }
308
+
309
+ /**
310
+ * Serialize the object
311
+ * @return string
312
+ */
313
+ public function serialize()
314
+ {
315
+ // serialize the data
316
+ return serialize(array(
317
+ $this->id(),
318
+ $this->quantity(),
319
+ $this->currency(),
320
+ $this->timestamp(),
321
+ $this->customerIP(),
322
+ $this->items(),
323
+ $this->storeview(),
324
+ is_object($customer = $this->customer()) ? $customer->id() : null,
325
+ $this->addresses(),
326
+ $this->price(),
327
+ $this->weight(),
328
+ $this->active(),
329
+ $this->shippingDescription(),
330
+ $this->paymentDescription()
331
+ ));
332
+ }
333
+
334
+ /**
335
+ * Unserialize the object
336
+ * @param string
337
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote
338
+ */
339
+ public function unserialize($string)
340
+ {
341
+ list(
342
+ $this->quoteId,
343
+ $this->quantity,
344
+ $this->currency,
345
+ $this->timestamp,
346
+ $this->customerIP,
347
+ $this->items,
348
+ $this->storeview,
349
+ $this->customerId,
350
+ $this->addresses,
351
+ $this->price,
352
+ $this->weight,
353
+ $this->active,
354
+ $this->shippingDescription,
355
+ $this->paymentDescription
356
+ ) = unserialize($string);
357
+ return $this;
358
+ }
359
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Quote/Item.php ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a Quote Item
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Quote_Item implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Quote_Item
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $quoteId;
18
+ private $storeId;
19
+ private $quantity;
20
+ private $price;
21
+ private $weight;
22
+ private $timestamp;
23
+ private $options;
24
+ private $product;
25
+
26
+ /**
27
+ * Sets the original model
28
+ * @param Mage_Sales_Model_Quote_Item $original
29
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote_Item
30
+ */
31
+ public function setOriginal(Mage_Sales_Model_Quote_Item $original)
32
+ {
33
+ $this->original = $original;
34
+ return $this;
35
+ }
36
+
37
+ /**
38
+ * The id of this quote item object
39
+ * @return integer
40
+ */
41
+ public function id()
42
+ {
43
+ // Is this object still present?
44
+ if (is_object($this->original))
45
+ {
46
+ return $this->original->getId();
47
+ }
48
+ else return $this->id;
49
+ }
50
+
51
+ /**
52
+ * Get the quote to which this item belongs
53
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote
54
+ */
55
+ public function quote()
56
+ {
57
+ // Is this object still present?
58
+ if (is_object($this->original))
59
+ {
60
+ if ($quote = $this->original->getQuote()) {
61
+ return Mage::getModel('marketingsoftware/abstraction_quote')->setOriginal($quote);
62
+ } else {
63
+ return null;
64
+ }
65
+ }
66
+ else return Mage::getModel('marketingsoftware/abstraction_quote')->loadQuote($this->quoteId);
67
+ }
68
+
69
+ /**
70
+ * The amount of this quote item
71
+ * @return integer
72
+ */
73
+ public function quantity()
74
+ {
75
+ // Is this object still present?
76
+ if (is_object($this->original))
77
+ {
78
+ return $this->original->getQty();
79
+ }
80
+ else return $this->quantity;
81
+ }
82
+
83
+ /**
84
+ * The price
85
+ * Note that an object is returned, which may consist of multiple components
86
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Price
87
+ */
88
+ public function price()
89
+ {
90
+ // Is this object still present?
91
+ if (is_object($this->original))
92
+ {
93
+ // Note that the price may consist of multiple elements
94
+ return Mage::getModel('marketingsoftware/abstraction_price')->setOriginal($this->original);
95
+ }
96
+ else return $this->price;
97
+ }
98
+
99
+ /**
100
+ * The weight
101
+ * @return float
102
+ */
103
+ public function weight()
104
+ {
105
+ // Is this object still present?
106
+ if (is_object($this->original))
107
+ {
108
+ return $this->original->getWeight();
109
+ }
110
+ else return $this->weight;
111
+ }
112
+
113
+ /**
114
+ * The timestamp at which this quote item was modified
115
+ * @return string
116
+ */
117
+ public function timestamp()
118
+ {
119
+ // Is this object still present?
120
+ if (is_object($this->original))
121
+ {
122
+ return $this->original->getUpdatedAt();
123
+ }
124
+ else return $this->timestamp;
125
+ }
126
+
127
+ /**
128
+ * Get the options of this quote item
129
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote_Item_Options
130
+ */
131
+ public function options()
132
+ {
133
+ // Is this object still present?
134
+ if (is_object($this->original))
135
+ {
136
+ $options = Mage::getModel('marketingsoftware/abstraction_quote_item_options')->setOriginal($this->original);
137
+ if ($options->attributes()) {
138
+ //only return option object if it this quote actually has options
139
+ return $options;
140
+ } else {
141
+ return null;
142
+ }
143
+ }
144
+ else return $this->options;
145
+ }
146
+
147
+ /**
148
+ * Get the product which belongs to this item
149
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Product
150
+ */
151
+ public function product()
152
+ {
153
+ // Is this object still present?
154
+ if (is_object($this->original))
155
+ {
156
+ return Mage::getModel('marketingsoftware/abstraction_product')->setOriginal($this->original);
157
+ }
158
+ else return $this->product;
159
+ }
160
+
161
+ /**
162
+ * Serialize the object
163
+ * @return string
164
+ */
165
+ public function serialize()
166
+ {
167
+ // serialize the data
168
+ return serialize(array(
169
+ $this->id(),
170
+ is_object($quote = $this->quote()) ? $quote->id() : null,
171
+ $this->quantity(),
172
+ $this->price(),
173
+ $this->weight(),
174
+ $this->timestamp(),
175
+ $this->options(),
176
+ $this->product(),
177
+ ));
178
+ }
179
+
180
+ /**
181
+ * Unserialize the object
182
+ * @param string
183
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote_Item
184
+ */
185
+ public function unserialize($string)
186
+ {
187
+ list(
188
+ $this->id,
189
+ $this->quoteId,
190
+ $this->quantity,
191
+ $this->price,
192
+ $this->weight,
193
+ $this->timestamp,
194
+ $this->options,
195
+ $this->product
196
+ ) = unserialize($string);
197
+ return $this;
198
+ }
199
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Quote/Item/Options.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around quote item options
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Quote_Item_Options implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Sales_Model_Quote_Item
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $name;
17
+ private $attributes;
18
+
19
+
20
+ /**
21
+ * Sets the original model
22
+ * @param Mage_Sales_Model_Quote_Item $original
23
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote_Item_Options
24
+ */
25
+ public function setOriginal(Mage_Sales_Model_Quote_Item $original)
26
+ {
27
+ $this->original = $original;
28
+ return $this;
29
+ }
30
+
31
+ /**
32
+ * The name of this set of options
33
+ * @return integer
34
+ */
35
+ public function name()
36
+ {
37
+ // Is this object still present?
38
+ if (is_object($this->original))
39
+ {
40
+ return $this->original->getName();
41
+ }
42
+ else return $this->name;
43
+ }
44
+
45
+ /**
46
+ * Return an assoc array with attributes
47
+ * @return array
48
+ */
49
+ public function attributes()
50
+ {
51
+ // Is this object still present?
52
+ if (is_object($this->original))
53
+ {
54
+ $data = array();
55
+ if ($optionData = $this->original->getOptionByCode('info_buyRequest')) {
56
+ $product = $optionData->getProduct();
57
+ //this converts the options to a usable format (same as order items)
58
+ //see: Mage_Sales_Model_Convert_Quote::itemToOrderItem
59
+ $options = $this->original->getProduct()->getTypeInstance(true)->getOrderOptions($this->original->getProduct());
60
+ $attributes = array();
61
+ if (isset($options['attributes_info'])) {
62
+ //configurable products
63
+ $attributes = $options['attributes_info'];
64
+ } elseif (isset($options['bundle_options'])) {
65
+ //bundle products
66
+ $attributes = $options['bundle_options'];
67
+ } elseif (isset($options['options'])) {
68
+ //generic products
69
+ $attributes = $options['options'];
70
+ }
71
+ if ($attributes) {
72
+ foreach ($attributes as $attribute) {
73
+ $data[$attribute['label']] = $attribute['value'];
74
+ }
75
+ return $data;
76
+ }
77
+ }
78
+ return null;
79
+ }
80
+ else return $this->attributes;
81
+ }
82
+
83
+ /**
84
+ * Return a string representation
85
+ * @return String
86
+ */
87
+ public function __toString()
88
+ {
89
+ return $this->arrayToString($this->attributes());
90
+ }
91
+
92
+ /**
93
+ * Return a string representation of an array
94
+ * @param array
95
+ * @return String
96
+ */
97
+ private function arrayToString($value, $prefix = '')
98
+ {
99
+ $string = "";
100
+ foreach ($value as $key => $value)
101
+ {
102
+ // is the value an array
103
+ if (is_array($value))
104
+ {
105
+ // if there is only one subvalue, use that instead
106
+ if (isset($value[0]) && count($value) == 1) $value = $value[0];
107
+
108
+ // compose the string
109
+ $string .= $prefix.$key.":\n".$this->arrayToString($value, $prefix.' ');
110
+ }
111
+ else $string.= $prefix.$key.": $value\n";
112
+ }
113
+ return $string;
114
+ }
115
+
116
+ /**
117
+ * Serialize the object
118
+ * @return string
119
+ */
120
+ public function serialize()
121
+ {
122
+ // serialize the data
123
+ return serialize(array(
124
+ $this->name(),
125
+ $this->attributes(),
126
+ ));
127
+ }
128
+
129
+ /**
130
+ * Unserialize the object
131
+ * @param string
132
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Quote_Item_Options
133
+ */
134
+ public function unserialize($string)
135
+ {
136
+ list(
137
+ $this->name,
138
+ $this->attributes
139
+ ) = unserialize($string);
140
+ return $this;
141
+ }
142
+ }
143
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Storeview.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a Store
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Storeview implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Core_Model_Store
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $websiteCode;
18
+ private $websiteLabel;
19
+ private $storeCode;
20
+ private $storeLabel;
21
+ private $viewCode;
22
+ private $viewLabel;
23
+
24
+
25
+ /**
26
+ * Sets the original model
27
+ * @param Mage_Core_Model_Store $original
28
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
29
+ */
30
+ public function setOriginal(Mage_Core_Model_Store $original)
31
+ {
32
+ $this->original = $original;
33
+ return $this;
34
+ }
35
+
36
+ /**
37
+ * Return the id for the storeview
38
+ * @return int
39
+ */
40
+ public function id()
41
+ {
42
+ // Is this object still present?
43
+ if (is_object($this->original))
44
+ {
45
+ return $this->original->getId();
46
+ }
47
+ else return $this->id;
48
+ }
49
+
50
+ /**
51
+ * Return the code for the website
52
+ * @return string
53
+ */
54
+ public function websiteCode()
55
+ {
56
+ // Is this object still present?
57
+ if (is_object($this->original))
58
+ {
59
+ return $this->original->getWebsite()->getCode();
60
+ }
61
+ else return $this->websiteCode;
62
+ }
63
+
64
+ /**
65
+ * Return the label for the website
66
+ * @return string
67
+ */
68
+ public function websiteLabel()
69
+ {
70
+ // Is this object still present?
71
+ if (is_object($this->original))
72
+ {
73
+ return $this->original->getWebsite()->getName();
74
+ }
75
+ else return $this->websiteLabel;
76
+ }
77
+
78
+ /**
79
+ * Return the code for the store
80
+ * @return string
81
+ */
82
+ public function storeCode()
83
+ {
84
+ // Is this object still present?
85
+ if (is_object($this->original))
86
+ {
87
+ return $this->original->getGroup()->getId();
88
+ }
89
+ else return $this->storeCode;
90
+ }
91
+
92
+ /**
93
+ * Return the label for the store
94
+ * @return string
95
+ */
96
+ public function storeLabel()
97
+ {
98
+ // Is this object still present?
99
+ if (is_object($this->original))
100
+ {
101
+ return $this->original->getGroup()->getName();
102
+ }
103
+ else return $this->storeLabel;
104
+ }
105
+
106
+ /**
107
+ * Return the code for the store
108
+ * @return string
109
+ */
110
+ public function viewCode()
111
+ {
112
+ // Is this object still present?
113
+ if (is_object($this->original))
114
+ {
115
+ return $this->original->getCode();
116
+ }
117
+ else return $this->viewCode;
118
+ }
119
+
120
+ /**
121
+ * Return the label for the store
122
+ * @return string
123
+ */
124
+ public function viewLabel()
125
+ {
126
+ // Is this object still present?
127
+ if (is_object($this->original))
128
+ {
129
+ return $this->original->getName();
130
+ }
131
+ else return $this->viewLabel;
132
+ }
133
+
134
+ /**
135
+ * Convert this value to a string
136
+ * @return String
137
+ */
138
+ public function __toString()
139
+ {
140
+ return implode(' > ', array(
141
+ $this->websiteLabel(),
142
+ $this->storeLabel(),
143
+ $this->viewLabel(),
144
+ ));
145
+ }
146
+
147
+ /**
148
+ * Serialize the object
149
+ * @return string
150
+ */
151
+ public function serialize()
152
+ {
153
+ // serialize the data
154
+ return serialize(array(
155
+ $this->id(),
156
+ $this->websiteCode(),
157
+ $this->websiteLabel(),
158
+ $this->storeCode(),
159
+ $this->storeLabel(),
160
+ $this->viewCode(),
161
+ $this->viewLabel(),
162
+ ));
163
+ }
164
+
165
+ /**
166
+ * Unserialize the object
167
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Storeview
168
+ */
169
+ public function unserialize($string)
170
+ {
171
+ list(
172
+ $this->id,
173
+ $this->websiteCode,
174
+ $this->websiteLabel,
175
+ $this->storeCode,
176
+ $this->storeLabel,
177
+ $this->viewCode,
178
+ $this->viewLabel
179
+ ) = unserialize($string);
180
+ return $this;
181
+ }
182
+ }
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/Subscription.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around a Newsletter Subscription
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Abstraction_Subscription implements Serializable
6
+ {
7
+ /**
8
+ * The original object
9
+ * @param Mage_Newsletter_Model_Subscriber
10
+ */
11
+ private $original;
12
+
13
+ /**
14
+ * Predefine the internal fields
15
+ */
16
+ private $id;
17
+ private $email;
18
+ private $status;
19
+ private $storeview;
20
+ private $customerId;
21
+
22
+ /**
23
+ * Sets the original model
24
+ * @param Mage_Newsletter_Model_Subscriber $original
25
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
26
+ */
27
+ public function setOriginal(Mage_Newsletter_Model_Subscriber $original)
28
+ {
29
+ $this->original = $original;
30
+ return $this;
31
+ }
32
+
33
+ /**
34
+ * Return the identifier for this object
35
+ * @return integer
36
+ */
37
+ public function id()
38
+ {
39
+ // Is this object still present?
40
+ if (is_object($this->original))
41
+ {
42
+ return $this->original->getId();
43
+ }
44
+ else return $this->id;
45
+ }
46
+
47
+ /**
48
+ * Return the e-mail address with which the user is subscribed
49
+ * @return string
50
+ */
51
+ public function email()
52
+ {
53
+ // Is this object still present?
54
+ if (is_object($this->original))
55
+ {
56
+ return $this->original->getEmail();
57
+ }
58
+ else return $this->email;
59
+ }
60
+
61
+ /**
62
+ * Return the status of this subscription
63
+ * Note that subscribed might be returned but the record is currently removed
64
+ * @return string
65
+ */
66
+ public function status()
67
+ {
68
+ // Is this object still present?
69
+ if (is_object($this->original))
70
+ {
71
+ switch ($this->original->getStatus()) {
72
+ case Mage_Newsletter_Model_Subscriber::STATUS_SUBSCRIBED:
73
+ return 'subscribed';
74
+ break;
75
+ case Mage_Newsletter_Model_Subscriber::STATUS_NOT_ACTIVE:
76
+ return 'not active';
77
+ break;
78
+ case Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED:
79
+ return 'unsubscribed';
80
+ break;
81
+ case Mage_Newsletter_Model_Subscriber::STATUS_UNCONFIRMED:
82
+ return 'unconfirmed';
83
+ break;
84
+ default:
85
+ return 'unknown';
86
+ break;
87
+ }
88
+ }
89
+ else return $this->status;
90
+ }
91
+
92
+ /**
93
+ * The customer may return null
94
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Customer
95
+ */
96
+ public function customer()
97
+ {
98
+ // Is this object still present?
99
+ if (is_object($this->original))
100
+ {
101
+ if ($customerId = $this->original->getCustomerId()) {
102
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($customerId);
103
+ } else {
104
+ return null;
105
+ }
106
+ }
107
+ elseif ($this->customerId)
108
+ {
109
+ // construct an object given the identifier
110
+ return Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($this->customerId);
111
+ }
112
+ else return null;
113
+ }
114
+
115
+ /**
116
+ * Return the storeview for this subscription
117
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Storeview
118
+ */
119
+ public function storeView()
120
+ {
121
+ // Is this object still present?
122
+ if (is_object($this->original))
123
+ {
124
+ $store = Mage::getModel('core/store')->load($this->original->getStoreId());
125
+ return Mage::getModel('marketingsoftware/abstraction_storeview')->setOriginal($store);
126
+ }
127
+ else return $this->storeview;
128
+ }
129
+
130
+ /**
131
+ * Serialize the object
132
+ * @return string
133
+ */
134
+ public function serialize()
135
+ {
136
+ // serialize the data
137
+ return serialize(array(
138
+ $this->id(),
139
+ $this->email(),
140
+ $this->status(),
141
+ $this->storeview(),
142
+ is_object($customer = $this->customer()) ? $customer->id() : null,
143
+ ));
144
+ }
145
+
146
+ /**
147
+ * Unserialize the object
148
+ * @param string
149
+ * @return Copernica_MarketingSoftware_Model_Abstraction_Subscription
150
+ */
151
+ public function unserialize($string)
152
+ {
153
+ list(
154
+ $this->id,
155
+ $this->email,
156
+ $this->status,
157
+ $this->storeview,
158
+ $this->customerId
159
+ ) = unserialize($string);
160
+ return $this;
161
+ }
162
+ }
163
+
app/code/community/Copernica/MarketingSoftware/Model/Abstraction/readme.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ Note:
2
+ To ensure compatibility with Magento, Mage::getModel is used to load classes.
3
+ However, the Abstraction classes (and possibly other classes) do not extend
4
+ Mage_Core_Model_Abstract as documented in the getModel function's return type.
5
+ Extending this class would result in unnecessary overhead.
6
+ If you do encounter problems with model loading in future versions of Magento,
7
+ please check the getModel function in app/Mage.php.
app/code/community/Copernica/MarketingSoftware/Model/AsyncPomSoapClient.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Asynchronous SOAP api client.
4
+ * This is an extension to the normal soap client, because it can run multiple
5
+ * calls at the same time. It differs from the normal PomSoapClient class because
6
+ * the PxPomSoapClient::methodToCall() method does not return the result, but
7
+ * a handle that can be queried to see if it has already returned data.
8
+ *
9
+ * Example use:
10
+ *
11
+ * $client = new PomAsyncSoapClient($url, $login, $account, $password);
12
+ * $req1 = $client->someSoapMethod(...);
13
+ * $req2 = $client->someSoapMethod(...);
14
+ * $req3 = $client->someSoapMethod(...);
15
+ * $answer1 = $client->result($req1);
16
+ * $answer2 = $client->result($req2);
17
+ * $answer3 = $client->result($req3);
18
+ */
19
+ class Copernica_MarketingSoftware_Model_AsyncPomSoapClient extends Copernica_MarketingSoftware_Model_PomSoapClient
20
+ {
21
+ /**
22
+ * The curl multi handle
23
+ * @var resource
24
+ */
25
+ private $curl = false;
26
+
27
+ /**
28
+ * Set of pending requests ID's
29
+ * This is an assoc array: request ID maps to a array with handle and request
30
+ * @var array
31
+ */
32
+ private $pending = array();
33
+
34
+ /**
35
+ * Set of requests for which the answer has been received
36
+ * This is an assoc array: request ID maps to the received answer
37
+ * @var array
38
+ */
39
+ private $completed = array();
40
+
41
+ /**
42
+ * The last assigned request ID
43
+ * @var integer
44
+ */
45
+ private $freeID = 0;
46
+
47
+ /**
48
+ * Name of the cookie file
49
+ * @var string
50
+ */
51
+ private $cookies = false;
52
+
53
+ /**
54
+ * Is the object currently busy parsing an async answer?
55
+ * @var resource CURL resource identifier of the request that is internally processed
56
+ */
57
+ private $internalRequest = false;
58
+
59
+
60
+ /**
61
+ * Destructor
62
+ */
63
+ public function __destruct()
64
+ {
65
+ // skip if no calls were made
66
+ if (!$this->cookies) return;
67
+
68
+ // wait until everything is ready
69
+ $this->run();
70
+
71
+ // remove the cookie file
72
+ //unlink($this->cookies);
73
+
74
+ // close the connections
75
+ if(is_resource($this->curl)) curl_multi_close($this->curl);
76
+ }
77
+
78
+ /**
79
+ * Method returns the ID's of all requests, both the pending ones and the
80
+ * ones that have already been completed
81
+ * @return array of int
82
+ */
83
+ public function allRequests()
84
+ {
85
+ return array_merge($this->pendingRequests(), $this->completedRequests());
86
+ }
87
+
88
+ /**
89
+ * Method to retrieve the ID's of all pending requests
90
+ * @return array
91
+ */
92
+ public function pendingRequests()
93
+ {
94
+ return array_keys($this->pending);
95
+ }
96
+
97
+ /**
98
+ * Method to retrieve the ID's of all completed requests
99
+ * @return array
100
+ */
101
+ public function completedRequests()
102
+ {
103
+ return array_keys($this->completed);
104
+ }
105
+
106
+ /**
107
+ * Get the result of a certain request
108
+ * This method will block until the request has been completed
109
+ * @param integer ID of a request
110
+ * @return mixed The response from the request
111
+ */
112
+ public function result($requestID)
113
+ {
114
+ // if this a request for which the result was already found
115
+ if (isset($this->completed[$requestID])) return $this->completed[$requestID];
116
+
117
+ // skip if an invalid ID was supplied
118
+ if (!isset($this->pending[$requestID])) return false;
119
+
120
+ // wait for the next call
121
+ $this->wait();
122
+
123
+ // fetch the result (with recursion)
124
+ return $this->result($requestID);
125
+ }
126
+
127
+ /**
128
+ * Wait for the next pending request to complete
129
+ * This method will block until a SOAP call completes
130
+ * It returns the request ID of the soap call that completed
131
+ * @param float Timeout in seconds
132
+ * @return integer The ID of the request that was completed
133
+ */
134
+ public function wait($timeout = 1.0)
135
+ {
136
+ // not possible when nothing is pending
137
+ if (count($this->pending) == 0) return false;
138
+
139
+ // exec the connections
140
+ $active = null;
141
+ while(($execrun = curl_multi_exec($this->curl, $active)) == CURLM_CALL_MULTI_PERFORM) { /* do nothing */ }
142
+
143
+ // run a select call to wait for a connection to become ready
144
+ $ready = curl_multi_select($this->curl, $timeout);
145
+
146
+ // find all requests that are ready
147
+ while ($info = curl_multi_info_read($this->curl))
148
+ {
149
+ // find the request ID
150
+ $requestID = $this->resource2id($info['handle']);
151
+ $info = $this->pending[$requestID];
152
+
153
+ // make an internal call to find the answer
154
+ $this->internalRequest = $info['handle'];
155
+ $answer = $this->__call($info['method'], $info['params']);
156
+ $this->internalRequest = false;
157
+
158
+ // we have the answer
159
+ $this->completed[$requestID] = $answer;
160
+
161
+ // request is no longer pending
162
+ unset($this->pending[$requestID]);
163
+
164
+ // resource is no longer busy
165
+ curl_multi_remove_handle($this->curl, $info['handle']);
166
+ curl_close($info['handle']);
167
+
168
+ // done
169
+ return $requestID;
170
+ }
171
+
172
+ // not found
173
+ return false;
174
+ }
175
+
176
+ /**
177
+ * Run all requests
178
+ * This method will process all requests, until none of them is pending
179
+ */
180
+ public function run()
181
+ {
182
+ // keep waiting until all requests are completed
183
+ while (count($this->pending) > 0) $this->wait();
184
+ }
185
+
186
+ /**
187
+ * Helper method to map a curl resource to a request ID
188
+ * @param resource CURL resource
189
+ * @return integer Request ID
190
+ */
191
+ private function resource2id($resource)
192
+ {
193
+ // loop through all pending requests
194
+ foreach ($this->pending as $request => $data)
195
+ {
196
+ // compare ID's
197
+ if ($data['handle'] == $resource) return $request;
198
+ }
199
+
200
+ // not found
201
+ return false;
202
+ }
203
+
204
+ /**
205
+ * Overridden implementation of the __doRequest call. This method filters
206
+ * all calls, and adds them to the set of pending calls.
207
+ * @param string SOAP XML string to send to the server
208
+ * @param string URL to connect to
209
+ * @param string The SOAP action
210
+ * @param integer The SOAP version
211
+ * @param integer One way traffic, no result is expected
212
+ */
213
+ public function __doRequest($request, $location, $action, $version, $one_way = 0)
214
+ {
215
+ // is this an internal request, in that case we have already started the
216
+ // connection, and only need to fetch the data
217
+ if ($this->internalRequest) return curl_multi_getcontent($this->internalRequest);
218
+
219
+ // create a new curl resource
220
+ $curl = curl_init($location);
221
+
222
+ // do we already have a cookie file?
223
+ if (!$this->cookies) $this->cookies = Mage::getBaseDir('tmp') .'copernica.tmp';
224
+
225
+ // set all options for it
226
+ curl_setopt_array($curl, array(
227
+ CURLOPT_POST => true,
228
+ CURLOPT_RETURNTRANSFER => true,
229
+ CURLOPT_COOKIEFILE => $this->cookies,
230
+ CURLOPT_COOKIEJAR => $this->cookies,
231
+ CURLOPT_POSTFIELDS => $request,
232
+ ));
233
+
234
+ // find the method name
235
+ $methodName = preg_match('/#(.*)$/', $action, $matches) ? $matches[1] : '';
236
+
237
+ // is this a call that should be done immediately, and not asynchronous?
238
+ if (in_array($methodName, array('login')))
239
+ {
240
+ // the login call should not be postponed
241
+ return curl_exec($curl);
242
+ }
243
+ else
244
+ {
245
+ // do we a resource for multiple connections?
246
+ if (!$this->curl) $this->curl = curl_multi_init();
247
+
248
+ // add the curl handle
249
+ curl_multi_add_handle($this->curl, $curl);
250
+
251
+ // store the handle in the array of pending requests
252
+ $this->pending[$this->freeID] = array(
253
+ 'handle' => $curl,
254
+ );
255
+
256
+ // return the handle
257
+ return $this->freeID++;
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Method that handles the calls to the API
263
+ * @param string Name of the method
264
+ * @param array Associative array of parameters
265
+ * @return mixed
266
+ */
267
+ public function __call($methodname, $params)
268
+ {
269
+ // get all current pending requests
270
+ $pending = $this->pendingRequests();
271
+
272
+ try
273
+ {
274
+ // make the call
275
+ $result = parent::__call($methodname, $params);
276
+ return $result;
277
+ }
278
+ catch (Exception $e)
279
+ {
280
+ // do we have a new pending request
281
+ $newPending = array_values(array_diff($this->pendingRequests(), $pending));
282
+ if (count($newPending) < 1) return false;
283
+
284
+ // we have the request ID
285
+ $requestID = $newPending[0];
286
+
287
+ // we must add the methodname and parameters to the internal data structure
288
+ $this->pending[$requestID]['method'] = $methodname;
289
+ $this->pending[$requestID]['params'] = $params;
290
+
291
+ // return the result
292
+ return $requestID;
293
+ }
294
+ }
295
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Abstract.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ abstract class Copernica_MarketingSoftware_Model_Copernica_Abstract implements ArrayAccess
6
+ {
7
+ /**
8
+ * @var String
9
+ */
10
+ protected $direction = 'copernica';
11
+
12
+
13
+ /**
14
+ * Set the direction for this synchronisation
15
+ * @param String
16
+ * @return Copernica_MarketingSoftware_Model_Copernica_Orderitem_Subprofile
17
+ */
18
+ public function setDirection($direction)
19
+ {
20
+ $this->direction = $direction;
21
+ return $this;
22
+ }
23
+
24
+ /**
25
+ * Return the identifier for this profile
26
+ * @return string
27
+ */
28
+ abstract public function id();
29
+
30
+ /**
31
+ * Retrieve the data for this object
32
+ * @return array
33
+ */
34
+ abstract protected function _data();
35
+
36
+ /**
37
+ * Get linked fields
38
+ * @return array
39
+ */
40
+ abstract public function linkedFields();
41
+
42
+ /**
43
+ * Get the required fields
44
+ * @return array
45
+ */
46
+ abstract public function requiredFields();
47
+
48
+ /**
49
+ * @param mixed
50
+ * @return boolean
51
+ */
52
+ public function offsetExists($offset)
53
+ {
54
+ // Get the data from this profile
55
+ $data = $this->toArray();
56
+
57
+ // Return the data based on whether it exists
58
+ return isset($data[$offset]);
59
+ }
60
+
61
+ /**
62
+ * @param mixed
63
+ * @return mixed
64
+ */
65
+ public function offsetGet($offset)
66
+ {
67
+ // Get the data from this profile
68
+ $data = $this->toArray();
69
+
70
+ // Return the data based on whether it exists
71
+ return isset($data[$offset]) ? $data[$offset] : null;
72
+ }
73
+
74
+ /**
75
+ * Convert the data to an array for usage in SOAP
76
+ */
77
+ public function toArray()
78
+ {
79
+ // Get the data
80
+ $data = $this->_data();
81
+
82
+ // this data is meant for magento, return the data as is
83
+ if ($this->direction == 'magento') return $data;
84
+
85
+ // construct an array which contains the required base record
86
+ $returndata = array();
87
+
88
+ // check the required fields
89
+ foreach ($this->requiredFields() as $field) $returndata[$field] = $data[$field];
90
+
91
+ // iterate over the linked fields
92
+ foreach ($this->linkedFields() as $magentoField => $copernicaField)
93
+ {
94
+ // Not linked to a field, skip
95
+ if (empty($copernicaField) || !isset($data[$magentoField])) continue;
96
+
97
+ // Append it to the returned array
98
+ $returndata[$copernicaField] = $data[$magentoField];
99
+ }
100
+
101
+ // Return the mapped data
102
+ return $returndata;
103
+ }
104
+
105
+ /**
106
+ * @param mixed
107
+ * @param mixed
108
+ */
109
+ public function offsetSet($offset, $value)
110
+ {
111
+ return;
112
+ }
113
+
114
+ /**
115
+ * @param mixed
116
+ */
117
+ public function offsetUnset($offset)
118
+ {
119
+ return;
120
+ }
121
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Address/Subprofile.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_Address_Subprofile extends Copernica_MarketingSoftware_Model_Copernica_Abstract
6
+ {
7
+ /**
8
+ * Return the identifier for this profile
9
+ * @return string
10
+ */
11
+ public function id()
12
+ {
13
+ return $this['address_id'];
14
+ }
15
+
16
+ /**
17
+ * Try to store a quote item
18
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Address
19
+ */
20
+ public function setAddress($address)
21
+ {
22
+ $this->address = $address;
23
+ return $this;
24
+ }
25
+
26
+ /**
27
+ * Get linked fields
28
+ * @return array
29
+ */
30
+ public function linkedFields()
31
+ {
32
+ return Mage::helper('marketingsoftware/config')->getLinkedAddressFields();
33
+ }
34
+
35
+ /**
36
+ * Get the required fields
37
+ * @return array
38
+ */
39
+ public function requiredFields()
40
+ {
41
+ return array('address_id');
42
+ }
43
+
44
+ /**
45
+ * Retrieve the data for this object
46
+ * @return array
47
+ */
48
+ protected function _data()
49
+ {
50
+ // We might need to get the e-mail from the customer
51
+ if (($email = $this->address->email()) == "" && is_object($customer = $this->address->customer()))
52
+ {
53
+ $email = $customer->email();
54
+ }
55
+
56
+ // fetch the name object
57
+ $name = $this->address->name();
58
+
59
+ // Combine the data
60
+ return array(
61
+ 'address_id' => $this->address->id(),
62
+ 'firstname' => is_object($name) ? $name->firstname() : null,
63
+ 'prefix' => is_object($name) ? $name->prefix() : null,
64
+ 'middlename' => is_object($name) ? $name->middlename() : null,
65
+ 'lastname' => is_object($name) ? $name->lastname() : null,
66
+ 'email' => $email,
67
+ 'company' => $this->address->company(),
68
+ 'street' => $this->address->street(),
69
+ 'city' => $this->address->city(),
70
+ 'state' => $this->address->state(),
71
+ 'zipcode' => $this->address->zipcode(),
72
+ 'country_id' => $this->address->countryCode(),
73
+ 'telephone' => $this->address->telephone(),
74
+ 'fax' => $this->address->fax(),
75
+ );
76
+ }
77
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Cartitem/Subprofile.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_Cartitem_Subprofile extends Copernica_MarketingSoftware_Model_Copernica_Abstract
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Quote_Item
9
+ */
10
+ private $quoteItem = false;
11
+
12
+ /**
13
+ * @var string
14
+ */
15
+ private $status = 'basket';
16
+
17
+
18
+ /**
19
+ * Set the status of this cart item
20
+ * @param String
21
+ * @return Copernica_MarketingSoftware_Model_Copernica_Cartitem_Subprofile
22
+ */
23
+ public function setStatus($status)
24
+ {
25
+ $this->status = $status;
26
+ return $this;
27
+ }
28
+
29
+ /**
30
+ * Return the identifier for this profile
31
+ * @return string
32
+ */
33
+ public function id()
34
+ {
35
+ return $this['item_id'];
36
+ }
37
+
38
+ /**
39
+ * Try to store a quote item
40
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Quote_Item
41
+ */
42
+ public function setQuoteItem($item)
43
+ {
44
+ $this->quoteItem = $item;
45
+ return $this;
46
+ }
47
+
48
+ /**
49
+ * Get linked fields
50
+ * @return array
51
+ */
52
+ public function linkedFields()
53
+ {
54
+ return Mage::helper('marketingsoftware/config')->getLinkedCartItemFields();
55
+ }
56
+
57
+ /**
58
+ * Get the required fields
59
+ * @return array
60
+ */
61
+ public function requiredFields()
62
+ {
63
+ return array('item_id', 'quote_id', 'status');
64
+ }
65
+
66
+ /**
67
+ * Retrieve the data for this object
68
+ * @return array
69
+ */
70
+ protected function _data()
71
+ {
72
+ // Store the quoteItem and the product localy
73
+ $quoteItem = $this->quoteItem;
74
+ $product = $quoteItem->product();
75
+
76
+ // Get the store id to make sure that we retrieve the correct url's
77
+ if (($quote = $quoteItem->quote()) && ($storeview = $quote->storeview())) $storeId = $storeview->id();
78
+ else $storeId = null;
79
+
80
+ // flatten the categories
81
+ $categories = array();
82
+ foreach ($product->categories() as $category) $categories[] = implode(' > ', $category);
83
+
84
+ // Get the price object
85
+ $price = $quoteItem->price();
86
+
87
+ // construct an array of data
88
+ return array(
89
+ 'item_id' => $quoteItem->id(),
90
+ 'quote_id' => $quoteItem->quote()->id(),
91
+ 'product_id' => $product->id(),
92
+ 'price' => is_object($price) ? $price->itemPrice() : null,
93
+ 'status' => $this->status,
94
+ 'name' => $product->name(),
95
+ 'sku' => $product->sku(),
96
+ 'weight' => $quoteItem->weight(),
97
+ 'quantity' => $quoteItem->quantity(),
98
+ 'timestamp' => $quoteItem->timestamp(),
99
+ 'store_view' => (string)$quoteItem->quote()->storeView(),
100
+ 'total_price' => is_object($price) ? $price->total() : null,
101
+ 'url' => $product->productUrl($storeId),
102
+ 'image' => $product->imageUrl($storeId),
103
+ 'categories' => implode("\n", $categories),
104
+ 'attributes' => (string)$product->attributes(),
105
+ 'options' => (string)$quoteItem->options(),
106
+ );
107
+ }
108
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Order/Subprofile.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_Order_Subprofile extends Copernica_MarketingSoftware_Model_Copernica_Abstract
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Order
9
+ */
10
+ private $order = false;
11
+
12
+
13
+ /**
14
+ * Return the identifier for this profile
15
+ * @return string
16
+ */
17
+ public function id()
18
+ {
19
+ return $this['order_id'];
20
+ }
21
+
22
+ /**
23
+ * Try to store a quote item
24
+ * @param Copernica_MarketingSoftware_Model_Copernica_Order_Subprofile
25
+ */
26
+ public function setOrder($order)
27
+ {
28
+ $this->order = $order;
29
+ return $this;
30
+ }
31
+
32
+ /**
33
+ * Get linked fields
34
+ * @return array
35
+ */
36
+ public function linkedFields()
37
+ {
38
+ return Mage::helper('marketingsoftware/config')->getLinkedOrderFields();
39
+ }
40
+
41
+ /**
42
+ * Get the required fields
43
+ * @return array
44
+ */
45
+ public function requiredFields()
46
+ {
47
+ return array('order_id', 'quote_id');
48
+ }
49
+
50
+ /**
51
+ * Retrieve the data for this object
52
+ * @return array
53
+ */
54
+ protected function _data()
55
+ {
56
+ // initialize the addresses
57
+ $billingAddress = $shippingAddress = false;
58
+
59
+ // Get the addresses
60
+ foreach ($this->order->addresses() as $address)
61
+ {
62
+ if (in_array('billing', $address->type())) $billingAddress = $address;
63
+ if (in_array('shipping', $address->type())) $shippingAddress = $address;
64
+ }
65
+
66
+ // Get the price
67
+ $price = $this->order->price();
68
+
69
+ // Return the data array
70
+ return array(
71
+ 'order_id' => $this->order->id(),
72
+ 'quote_id' => $this->order->quoteId(),
73
+ 'increment_id' => $this->order->incrementId(),
74
+ 'timestamp' => $this->order->timestamp(),
75
+ 'quantity' => $this->order->quantity(),
76
+ 'total' => is_object($price) ? $price->total() : null,
77
+ 'shipping' => is_object($price) ? $price->shipping() : null,
78
+ 'currency' => is_object($price) ? $price->currency() : null,
79
+ 'weight' => $this->order->weight(),
80
+ 'status' => $this->order->status(),
81
+ 'store_view' => (string)$this->order->storeview(),
82
+ 'remote_ip' => $this->order->customerIP(),
83
+ 'shipping_description' => $this->order->shippingDescription(),
84
+ 'payment_description' => $this->order->paymentDescription(),
85
+ 'shipping_address_id' => is_object($shippingAddress) ? $shippingAddress->id() : '',
86
+ 'billing_address_id' => is_object($billingAddress) ? $billingAddress->id() : '',
87
+ );
88
+ }
89
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Orderitem/Subprofile.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_Orderitem_Subprofile extends Copernica_MarketingSoftware_Model_Copernica_Abstract
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Order_Item
9
+ */
10
+ private $orderItem = false;
11
+
12
+
13
+ /**
14
+ * Return the identifier for this profile
15
+ * @return string
16
+ */
17
+ public function id()
18
+ {
19
+ return $this['item_id'];
20
+ }
21
+
22
+ /**
23
+ * Try to store a quote item
24
+ * @param Copernica_MarketingSoftware_Model_Copernica_Orderitem_Subprofile
25
+ */
26
+ public function setOrderItem($item)
27
+ {
28
+ $this->orderItem = $item;
29
+ return $this;
30
+ }
31
+
32
+ /**
33
+ * Get linked fields
34
+ * @return array
35
+ */
36
+ public function linkedFields()
37
+ {
38
+ return Mage::helper('marketingsoftware/config')->getLinkedOrderItemFields();
39
+ }
40
+
41
+ /**
42
+ * Get the required fields
43
+ * @return array
44
+ */
45
+ public function requiredFields()
46
+ {
47
+ return array('item_id','order_id');
48
+ }
49
+
50
+ /**
51
+ * Retrieve the data for this object
52
+ * @return array
53
+ */
54
+ protected function _data()
55
+ {
56
+ // Store the orderItem and the product localy
57
+ $orderItem = $this->orderItem;
58
+ $product = $orderItem->product();
59
+
60
+ // Get the store id to make sure that we retrieve the correct url's
61
+ if (($order = $orderItem->order()) && is_object($order) && ($storeview = $order->storeview())) $storeId = $storeview->id();
62
+ else $storeId = null;
63
+
64
+ // flatten the categories
65
+ $categories = array();
66
+ foreach ($product->categories() as $category) $categories[] = implode(' > ', $category);
67
+
68
+ // Get the price
69
+ $price = $orderItem->price();
70
+
71
+ // construct an array of data
72
+ return array(
73
+ 'item_id' => $orderItem->id(),
74
+ 'order_id' => is_object($order) ? $order->id() : null,
75
+ 'increment_id' => is_object($order) ? $order->incrementId() : null,
76
+ 'product_id' => $product->id(),
77
+ 'price' => is_object($price) ? $price->itemPrice() : null,
78
+ 'name' => $product->name(),
79
+ 'sku' => $product->sku(),
80
+ 'weight' => $orderItem->weight(),
81
+ 'quantity' => $orderItem->quantity(),
82
+ 'timestamp' => $orderItem->timestamp(),
83
+ 'store_view' => is_object($order) ? (string)$order->storeView() : null,
84
+ 'total_price' => is_object($price) ? $price->total() : null,
85
+ 'url' => $product->productUrl($storeId),
86
+ 'image' => $product->imageUrl($storeId),
87
+ 'categories' => implode("\n", $categories),
88
+ 'attributes' => (string)$product->attributes(),
89
+ 'options' => (string)$orderItem->options(),
90
+ );
91
+ }
92
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profile.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ abstract class Copernica_MarketingSoftware_Model_Copernica_Profile extends Copernica_MarketingSoftware_Model_Copernica_Abstract
6
+ {
7
+ /**
8
+ * Return the identifier for this profile
9
+ * @return string
10
+ */
11
+ public function id()
12
+ {
13
+ return $this['customer_id'];
14
+ }
15
+
16
+ /**
17
+ * Get linked fields
18
+ * @return array
19
+ */
20
+ public function linkedFields()
21
+ {
22
+ return Mage::helper('marketingsoftware/config')->getLinkedCustomerFields();
23
+ }
24
+
25
+ /**
26
+ * Get the required fields
27
+ * @return array
28
+ */
29
+ public function requiredFields()
30
+ {
31
+ return array('customer_id');
32
+ }
33
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profilecustomer.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer extends Copernica_MarketingSoftware_Model_Copernica_Profile
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Customer
9
+ */
10
+ private $customer = false;
11
+
12
+ /**
13
+ * Set the customer object to this object
14
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Customer
15
+ * @return Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer
16
+ */
17
+ public function setCustomer($customer)
18
+ {
19
+ $this->customer = $customer;
20
+ return $this;
21
+ }
22
+
23
+ /**
24
+ * Retrieve the data for this object
25
+ * @return array
26
+ */
27
+ protected function _data()
28
+ {
29
+ // Get the subscription
30
+ $subscription = $this->customer->subscription();
31
+
32
+ // fetch the name object
33
+ $name = $this->customer->name();
34
+
35
+ // return an array with customer data
36
+ return array(
37
+ 'customer_id' => $this->customer->id(),
38
+ 'store_view' => (string)$this->customer->storeview(),
39
+ 'firstname' => is_object($name) ? $name->firstname() : null,
40
+ 'middlename' => is_object($name) ? $name->middlename() : null,
41
+ 'lastname' => is_object($name) ? $name->lastname() : null,
42
+ 'email' => is_object($subscription) ? $subscription->email() : $this->customer->email(),
43
+ 'group' => $this->customer->group(),
44
+ 'newsletter' => is_object($subscription) ? $subscription->status() : 'unknown',
45
+ );
46
+ }
47
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profileorder.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_ProfileOrder extends Copernica_MarketingSoftware_Model_Copernica_Profile
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Customer
9
+ */
10
+ private $order = false;
11
+
12
+ /**
13
+ * Set the customer object to this object
14
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Quote
15
+ * @return Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer
16
+ */
17
+ public function setOrder($order)
18
+ {
19
+ $this->order = $order;
20
+ return $this;
21
+ }
22
+
23
+ /**
24
+ * Retrieve the data for this object
25
+ * @return array
26
+ */
27
+ protected function _data()
28
+ {
29
+ // Get the addresses
30
+ $addresses = $this->order->addresses();
31
+
32
+ // Select an address
33
+ if (count($addresses) == 1) $address = $addresses[0];
34
+ else foreach ($addresses as $addr) if (in_array('billing', $addr->type())) $address = $addr;
35
+
36
+ // Get subscription
37
+ if (Mage::getModel('newsletter/subscriber')->loadByEmail($address->email())->getId())
38
+ {
39
+ $subscription = Mage::getModel('marketingsoftware/abstraction_subscription')
40
+ ->setOriginal(Mage::getModel('newsletter/subscriber')->loadByEmail($address->email()));
41
+ }
42
+ else $subscription = false;
43
+
44
+ // fetch the name object
45
+ $name = $address->name();
46
+
47
+ // return an array with customer data
48
+ return array(
49
+ 'customer_id' => "guest_".$this->order->quoteId(),
50
+ 'store_view' => (string)$this->order->storeview(),
51
+ 'firstname' => is_object($name) ? $name->firstname() : null,
52
+ 'middlename' => is_object($name) ? $name->middlename() : null,
53
+ 'lastname' => is_object($name) ? $name->lastname() : null,
54
+ 'email' => $address->email(),
55
+ 'group' => Mage::getModel('customer/group')->load(0)->getCode(),
56
+ 'newsletter' => is_object($subscription) ? $subscription->status() : 'unknown',
57
+ );
58
+ }
59
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profilequote.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_ProfileQuote extends Copernica_MarketingSoftware_Model_Copernica_Profile
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Customer
9
+ */
10
+ private $quote = false;
11
+
12
+ /**
13
+ * Set the customer object to this object
14
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Quote
15
+ * @return Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer
16
+ */
17
+ public function setQuote($quote)
18
+ {
19
+ $this->quote = $quote;
20
+ return $this;
21
+ }
22
+
23
+ /**
24
+ * Retrieve the data for this object
25
+ * @return array
26
+ */
27
+ protected function _data()
28
+ {
29
+ // Get the addresses
30
+ $addresses = $this->quote->addresses();
31
+
32
+ // Select an address
33
+ if (count($addresses) == 1) $address = $addresses[0];
34
+ else foreach ($addresses as $addr) if (in_array('billing', $addr->type())) $address = $addr;
35
+
36
+ // Get subscription
37
+ if (Mage::getModel('newsletter/subscriber')->loadByEmail($address->email())->getId())
38
+ {
39
+ $subscription = Mage::getModel('marketingsoftware/abstraction_subscription')
40
+ ->setOriginal(Mage::getModel('newsletter/subscriber')->loadByEmail($address->email()));
41
+ }
42
+ else $subscription = false;
43
+
44
+ // fetch the name object
45
+ $name = $address->name();
46
+
47
+ // return an array with customer data
48
+ return array(
49
+ 'customer_id' => "guest_".$this->quote->id(),
50
+ 'store_view' => (string)$this->quote->storeview(),
51
+ 'firstname' => is_object($name) ? $name->firstname() : null,
52
+ 'middlename' => is_object($name) ? $name->middlename() : null,
53
+ 'lastname' => is_object($name) ? $name->lastname() : null,
54
+ 'email' => $address->email(),
55
+ 'group' => Mage::getModel('customer/group')->load(0)->getCode(),
56
+ 'newsletter' => is_object($subscription) ? $subscription->status() : 'unknown',
57
+ );
58
+ }
59
+ }
app/code/community/Copernica/MarketingSoftware/Model/Copernica/Profilesubscription.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * An object to wrap the Copernica profile
4
+ */
5
+ class Copernica_MarketingSoftware_Model_Copernica_ProfileSubscription extends Copernica_MarketingSoftware_Model_Copernica_Profile
6
+ {
7
+ /**
8
+ * @var Copernica_MarketingSoftware_Model_Abstraction_Customer
9
+ */
10
+ private $subscription = false;
11
+
12
+ /**
13
+ * Set the customer object to this object
14
+ * @param Copernica_MarketingSoftware_Model_Abstraction_Subscription
15
+ * @return Copernica_MarketingSoftware_Model_Copernica_ProfileCustomer
16
+ */
17
+ public function setSubscription($customer)
18
+ {
19
+ $this->subscription = $customer;
20
+ return $this;
21
+ }
22
+
23
+ /**
24
+ * Retrieve the data for this object
25
+ * @return array
26
+ */
27
+ protected function _data()
28
+ {
29
+ // return an array with customer data
30
+ return array(
31
+ 'customer_id' => "subcr_".$this->subscription->id(),
32
+ 'store_view' => (string)$this->subscription->storeView(),
33
+ 'email' => $this->subscription->email(),
34
+ 'group' => Mage::getModel('customer/group')->load(0)->getCode(),
35
+ 'newsletter' => $this->subscription->status(),
36
+ );
37
+ }
38
+ }
app/code/community/Copernica/MarketingSoftware/Model/Error.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file holds the implmentation of the Copernica_MarketingSoftware_Model_Error class.
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ /**
10
+ * All error codes that are defined
11
+ */
12
+ define('COPERNICAERROR_UNREACHABLE', 1); // The SOAP API is unreachable
13
+ define('COPERNICAERROR_LOGINFAILURE', 2); // The login information for the API is not correct
14
+ define('COPERNICAERROR_NODATABASE', 3); // The database does not exist, or could not be created
15
+ define('COPERNICAERROR_INVALIDDATABASE', 4); // The database structure is wrong
16
+ define('COPERNICAERROR_NOCOLLECTION', 5); // The collection does not exist, or could not created
17
+ define('COPERNICAERROR_DEFAULTFIELDSEXISTS', 6); // The database default fields already exists
18
+ define('COPERNICAERROR_NOFIELD', 7); // The field doesn't exists
19
+ define('COPERNICAERROR_CANNOTCREATEFIELD', 8); // The field can't be created
20
+ define('COPERNICAERROR_NOCOLLECTIONFIELDS', 9); // The default collection fields set doesn't exists
21
+ define('COPERNICAERROR_NOCOLLECTIONFIELDSMISSING', 10); // There aren't any default collection fields missing
22
+ define('COPERNICAERROR_PCNTLNOTENABLED', 11); // The PCNTL module is not enabled
23
+ define('COPERNICAERROR_CLINOTENABLED', 12); // The CLI is not enabled
24
+ define('COPERNICAERROR_SOAPNOTENABLED', 13); // The SOAP is not enabled
25
+ define('COPERNICAERROR_CURLNOTENABLED', 14); // The CURL is not enabled
26
+ define('COPERNICAERROR_CANNOTSEARCHPROFILE', 15); // Cannot search profile
27
+ define('COPERNICAERROR_CANNOTUPDATESUBPROFILE', 16); // Cannot update subprofile
28
+ define('COPERNICAERROR_CANNOTMATCHPROFILE', 17); // Cannot match the profile
29
+ define('COPERNICAERROR_CANNOTREMOVESUBPROFILE', 18); // Cannot remove the subprofile
30
+ define('COPERNICAERROR_LOGINNOTVALID', 19); // The login credentials/hostname are not valid
31
+ define('COPERNICAERROR_FIELDLINKSNOTVALID', 20); // Not all required fields are linked
32
+ define('COPERNICAERROR_UPGRADEWARNING118', 21); // We upgraded to this version, so a warning has to given
33
+ define('COPERNICAERROR_UNRECOGNIZEDEVENT', 22);
34
+
35
+ /**
36
+ * Instances of the Copernica_MarketingSoftware_Model_Error class are returned whenever our Model and API
37
+ * objects need to report an error
38
+ */
39
+ class CopernicaError extends Exception
40
+ {
41
+ /**
42
+ * Construct the exception
43
+ * @param integer numeric value indicating a certain error message
44
+ */
45
+ public function __construct($code)
46
+ {
47
+ $this->code = $code;
48
+ parent::__construct($this->getDescription(), $code);
49
+ }
50
+
51
+ /**
52
+ * Return an string representation
53
+ * @return string
54
+ */
55
+ public function __toString()
56
+ {
57
+ return $this->getDescription();
58
+ }
59
+
60
+ /**
61
+ * Return an error description
62
+ * @return string
63
+ */
64
+ public function getDescription()
65
+ {
66
+ // we loop throught our error codes to send back the error description
67
+ switch ($this->code)
68
+ {
69
+ case COPERNICAERROR_UNREACHABLE:
70
+ return "Invalid hostname. Please use the following example as format: http://publisher.copernica.nl";
71
+ case COPERNICAERROR_LOGINFAILURE:
72
+ return "Invalid credentials, please check your accountname, username and password.";
73
+ case COPERNICAERROR_NODATABASE:
74
+ return "The database does not exist";
75
+ case COPERNICAERROR_INVALIDDATABASE:
76
+ return "notvalid";
77
+ case COPERNICAERROR_NOCOLLECTION:
78
+ return "One of the collections does not exist";
79
+ case COPERNICAERROR_DEFAULTFIELDSEXISTS:
80
+ return "The database default fields already exists";
81
+ case COPERNICAERROR_NOFIELD:
82
+ return "notexists";
83
+ case COPERNICAERROR_CANNOTCREATEFIELD:
84
+ return "notexists";
85
+ case COPERNICAERROR_NOCOLLECTIONFIELDS:
86
+ return "notvalid";
87
+ case COPERNICAERROR_NOCOLLECTIONFIELDSMISSING:
88
+ return "There aren't any default collection fields missing";
89
+ case COPERNICAERROR_PCNTLNOTENABLED:
90
+ return "Warning: The PCNTL module is not enabled in your PHP installation. You need this module to activate Copernica background processing feature.";
91
+ case COPERNICAERROR_CLINOTENABLED:
92
+ return "Warning: The CLI (command line) module is not enabled in your PHP installation. You need this module to activate Copernica background processing feature.";
93
+ case COPERNICAERROR_SOAPNOTENABLED:
94
+ return "Error: The SOAP module is not enabled in your PHP installation. You need this module to activate Copernica extension";
95
+ case COPERNICAERROR_CURLNOTENABLED:
96
+ return "Error: The CURL module is not enabled in your PHP installation, and 'allow_url_fopen' is set to 'Off' in your php.ini configuration. To activate the Copernica extension, either the allow_url_fopen setting should be set to 'On' or the CURL module should be installed";
97
+ case COPERNICAERROR_LOGINNOTVALID:
98
+ return "Error: The supplied hostname and/or credentials are not correct, you must <a href=\"../settings/\">correct this</a> in order to make the plugin function.";
99
+ case COPERNICAERROR_FIELDLINKSNOTVALID:
100
+ return "Error: Some of the required fields are not linked, you must <a href=\"../link/\">correct this</a> in order to make the plugin function.";
101
+ case COPERNICAERROR_CANNOTSEARCHPROFILE:
102
+ return "Cannot search profile";
103
+ case COPERNICAERROR_CANNOTUPDATESUBPROFILE:
104
+ return "Cannot update subprofile";
105
+ case COPERNICAERROR_CANNOTMATCHPROFILE:
106
+ return "Cannot match the profile";
107
+ case COPERNICAERROR_CANNOTREMOVESUBPROFILE:
108
+ return "Cannot remove the subprofile";
109
+ case COPERNICAERROR_UNRECOGNIZEDEVENT:
110
+ return "This event has not been recognized.";
111
+ default:
112
+ return "There has been an error with your request";
113
+ }
114
+ }
115
+ }
app/code/community/Copernica/MarketingSoftware/Model/Marketingsoftware.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_Model_MarketingSoftware extends Varien_Object
3
+ {
4
+ /**
5
+ * Holds API object
6
+ *
7
+ * @var Copernica_MarketingSoftware_Helper_Api
8
+ */
9
+ protected $_api;
10
+
11
+ /**
12
+ * Get the API helper object with the settings as defined in the config.
13
+ *
14
+ * @return Copernica_MarketingSoftware_Helper_Api
15
+ */
16
+ public function api()
17
+ {
18
+ if (!$this->_api) {
19
+ // Get the config helper
20
+ $config = Mage::helper('marketingsoftware/config');
21
+
22
+ // Get an api which is logged on on the right Copernica env
23
+ $this->_api = Mage::helper('marketingsoftware/api')->init(
24
+ $config->getHostname(),
25
+ $config->getUsername(),
26
+ $config->getAccount(),
27
+ $config->getPassword()
28
+ );
29
+ }
30
+
31
+ // Return the api object
32
+ return $this->_api;
33
+ }
34
+ }
app/code/community/Copernica/MarketingSoftware/Model/Mysql4/Queue.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_Model_Mysql4_Queue extends Mage_Core_Model_Mysql4_Abstract
3
+ {
4
+ /**
5
+ * Construct the object and initialize the values
6
+ */
7
+ protected function _construct()
8
+ {
9
+ $this->_init('marketingsoftware/queue', 'id');
10
+ }
11
+ }
app/code/community/Copernica/MarketingSoftware/Model/Mysql4/Queue/Collection.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_Model_Mysql4_Queue_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
3
+ {
4
+ protected function _construct()
5
+ {
6
+ $this->_init('marketingsoftware/queue');
7
+ }
8
+
9
+ /**
10
+ * Add a default order, sorted ascending by queue time
11
+ * @return Copernica_MarketingSoftware_Model_Mysql4_Queue_Collection
12
+ */
13
+ public function addDefaultOrder()
14
+ {
15
+ // If a result was processed before, we should process it if we have nothing
16
+ // else to process, we want to import the queue items without an result_time
17
+ // first and then in order of queue time.
18
+ return $this->addOrder('result_time', self::SORT_ORDER_ASC)
19
+ ->addOrder('queue_time', self::SORT_ORDER_ASC);
20
+ }
21
+
22
+ /**
23
+ * Get the time of the oldest record
24
+ * @return string mysql formatted date timestamp
25
+ */
26
+ public function getQueueStartTime()
27
+ {
28
+ return $this->addDefaultOrder()->setPageSize(1)->getFirstItem()->getQueueTime();
29
+ }
30
+
31
+ /**
32
+ * Get the result of the oldest record
33
+ * @return string message
34
+ */
35
+ public function getOldestResult()
36
+ {
37
+ return $this->addDefaultOrder()->setPageSize(1)->getFirstItem()->getResult();
38
+ }
39
+ }
app/code/community/Copernica/MarketingSoftware/Model/Observer.php ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_Model_Observer
3
+ {
4
+ /**
5
+ * Method for the following events:
6
+ * 'checkout_controller_onepage_save_shipping_method'
7
+ * 'checkout_controller_multishipping_shipping_post'
8
+ * This method is fired during checkout process, after the customer has entered billing address
9
+ * and saved the shipping method
10
+ * @param $observer Varien_Event_Observer
11
+ */
12
+ public function checkoutSaveStep(Varien_Event_Observer $observer)
13
+ {
14
+ // if the plug-in is not enabled, skip this
15
+ if (!$this->enabled()) return;
16
+
17
+ // Do we have a valid item?
18
+ if ($quote = $observer->getEvent()->getQuote())
19
+ {
20
+ // wrap the object
21
+ $object = Mage::getModel('marketingsoftware/abstraction_quote')->setOriginal($quote);
22
+
23
+ // This quote should be added to the queue
24
+ $queue = Mage::getModel('marketingsoftware/queue')
25
+ ->setObject($object)
26
+ ->save();
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Method for event 'sales_quote_item_delete_before'.
32
+ * An item is removed from a quote
33
+ */
34
+ public function quoteItemRemoved(Varien_Event_Observer $observer)
35
+ {
36
+ // if the plug-in is not enabled, skip this
37
+ if (!$this->enabled()) return;
38
+
39
+ // Do we have a valid item?
40
+ if ($item = $observer->getEvent()->getItem())
41
+ {
42
+ if ($item->getParentItemId()) {
43
+ //this item has a parent so its data is already contained within the parent item
44
+ return;
45
+ }
46
+
47
+ if (!$item->getQuote()->getCustomerId()) {
48
+ //this item cannot be linked to a customer, so is not relevant at this moment
49
+ return;
50
+ }
51
+
52
+ // wrap the object
53
+ $object = Mage::getModel('marketingsoftware/abstraction_quote_item')->setOriginal($item);
54
+
55
+ // This quote item should be added to the queue
56
+ $queue = Mage::getModel('marketingsoftware/queue')
57
+ ->setObject($object)
58
+ ->setAction('remove')
59
+ ->save();
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Method for event 'sales_quote_item_save_after'.
65
+ * An item is added or modified
66
+ */
67
+ public function quoteItemModified(Varien_Event_Observer $observer)
68
+ {
69
+ // if the plug-in is not enabled, skip this
70
+ if (!$this->enabled()) return;
71
+
72
+ // Do we have a valid item?
73
+ if ($item = $observer->getEvent()->getItem())
74
+ {
75
+ // unfortunately hasDataChanges is only available in Mage 1.5 and up
76
+ if (!$item->hasDataChanges() && method_exists($item, 'hasDataChanges')) {
77
+ //an event is triggered every time the object is saved, even when nothing has changed
78
+ //for example, when an item is added to the quote
79
+ //however, the update date may have changed (even by 1 second) which will trigger a new queue item any way
80
+ return;
81
+ }
82
+
83
+ if ($item->getParentItemId()) {
84
+ //this item has a parent so its data is already contained within the parent item
85
+ return;
86
+ }
87
+
88
+ if (!$item->getQuote()->getCustomerId()) {
89
+ //this item cannot be linked to a customer, so is not relevant at this moment
90
+ return;
91
+ }
92
+
93
+ // wrap the object
94
+ $object = Mage::getModel('marketingsoftware/abstraction_quote_item')->setOriginal($item);
95
+
96
+ // This quote item should be added to the queue
97
+ $queue = Mage::getModel('marketingsoftware/queue')
98
+ ->setObject($object)
99
+ ->setAction($item->isObjectNew() ? 'add' : 'modify')
100
+ ->save();
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Method for event 'sales_order_save_after'.
106
+ * An order is added or modified
107
+ */
108
+ public function orderModified(Varien_Event_Observer $observer)
109
+ {
110
+ // if the plug-in is not enabled, skip this
111
+ if (!$this->enabled()) return;
112
+
113
+ // Do we have a valid item?
114
+ if ($order = $observer->getEvent()->getOrder())
115
+ {
116
+ if (!$order->getState()) {
117
+ //if an order has no state, it will get one in the next call (usually a few seconds later)
118
+ return;
119
+ }
120
+
121
+ // wrap the object
122
+ $object = Mage::getModel('marketingsoftware/abstraction_order')->setOriginal($order);
123
+
124
+ // This order should be added to the queue
125
+ $queue = Mage::getModel('marketingsoftware/queue')
126
+ ->setObject($object)
127
+ ->setAction($order->isObjectNew() ? 'add' : 'modify')
128
+ ->save();
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Method for event 'newsletter_subscriber_delete_before'.
134
+ * The newsletter subscription is deleted, do something with it,
135
+ */
136
+ public function newsletterSubscriptionRemoved(Varien_Event_Observer $observer)
137
+ {
138
+ // if the plug-in is not enabled, skip this
139
+ if (!$this->enabled()) return;
140
+
141
+ // Do we have a valid item?
142
+ if ($subscriber = $observer->getEvent()->getSubscriber())
143
+ {
144
+ // wrap the object
145
+ $object = Mage::getModel('marketingsoftware/abstraction_subscription')->setOriginal($subscriber);
146
+
147
+ // This newsletter subscription should be added to the queue
148
+ $queue = Mage::getModel('marketingsoftware/queue')
149
+ ->setObject($object)
150
+ ->setAction('remove')
151
+ ->save();
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Method for event 'newsletter_subscriber_save_after'.
157
+ * The newsletter subscription is added or modified
158
+ */
159
+ public function newsletterSubscriptionModified(Varien_Event_Observer $observer)
160
+ {
161
+ // if the plug-in is not enabled, skip this
162
+ if (!$this->enabled()) return;
163
+
164
+ // Do we have a valid item?
165
+ if ($subscriber = $observer->getEvent()->getSubscriber())
166
+ {
167
+ // unfortunately hasDataChanges is only available in Mage 1.5 and up
168
+ if (!$subscriber->hasDataChanges() && method_exists($subscriber, 'hasDataChanges')) {
169
+ // an event is triggered every time the object is saved, even when nothing has changed
170
+ // for example, when an order is placed
171
+ return;
172
+ }
173
+
174
+ // wrap the object
175
+ $object = Mage::getModel('marketingsoftware/abstraction_subscription')->setOriginal($subscriber);
176
+
177
+ // This newsletter subscription should be added to the queue
178
+ $queue = Mage::getModel('marketingsoftware/queue')
179
+ ->setObject($object)
180
+ ->setAction($subscriber->isObjectNew() ? 'add' : 'modify')
181
+ ->save();
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Method for event 'customer_delete_before'.
187
+ * The customer is deleted, do something with it,
188
+ */
189
+ public function customerRemoved(Varien_Event_Observer $observer)
190
+ {
191
+ // if the plug-in is not enabled, skip this
192
+ if (!$this->enabled()) return;
193
+
194
+ // Do we have a valid item?
195
+ if ($customer = $observer->getEvent()->getCustomer())
196
+ {
197
+ // wrap the object
198
+ $object = Mage::getModel('marketingsoftware/abstraction_customer')->setOriginal($customer);
199
+
200
+ // This customer should be added to the queue
201
+ $queue = Mage::getModel('marketingsoftware/queue')
202
+ ->setObject($object)
203
+ ->setAction('remove')
204
+ ->save();
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Method for event 'customer_save_after'.
210
+ * The customer is added or modified, do something with it,
211
+ */
212
+ public function customerModified(Varien_Event_Observer $observer)
213
+ {
214
+ // if the plug-in is not enabled, skip this
215
+ if (!$this->enabled()) return;
216
+
217
+ // Do we have a valid item?
218
+ if ($customer = $observer->getEvent()->getCustomer())
219
+ {
220
+ // wrap the object
221
+ $object = Mage::getModel('marketingsoftware/abstraction_customer')->setOriginal($customer);
222
+
223
+ // This customer should be added to the queue
224
+ $queue = Mage::getModel('marketingsoftware/queue')
225
+ ->setObject($object)
226
+ ->setAction($customer->isObjectNew() ? 'add' : 'modify')
227
+ ->save();
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Is the Copernica module enabled?
233
+ * @return boolean
234
+ */
235
+ private function enabled()
236
+ {
237
+ // get the result from the helper
238
+ return Mage::helper('marketingsoftware')->enabled();
239
+ }
240
+
241
+ /**
242
+ * Process the queue
243
+ * Note that this function might run for a longer time
244
+ */
245
+ public function processQueue()
246
+ {
247
+ // get the config
248
+ $config = Mage::helper('marketingsoftware/config');
249
+ $config->setLastStartTimeCronjob(date("Y-m-d H:i:s"));
250
+
251
+ // if the plug-in is not enabled, skip this
252
+ if (!$this->enabled()) return;
253
+
254
+ // Set the the time limit to a high number
255
+ set_time_limit(0);
256
+ $collection = Mage::getResourceModel('marketingsoftware/queue_collection')
257
+ ->addDefaultOrder()->setPageSize(150);
258
+
259
+ // store the start time
260
+ $time = time();
261
+
262
+ // are there any items?
263
+ if (count($collection) == 0)
264
+ {
265
+ // set some debug info
266
+ $config->setLastCronjobProcessedTasks(0);
267
+ $config->setLastEndTimeCronjob(date("Y-m-d H:i:s"));
268
+ return true;
269
+ }
270
+
271
+ try
272
+ {
273
+ // Perform some basic checks first
274
+ Mage::getSingleton('marketingsoftware/marketingsoftware')->api()->check(true);
275
+ }
276
+ catch (CopernicaError $e)
277
+ {
278
+ // log the message
279
+ Mage::log("Copernica/marketingSoftware: ".(string)$e);
280
+
281
+ // Do not process any records
282
+ return;
283
+ }
284
+ catch(Exception $e)
285
+ {
286
+ Mage::logException($e);
287
+ return;
288
+ }
289
+
290
+ // get the number of processed iterations
291
+ $processedTasks = 0;
292
+
293
+ // iterate over the collection
294
+ foreach ($collection as $queue)
295
+ {
296
+ // Is the timer already expired
297
+ if (time() > ($time + 3 * 60)) break;
298
+
299
+ try
300
+ {
301
+ // we still have time, so lets process an item from the queue
302
+ $success = $queue->process();
303
+
304
+ // the processing is successful, remove the item from the queue
305
+ if ($success)
306
+ {
307
+ // increment the counter for the processed tasks
308
+ $processedTasks++;
309
+
310
+ // also delete the item from the queue
311
+ $queue->delete();
312
+ }
313
+ }
314
+ catch(Exception $e)
315
+ {
316
+ // If its not an Copernica Error than get the message
317
+ if ($e instanceOf CopernicaError)
318
+ {
319
+ // assign the message
320
+ $message = (string)$e;
321
+ }
322
+ else
323
+ {
324
+ // Log the message and the exception
325
+ $message = '['.get_class($e).'] '.$e->getMessage();
326
+
327
+ // Write the error to the log
328
+ Mage::logException($e);
329
+ }
330
+
331
+ // store the log message
332
+ Mage::log($message);
333
+
334
+ // write the error to the database and store the time of the error
335
+ $queue->setResult($message)
336
+ ->setResultTime(date('Y-m-d H:i:s'))
337
+ ->save();
338
+ }
339
+ }
340
+
341
+ // Finished
342
+ $config->setLastCronjobProcessedTasks($processedTasks);
343
+ $config->setLastEndTimeCronjob(date("Y-m-d H:i:s"));
344
+ }
345
+ }
app/code/community/Copernica/MarketingSoftware/Model/PomSoapClient.php ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copernica Soap Client
4
+ * @version 1.1
5
+ */
6
+ class Copernica_MarketingSoftware_Model_PomSoapClient extends SoapClient
7
+ {
8
+ /**
9
+ * Sets connection settings
10
+ * @param string URL of the application
11
+ * @param string Login name
12
+ * @param string Account name
13
+ * @param string Password
14
+ */
15
+ public function __construct($connectionSettings)
16
+ {
17
+ // parameters for the SOAP connection
18
+ $params = array(
19
+ 'soap_version' => SOAP_1_1,
20
+ 'cache_wsdl' => WSDL_CACHE_BOTH,
21
+ 'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
22
+ );
23
+
24
+ // url of the wsdl
25
+ $url = $connectionSettings['url']."?SOAPAPI=WSDL";
26
+
27
+ // create connection
28
+ parent::__construct($url, $params);
29
+
30
+ // try to login
31
+ // @todo check session time
32
+ $result = $this->login(array(
33
+ 'username' => $connectionSettings['login'],
34
+ 'password' => $connectionSettings['password'],
35
+ 'account' => $connectionSettings['account'],
36
+ ));
37
+ }
38
+
39
+ /**
40
+ * Method that handles the calls to the API
41
+ * @param string Name of the method
42
+ * @param array Associative array of parameters
43
+ * @return mixed
44
+ */
45
+ public function __call($methodname, $params)
46
+ {
47
+ // one parameter is required
48
+ $params = count($params) == 0 ? array() : $params[0];
49
+
50
+ // check if the first param was an array
51
+ if (!is_array($params)) trigger_error("Invalid parameters, array is required");
52
+
53
+ // convert the parameters
54
+ foreach ($params as $key => $value)
55
+ {
56
+ // check the type of the value, and so some conversions
57
+ if (self::isAssoc($value)) {
58
+ $params[$key] = self::encodeAssoc($value);
59
+ } elseif (is_array($value)) {
60
+ $params[$key] = self::encodeArray($value);
61
+ } elseif (is_object($value)) {
62
+ $params[$key] = self::encodeObject($value);
63
+ } else {
64
+ $params[$key] = $value;
65
+ }
66
+ }
67
+
68
+ // convert the parameters to an object
69
+ $params = self::toObject($params);
70
+
71
+ // call the method
72
+ $result = parent::__call($methodname, array($params));
73
+
74
+ return self::decodeResult($result);
75
+ }
76
+
77
+ /**
78
+ * Helper method that converts the result
79
+ * @param object with the result
80
+ * @return mixed
81
+ */
82
+ private static function decodeResult($result)
83
+ {
84
+ // is this a regular, scalar, result?
85
+ if (isset($result->value)) return $result->value;
86
+
87
+ // is this an array result?
88
+ if (isset($result->array))
89
+ {
90
+ // check if there are items
91
+ if (!isset($result->array->item)) return array();
92
+
93
+ // get the items, and make sure they are an array
94
+ $items = $result->array->item;
95
+ return array($items);
96
+ }
97
+
98
+ // is this an assoc result
99
+ if (isset($result->map))
100
+ {
101
+ // check if there are pairs
102
+ if (!isset($result->map->pair)) return array();
103
+
104
+ // get the pairs and make sure they are an array
105
+ $pairs = $result->map->pair;
106
+ if (!is_array($pairs)) $pairs = array($pairs);
107
+
108
+ // loop through the pairs and convert them to an array
109
+ $result = array();
110
+ foreach ($pairs as $pair) $result[$pair->key] = $pair->value;
111
+ return $result;
112
+ }
113
+
114
+ // is this a collection?
115
+ if (isset($result->start) && isset($result->length) && isset($result->total) && isset($result->items))
116
+ {
117
+ // empty array
118
+ $items = array();
119
+
120
+ // what is the name of the collection?
121
+ $vars = array_keys(get_object_vars($result->items));
122
+ foreach (array_unique($vars) as $membername)
123
+ {
124
+ // get the members
125
+ $members = isset($result->items->$membername) ? $result->items->$membername : array();
126
+ if (!is_array($members)) $members = array($members);
127
+
128
+ // loop through the members
129
+ foreach ($members as $member)
130
+ {
131
+ // replace the items
132
+ $items[] = self::decodeObject($member);
133
+ }
134
+ }
135
+
136
+ // done
137
+ $result->items = $items;
138
+ return $result;
139
+ }
140
+
141
+ // finally, we assume this is an entity
142
+ $vars = array_keys(get_object_vars($result));
143
+ if (count($vars) == 0) return false;
144
+ $membername = $vars[0];
145
+
146
+ // return just the member
147
+ return self::decodeObject($result->$membername);
148
+ }
149
+
150
+ /**
151
+ * Encode an associative array to be used as parameter
152
+ * @param associative array
153
+ * @return array
154
+ */
155
+ private static function encodeAssoc($array)
156
+ {
157
+ // we are going to construct an array of pairs
158
+ $pairs = array();
159
+
160
+ // loop through all keys and values in the array
161
+ foreach ($array as $key => $value)
162
+ {
163
+ // check if the assoc array is nested
164
+ if ((!is_scalar($key) && !is_null($key)) || (!is_scalar($value) && !is_null($value)))
165
+ {
166
+ trigger_error('Nested assoc array is not supported');
167
+ continue;
168
+ }
169
+
170
+ // create a pair
171
+ $pairs[] = self::toObject(array('key' => $key, 'value' => $value));
172
+ }
173
+
174
+ // done
175
+ return $pairs;
176
+ }
177
+
178
+ /**
179
+ * Encode a normal array to be used as parameter
180
+ * @param Normal array
181
+ * @return array
182
+ */
183
+ private static function encodeArray($array)
184
+ {
185
+ // the result array
186
+ $result = array();
187
+
188
+ // loop through the values
189
+ foreach ($array as $value)
190
+ {
191
+ // array values should be objects
192
+ if (is_object($value)) $result[] = self::encodeObject($value);
193
+ elseif (is_array($value)) trigger_error('Invalid parameter: arrays of objects are not supported');
194
+ else $result[] = $value;
195
+ }
196
+
197
+ // done
198
+ return $result;
199
+ }
200
+
201
+ /**
202
+ * Encode an object to be used as parameter
203
+ * @param object
204
+ * @return object
205
+ */
206
+ private static function encodeObject($object)
207
+ {
208
+ // result object
209
+ $result = new stdClass();
210
+
211
+ // loop through the object vars
212
+ foreach (get_object_vars($object) as $key => $value)
213
+ {
214
+ // check if the assoc array is nested
215
+ if ((!is_scalar($key) && !is_null($key)) || (!is_scalar($value) && !is_null($value)))
216
+ {
217
+ trigger_error('Nested object is not supported');
218
+ continue;
219
+ }
220
+
221
+ // add the var
222
+ $result->$key = $value;
223
+ }
224
+
225
+ // done
226
+ return $result;
227
+ }
228
+
229
+ /**
230
+ * Decode an object to be used as result
231
+ * @param object
232
+ * @return object
233
+ */
234
+ private static function decodeObject($object)
235
+ {
236
+ // result object
237
+ $result = new stdClass();
238
+
239
+ // loop through the object vars
240
+ foreach (get_object_vars($object) as $key => $value)
241
+ {
242
+ if (is_object($value)) $value = self::decodeObject($value);
243
+
244
+ // add the var
245
+ $result->$key = $value;
246
+ }
247
+
248
+ // done
249
+ return $result;
250
+ }
251
+
252
+ /**
253
+ * Helper function checks if an array is associative
254
+ * @param array
255
+ * @return boolean
256
+ */
257
+ public static function isAssoc($array)
258
+ {
259
+ if (!is_array($array)) return false;
260
+ foreach (array_keys($array) as $k => $v)
261
+ {
262
+ if ($k !== $v) return true;
263
+ }
264
+ return false;
265
+ }
266
+
267
+ /**
268
+ * Helper function that maps an assoc array to an object
269
+ * @param associative array
270
+ * @return object
271
+ */
272
+ public static function toObject($array)
273
+ {
274
+ $object = new stdClass();
275
+ foreach ($array as $key => $value) $object->$key = $value;
276
+ return $object;
277
+ }
278
+ }
279
+
280
+ ?>
app/code/community/Copernica/MarketingSoftware/Model/Queue.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_Model_Queue extends Mage_Core_Model_Abstract
3
+ {
4
+ /**
5
+ * Constructor for the model
6
+ */
7
+ protected function _construct()
8
+ {
9
+ $this->_init('marketingsoftware/queue');
10
+ }
11
+
12
+ /**
13
+ * Get the data from the model
14
+ * @return mixed
15
+ */
16
+ public function getObject()
17
+ {
18
+ // return the value
19
+ return unserialize(parent::getData('object'));
20
+ }
21
+
22
+ /**
23
+ * Set the data to the model
24
+ * @return mixed
25
+ */
26
+ public function setObject($object)
27
+ {
28
+ // set the value from the parent implementation
29
+ return parent::setData('object', serialize($object));
30
+ }
31
+
32
+ /**
33
+ * Process this item in the queue
34
+ * @return boolean was the processing successfull
35
+ */
36
+ public function process()
37
+ {
38
+ // Wrap the event in a command object (pattern alarm!)
39
+ $event = Copernica_MarketingSoftware_Model_QueueEvent_Abstract::get($this);
40
+
41
+ // call the process function on the object
42
+ return $event->process();
43
+ }
44
+
45
+ /**
46
+ * Function to save the correct queue time
47
+ */
48
+ public function save()
49
+ {
50
+ // save the queuetime
51
+ $this->setQueueTime(date("Y-m-d H:i:s"));
52
+
53
+ // rely on parent
54
+ return parent::save();
55
+ }
56
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/Abstract.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once(dirname(__FILE__).'/../Error.php');
3
+ /**
4
+ * A wrapper object around an event
5
+ */
6
+ abstract class Copernica_MarketingSoftware_Model_QueueEvent_Abstract
7
+ {
8
+ /**
9
+ * What queue item was used to construct this item
10
+ * @var Copernica_MarketingSoftware_Model_Queue
11
+ */
12
+ private $queueItem;
13
+
14
+ /**
15
+ * Get the right object
16
+ */
17
+ public static function get($queueItem)
18
+ {
19
+ // If we want to start a full synchronisation, we should return a start sync object
20
+ if ($queueItem->getAction() == 'start_sync') return new Copernica_MarketingSoftware_Model_QueueEvent_StartSync($queueItem);
21
+
22
+ // Prepare the action, to append it to the classname
23
+ $action = ucfirst($queueItem->getAction());
24
+
25
+ // What kind of class is given
26
+ switch (get_class($queueItem->getObject()))
27
+ {
28
+ case "Copernica_MarketingSoftware_Model_Abstraction_Quote":
29
+ $classname = "Copernica_MarketingSoftware_Model_QueueEvent_Quote".$action;
30
+ break;
31
+
32
+ case "Copernica_MarketingSoftware_Model_Abstraction_Quote_Item":
33
+ $classname = "Copernica_MarketingSoftware_Model_QueueEvent_QuoteItem".$action;
34
+ break;
35
+
36
+ case "Copernica_MarketingSoftware_Model_Abstraction_Customer":
37
+ $classname = "Copernica_MarketingSoftware_Model_QueueEvent_Customer".$action;
38
+ break;
39
+
40
+ case "Copernica_MarketingSoftware_Model_Abstraction_Order":
41
+ $classname = "Copernica_MarketingSoftware_Model_QueueEvent_Order".$action;
42
+ break;
43
+
44
+ case "Copernica_MarketingSoftware_Model_Abstraction_Subscription":
45
+ $classname = "Copernica_MarketingSoftware_Model_QueueEvent_Subscription".$action;
46
+ break;
47
+ }
48
+
49
+ // No classname, throw an error
50
+ if (!isset($classname)) throw(new CopernicaError(COPERNICAERROR_UNRECOGNIZEDEVENT));
51
+
52
+ // construct the object
53
+ return new $classname($queueItem);
54
+ }
55
+
56
+ /**
57
+ * Construct the item given the queueitem
58
+ * @param Copernica_MarketingSoftware_Model_Queue $queueItem
59
+ */
60
+ private function __construct($queueItem)
61
+ {
62
+ $this->queueItem = $queueItem;
63
+ }
64
+
65
+ /**
66
+ * Get the object for this queue item
67
+ * @return Abstraction object
68
+ */
69
+ protected function getObject()
70
+ {
71
+ return $this->queueItem->getObject();
72
+ }
73
+
74
+ /**
75
+ * Process this item in the queue
76
+ * @return boolean was the processing successfull
77
+ */
78
+ public abstract function process();
79
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerAdd.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_CustomerAdd extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the customer
17
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
18
+ ->setCustomer($customer = $this->getObject())
19
+ ->setDirection('copernica');
20
+
21
+ // this customer might be based upon a guest order
22
+ $orders = $customer->orders();
23
+ $identifier = false;
24
+
25
+ // Is there exactely one order?
26
+ if (count($orders) == 1)
27
+ {
28
+ // Get that order and get its quote id
29
+ $order = $orders[0];
30
+ $identifier = 'guest_'.$order->quoteId();
31
+ }
32
+
33
+ // Update the profiles given the customer
34
+ $api->updateProfiles($customerData, $identifier);
35
+
36
+ // this customer is processed
37
+ return true;
38
+ }
39
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerFull.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_CustomerFull extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the customer object
17
+ $customer = $this->getObject();
18
+
19
+ // Get the customer
20
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
21
+ ->setCustomer($customer)
22
+ ->setDirection('copernica');
23
+
24
+ // Update the profiles given the customer and return the found profiles
25
+ $api->updateProfiles($customerData);
26
+ $profiles = $api->searchProfiles($customerData->id());
27
+
28
+ // Process all the profiles
29
+ foreach ($profiles->items as $profile)
30
+ {
31
+ // add all addresses to the address collection
32
+ foreach ($customer->addresses() as $address)
33
+ {
34
+ // Get the information of this item
35
+ $addressData = Mage::getModel('marketingsoftware/copernica_address_subprofile')
36
+ ->setAddress($address)
37
+ ->setDirection('copernica');
38
+
39
+ // Update the subprofile of this profile
40
+ $api->updateAddressSubProfiles($profile->id, $addressData);
41
+ }
42
+
43
+ $processedQuotes = array();
44
+
45
+ // Add all the orders + items
46
+ foreach ($customer->orders() as $order)
47
+ {
48
+ // Add an record to the order collection of the profile.
49
+ // Get the order data to prepare for sending it to Copernica
50
+ $orderData = Mage::getModel('marketingsoftware/copernica_order_subprofile')
51
+ ->setOrder($order)
52
+ ->setDirection('copernica');
53
+
54
+ // Update the subprofile in the order collection
55
+ $api->updateOrderSubProfile($profile->id, $orderData);
56
+
57
+ // add all order items to the order items collection
58
+ foreach ($order->items() as $orderItem)
59
+ {
60
+ // Get the information of this item
61
+ $itemData = Mage::getModel('marketingsoftware/copernica_orderitem_subprofile')
62
+ ->setOrderItem($orderItem)
63
+ ->setDirection('copernica');
64
+
65
+ // Update the subprofile of this profile
66
+ $api->updateOrderItemSubProfiles($profile->id, $itemData);
67
+ }
68
+
69
+ // Add this orders quote_id to the list of processed quotes
70
+ $processedQuotes[] = $order->quoteId();
71
+ }
72
+
73
+ // add all the cart items
74
+ foreach ($customer->quotes() as $quote)
75
+ {
76
+ // this has alread become an order
77
+ if (in_array($quote->id(), $processedQuotes)) continue;
78
+
79
+ // iterate over the items to add them to the cart items collection
80
+ foreach ($quote->items() as $quoteItem)
81
+ {
82
+ // Get the cart item data
83
+ $cartItemData = Mage::getModel('marketingsoftware/copernica_cartitem_subprofile')
84
+ ->setQuoteItem($quoteItem)
85
+ ->setDirection('copernica')
86
+ ->setStatus('basket');
87
+
88
+ // add / update the quote item
89
+ $api->updateCartItemSubProfiles($profile->id, $cartItemData);
90
+ }
91
+ }
92
+ }
93
+
94
+ // this was processed
95
+ return true;
96
+ }
97
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerModify.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_CustomerModify extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the customer
17
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
18
+ ->setCustomer($this->getObject())
19
+ ->setDirection('copernica');
20
+
21
+ // Update the profiles given the customer
22
+ $api->updateProfiles($customerData);
23
+
24
+ // this customer is processed
25
+ return true;
26
+ }
27
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/CustomerRemove.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copernica Marketing Software Plugin
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@cream.nl so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade this plugin
18
+ * to newer versions in the future. If you wish to customize it for
19
+ * your needs please look at the documentation for more information.
20
+ *
21
+ * @category Copernica
22
+ * @package Copernica_MarketingSoftware
23
+ * @copyright Copyright (c) 2012 Cream (http://www.cream.nl)
24
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25
+ */
26
+
27
+ /**
28
+ * A wrapper object around an event
29
+ */
30
+ class Copernica_MarketingSoftware_Model_QueueEvent_CustomerRemove extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
31
+ {
32
+ /**
33
+ * Process this item in the queue
34
+ * @return boolean was the processing successfull
35
+ */
36
+ public function process()
37
+ {
38
+ // Get the copernica API
39
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
40
+
41
+ // Get the customer
42
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
43
+ ->setCustomer($customer = $this->getObject())
44
+ ->setDirection('copernica');
45
+
46
+ // Remove the profiles given the customer
47
+ $api->removeProfiles($customerData);
48
+
49
+ // this customer is processed
50
+ return true;
51
+ }
52
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/OrderAdd.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_OrderAdd extends Copernica_MarketingSoftware_Model_QueueEvent_OrderModify
6
+ {
7
+ /**
8
+ * Process this item in the same way as the modification of an order
9
+ */
10
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/OrderModify.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_OrderModify extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API and config helper
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the subscription which has been modified
17
+ $order = $this->getObject();
18
+
19
+ // is there a customer?
20
+ if (is_object($customer = $order->customer()))
21
+ {
22
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
23
+ ->setCustomer($customer);
24
+ }
25
+ else
26
+ {
27
+ $customerData = Mage::getModel('marketingsoftware/copernica_profileorder')
28
+ ->setOrder($order);
29
+ }
30
+
31
+ // The direction should be set
32
+ $customerData->setDirection('copernica');
33
+
34
+ // Update the profiles given the customer and return the found profiles
35
+ $api->updateProfiles($customerData);
36
+ $profiles = $api->searchProfiles($customerData->id());
37
+
38
+ // Process all the profiles
39
+ foreach ($profiles->items as $profile)
40
+ {
41
+ // Remove any cart items belonging to this quote, which have not been
42
+ // deleted
43
+ $api->removeOldCartItems($profile->id, $order->quoteId());
44
+
45
+ // Add an record to the order collection of the profile.
46
+ // Get the order data to prepare for sending it to Copernica
47
+ $orderData = Mage::getModel('marketingsoftware/copernica_order_subprofile')
48
+ ->setOrder($order)
49
+ ->setDirection('copernica');
50
+
51
+ // Update the subprofile in the order collection
52
+ $api->updateOrderSubProfile($profile->id, $orderData);
53
+
54
+ // add all order items to the order items collection
55
+ foreach ($order->items() as $orderItem)
56
+ {
57
+ // Get the information of this item
58
+ $itemData = Mage::getModel('marketingsoftware/copernica_orderitem_subprofile')
59
+ ->setOrderItem($orderItem)
60
+ ->setDirection('copernica');
61
+
62
+ // Update the subprofile of this profile
63
+ $api->updateOrderItemSubProfiles($profile->id, $itemData);
64
+ }
65
+
66
+ // add all addresses to the address collection
67
+ foreach ($order->addresses() as $address)
68
+ {
69
+ // Get the information of this item
70
+ $addressData = Mage::getModel('marketingsoftware/copernica_address_subprofile')
71
+ ->setAddress($address)
72
+ ->setDirection('copernica');
73
+
74
+ // Update the subprofile of this profile
75
+ $api->updateAddressSubProfiles($profile->id, $addressData);
76
+ }
77
+ }
78
+
79
+ // This order was successfully synchronized
80
+ return true;
81
+ }
82
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItem.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ abstract class Copernica_MarketingSoftware_Model_QueueEvent_QuoteItem extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API and config helper
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the subscription which has been modified
17
+ $quoteItem = $this->getObject();
18
+ $quote = $quoteItem->quote();
19
+
20
+ // if there is no customer, we cannot process this so return immediately
21
+ if (!is_object($customer = $quote->customer())) return true;
22
+
23
+ // Get the customer
24
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
25
+ ->setCustomer($quote->customer())
26
+ ->setDirection('copernica');
27
+
28
+ // Get the profiles from the api
29
+ $api->updateProfiles($customerData);
30
+ $profiles = $api->searchProfiles($customerData->id());
31
+
32
+ // Get the cart item data
33
+ $cartItemData = Mage::getModel('marketingsoftware/copernica_cartitem_subprofile')
34
+ ->setQuoteItem($quoteItem)
35
+ ->setDirection('copernica')
36
+ ->setStatus($this->status());
37
+
38
+ // Iterate over the matching profiles and add / update the quote item
39
+ foreach ($profiles->items as $profile)
40
+ {
41
+ $api->updateCartItemSubProfiles($profile->id, $cartItemData);
42
+ }
43
+
44
+ // all went allright
45
+ return true;
46
+ }
47
+
48
+ /**
49
+ * In what status is this cart item
50
+ * @return String
51
+ */
52
+ abstract protected function status();
53
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItemAdd.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_QuoteItemAdd extends Copernica_MarketingSoftware_Model_QueueEvent_QuoteItem
6
+ {
7
+ /**
8
+ * In what status is this cart item
9
+ * @return String
10
+ */
11
+ protected function status()
12
+ {
13
+ return 'basket';
14
+ }
15
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItemModify.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_QuoteItemModify extends Copernica_MarketingSoftware_Model_QueueEvent_QuoteItem
6
+ {
7
+ /**
8
+ * In what status is this cart item
9
+ * @return String
10
+ */
11
+ protected function status()
12
+ {
13
+ return 'basket';
14
+ }
15
+
16
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteItemRemove.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_QuoteItemRemove extends Copernica_MarketingSoftware_Model_QueueEvent_QuoteItem
6
+ {
7
+ /**
8
+ * In what status is this cart item
9
+ * @return String
10
+ */
11
+ protected function status()
12
+ {
13
+ return 'deleted';
14
+ }
15
+
16
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/QuoteModify.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_QuoteModify extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API and config helper
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the subscription which has been modified
17
+ $quote = $this->getObject();
18
+
19
+ // is there a customer?
20
+ if (is_object($customer = $quote->customer()))
21
+ {
22
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
23
+ ->setCustomer($customer);
24
+ }
25
+ else
26
+ {
27
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilequote')
28
+ ->setQuote($quote);
29
+ }
30
+
31
+ // The direction should be set
32
+ $customerData->setDirection('copernica');
33
+
34
+ // Update the profiles given the customer and return the found profiles
35
+ $api->updateProfiles($customerData);
36
+ $profiles = $api->searchProfiles($customerData->id());
37
+
38
+ // iterate over the items to add them to the cart items collection
39
+ foreach ($quote->items() as $quoteItem)
40
+ {
41
+ // Get the cart item data
42
+ $cartItemData = Mage::getModel('marketingsoftware/copernica_cartitem_subprofile')
43
+ ->setQuoteItem($quoteItem)
44
+ ->setDirection('copernica')
45
+ ->setStatus('basket');
46
+
47
+ // Iterate over the matching profiles and add / update the quote item
48
+ foreach ($profiles->items as $profile)
49
+ {
50
+ $api->updateCartItemSubProfiles($profile->id, $cartItemData);
51
+ }
52
+ }
53
+
54
+ // This quote was successfully synchronized
55
+ return true;
56
+ }
57
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/StartSync.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_StartSync extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * @var integer store the start time
9
+ */
10
+ private $startTime;
11
+
12
+ /**
13
+ * @var integer store the time limit
14
+ */
15
+ private $timeLimit;
16
+
17
+
18
+ /**
19
+ * Process this item in the queue
20
+ * @return boolean was the processing successfull
21
+ */
22
+ public function process()
23
+ {
24
+ // store the start time
25
+ $this->startTime = time();
26
+
27
+ // store the time limit
28
+ $this->timeLimit = 3*60;
29
+
30
+ // A page size to limit the data in memory
31
+ $pageSize = 20;
32
+
33
+ // add all the customers to the queue
34
+ if (!$this->_addCustomersToQueue($pageSize)) return false;
35
+
36
+ // add all the orders (which don't have a customer) to the queue
37
+ if (!$this->_addOrdersToQueue($pageSize)) return false;
38
+
39
+ // add the newsletter subscriptions to the queue
40
+ if (!$this->_addSubscriptionsToQueue($pageSize)) return false;
41
+
42
+ // It succeeded
43
+ return true;
44
+ }
45
+
46
+ /**
47
+ * Add all the customers to the queue
48
+ * this piece of code has been improved by Cream (www.cream.nl)
49
+ * @param integer page size
50
+ */
51
+ private function _addCustomersToQueue($pageSize)
52
+ {
53
+ // Get the config helper
54
+ $config = Mage::helper('marketingsoftware/config');
55
+
56
+ // get the customers,
57
+ // this piece of code has been improved by Cream (www.cream.nl)
58
+ $customers = Mage::getModel('customer/customer')
59
+ ->getCollection()
60
+ ->setPageSize($pageSize)
61
+ ->addAttributeToSort('updated_at')
62
+ ->addAttributeToFilter('updated_at', array(
63
+ 'from' => $config->getCustomerProgressStatus()
64
+ ));
65
+
66
+ // Get the id of last customer which has been processed via this synchronisation
67
+ $progressDateTime = $config->getCustomerProgressStatus();
68
+
69
+ // iterate over the pages with customers
70
+ for ($page = 1; $page <= $customers->getLastPageNumber(); $page++)
71
+ {
72
+ // load the data for this page
73
+ $customers->setPage($page, $pageSize)->load();
74
+
75
+ // iterate over the customers
76
+ foreach ($customers as $customer)
77
+ {
78
+ // Was this record changed or modified after the last synchronisation
79
+ if ($customer->getCreatedAt() <= $progressDateTime &&
80
+ $customer->getUpdatedAt() <= $progressDateTime ) continue;
81
+
82
+ // wrap the object
83
+ $object = Mage::getModel('marketingsoftware/abstraction_customer')->loadCustomer($customer->getEntityId());
84
+
85
+ // This customer should be added to the queue
86
+ $queue = Mage::getModel('marketingsoftware/queue')
87
+ ->setObject($object)
88
+ ->setAction('full')
89
+ ->save();
90
+
91
+ // Get the maximum progress time
92
+ $progressDateTime = max($progressDateTime, $customer->getUpdatedAt());
93
+
94
+ // get rid of the customer and the object
95
+ unset($customer);
96
+ unset($object);
97
+ }
98
+
99
+ // Store the progress status
100
+ $config->setCustomerProgressStatus($progressDateTime);
101
+
102
+ // Clear the cached customers
103
+ $customers->clear();
104
+
105
+ // Did we already spend to long on processing the records
106
+ if (time() > ($this->startTime + $this->timeLimit)) return false;
107
+ }
108
+ // clear the customers variable
109
+ unset($customers);
110
+
111
+ // Store the progress status
112
+ $config->setCustomerProgressStatus(date('Y-m-d H:i:s'));
113
+
114
+ // we did complete
115
+ return true;
116
+ }
117
+
118
+ /**
119
+ * Add all the orders to the queue, which are placed by guest subscribers
120
+ * this piece of code has been improved by Cream (www.cream.nl)
121
+ * @param integer page size
122
+ */
123
+ private function _addOrdersToQueue($pageSize)
124
+ {
125
+ // Get the config helper
126
+ $config = Mage::helper('marketingsoftware/config');
127
+
128
+ // get the orders, which don't have a customer_id
129
+ // this piece of code has been improved by Cream (www.cream.nl)
130
+ $orders = Mage::getModel('sales/order')
131
+ ->getCollection()
132
+ ->addAttributeToSort('updated_at')
133
+ ->addAttributeToFilter('updated_at', array(
134
+ 'from' => $config->getOrderProgressStatus()
135
+ ));
136
+
137
+ // The add field to search filter is not supported in Magento 1.4
138
+ if (is_callable(array($orders, 'addFieldToSearchFilter')))
139
+ {
140
+ $orders->addFieldToSearchFilter('customer_id', 0)
141
+ ->addFieldToSearchFilter('customer_id', array('null' => 1));
142
+ }
143
+
144
+ // Set the page size
145
+ $orders->setPageSize($pageSize);
146
+
147
+ // Get the id of last order which has been processed via this synchronisation
148
+ $progressDateTime = $config->getOrderProgressStatus();
149
+
150
+ // iterate over the pages with orders
151
+ for ($page = 1; $page <= $orders->getLastPageNumber(); $page++)
152
+ {
153
+ // load the data for this page
154
+ $orders->setPage($page, $pageSize)->load();
155
+
156
+ // iterate over the orders
157
+ foreach ($orders as $order)
158
+ {
159
+ // Was this record changed or modified after the last synchronisation
160
+ if ($order->getCreatedAt() <= $progressDateTime &&
161
+ $order->getUpdatedAt() <= $progressDateTime ) continue;
162
+
163
+ // Does this order have a customer id? This check is needed for Magento 1.4
164
+ if ($order->getCustomerId()) continue;
165
+
166
+ // wrap the object
167
+ $object = Mage::getModel('marketingsoftware/abstraction_order')->loadOrder($order->getEntityId());
168
+
169
+ // This order should be added to the queue
170
+ $queue = Mage::getModel('marketingsoftware/queue')
171
+ ->setObject($object)
172
+ ->save();
173
+
174
+ // Get the maximum progress time
175
+ $progressDateTime = max($progressDateTime, $order->getUpdatedAt());
176
+
177
+ // get rid of the order and the object
178
+ unset($order);
179
+ unset($object);
180
+ }
181
+
182
+ // Store the progress status
183
+ $config->setOrderProgressStatus($progressDateTime);
184
+
185
+ // Clear the cached orders
186
+ $orders->clear();
187
+
188
+ // Did we already spend to long on processing the records
189
+ if (time() > ($this->startTime + $this->timeLimit)) return false;
190
+ }
191
+
192
+ // clear the orders variable
193
+ unset($orders);
194
+
195
+ // Store the progress status
196
+ $config->setOrderProgressStatus(date('Y-m-d H:i:s'));
197
+
198
+ // we did complete
199
+ return true;
200
+ }
201
+
202
+ /**
203
+ * Add all the subscriptions to the queue, which are placed by guest subscribers
204
+ * @param integer page size
205
+ */
206
+ private function _addSubscriptionsToQueue($pageSize)
207
+ {
208
+ // Get the config helper
209
+ $config = Mage::helper('marketingsoftware/config');
210
+
211
+ // get the subscriptions
212
+ $subscriptions = Mage::getModel('newsletter/subscriber')
213
+ ->getCollection()
214
+ ->addFieldToFilter('customer_id', array(0, 'null'));
215
+
216
+ // iterate over the subscriptions
217
+ foreach ($subscriptions as $subscription)
218
+ {
219
+ // wrap the object
220
+ $object = Mage::getModel('marketingsoftware/abstraction_subscription')
221
+ ->setOriginal($subscription);
222
+
223
+ // This subscription should be added to the queue
224
+ $queue = Mage::getModel('marketingsoftware/queue')
225
+ ->setObject($object)
226
+ ->save();
227
+
228
+ // get rid of the subscription and the object
229
+ unset($subscription);
230
+ unset($object);
231
+ }
232
+
233
+ // clear the subscriptions variable
234
+ unset($subscriptions);
235
+
236
+ // we did complete
237
+ return true;
238
+ }
239
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/SubscriptionAdd.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_SubscriptionAdd extends Copernica_MarketingSoftware_Model_QueueEvent_SubscriptionModify
6
+ {
7
+ /**
8
+ * Process this item in the queue the behaviour is the same is for a modification
9
+ */
10
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/SubscriptionModify.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_SubscriptionModify extends Copernica_MarketingSoftware_Model_QueueEvent_Abstract
6
+ {
7
+ /**
8
+ * Process this item in the queue
9
+ * @return boolean was the processing successfull
10
+ */
11
+ public function process()
12
+ {
13
+ // Get the copernica API
14
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
15
+
16
+ // Get the subscription which has been modified
17
+ $subscription = $this->getObject();
18
+
19
+ // is there a customer?
20
+ if (is_object($customer = $subscription->customer()))
21
+ {
22
+ // Maybe this is an old subscription which is updated, use the subscriber
23
+ // identifier, so that the old record is updated, the typo 'subcr' should
24
+ // remain there for backwards compatibility
25
+ $identifier = 'subcr_'.$subscription->id();
26
+
27
+ // get the customer data
28
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilecustomer')
29
+ ->setCustomer($customer);
30
+ }
31
+ else
32
+ {
33
+ // use the normal identifier
34
+ $identifier = false;
35
+
36
+ // get the customer data
37
+ $customerData = Mage::getModel('marketingsoftware/copernica_profilesubscription')
38
+ ->setSubscription($subscription);
39
+ }
40
+
41
+ // The direction should be set
42
+ $customerData->setDirection('copernica');
43
+
44
+ // Update the profiles given the customer
45
+ $api->updateProfiles($customerData, $identifier);
46
+
47
+ // this might result in two profiles with the same customer_id
48
+ $profiles = $api->searchProfiles($customerData->id());
49
+
50
+ // we received an invalid response
51
+ if (!is_object($profiles)) return false;
52
+
53
+ // We have only one profile everything is fine
54
+ if ($profiles->length == 1) return true;
55
+
56
+ // Merge the profiles
57
+ $api->mergeProfiles($profiles->items);
58
+
59
+ // this subscription is processed
60
+ return true;
61
+ }
62
+ }
app/code/community/Copernica/MarketingSoftware/Model/QueueEvent/SubscriptionRemove.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A wrapper object around an event
4
+ */
5
+ class Copernica_MarketingSoftware_Model_QueueEvent_SubscriptionRemove extends Copernica_MarketingSoftware_Model_QueueEvent_SubscriptionModify
6
+ {
7
+ /**
8
+ * Process this item in the queue the behaviour is the same is for a modification
9
+ */
10
+ }
app/code/community/Copernica/MarketingSoftware/controllers/Adminhtml/Marketingsoftware/ExportController.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Export Controller, which takes care of the export data menu.
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ class Copernica_MarketingSoftware_Adminhtml_Marketingsoftware_ExportController extends Mage_Adminhtml_Controller_Action
9
+ {
10
+ /**
11
+ * indexAction() takes care of displaying the form which
12
+ * contains the details used for the SOAP connection
13
+ */
14
+ public function indexAction()
15
+ {
16
+ // Call the helper, to validate the settings
17
+ Mage::helper('marketingsoftware')->validatePluginBehaviour();
18
+
19
+ // Load the layout
20
+ $this->loadLayout();
21
+
22
+ // The copernica Menu is active
23
+ $this->_setActiveMenu('copernica');
24
+
25
+ $this->getLayout()
26
+ ->getBlock('content')->append(
27
+ $this->getLayout()->createBlock('marketingsoftware/adminhtml_marketingsoftware_export')
28
+ );
29
+ $this->getLayout()->getBlock('head')->setTitle($this->__('Synchronize Data / Copernica Marketing Software / Magento Admin'));
30
+
31
+ $this->renderLayout();
32
+ }
33
+
34
+ /**
35
+ * progressAction() takes care of placing a loader
36
+ * during the background export action
37
+ * @return string Returns a 'completed' or 'in progress' message, depending
38
+ * on the state of the sync tool
39
+ */
40
+ public function progressAction()
41
+ {
42
+ // get the Collection and the helper
43
+ $queueCollection = Mage::getResourceModel('marketingsoftware/queue_collection');
44
+ $helper = Mage::helper('marketingsoftware');
45
+
46
+ // Get the response, set the header and clear the body
47
+ $response = $this->getResponse();
48
+ $response->setHeader('Content-Type', 'text/plain', true);
49
+ $response->clearBody();
50
+
51
+ // Send the headers
52
+ $response->sendHeaders();
53
+
54
+ // Is the synchronisation ready to be started?
55
+ if ($helper->isSynchronisationStartScheduled())
56
+ {
57
+ $string = "Synchronisation scheduled to be started.";
58
+ }
59
+ elseif ($queueCollection->getSize() > 0)
60
+ {
61
+ $string = "<b>Number of records</b> : " . $queueCollection->getSize();
62
+ $string .= "<br/><b>Oldest record</b> : " . $queueCollection->getQueueStartTime();
63
+ }
64
+ else
65
+ {
66
+ $string = 'Idle, no recods in queue.';
67
+ }
68
+
69
+ // Sent the data
70
+ $response->setBody($string);
71
+ return;
72
+ }
73
+
74
+ /**
75
+ * getAction() takes care of exporting customers account information
76
+ * from Magento to Copernica
77
+ * @return string Returns the current page reloaded, containing an information message
78
+ */
79
+ public function getAction()
80
+ {
81
+ // get all POST values
82
+ $post = $this->getRequest()->getPost();
83
+
84
+ // check to see if there is any POST data along
85
+ if (empty($post))
86
+ {
87
+ Mage::getSingleton('adminhtml/session')->addError('Invalid data.');
88
+ return $this->_redirect('*/*');
89
+ }
90
+
91
+ // Get the helper
92
+ $helper = Mage::helper('marketingsoftware');
93
+
94
+ // Is the synchronisation ready to be started?
95
+ if ($helper->isSynchronisationStartScheduled())
96
+ {
97
+ // The item has been scheduled already
98
+ Mage::getSingleton('adminhtml/session')
99
+ ->addError('A synchronization has already been scheduled, please be patient for it to finish.');
100
+ }
101
+ else
102
+ {
103
+ // The start synch token must be added to the queue
104
+ $queue = Mage::getModel('marketingsoftware/queue')
105
+ ->setObject(null)
106
+ ->setAction('start_sync')
107
+ ->save();
108
+
109
+ // The item has been scheduled successfully
110
+ Mage::getSingleton('adminhtml/session')->addSuccess("The synchronization process has been scheduled!");
111
+ }
112
+
113
+ return $this->_redirect('*/*');
114
+ }
115
+ }
app/code/community/Copernica/MarketingSoftware/controllers/Adminhtml/Marketingsoftware/LinkController.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Link Controller, which takes care of the link fields menu.
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ class Copernica_MarketingSoftware_Adminhtml_Marketingsoftware_LinkController extends Mage_Adminhtml_Controller_Action
9
+ {
10
+ /**
11
+ * indexAction() takes care of displaying the form which
12
+ * contains the details used for the SOAP connection
13
+ */
14
+ public function indexAction()
15
+ {
16
+ // Call the helper, to validate the settings
17
+ Mage::helper('marketingsoftware')->validatePluginBehaviour();
18
+
19
+ // Load the layout
20
+ $this->loadLayout();
21
+
22
+ // The copernica Menu is active
23
+ $this->_setActiveMenu('copernica');
24
+
25
+ $this->getLayout()
26
+ ->getBlock('content')->append(
27
+ $this->getLayout()->createBlock('marketingsoftware/adminhtml_marketingsoftware_link')
28
+ );
29
+ $this->getLayout()->getBlock('head')->setTitle($this->__('Link Fields / Copernica Marketing Software / Magento Admin'));
30
+
31
+ // Add the javascript headers
32
+ $this->getLayout()->getBlock('head')->addJs('copernica/marketingsoftware/field.js');
33
+ $this->getLayout()->getBlock('head')->addJs('copernica/marketingsoftware/collection.js');
34
+ $this->getLayout()->getBlock('head')->addJs('copernica/marketingsoftware/database.js');
35
+
36
+ // Render the layout
37
+ $this->renderLayout();
38
+ }
39
+
40
+ /**
41
+ * Check and process incoming ajax request
42
+ * @return string The error description, or 'ok' if not error was detected
43
+ */
44
+ public function checkAjaxAction()
45
+ {
46
+ // get all post values
47
+ $data = $this->getRequest()->getPost();
48
+
49
+ // Get the response, set the header and clear the body
50
+ $response = $this->getResponse();
51
+ $response->setHeader('Content-Type', 'text/plain', true);
52
+ $response->clearBody();
53
+
54
+ // Send the headers
55
+ $response->sendHeaders();
56
+
57
+ // check to see if there is any POST data along
58
+ if (empty($data))
59
+ {
60
+ $response->setBody('Invalid Ajax call');
61
+ return;
62
+ }
63
+
64
+ // get access to the copernica API
65
+ $api = Mage::getSingleton('marketingsoftware/marketingsoftware')->api();
66
+
67
+ // now we need to process the request
68
+ switch ($data['type'])
69
+ {
70
+ case 'check_database': $result = $api->validateDatabase($data['database']); break;
71
+ case 'repair_database':
72
+ case 'create_database': $result = $api->repairDatabase($data['database']); break;
73
+
74
+ case 'check_collection': $result = $api->validateCollection($data['database'], $data['collection_type'], $data['collection']); break;
75
+ case 'create_collection':
76
+ case 'repair_collection': $result = $api->repairCollection($data['database'], $data['collection_type'], $data['collection']); break;
77
+
78
+ case 'check_field': $result = $api->validateField($data['field_system_name'], $data['field'], $data['database'], $data['collection'] == 'database' ? false : $data['collection'], $data['collectionName']); break;
79
+ case 'repair_field':
80
+ case 'create_field': $result = $api->repairField($data['field_system_name'], $data['field'], $data['database'], $data['collection'] == 'database' ? false : $data['collection'], $data['collectionName']); break;
81
+ default: $result = "impossible";
82
+ }
83
+
84
+ // store the result
85
+ $response->setBody($result);
86
+ }
87
+
88
+ /**
89
+ * saveProfilesAndCollectionsAction() takes care of saving Customer Profile and Orders/Products Collection details.
90
+ * @return Object Returns the '_redirect' object that loads the parent page
91
+ */
92
+ public function saveProfilesAndCollectionsAction()
93
+ {
94
+ // get all POST values
95
+ $post = $this->getRequest()->getPost();
96
+
97
+ // check to see if there is any POST data along
98
+ if (empty($post)) Mage::getSingleton('adminhtml/session')->addError('Invalid data.');
99
+ else
100
+ {
101
+ // we set up some arrays to store the content of each section (customer, products, orders)
102
+ $customer_array = array();
103
+ $cartproducts_array = array();
104
+ $orders_array = array();
105
+ $orderproducts_array = array();
106
+ $address_array = array();
107
+
108
+ // we loop throught the POST data and store each data inside the array it belongs to
109
+ foreach ($post as $fieldname => $fieldvalue)
110
+ {
111
+ if (strpos($fieldname, 'input_customer') !== false)
112
+ {
113
+ $fieldname = str_replace('input_customer_', '', $fieldname);
114
+ $customer_array[$fieldname] = $fieldvalue;
115
+ }
116
+ elseif (strpos($fieldname, 'input_cartproducts') !== false)
117
+ {
118
+ $fieldname = str_replace('input_cartproducts_', '', $fieldname);
119
+ $cartproducts_array[$fieldname] = $fieldvalue;
120
+ }
121
+ elseif (strpos($fieldname, 'input_orderproducts') !== false)
122
+ {
123
+ $fieldname = str_replace('input_orderproducts_', '', $fieldname);
124
+ $orderproducts_array[$fieldname] = $fieldvalue;
125
+ }
126
+ elseif (strpos($fieldname, 'input_orders') !== false)
127
+ {
128
+ $fieldname = str_replace('input_orders_', '', $fieldname);
129
+ $orders_array[$fieldname] = $fieldvalue;
130
+ }
131
+ elseif (strpos($fieldname, 'input_addresses') !== false)
132
+ {
133
+ $fieldname = str_replace('input_addresses_', '', $fieldname);
134
+ $address_array[$fieldname] = $fieldvalue;
135
+ }
136
+ }
137
+
138
+ // store the database and collection names
139
+ $config = Mage::helper('marketingsoftware/config')
140
+ ->setDatabaseName($post['db_input'])
141
+ ->setCartItemsCollectionName($post['cartproducts_input'])
142
+ ->setOrdersCollectionName($post['orders_input'])
143
+ ->setOrderItemsCollectionName($post['orderproducts_input'])
144
+ ->setAddressesCollectionName($post['addresses_input'])
145
+ ->setLinkedCustomerFields($customer_array)
146
+ ->setLinkedCartItemFields($cartproducts_array)
147
+ ->setLinkedOrderFields($orders_array)
148
+ ->setLinkedOrderItemFields($orderproducts_array)
149
+ ->setLinkedAddressFields($address_array);
150
+
151
+ // add a success notice
152
+ Mage::getSingleton('adminhtml/session')->addSuccess('Settings were successfully saved.');
153
+ }
154
+
155
+ // reload the link fields page
156
+ return $this->_redirect('*/*');
157
+
158
+ }
159
+ }
app/code/community/Copernica/MarketingSoftware/controllers/Adminhtml/Marketingsoftware/SettingsController.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings Controller, which takes care of the settings menu.
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ class Copernica_MarketingSoftware_Adminhtml_Marketingsoftware_SettingsController extends Mage_Adminhtml_Controller_Action
9
+ {
10
+ /**
11
+ * indexAction() takes care of displaying the form which
12
+ * contains the details used for the SOAP connection
13
+ */
14
+ public function indexAction()
15
+ {
16
+ // Call the helper, to validate the settings
17
+ Mage::helper('marketingsoftware')->validatePluginBehaviour();
18
+
19
+ // Load the layout
20
+ $this->loadLayout();
21
+
22
+ // The copernica Menu is active
23
+ $this->_setActiveMenu('copernica');
24
+
25
+ $this->getLayout()
26
+ ->getBlock('content')->append(
27
+ $this->getLayout()->createBlock('marketingsoftware/adminhtml_marketingsoftware_settings')
28
+ );
29
+ $this->getLayout()->getBlock('head')->setTitle($this->__('Settings / Copernica Marketing Software / Magento Admin'));
30
+
31
+ // Render the layout
32
+ $this->renderLayout();
33
+ }
34
+
35
+ /**
36
+ * sendAction() takes care of checking and storing the login details to the SOAP
37
+ * It also performs checks on database and in case it doesn't exists, it will create it.
38
+ * @return Object Returns the '_redirect' object that loads the parent page
39
+ */
40
+ public function sendAction()
41
+ {
42
+ // get all post values from the request
43
+ $post = $this->getRequest()->getPost();
44
+
45
+ // check to see if there is any POST data along
46
+ if (empty($post))
47
+ {
48
+ Mage::getSingleton('adminhtml/session')->addError('Invalid data.');
49
+ }
50
+ // we have post data check if its correct
51
+ else
52
+ {
53
+ // check connection based on sent post data
54
+ $api = Mage::helper('marketingsoftware/api')->init($post['cp_host'], $post['cp_user'], $post['cp_account'], $post['cp_pass']);
55
+
56
+ try
57
+ {
58
+ // check the data
59
+ $result = $api->check();
60
+ }
61
+ catch(Exception $e)
62
+ {
63
+ // No valid result has been retrieved
64
+ $result = false;
65
+
66
+ // An exception is found add it to the session
67
+ Mage::getSingleton('adminhtml/session')->addException($e,(string)$e);
68
+ }
69
+
70
+ // The data is verified, store it
71
+ if ($result)
72
+ {
73
+ // everything is fine store the data in the config
74
+ Mage::helper('marketingsoftware/config')
75
+ ->setHostname($post['cp_host'])
76
+ ->setUsername($post['cp_user'])
77
+ ->setAccount($post['cp_account'])
78
+ ->setPassword($post['cp_pass']);
79
+
80
+ // Settings were successfully stored, add the success message
81
+ Mage::getSingleton('adminhtml/session')->addSuccess('Settings were successfully saved.');
82
+ }
83
+ }
84
+
85
+ // load the initial page
86
+ return $this->_redirect('*/*');
87
+ }
88
+
89
+ /**
90
+ * recheckAction() takes care of an ajax settings checker
91
+ */
92
+ public function checkerAction()
93
+ {
94
+ // Get the response, set the header and clear the body
95
+ $response = $this->getResponse();
96
+ $response->setHeader('Content-Type', 'text/plain', true);
97
+ $response->clearBody();
98
+
99
+ // Send the headers
100
+ $response->sendHeaders();
101
+
102
+ // get all POST values
103
+ $post = $this->getRequest()->getPost();
104
+
105
+ // check to see if there is any POST data along
106
+ if (empty($post))
107
+ {
108
+ $response->setBody('Invalid Ajax call');
109
+ return;
110
+ }
111
+
112
+ try
113
+ {
114
+ // check connection based on sent post data
115
+ $api = Mage::helper('marketingsoftware/api')->init($post['cp_host'], $post['cp_user'], $post['cp_account'], $post['cp_pass']);
116
+
117
+ // check the data
118
+ $result = $api->check();
119
+ }
120
+ catch (Exception $e)
121
+ {
122
+ $response->setBody((String)$e);
123
+ }
124
+
125
+ // everything seems to be OK, we already cleared the body
126
+ }
127
+ }
app/code/community/Copernica/MarketingSoftware/controllers/ProductController.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_ProductController extends Mage_Core_Controller_Front_Action
3
+ {
4
+ /**
5
+ * Handles a request to copernica/product/xml
6
+ */
7
+ public function xmlAction()
8
+ {
9
+ //TODO: some security
10
+ $request = $this->getRequest();
11
+ if ($product = $this->_getProduct($request->getParam('id'))) {
12
+ $xml = $this->_buildProductXML(array($product));
13
+ $this->_prepareResponse($xml);
14
+ }
15
+ elseif ($request->getParam('new'))
16
+ {
17
+ // Today it is:
18
+ $todayDate = date('Y-m-d H:i:s');
19
+
20
+ // Get the collection, add the filters and select all data
21
+ $collection = Mage::getResourceModel('catalog/product_collection')
22
+ ->addAttributeToFilter('news_from_date', array(
23
+ 'date' => true,
24
+ 'to' => $todayDate)
25
+ )
26
+ ->addAttributeToFilter('news_to_date', array(
27
+ 'or'=> array(
28
+ 0 => array('date' => true, 'from' => $todayDate),
29
+ 1 => array('is' => new Zend_Db_Expr('null')))
30
+ ), 'left'
31
+ )
32
+ ->addAttributeToSelect('id');
33
+
34
+ // construct the XML
35
+ $xml = $this->_buildProductXML($collection);
36
+ $this->_prepareResponse($xml);
37
+ } else {
38
+ $this->norouteAction();
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Constructs an XML object for the given product
44
+ *
45
+ * @param Mage_Catalog_Model_Product $product
46
+ * @return SimpleXMLElement
47
+ */
48
+ private function _buildProductXML($collection)
49
+ {
50
+ $xml = new SimpleXMLElement('<products/>');
51
+
52
+ // iterate over the collection
53
+ foreach ($collection as $product)
54
+ {
55
+ // Add a product node
56
+ $element = $xml->addChild('product');
57
+
58
+ // wrap the product
59
+ $product = Mage::getModel('marketingsoftware/abstraction_product')->loadProduct($product->getId());
60
+
61
+ // Collection of relevant fields
62
+ $fields = array(
63
+ 'id',
64
+ 'sku',
65
+ 'name',
66
+ 'description',
67
+ 'price',
68
+ 'modified',
69
+ 'created',
70
+ 'productUrl',
71
+ 'imageUrl',
72
+ 'weight',
73
+ 'isNew',
74
+ 'categories',
75
+ 'attributes'
76
+ );
77
+
78
+ // Add the internal product fields to the database
79
+ foreach ($fields as $name)
80
+ {
81
+ // Get the value
82
+ $value = $product->$name();
83
+
84
+ // Get the attributes of the attributes
85
+ if ($name == 'attributes') $value = $value->attributes();
86
+
87
+ if (is_bool($value))
88
+ {
89
+ $element->addChild($name, htmlspecialchars(html_entity_decode($value ? 'yes' : 'no')));
90
+ continue;
91
+ }
92
+ elseif (!is_array($value))
93
+ {
94
+ $element->addChild($name, htmlspecialchars(html_entity_decode((string)$value)));
95
+ continue;
96
+ }
97
+
98
+ // We have an array here
99
+
100
+ // Add an element, to bundle all the elements of the array
101
+ $node = $element->addChild($name);
102
+
103
+ // we have an array here
104
+ foreach ($value as $key => $attribute)
105
+ {
106
+ // prepare the key
107
+ if (is_numeric($key)) $key = 'items';
108
+ else $key = str_replace(' ', '_', $key);
109
+
110
+ // special treatment for categories and empty values
111
+ if ($name == 'categories') $attribute = implode(' > ', $attribute);
112
+ elseif (trim($attribute) === '') continue;
113
+
114
+ // Add the child
115
+ $node->addChild($key, htmlspecialchars(html_entity_decode((string)$attribute)));
116
+ }
117
+ }
118
+ }
119
+
120
+ return $xml;
121
+ }
122
+
123
+ /**
124
+ * Prepare response based on the given XML object
125
+ *
126
+ * @param SimpleXMLElement $xml
127
+ */
128
+ private function _prepareResponse(SimpleXMLElement $xml)
129
+ {
130
+ $response = $this->getResponse();
131
+
132
+ //set correct header
133
+ $response->setHeader('Content-Type', 'text/xml', true);
134
+
135
+ //clear anything another controller may have set
136
+ $response->clearBody();
137
+
138
+ //send headers
139
+ $response->sendHeaders();
140
+
141
+ //set xml content
142
+ $response->setBody($xml->asXML());
143
+ }
144
+
145
+ /**
146
+ * Retrieves a product
147
+ *
148
+ * @param int $productId
149
+ * @return Mage_Catalog_Model_Product
150
+ */
151
+ private function _getProduct($productId)
152
+ {
153
+ $product = Mage::getModel('catalog/product')
154
+ ->load($productId);
155
+
156
+ // only a product with an id exists
157
+ return $product->getId() ? $product : null;
158
+ }
159
+ }
app/code/community/Copernica/MarketingSoftware/controllers/UnsubscribeController.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Copernica_MarketingSoftware_UnsubscribeController extends Mage_Core_Controller_Front_Action
3
+ {
4
+ /**
5
+ * Handles a request to copernica/unsubscribe/process
6
+ */
7
+ public function processAction()
8
+ {
9
+ // Get the post
10
+ $post = $this->getRequest()->getPost();
11
+
12
+ // there are parameters and they can be json decoded
13
+ if (isset($post['json']) && $data = json_decode($post['json']))
14
+ {
15
+ // Get the linked customer fields
16
+ $fields = Mage::helper('marketingsoftware/config')->getLinkedCustomerFields();
17
+
18
+ // is the 'newsletter' field given
19
+ if (isset($data->parameters) && $data->parameters->$fields['newsletter'] == 'unsubscribed_copernica')
20
+ {
21
+ // get the customer id
22
+ $customerID = $data->profile->fields->customer_id;
23
+ $customer = Mage::getModel('customer/customer')->load($customerID);
24
+ $email = $data->profile->fields->$fields['email'];
25
+
26
+ // Get the subscriber
27
+ $subscriber = Mage::getModel('newsletter/subscriber');
28
+ if (
29
+ $subscriber->loadByCustomer($customer)->getId() ||
30
+ $subscriber->loadByEmail($email)->getId()
31
+ ) {
32
+ // we have a valid subscriber object now, so unsubscribe the user
33
+ $subscriber->setSubscriberStatus(Mage_Newsletter_Model_Subscriber::STATUS_UNSUBSCRIBED)->save();
34
+ echo 'ok';
35
+ return;
36
+ }
37
+ }
38
+ }
39
+ echo 'not ok';
40
+ }
41
+ }
app/code/community/Copernica/MarketingSoftware/etc/adminhtml.xml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <menu>
3
+ <copernica translate="title" module="marketingsoftware">
4
+ <title>Copernica</title>
5
+ <sort_order>120</sort_order>
6
+ <depends>
7
+ <module>Copernica_MarketingSoftware</module>
8
+ </depends>
9
+ <children>
10
+ <settings translate="title" module="marketingsoftware">
11
+ <title>Account Settings</title>
12
+ <action>*/marketingsoftware_settings</action>
13
+ </settings>
14
+ <links translate="title" module="marketingsoftware">
15
+ <title>Link Fields</title>
16
+ <action>*/marketingsoftware_link</action>
17
+ </links>
18
+ <export translate="title" module="marketingsoftware">
19
+ <title>Synchronize Data</title>
20
+ <action>*/marketingsoftware_export</action>
21
+ </export>
22
+ </children>
23
+ </copernica>
24
+ </menu>
25
+ <acl>
26
+ <resources>
27
+ <admin>
28
+ <children>
29
+ <copernica translate="title" module="marketingsoftware">
30
+ <title>Copernica Marketing Software</title>
31
+ <sort_order>120</sort_order>
32
+ <children>
33
+ <settings translate="title">
34
+ <title>Settings</title>
35
+ </settings>
36
+ <links translate="title">
37
+ <title>Link Fields</title>
38
+ </links>
39
+ <export translate="title">
40
+ <title>Synchronize Data</title>
41
+ </export>
42
+ </children>
43
+ </copernica>
44
+ </children>
45
+ </admin>
46
+ </resources>
47
+ </acl>
48
+ </config>
app/code/community/Copernica/MarketingSoftware/etc/config.xml ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Copernica_MarketingSoftware>
5
+ <version>1.2.4</version>
6
+ </Copernica_MarketingSoftware>
7
+ </modules>
8
+ <global>
9
+ <models>
10
+ <marketingsoftware>
11
+ <class>Copernica_MarketingSoftware_Model</class>
12
+ <resourceModel>marketingsoftware_mysql4</resourceModel>
13
+ </marketingsoftware>
14
+ <marketingsoftware_mysql4>
15
+ <class>Copernica_MarketingSoftware_Model_Mysql4</class>
16
+ <entities>
17
+ <queue>
18
+ <table>copernica_queue</table>
19
+ </queue>
20
+ <marketingsoftware>
21
+ <table>copernica_marketingsoftware</table>
22
+ </marketingsoftware>
23
+ </entities>
24
+ </marketingsoftware_mysql4>
25
+ </models>
26
+ <events>
27
+ <checkout_controller_onepage_save_shipping_method>
28
+ <observers>
29
+ <marketingsoftware_observer>
30
+ <class>marketingsoftware/observer</class>
31
+ <method>checkoutSaveStep</method>
32
+ </marketingsoftware_observer>
33
+ </observers>
34
+ </checkout_controller_onepage_save_shipping_method>
35
+ <checkout_controller_multishipping_shipping_post>
36
+ <observers>
37
+ <marketingsoftware_observer>
38
+ <class>marketingsoftware/observer</class>
39
+ <method>checkoutSaveStep</method>
40
+ </marketingsoftware_observer>
41
+ </observers>
42
+ </checkout_controller_multishipping_shipping_post>
43
+ <sales_quote_item_delete_before>
44
+ <observers>
45
+ <marketingsoftware_observer>
46
+ <class>marketingsoftware/observer</class>
47
+ <method>quoteItemRemoved</method>
48
+ </marketingsoftware_observer>
49
+ </observers>
50
+ </sales_quote_item_delete_before>
51
+ <sales_quote_item_save_after>
52
+ <observers>
53
+ <marketingsoftware_observer>
54
+ <class>marketingsoftware/observer</class>
55
+ <method>quoteItemModified</method>
56
+ </marketingsoftware_observer>
57
+ </observers>
58
+ </sales_quote_item_save_after>
59
+ <sales_order_save_after>
60
+ <observers>
61
+ <marketingsoftware_observer>
62
+ <class>marketingsoftware/observer</class>
63
+ <method>orderModified</method>
64
+ </marketingsoftware_observer>
65
+ </observers>
66
+ </sales_order_save_after>
67
+ <newsletter_subscriber_delete_before>
68
+ <observers>
69
+ <marketingsoftware_observer>
70
+ <class>marketingsoftware/observer</class>
71
+ <method>newsletterSubscriptionRemoved</method>
72
+ </marketingsoftware_observer>
73
+ </observers>
74
+ </newsletter_subscriber_delete_before>
75
+ <newsletter_subscriber_save_after>
76
+ <observers>
77
+ <marketingsoftware_observer>
78
+ <class>marketingsoftware/observer</class>
79
+ <method>newsletterSubscriptionModified</method>
80
+ </marketingsoftware_observer>
81
+ </observers>
82
+ </newsletter_subscriber_save_after>
83
+ <customer_delete_before>
84
+ <observers>
85
+ <marketingsoftware_observer>
86
+ <class>marketingsoftware/observer</class>
87
+ <method>customerRemoved</method>
88
+ </marketingsoftware_observer>
89
+ </observers>
90
+ </customer_delete_before>
91
+ <customer_save_after>
92
+ <observers>
93
+ <marketingsoftware_observer>
94
+ <class>marketingsoftware/observer</class>
95
+ <method>customerModified</method>
96
+ </marketingsoftware_observer>
97
+ </observers>
98
+ </customer_save_after>
99
+ </events>
100
+ <resources>
101
+ <marketingsoftware_setup>
102
+ <setup>
103
+ <module>Copernica_MarketingSoftware</module>
104
+ </setup>
105
+ <connection>
106
+ <use>core_setup</use>
107
+ </connection>
108
+ </marketingsoftware_setup>
109
+ <marketingsoftware_write>
110
+ <connection>
111
+ <use>core_write</use>
112
+ </connection>
113
+ </marketingsoftware_write>
114
+ <marketingsoftware_read>
115
+ <connection>
116
+ <use>core_read</use>
117
+ </connection>
118
+ </marketingsoftware_read>
119
+ </resources>
120
+ <blocks>
121
+ <marketingsoftware>
122
+ <class>Copernica_MarketingSoftware_Block</class>
123
+ </marketingsoftware>
124
+ </blocks>
125
+ <helpers>
126
+ <marketingsoftware>
127
+ <class>Copernica_MarketingSoftware_Helper</class>
128
+ </marketingsoftware>
129
+ </helpers>
130
+ </global>
131
+ <frontend>
132
+ <routers>
133
+ <marketingsoftware>
134
+ <use>standard</use>
135
+ <args>
136
+ <module>Copernica_MarketingSoftware</module>
137
+ <frontName>copernica</frontName>
138
+ </args>
139
+ </marketingsoftware>
140
+ </routers>
141
+ </frontend>
142
+ <admin>
143
+ <routers>
144
+ <adminhtml>
145
+ <args>
146
+ <modules>
147
+ <Copernica_MarketingSoftware after="Mage_Adminhtml">Copernica_MarketingSoftware_Adminhtml</Copernica_MarketingSoftware>
148
+ </modules>
149
+ </args>
150
+ </adminhtml>
151
+ </routers>
152
+ </admin>
153
+ <crontab>
154
+ <jobs>
155
+ <marketingsoftware_process_queue>
156
+ <schedule><cron_expr>*/5 * * * *</cron_expr></schedule>
157
+ <run><model>marketingsoftware/observer::processQueue</model></run>
158
+ </marketingsoftware_process_queue>
159
+ </jobs>
160
+ </crontab>
161
+ </config>
app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-install-1.2.0.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+ /* @var $installer Mage_Core_Model_Resource_Setup */
4
+
5
+ $installer->startSetup();
6
+
7
+ $installer->run("
8
+ DROP TABLE IF EXISTS `{$installer->getTable('marketingsoftware/queue')}`;
9
+ CREATE TABLE `{$installer->getTable('marketingsoftware/queue')}` (
10
+ `id` int(10) unsigned NOT NULL auto_increment,
11
+ `object` text NOT NULL,
12
+ `action` enum('add', 'remove', 'modify','full', 'start_sync') NOT NULL DEFAULT 'modify',
13
+ `queue_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
14
+ `result` text NULL,
15
+ `result_time` timestamp NULL,
16
+ PRIMARY KEY (`id`)
17
+ ) ENGINE=InnoDB default CHARSET=utf8;
18
+ ");
19
+
20
+ $installer->endSetup();
app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.5-1.1.6.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Upgrader from version 1.1.5 to 1.1.6
4
+ * Copernica Marketing Software v 1.1.8
5
+ * October 2010
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ $installer = $this;
10
+ $installer->startSetup();
11
+
12
+ $installer->run("
13
+ ALTER TABLE {$installer->getTable('copernica_marketingsoftware')}
14
+ ADD extensionversion VARCHAR(250) NOT NULL;
15
+
16
+ UPDATE {$installer->getTable('copernica_marketingsoftware')}
17
+ SET `extensionversion` = '1.1.6'
18
+ WHERE 1 = 1;
19
+ ");
20
+
21
+ $installer->endSetup();
app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.6-1.1.7.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Upgrader from version 1.1.5 to 1.1.6
4
+ * Copernica Marketing Software v 1.1.8
5
+ * October 2010
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ $installer = $this;
10
+ $installer->startSetup();
11
+
12
+ $installer->run("
13
+ UPDATE {$installer->getTable('copernica_marketingsoftware')}
14
+ SET `extensionversion` = '1.1.7'
15
+ WHERE 1 = 1;
16
+ ");
17
+
18
+ $installer->endSetup();
app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.7-1.1.8.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Upgrader from version 1.1.7 to 1.1.8
4
+ * Copernica Marketing Software v 1.1.8
5
+ * October 2010
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ $installer = $this;
10
+ $installer->startSetup();
11
+
12
+ $installer->run("
13
+ ALTER TABLE {$installer->getTable('copernica_marketingsoftware')}
14
+ ADD login_valid ENUM('yes', 'no') NOT NULL default 'yes',
15
+ ADD linked_fields_valid ENUM('yes', 'no') NOT NULL default 'no',
16
+ ADD `addressfields` TEXT NOT NULL,
17
+ ADD `addresscollectionname` VARCHAR(250) NOT NULL default 'Addresses',
18
+ MODIFY COLUMN progressstatus VARCHAR(250) NOT NULL default 'none',
19
+ DROP COLUMN extensionversion;
20
+
21
+ UPDATE {$installer->getTable('copernica_marketingsoftware')}
22
+ SET progressstatus = 'none', addresscollectionname = '';
23
+ ");
24
+
25
+ $installer->endSetup();
app/code/community/Copernica/MarketingSoftware/sql/marketingsoftware_setup/mysql4-upgrade-1.1.8-1.2.0.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Upgrader from version 1.1.7 to 1.1.8
4
+ * Copernica Marketing Software v 1.1.8
5
+ * October 2010
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ $installer = $this;
10
+ $installer->startSetup();
11
+
12
+ $installer->run("
13
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
14
+ SELECT 'marketingsoftware/hostname', hostname
15
+ FROM {$installer->getTable('copernica_marketingsoftware')}
16
+ WHERE marketingsoftware_id = 1;
17
+
18
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
19
+ SELECT 'marketingsoftware/username', username
20
+ FROM {$installer->getTable('copernica_marketingsoftware')}
21
+ WHERE marketingsoftware_id = 1;
22
+
23
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
24
+ SELECT 'marketingsoftware/password', password
25
+ FROM {$installer->getTable('copernica_marketingsoftware')}
26
+ WHERE marketingsoftware_id = 1;
27
+
28
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
29
+ SELECT 'marketingsoftware/account', account
30
+ FROM {$installer->getTable('copernica_marketingsoftware')}
31
+ WHERE marketingsoftware_id = 1;
32
+
33
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
34
+ SELECT 'marketingsoftware/database', `database`
35
+ FROM {$installer->getTable('copernica_marketingsoftware')}
36
+ WHERE marketingsoftware_id = 1;
37
+
38
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
39
+ SELECT 'marketingsoftware/linked_customer_fields', customerfields
40
+ FROM {$installer->getTable('copernica_marketingsoftware')}
41
+ WHERE marketingsoftware_id = 1;
42
+
43
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
44
+ SELECT 'marketingsoftware/orders_collection_name', orderscollectionname
45
+ FROM {$installer->getTable('copernica_marketingsoftware')}
46
+ WHERE marketingsoftware_id = 1;
47
+
48
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
49
+ SELECT 'marketingsoftware/linked_order_fields', orderfields
50
+ FROM {$installer->getTable('copernica_marketingsoftware')}
51
+ WHERE marketingsoftware_id = 1;
52
+
53
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
54
+ SELECT 'marketingsoftware/address_collection_name', addresscollectionname
55
+ FROM {$installer->getTable('copernica_marketingsoftware')}
56
+ WHERE marketingsoftware_id = 1;
57
+
58
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
59
+ SELECT 'marketingsoftware/linked_address_fields', addressfields
60
+ FROM {$installer->getTable('copernica_marketingsoftware')}
61
+ WHERE marketingsoftware_id = 1;
62
+
63
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
64
+ SELECT 'marketingsoftware/order_items_collection_name', productcollectionname
65
+ FROM {$installer->getTable('copernica_marketingsoftware')}
66
+ WHERE marketingsoftware_id = 1;
67
+
68
+ INSERT INTO `{$installer->getTable('core_config_data')}` (path, value)
69
+ SELECT 'marketingsoftware/linked_order_item_fields', productfields
70
+ FROM {$installer->getTable('copernica_marketingsoftware')}
71
+ WHERE marketingsoftware_id = 1;
72
+
73
+ DROP TABLE IF EXISTS `{$installer->getTable('marketingsoftware/queue')}`;
74
+
75
+ CREATE TABLE `{$installer->getTable('marketingsoftware/queue')}` (
76
+ `id` int(10) unsigned NOT NULL auto_increment,
77
+ `object` text NOT NULL,
78
+ `action` enum('add', 'remove', 'modify', 'full', 'start_sync') NOT NULL DEFAULT 'modify',
79
+ `queue_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
80
+ `result` text NULL,
81
+ `result_time` timestamp NULL,
82
+ PRIMARY KEY (`id`)
83
+ ) ENGINE=InnoDB default CHARSET=utf8;
84
+ ");
85
+
86
+ $installer->endSetup();
app/design/adminhtml/default/default/template/marketingsoftware/export.phtml ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * View for Export controller
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ $_helper = Mage::helper('marketingsoftware');
10
+ $_config = Mage::helper('marketingsoftware/config');
11
+ $_collection = Mage::getResourceModel('marketingsoftware/queue_collection');
12
+ $_general_config = Mage::getConfig();
13
+ $_core = Mage::helper('core');
14
+
15
+ // format some dates
16
+ $oldestRecordTime = $_collection->getQueueStartTime();
17
+ $printableOldestRecordTime = $oldestRecordTime ? $_core->formatDate($oldestRecordTime, 'short', true) : "No records in queue";
18
+ $lastStartTime = $_config->getLastStartTimeCronjob();
19
+ $printableLastStartTime = $lastStartTime ? $_core->formatDate($lastStartTime, 'short', true) : "Never started";
20
+ $lastEndTime = $_config->getLastEndTimeCronjob();
21
+ $printableLastEndTime = $lastEndTime ? $_core->formatDate($lastEndTime, 'short', true) : "Never finished";
22
+
23
+ // is there a queue?
24
+ $queueLength = $_collection->getSize();
25
+ $open = $queueLength > 0;
26
+
27
+ ?>
28
+ <!-- javascript loader for sync process -->
29
+ <script type="text/javascript">
30
+
31
+ // on page loader
32
+ Event.observe(window, 'load', timeoutSync, false);
33
+
34
+ // define a timer variabile
35
+ var timer;
36
+
37
+ // sync status loop
38
+ function timeoutSync()
39
+ {
40
+ var url = <?php echo(json_encode($this->getIframeUrl())); ?>;
41
+ var div = $('sync');
42
+ new Ajax.Request(url, {
43
+ method: 'post',
44
+ onLoading: function() {
45
+ $('loading-mask', 'loading_mask_loader').invoke('hide');
46
+ },
47
+ onComplete: function(answer) {
48
+ div.innerHTML = answer.responseText;
49
+ }});
50
+
51
+ // set the timeout
52
+ timer = setTimeout("timeoutSync()", 10000);
53
+ }
54
+ </script>
55
+ <!-- end of loader -->
56
+
57
+ <div class="content-header">
58
+ <h3 class="icon-head head-system-account">Copernica Marketing Software : Synchronize Data</h3>
59
+ <p class="form-buttons"><button type="button" onclick="cpgForm.submit();" name="cp_export" id="cp_export">Synchronize Data</button></p>
60
+ <!-- <div style="float: rightbackground-color: #CCCCCC; padding: 2px 8px; color: white; font-weight: bold">Synchronize Data</div> -->
61
+ </div>
62
+ <div class="entry-edit">
63
+ <form action="<?php echo $this->getPostUrl(); ?>" method="post" name="cp_form_get" id="cp_form_get">
64
+ <?php echo $this->getBlockHtml('formkey'); ?>
65
+ <div class="entry-edit-head collapseable">
66
+ <h4 class="icon-head head-edit-form fieldset-legend">Export customers and their orders</h4>
67
+ <a href="#" onclick ="document.getElementById('export_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
68
+ </div>
69
+ <div class="fieldset collapseable">
70
+ <div class="hor-scroll">
71
+ <input type="hidden" id="cp_securitycheck" name="cp_securitycheck" value="export_data_only_when_needed">
72
+ <div id="sync">Loading...</div>
73
+ </div>
74
+ </div>
75
+ </form>
76
+
77
+ <div class="entry-edit-head collapseable">
78
+ <a id="debug_info-head" <?php if ($open) echo "class=\"open\""; ?> onclick="Fieldset.toggleCollapse('debug_info'); return false;" href="#">Debug information</a>
79
+ </div>
80
+ <input id="debug_info-state" type="hidden" <?php if($open) echo "value=\"1\""; ?> name="config_state[debug_info]">
81
+ <div class="fieldset collapseable" id="debug_info" style="<?php if (!$open) echo "display:none"; ?>">
82
+ <div class="hor-scroll">
83
+ <table cellspacing="0" class="form-list">
84
+ <tbody>
85
+ <tr>
86
+ <td class="label">Plug-in enabled: </td>
87
+ <td class="value"><strong><?php echo $_helper->enabled() ? "Yes" : "No";?></strong></td>
88
+ </tr>
89
+ <tr>
90
+ <td class="label">Queue length: </td>
91
+ <td class="value"><strong><?php echo $queueLength;?></strong></td>
92
+ </tr>
93
+ <tr>
94
+ <td class="label">Last time cronjob started: </td>
95
+ <td class="value"><strong><?php echo $printableLastStartTime;?></strong></td>
96
+ </tr>
97
+ <tr>
98
+ <td class="label">Last time cronjob finished: </td>
99
+ <td class="value"><strong><?php echo $printableLastEndTime;?></strong></td>
100
+ </tr>
101
+ <tr>
102
+ <td class="label">Proccesed task(s) in last run: </td>
103
+ <td class="value"><strong><?php echo $_config->getLastCronjobProcessedTasks();?></strong></td>
104
+ </tr>
105
+ <?php if ($queueLength > 0)
106
+ {
107
+ ?>
108
+ <tr>
109
+ <td class="label">Synchronization start scheduled: </td>
110
+ <td class="value"><strong><?php echo $_helper->isSynchronisationStartScheduled() ? "Yes" : "No";?></strong></td>
111
+ </tr>
112
+ <tr>
113
+ <td class="label">Oldest queue-ed change: </td>
114
+ <td class="value"><strong><?php echo $printableOldestRecordTime;?></strong></td>
115
+ </tr>
116
+ <tr>
117
+ <td class="label">Oldest warning: </td>
118
+ <td class="value"><strong><?php echo ($result = $_collection->getOldestResult()) ? $result : '<i>No problems occured</i>';?></strong></td>
119
+ </tr>
120
+ <?php
121
+ }
122
+ ?>
123
+ </tbody>
124
+ </table>
125
+ </div>
126
+ </div>
127
+
128
+ <div class="entry-edit-head collapseable">
129
+ <h4 class="icon-head head-edit-form fieldset-legend">Environment Information</h4>
130
+ </div>
131
+ <div class="fieldset collapseable">
132
+ <div class="hor-scroll">
133
+ <table cellspacing="0" class="form-list">
134
+ <tbody>
135
+ <tr>
136
+ <td class="label">Copernica extension version: </td>
137
+ <td class="value"><strong><?php echo $_helper->getExtensionVersion();?></strong></td>
138
+ </tr>
139
+ <tr>
140
+ <td class="label">Magento webshop version: </td>
141
+ <td class="value"><strong><?php echo Mage::getVersion();?></strong></td>
142
+ </tr>
143
+ </tbody>
144
+ </table>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ <!-- export help -->
149
+ <div id="export_help" style="display: none; position: absolute; top: 20%; left: 25%; width: 650px; height: 425px; padding: 20px; border: 1px solid black; z-index:1002;background-color: #FDFAB1; color: black;">
150
+ <h3 style="text-align: center;">Synchronize Data HOW-TO</h3>
151
+ Synchronize existing Magento data (Customers, Orders - including the Ordered Products) with the Copernica Database.
152
+ <br/><br/>
153
+ To export current Magento data to your Copernica Database, press the "Synchronize Data" button, which can be found in the top-right corner.
154
+ <br/><br/>
155
+ This will export all Magento Customers to the Copernica Profiles, all Magento Orders to the Copernica Orders Collection and all Magento Orderd Products to the Copernica Products Collection.
156
+ <br/><br/>
157
+ A timestamp is attached to the last synchronization operation and displayed in the "Last synchronization was completed on :" message, on this page. This way, you can keep track of your past synchronizations.
158
+ <br/><br/>
159
+ A synchronization in progress will lock the system for further launches of the "Synchronize Data" operation, until the current operation is successfully completed.
160
+ <br/><br/>
161
+ [+] If, for some reason, the synchronization operation doesn't respond anymore, you can reset its status by going to the "Account Settings" submenu under the "Copernica Marketing Software" menu and click the "Save connection settings" button, which can be found in top-right corner.
162
+ <br/><br/>
163
+ [+] We recommend running this feature only when you first install the extension.
164
+ <br/><br/>
165
+ [+] After the Copernica Database is synchronized with the Magento Data, further Magento Data, coming from live customer's actions, are automatically exported to the Copernica Database by the extension itself.
166
+ <br/>
167
+ <a href="#" onclick="document.getElementById('export_help').style.display='none';" style="top:0; right:6px; position: absolute; return false;">Close</a>
168
+ </div>
169
+
170
+ <script type="text/javascript">
171
+ //<![CDATA[
172
+ cpgForm = new varienForm('cp_form_get', '');
173
+ //]]>
174
+ </script>
app/design/adminhtml/default/default/template/marketingsoftware/link.phtml ADDED
@@ -0,0 +1,666 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * View for Link controller
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+ $_helper = Mage::helper('marketingsoftware');
9
+ $_config = Mage::helper('marketingsoftware/config') ?>
10
+
11
+ <div class="content-header">
12
+ <h3 class="icon-head head-system-account">Copernica Marketing Software : Link Fields</h3>
13
+ <p class="content-buttons">
14
+ <span id="cp_warning_notice" style="color: white; font-weight: bold; padding: 2px 4px; background-color: #CC3300; border: thin solid #660000; display:none;">Warning: the field settings are not valid !</span>
15
+ <span id="cp_save_notice" style="color: white; font-weight: bold; padding: 2px 4px; background-color: #188F11; border: thin solid #660000; display:none;">Warning: the settings are not yet saved !</span>
16
+ <button type="button" onclick="cpProfileCollectionForm.submit();" name="cp_pc_save" id="cp_pc_save">Save profile and collections settings</button>
17
+ </p>
18
+ </div>
19
+
20
+ <div class="entry-edit">
21
+
22
+ <!-- fields linking form. -->
23
+ <form action="<?php echo $this->getPostUrl(); ?>" method="post" name="cp_profile_collection" id="cp_profile_collection">
24
+ <?php echo $this->getBlockHtml('formkey'); ?>
25
+
26
+ <!-- database checker section. -->
27
+ <div class="entry-edit-head">
28
+ <h4 class="icon-head head-edit-form fieldset-legend">Database</h4>
29
+ <a href="#" onclick ="document.getElementById('database_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
30
+ </div>
31
+ <div class="fieldset">
32
+ <div class="hor-scroll">
33
+ <table cellspacing="0" class="form-list">
34
+ <tbody>
35
+ <tr>
36
+ <td class="value">Name</td>
37
+ <td class="value">Status</td>
38
+ </tr>
39
+ <tr>
40
+ <td class="value">
41
+ <input type="text" class="input-text" value="<?php echo(htmlspecialchars($_config->getDatabaseName())); ?>" name="db_input" id="db_input"/>
42
+ </td>
43
+ <td class="value">
44
+ <span style="display:none;" id="db_checking">Checking database....</span>
45
+ <span style="display:none;" id="db_impossible">Database can not be checked.</span>
46
+ <span style="display:none;" id="db_notexists">Database does not exist. <a href="javascript:database.create()">Create database.</a></span>
47
+ <span style="display:none;" id="db_notvalid">Database structure not valid. <a href="javascript:database.repair()">Fix structure.</a></span>
48
+ <span style="display:none;" id="db_ok">Database exists.</span>
49
+ </td>
50
+ </tr>
51
+ </tbody>
52
+ </table>
53
+ </div>
54
+ </div>
55
+ <!-- end of database checker section. -->
56
+
57
+ <!-- first section: customer profiles. -->
58
+ <div class="entry-edit-head">
59
+ <h4 class="icon-head head-edit-form fieldset-legend" id="customers_profiles_label" name="customers_profiles_label">Customers Profiles</h4>
60
+ <a href="#" onclick ="document.getElementById('profiles_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
61
+ </div>
62
+
63
+ <div class="fieldset">
64
+ <div class="hor-scroll">
65
+ <table cellspacing="0" class="form-list">
66
+ <tbody>
67
+ <tr>
68
+ <td class="value">Magento field</td>
69
+ <td class="value">Copernica link</td>
70
+ <td class="value">Copernica field</td>
71
+ <td class="value">Status</td>
72
+ </tr>
73
+ <?php
74
+ // get the linked Customer fields
75
+ $linkedFields = $_config->getLinkedCustomerFields();
76
+ $customerFields = array();
77
+
78
+ foreach ($_helper->supportedCustomerFields() as $magentoField => $label)
79
+ {
80
+ // Get the field which is used in Copernica
81
+ $copernicaField = isset($linkedFields[$magentoField]) ? $linkedFields[$magentoField] : '';
82
+
83
+ // append a prefix to the customer
84
+ $magentoField = 'customer_'.$magentoField;
85
+
86
+ // Create an array for using in javascript
87
+ $customerFields[$magentoField] = $copernicaField;
88
+
89
+ // Name for the dropdown field, and name for the textfield
90
+ $dropdown_name = "select_$magentoField";
91
+ $textfield_name = "input_$magentoField";
92
+ ?>
93
+ <tr>
94
+ <td class="value">
95
+ <input type="text" class="input-text disabled" value="<?php echo(htmlspecialchars($label)); ?>" name="<?php echo(htmlspecialchars($label)); ?>" disabled="disabled" />
96
+ </td>
97
+ <td class="value">
98
+ <select class="select" id="<?php echo htmlspecialchars($dropdown_name); ?>" name="<?php echo htmlspecialchars($dropdown_name); ?>">
99
+ <option value="0">Don't link</option>
100
+ <option value="1" <?php if ($copernicaField != '') echo "selected='selected'"; ?>>Create link</option>
101
+ <option value="2">Use default name</option>
102
+ </select>
103
+ </td>
104
+ <td class="value">
105
+ <input type="text" class="input-text " value="<?php echo htmlspecialchars($copernicaField); ?>" name="<?php echo htmlspecialchars($textfield_name); ?>" id="<?php echo htmlspecialchars($textfield_name); ?>" <?php if ($copernicaField == '') echo "style='display: none;'"; ?>>
106
+ </td>
107
+ <td class="value">
108
+ <span style="display:none;" id="checking_<?php echo $magentoField; ?>">Checking field....</span>
109
+ <span style="display:none;" id="impossible_<?php echo $magentoField; ?>">Field cannot be checked.</span>
110
+ <span style="display:none;" id="notexists_<?php echo $magentoField; ?>">Field does not exist. <a href="javascript:database.field('<?php echo $magentoField; ?>').create()">Create field.</a></span>
111
+ <span style="display:none;" id="notlinked_<?php echo $magentoField; ?>">Field is not linked.</a></span>
112
+ <span style="display:none;" id="notvalid_<?php echo $magentoField; ?>">Field is not valid. <a href="javascript:database.field('<?php echo $magentoField; ?>').repair()">Repair field.</a></span>
113
+ <span style="display:none;" id="ok_<?php echo $magentoField; ?>">Field exists.</span>
114
+ </td>
115
+ </tr>
116
+ <?php
117
+ }
118
+ ?>
119
+ </tbody>
120
+ </table>
121
+ </div>
122
+ </div>
123
+ <!-- end of first section. -->
124
+
125
+ <!-- second section: cart products collection. -->
126
+ <div class="entry-edit-head">
127
+ <h4 class="icon-head head-edit-form fieldset-legend" id="edit_cartproducts_collection_current_label" name="edit_cartproducts_collection_current_label">Cart items Collection</h4>
128
+ <a href="#" onclick ="document.getElementById('collection_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
129
+ </div>
130
+ <div class="fieldset">
131
+ <div class="hor-scroll">
132
+ <table cellspacing="0" class="form-list">
133
+ <tbody>
134
+ <tr>
135
+ <td class="value">Collection name</td>
136
+ </tr>
137
+ <tr>
138
+ <td class="value">
139
+ <input type="text" class="input-text " title="Cart Products Collection" value="<?php echo(htmlspecialchars($_config->getCartItemsCollectionName())); ?>" name="cartproducts_input" id="cartproducts_input">
140
+ </td>
141
+ <td class="value">
142
+ <span style="display:none;" id="cartproducts_checking">Checking collection....</span>
143
+ <span style="display:none;" id="cartproducts_impossible">Collection cannot be checked.</span>
144
+ <span style="display:none;" id="cartproducts_notexists">Collection does not exist. <a href="javascript:database.cartItemsCollection.create()">Create collection.</a></span>
145
+ <span style="display:none;" id="cartproducts_notvalid">Collection structure not valid.<a href="javascript:database.cartItemsCollection.repair()">Repair collection.</a></span>
146
+ <span style="display:none;" id="cartproducts_ok">Collection exists.</span>
147
+ </td>
148
+ </tr>
149
+ </tbody>
150
+ </table>
151
+ </div>
152
+ </div>
153
+ <div class="fieldset">
154
+ <div class="hor-scroll">
155
+ <table cellspacing="0" class="form-list">
156
+ <tbody>
157
+ <tr>
158
+ <td class="value">Magento field</td>
159
+ <td class="value">Copernica link</td>
160
+ <td class="value">Copernica field</td>
161
+ <td class="value">Status</td>
162
+ </tr>
163
+ <?php
164
+ // get the linked Customer fields
165
+ $linkedFields = $_config->getLinkedCartItemFields();
166
+ $cartItemFields = array();
167
+
168
+ foreach ($_helper->supportedCartItemFields() as $magentoField => $label)
169
+ {
170
+ // Get the field which is used in Copernica
171
+ $copernicaField = isset($linkedFields[$magentoField]) ? $linkedFields[$magentoField] : '';
172
+
173
+ // append a prefix to the fieldname
174
+ $magentoField = 'cartproducts_'.$magentoField;
175
+
176
+ // append the data to the array
177
+ $cartItemFields[$magentoField] = $copernicaField;
178
+
179
+ // Name for the dropdown field, and name for the textfield
180
+ $dropdown_name = "select_$magentoField";
181
+ $textfield_name = "input_$magentoField";
182
+ ?>
183
+ <tr>
184
+ <td class="value">
185
+ <input type="text" class="input-text disabled" value="<?php echo(htmlspecialchars($label)); ?>" name="<?php echo(htmlspecialchars($label)); ?>" disabled="disabled" />
186
+ </td>
187
+ <td class="value">
188
+ <select class="select" id="<?php echo htmlspecialchars($dropdown_name); ?>" name="<?php echo htmlspecialchars($dropdown_name); ?>">
189
+ <option value="0">Don't link</option>
190
+ <option value="1" <?php if ($copernicaField != '') echo "selected='selected'"; ?>>Create link</option>
191
+ <option value="2">Use default name</option>
192
+ </select>
193
+ </td>
194
+ <td class="value">
195
+ <input type="text" class="input-text " value="<?php echo htmlspecialchars($copernicaField); ?>" name="<?php echo htmlspecialchars($textfield_name); ?>" id="<?php echo htmlspecialchars($textfield_name); ?>" <?php if ($copernicaField == '') echo "style='display: none;'"; ?>>
196
+ </td>
197
+ <td class="value">
198
+ <span style="display:none;" id="checking_<?php echo $magentoField; ?>">Checking field....</span>
199
+ <span style="display:none;" id="impossible_<?php echo $magentoField; ?>">Field cannot be checked.</span>
200
+ <span style="display:none;" id="notexists_<?php echo $magentoField; ?>">Field does not exist. <a href="javascript:database.cartItemsCollection.field('<?php echo $magentoField; ?>').create()">Create field.</a></span>
201
+ <span style="display:none;" id="notlinked_<?php echo $magentoField; ?>">Field is not linked.</a></span>
202
+ <span style="display:none;" id="notvalid_<?php echo $magentoField; ?>">Field is not valid. <a href="javascript:database.cartItemsCollection.field('<?php echo $magentoField; ?>').repair()">Repair field.</a></span>
203
+ <span style="display:none;" id="ok_<?php echo $magentoField; ?>">Field exists.</span>
204
+ </td>
205
+ </tr>
206
+ <?php
207
+ }
208
+ ?>
209
+ </tbody>
210
+ </table>
211
+ </div>
212
+ </div>
213
+ <!-- end of second section. -->
214
+
215
+ <!-- third section: orders collection. -->
216
+ <div class="entry-edit-head">
217
+ <h4 class="icon-head head-edit-form fieldset-legend" id="edit_orders_collection_current_label" name="edit_orders_collection_current_label">Orders Collection</h4>
218
+ <a href="#" onclick ="document.getElementById('collection_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
219
+ </div>
220
+ <div class="fieldset">
221
+ <div class="hor-scroll">
222
+ <table cellspacing="0" class="form-list">
223
+ <tbody>
224
+ <tr>
225
+ <td class="value">Collection name</td>
226
+ </tr>
227
+ <tr>
228
+ <td class="value">
229
+ <input type="text" class="input-text " title="Completed Orders Collection" value="<?php echo(htmlspecialchars($_config->getOrdersCollectionName())); ?>" name="orders_input" id="orders_input">
230
+ </td>
231
+ <td class="value">
232
+ <span style="display:none;" id="orders_checking">Checking collection....</span>
233
+ <span style="display:none;" id="orders_impossible">Collection cannot be checked.</span>
234
+ <span style="display:none;" id="orders_notexists">Collection does not exist. <a href="javascript:database.ordersCollection.create()">Create collection.</a></span>
235
+ <span style="display:none;" id="orders_notvalid">Collection structure not valid.<a href="javascript:database.ordersCollection.repair()">Repair collection.</a></span>
236
+ <span style="display:none;" id="orders_ok">Collection exists.</span>
237
+ </td>
238
+ </tr>
239
+ </tbody>
240
+ </table>
241
+ </div>
242
+ </div>
243
+ <div class="fieldset">
244
+ <div class="hor-scroll">
245
+ <table cellspacing="0" class="form-list">
246
+ <tbody>
247
+ <tr>
248
+ <td class="value">Magento field</td>
249
+ <td class="value">Copernica link</td>
250
+ <td class="value">Copernica field</td>
251
+ <td class="value">Status</td>
252
+ </tr>
253
+ <?php
254
+ // get the linked Customer fields
255
+ $linkedFields = $_config->getLinkedOrderFields();
256
+ $orderFields = array();
257
+
258
+ foreach ($_helper->supportedOrderFields() as $magentoField => $label)
259
+ {
260
+ // Get the field which is used in Copernica
261
+ $copernicaField = isset($linkedFields[$magentoField]) ? $linkedFields[$magentoField] : '';
262
+
263
+ // append a prefix to the fieldname
264
+ $magentoField = 'orders_'.$magentoField;
265
+
266
+ // Construct an array for use in the javascript array
267
+ $orderFields[$magentoField] = $copernicaField;
268
+
269
+ // Name for the dropdown field, and name for the textfield
270
+ $dropdown_name = "select_$magentoField";
271
+ $textfield_name = "input_$magentoField";
272
+ ?>
273
+ <tr>
274
+ <td class="value">
275
+ <input type="text" class="input-text disabled" value="<?php echo(htmlspecialchars($label)); ?>" name="<?php echo(htmlspecialchars($label)); ?>" disabled="disabled" />
276
+ </td>
277
+ <td class="value">
278
+ <select class="select" id="<?php echo htmlspecialchars($dropdown_name); ?>" name="<?php echo htmlspecialchars($dropdown_name); ?>">
279
+ <option value="0">Don't link</option>
280
+ <option value="1" <?php if ($copernicaField != '') echo "selected='selected'"; ?>>Create link</option>
281
+ <option value="2">Use default name</option>
282
+ </select>
283
+ </td>
284
+ <td class="value">
285
+ <input type="text" class="input-text " value="<?php echo htmlspecialchars($copernicaField); ?>" name="<?php echo htmlspecialchars($textfield_name); ?>" id="<?php echo htmlspecialchars($textfield_name); ?>" <?php if ($copernicaField == '') echo "style='display: none;'"; ?>>
286
+ </td>
287
+ <td class="value">
288
+ <span style="display:none;" id="checking_<?php echo $magentoField; ?>">Checking field....</span>
289
+ <span style="display:none;" id="impossible_<?php echo $magentoField; ?>">Field cannot be checked.</span>
290
+ <span style="display:none;" id="notexists_<?php echo $magentoField; ?>">Field does not exist. <a href="javascript:database.ordersCollection.field('<?php echo $magentoField; ?>').create()">Create field.</a></span>
291
+ <span style="display:none;" id="notlinked_<?php echo $magentoField; ?>">Field is not linked.</a></span>
292
+ <span style="display:none;" id="notvalid_<?php echo $magentoField; ?>">Field is not correct. <a href="javascript:database.ordersCollection.field('<?php echo $magentoField; ?>').repair()">Repair field.</a></a></span>
293
+ <span style="display:none;" id="ok_<?php echo $magentoField; ?>">Field exists.</span>
294
+ </td>
295
+ </tr>
296
+ <?php
297
+ }
298
+ ?>
299
+ </tbody>
300
+ </table>
301
+ </div>
302
+ </div>
303
+ <!-- end of third section. -->
304
+
305
+ <!-- fourth section: orders products collection. -->
306
+ <div class="entry-edit-head">
307
+ <h4 class="icon-head head-edit-form fieldset-legend" id="edit_orderproducts_collection_current_label" name="edit_orderproducts_collection_current_label">Order products Collection</h4>
308
+ <a href="#" onclick ="document.getElementById('collection_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
309
+ </div>
310
+ <div class="fieldset">
311
+ <div class="hor-scroll">
312
+ <table cellspacing="0" class="form-list">
313
+ <tbody>
314
+ <tr>
315
+ <td class="value">Collection name</td>
316
+ </tr>
317
+ <tr>
318
+ <td class="value">
319
+ <input type="text" class="input-text " title="Cart Products Collection" value="<?php echo(htmlspecialchars($_config->getOrderItemsCollectionName()))?>" name="orderproducts_input" id="orderproducts_input">
320
+ </td>
321
+ <td class="value">
322
+ <span style="display:none;" id="orderproducts_checking">Checking collection....</span>
323
+ <span style="display:none;" id="orderproducts_impossible">Collection cannot be checked.</span>
324
+ <span style="display:none;" id="orderproducts_notexists">Collection does not exist. <a href="javascript:database.orderItemsCollection.create()">Create collection.</a></span>
325
+ <span style="display:none;" id="orderproducts_notvalid">Collection structure not valid.<a href="javascript:database.orderItemsCollection.repair()">Repair collection.</a></span>
326
+ <span style="display:none;" id="orderproducts_ok">Collection exists.</span>
327
+ </td>
328
+ </tr>
329
+ </tbody>
330
+ </table>
331
+ </div>
332
+ </div>
333
+ <div class="fieldset">
334
+ <div class="hor-scroll">
335
+ <table cellspacing="0" class="form-list">
336
+ <tbody>
337
+ <tr>
338
+ <td class="value">Magento field</td>
339
+ <td class="value">Copernica link</td>
340
+ <td class="value">Copernica field</td>
341
+ <td class="value">Status</td>
342
+ </tr>
343
+ <?php
344
+ // get the linked Customer fields
345
+ $linkedFields = $_config->getLinkedOrderItemFields();
346
+ $orderItemFields = array();
347
+
348
+ foreach ($_helper->supportedOrderItemFields() as $magentoField => $label)
349
+ {
350
+ // Get the field which is used in Copernica
351
+ $copernicaField = isset($linkedFields[$magentoField]) ? $linkedFields[$magentoField] : '';
352
+
353
+ // append a prefix to the fieldname
354
+ $magentoField = 'orderproducts_'.$magentoField;
355
+
356
+ // Construct an array for use in the javascript array
357
+ $orderItemFields[$magentoField] = $copernicaField;
358
+
359
+ // Name for the dropdown field, and name for the textfield
360
+ $dropdown_name = "select_$magentoField";
361
+ $textfield_name = "input_$magentoField";
362
+ ?>
363
+ <tr>
364
+ <td class="value">
365
+ <input type="text" class="input-text disabled" value="<?php echo(htmlspecialchars($label)); ?>" name="<?php echo(htmlspecialchars($label)); ?>" disabled="disabled" />
366
+ </td>
367
+ <td class="value">
368
+ <select class="select" id="<?php echo htmlspecialchars($dropdown_name); ?>" name="<?php echo htmlspecialchars($dropdown_name); ?>">
369
+ <option value="0">Don't link</option>
370
+ <option value="1" <?php if ($copernicaField != '') echo "selected='selected'"; ?>>Create link</option>
371
+ <option value="2">Use default name</option>
372
+ </select>
373
+ </td>
374
+ <td class="value">
375
+ <input type="text" class="input-text " value="<?php echo htmlspecialchars($copernicaField); ?>" name="<?php echo htmlspecialchars($textfield_name); ?>" id="<?php echo htmlspecialchars($textfield_name); ?>" <?php if ($copernicaField == '') echo "style='display: none;'"; ?>>
376
+ </td>
377
+ <td class="value">
378
+ <span style="display:none;" id="checking_<?php echo $magentoField; ?>">Checking field....</span>
379
+ <span style="display:none;" id="impossible_<?php echo $magentoField; ?>">Field cannot be checked.</span>
380
+ <span style="display:none;" id="notexists_<?php echo $magentoField; ?>">Field does not exist. <a href="javascript:database.orderItemsCollection.field('<?php echo $magentoField; ?>').create()">Create field.</a></span>
381
+ <span style="display:none;" id="notlinked_<?php echo $magentoField; ?>">Field is not linked.</a></span>
382
+ <span style="display:none;" id="notvalid_<?php echo $magentoField; ?>">Field is not valid. <a href="javascript:database.orderItemsCollection.field('<?php echo $magentoField; ?>').repair()">Repair field.</a></span>
383
+ <span style="display:none;" id="ok_<?php echo $magentoField; ?>">Field exists.</span>
384
+ </td>
385
+ </tr>
386
+ <?php
387
+ }
388
+ ?>
389
+ </tbody>
390
+ </table>
391
+ </div>
392
+ </div>
393
+ <!-- end of fourth section. -->
394
+
395
+ <!-- fifth section: address collection. -->
396
+ <div class="entry-edit-head">
397
+ <h4 class="icon-head head-edit-form fieldset-legend" id="edit_addresses_collection_current_label" name="edit_addresscollection_current_label">Address Collection</h4>
398
+ <a href="#" onclick ="document.getElementById('collection_help').style.display='block'; return false;" id="page-help-link" style="float: right; line-height:18px;">More information</a>
399
+ </div>
400
+ <div class="fieldset">
401
+ <div class="hor-scroll">
402
+ <table cellspacing="0" class="form-list">
403
+ <tbody>
404
+ <tr>
405
+ <td class="value">Collection name</td>
406
+ </tr>
407
+ <tr>
408
+ <td class="value">
409
+ <input type="text" class="input-text " title="Completed Orders Collection" value="<?php echo(htmlspecialchars($_config->getAddressesCollectionName()))?>" name="addresses_input" id="addresses_input">
410
+ </td>
411
+ <td class="value">
412
+ <span style="display:none;" id="addresses_checking">Checking collection....</span>
413
+ <span style="display:none;" id="addresses_impossible">Collection cannot be checked.</span>
414
+ <span style="display:none;" id="addresses_notexists">Collection does not exist. <a href="javascript:database.addressCollection.create()">Create collection.</a></span>
415
+ <span style="display:none;" id="addresses_notvalid">Collection structure not valid.<a href="javascript:database.addressCollection.repair()">Repair collection.</a></span>
416
+ <span style="display:none;" id="addresses_ok">Collection exists.</span>
417
+ </td>
418
+ </tr>
419
+ </tbody>
420
+ </table>
421
+ </div>
422
+ </div>
423
+ <div class="fieldset">
424
+ <div class="hor-scroll">
425
+ <table cellspacing="0" class="form-list">
426
+ <tbody>
427
+ <tr>
428
+ <td class="value">Magento field</td>
429
+ <td class="value">Copernica link</td>
430
+ <td class="value">Copernica field</td>
431
+ <td class="value">Status</td>
432
+ </tr>
433
+ <?php
434
+ // get the linked Customer fields
435
+ $linkedFields = $_config->getLinkedAddressFields();
436
+
437
+ $addressFields = array();
438
+
439
+ foreach ($_helper->supportedAddressFields() as $magentoField => $label)
440
+ {
441
+ // Get the field which is used in Copernica
442
+ $copernicaField = isset($linkedFields[$magentoField]) ? $linkedFields[$magentoField] : '';
443
+
444
+ // append a prefix to the fieldname
445
+ $magentoField = 'addresses_'.$magentoField;
446
+
447
+ // Construct an array for use in the javascript array
448
+ $addressFields[$magentoField] = $copernicaField;
449
+
450
+ // Name for the dropdown field, and name for the textfield
451
+ $dropdown_name = "select_$magentoField";
452
+ $textfield_name = "input_$magentoField";
453
+ ?>
454
+ <tr>
455
+ <td class="value">
456
+ <input type="text" class="input-text disabled" value="<?php echo(htmlspecialchars($label)); ?>" name="<?php echo(htmlspecialchars($label)); ?>" disabled="disabled" />
457
+ </td>
458
+ <td class="value">
459
+ <select class="select" id="<?php echo htmlspecialchars($dropdown_name); ?>" name="<?php echo htmlspecialchars($dropdown_name); ?>">
460
+ <option value="0">Don't link</option>
461
+ <option value="1" <?php if ($copernicaField != '') echo "selected='selected'"; ?>>Create link</option>
462
+ <option value="2">Use default name</option>
463
+ </select>
464
+ </td>
465
+ <td class="value">
466
+ <input type="text" class="input-text " value="<?php echo htmlspecialchars($copernicaField); ?>" name="<?php echo htmlspecialchars($textfield_name); ?>" id="<?php echo htmlspecialchars($textfield_name); ?>" <?php if ($copernicaField == '') echo "style='display: none;'"; ?>>
467
+ </td>
468
+ <td class="value">
469
+ <span style="display:none;" id="checking_<?php echo $magentoField; ?>">Checking field....</span>
470
+ <span style="display:none;" id="impossible_<?php echo $magentoField; ?>">Field cannot be checked.</span>
471
+ <span style="display:none;" id="notexists_<?php echo $magentoField; ?>">Field does not exist. <a href="javascript:database.addressCollection.field('<?php echo $magentoField; ?>').create()">Create field.</a></span>
472
+ <span style="display:none;" id="notlinked_<?php echo $magentoField; ?>">Field is not linked.</a></span>
473
+ <span style="display:none;" id="notvalid_<?php echo $magentoField; ?>">Field is not valid. <a href="javascript:database.addressCollection.field('<?php echo $magentoField; ?>').repair()">Repair field.</a></span>
474
+ <span style="display:none;" id="ok_<?php echo $magentoField; ?>">Field exists.</span>
475
+ </td>
476
+ </tr>
477
+ <?php
478
+ }
479
+ ?>
480
+ </tbody>
481
+ </table>
482
+ </div>
483
+ </div>
484
+ <!-- end of fifth section. -->
485
+
486
+ </form>
487
+ <!-- end of fields linking form. -->
488
+
489
+ <div class="entry-edit-head">
490
+ <h4 class="icon-head head-edit-form fieldset-legend">Important Notice</h4>
491
+ </div>
492
+ <div class="fieldset">
493
+ <div class="hor-scroll">
494
+ <table cellspacing="0" class="form-list">
495
+ <tbody>
496
+ <tr>
497
+ <td>To enable the Magento extension, you need to have a valid license for <a href="https://www.copernica.com/en/magento" target="_blank" title="Copernica Marketing Software">Copernica Marketing Software</a>.</td>
498
+ </tr>
499
+ </tbody>
500
+ </table>
501
+ </div>
502
+ </div>
503
+
504
+ <div class="entry-edit-head">
505
+ <h4 class="icon-head head-edit-form fieldset-legend">Environment Information</h4>
506
+ </div>
507
+ <div class="fieldset">
508
+ <div class="hor-scroll">
509
+ <table cellspacing="0" class="form-list">
510
+ <tbody>
511
+ <tr>
512
+ <td class="label">Copernica extension version: </td>
513
+ <td class="value"><strong><?php echo $_helper->getExtensionVersion();?></strong></td>
514
+ </tr>
515
+ <tr>
516
+ <td class="label">Magento webshop version: </td>
517
+ <td class="value"><strong><?php echo Mage::getVersion();?></strong></td>
518
+ </tr>
519
+ </tbody>
520
+ </table>
521
+ </div>
522
+ </div>
523
+ </div>
524
+
525
+ <!-- define the popup "More information" messages -->
526
+
527
+ <!-- database help -->
528
+ <div id="database_help" style="display: none; position: fixed; top: 30%; left: 30%; width: 580px; height: 385px; padding: 20px; border: 1px solid black; z-index:1002;background-color: #FDFAB1; color: black;">
529
+ <h3 style="text-align: center;">Database HOW-TO</h3>
530
+ Set your Copernica Database, which will be used for Magento shop information import.
531
+ <br/><br/>
532
+ You can type the name of your Copernica Database in the "Name" field.
533
+ <br/><br/>
534
+ If the Database exists, the "Status" will confirm with a "Database exists" message.
535
+ <br/>
536
+ Else, the "Status" will serve you a link to "Create Database" in your Copernica Environment, while not leaving this page.
537
+ <br/>
538
+ It is also possible that a Database can exist with the name you specified, but needed fields for the extension are not available in its structure.
539
+ <br/>
540
+ In this case, you will be provided with a link to "Repair the database". This operation will also be completed while not leaving this page.
541
+ <br/><br/>
542
+ [+] A "Database exists" status message confirms that you have a valid Database created in the Copernica environment and linked to be used with your Magento Webshop.
543
+ <br/><br/>
544
+ [+] Be sure to "Save profile and collections settings" after specifying new database details. You can do this by using the button in the top-right corner.
545
+ <br/><br/>
546
+ [+] Operations on this page can only be executed if we have a valid Copernica account connection, that was set on the "Account Settings" page, which can be found under the "Copernica Marketing Software" menu.
547
+ <br/>
548
+ <a href="#" onclick="document.getElementById('database_help').style.display='none'; return false;" style="top:0; right:6px; position: absolute;">Close</a>
549
+ </div>
550
+
551
+ <!-- profiles help -->
552
+ <div id="profiles_help" style="display: none; position: fixed; top: 30%; left: 30%; width: 600px; height: 420px; padding: 20px; border: 1px solid black; z-index:1002;background-color: #FDFAB1; color: black;">
553
+ <h3 style="text-align: center;">Profiles HOW-TO</h3>
554
+ Link Magento Customer fields to Copernica Profiles fields.
555
+ <br/><br/>
556
+ You can link or unlink any fields you wish, which are displayed in the "Customers profiles" section, on this page.
557
+ <br/><br/>
558
+ To link a certain field, select the "Create link" option from the "Copernica link" drop-down list, related to that field.
559
+ <br/>
560
+ Further on, you need to label this field with your own value, inside the "Copernica field" textbox. The value should not be empty, should not contain spaces and should not start with a number.
561
+ <br/><br/>
562
+ If the field already exists in the Copernica Profiles structure, the "Status" will display a "Field exists" message.
563
+ <br/>
564
+ Else the "Status" will serve you a "Create field" link which can be used to create the field inside the Copernica Profiles structure, while not leaving this page.
565
+ <br/><br/>
566
+ To unlink a certain field, select the "Don't link" option from the "Copernica link" drop-down list, related to that field.
567
+ <br/><br/>
568
+ [+] A "Field exists" status message confirms that you have a valid field inside the Copernica Profiles structure, which can be used with the Magento linking system.
569
+ <br/><br/>
570
+ [+] Be sure to "Save profile and collections settings" after modifying the fields status and values. You can do this by using the button in the top-right corner.
571
+ <br/><br/>
572
+ [+] Operations on this page can only be executed if there is a valid Copernica account connection, that was set on the "Account Settings" page, which can be found under the "Copernica Marketing Software" menu.
573
+ <br/>
574
+ <a href="#" onclick="document.getElementById('profiles_help').style.display='none'; return false;" style="top:0; right:6px; position: absolute;">Close</a>
575
+ </div>
576
+
577
+ <!-- collection help -->
578
+ <div id="collection_help" style="display: none; position: fixed; top: 15%; left: 25%; width: 700px; height: 680px; padding: 20px; border: 1px solid black; z-index:1002;background-color: #FDFAB1; color: black;">
579
+ <h3 style="text-align: center;">Collections HOW-TO</h3>
580
+ Create Copernica Collections. Link Magento Products and Orders fields to Copernica Collections fields.
581
+ <br/><br/>
582
+ You can type the name of your Copernica Collection in the "Collection name" field.
583
+ <br/><br/>
584
+ If the Collection exists, the "Status" will confirm with a "Collection exists" message.
585
+ <br/>
586
+ Else, the "Status" will serve you a link to "Create Collection" in your Copernica Environment, while not leaving this page.
587
+ <br/>
588
+ It is also possible that a Collection can exist with the name you specified, but needed fields for the extension are not available in its structure.
589
+ <br/>
590
+ In this case, you will be provided with a link to "Repair collection". This operation will also be completed while not leaving this page.
591
+ <br/><br/>
592
+ You can link or unlink any fields you wish, which are displayed in the Collection sections, on this page.
593
+ <br/><br/>
594
+ To link a certain field, select the "Create link" option from the "Copernica link" drop-down list, related to that field.
595
+ <br/>
596
+ Further on, you need to label this field with your own value, inside the "Copernica field" textbox. The value should not be empty, should not contain spaces and should not start with a number.
597
+ <br/><br/>
598
+ If the field already exists in the Copernica Collection structure, the "Status" will display a "Field exists" message.
599
+ <br/>
600
+ Else the "Status" will serve you a "Create field" link which can be used to create the field inside the Copernica Collection structure, while not leaving this page.
601
+ <br/><br/>
602
+ To unlink a certain field, select the "Don't link" option from the "Copernica link" drop-down list, related to that field.
603
+ <br/><br/>
604
+ [+] First collection section from this page is related to Products Collection. The second collection section is related to Orders Collection.
605
+ <br/><br/>
606
+ [+] A "Collection exists" status message confirms that you have a valid Collection created in the Copernica environment and linked to be used with your Magento Webshop.
607
+ <br/><br/>
608
+ [+] A "Field exists" status message confirms that you have a valid field inside the Copernica Profiles structure, which can be used with the Magento linking system.
609
+ <br/><br/>
610
+ [+] Be sure to "Save profile and collections settings" after modifying the fields status and values or specifying new collection details. You can do this by using the button in the top-right corner.
611
+ <br/><br/>
612
+ [+] Operations on this page can only be executed if there is a valid Copernica account connection, that was set on the "Account Settings" page, which can be found under the "Copernica Marketing Software" menu.
613
+ <br/>
614
+ <a href="#" onclick="document.getElementById('collection_help').style.display='none'; return false;" style="top:0; right:6px; position: absolute;">Close</a>
615
+ </div>
616
+
617
+ <script type="text/javascript">
618
+ /**
619
+ * Javascript variables with all database and collection fields
620
+ * @var array
621
+ */
622
+ var customerFields = <?php echo(json_encode($customerFields)); ?>;
623
+ var cartItemFields = <?php echo(json_encode($cartItemFields)); ?>;
624
+ var orderFields = <?php echo(json_encode($orderFields)); ?>;
625
+ var orderItemFields = <?php echo(json_encode($orderItemFields)); ?>;
626
+ var addressFields = <?php echo(json_encode($addressFields)); ?>;
627
+
628
+
629
+ /**
630
+ * The main database object (that also does all initialisation)
631
+ * @var Database
632
+ */
633
+ var database = new CopernicaDatabase();
634
+
635
+ // check all fields in the database
636
+ database.check();
637
+
638
+ /**
639
+ * Do an ajax call to the server
640
+ * @param array Data to send to the server
641
+ * @param function Callback function that will be called when the answer is received from the server
642
+ */
643
+ function doAjaxCall(data, callback)
644
+ {
645
+ // we define our processing URL
646
+ var url = <?php echo(json_encode($this->getAjaxUrl())); ?>;
647
+
648
+ // make the request, and decode the answer back from json
649
+ new Ajax.Request(url, {
650
+ method: 'post',
651
+ parameters: data,
652
+ onLoading: function() {
653
+ $('loading-mask', 'loading_mask_loader').invoke('hide');
654
+ },
655
+ onComplete: function(answer) {
656
+ callback(eval(answer));
657
+ }
658
+ });
659
+ }
660
+
661
+ //<![CDATA[
662
+ var customForm = new varienForm('cp_form', true);
663
+ cpForm = new varienForm('cp_form', '');
664
+ cpProfileCollectionForm = new varienForm('cp_profile_collection', '');
665
+ //]]>
666
+ </script>
app/design/adminhtml/default/default/template/marketingsoftware/settings.phtml ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * View for Settings controller
4
+ * Copernica Marketing Software v 1.2.0
5
+ * March 2011
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ $_helper = Mage::helper('marketingsoftware');
10
+ $_config = Mage::helper('marketingsoftware/config');
11
+ ?>
12
+ <script type="text/javascript">
13
+
14
+ // define timeout variable
15
+ var timerID = 0;
16
+
17
+ // on page loader
18
+ Event.observe(window, 'load', init, false);
19
+
20
+ /**
21
+ * Function that is loaded on window load.
22
+ * It contains a default settings checker and multiple event listeners
23
+ */
24
+ function init() {
25
+ checksettings('onload');
26
+ $('cp_host').observe('keyup', checksettings);
27
+ $('cp_user').observe('keyup', checksettings);
28
+ $('cp_pass').observe('keyup', checksettings);
29
+ $('cp_account').observe('keyup', checksettings);
30
+ }
31
+
32
+ /**
33
+ * Function that checks account settings.
34
+ * This method will send an ajax call to the server.
35
+ * @param string|object We can have either a string ('onload') for calling the function on page load, or we can have a 'on key press' event object.
36
+ */
37
+ function checksettings(event) {
38
+
39
+ // the data that we want to send to the server
40
+ var data = {
41
+ cp_host : document.getElementById('cp_host').value,
42
+ cp_user : document.getElementById('cp_user').value,
43
+ cp_pass : document.getElementById('cp_pass').value,
44
+ cp_account : document.getElementById('cp_account').value
45
+ };
46
+
47
+ // Ajax URL
48
+ var url = <?php echo(json_encode($this->getCheckSettingsUrl())); ?>;
49
+
50
+ // status DIV
51
+ var div = $('settings_status');
52
+
53
+ // reset timer
54
+ if (timerID) clearTimeout(timerID);
55
+
56
+ // proceed with the function
57
+ timerID = setTimeout(function() {
58
+
59
+ // display a 'checking' status
60
+ div.innerHTML = 'Checking account information...';
61
+
62
+ // proceed with the AJAX call
63
+ new Ajax.Request(url, {
64
+ method: 'post',
65
+ parameters: data,
66
+ onLoading: function() {
67
+ $('loading-mask', 'loading_mask_loader').invoke('hide');
68
+ },
69
+ onComplete: function(answer) {
70
+ if (answer.responseText == '')
71
+ {
72
+ // set the return message
73
+ answer.responseText = 'Acount information is valid.';
74
+
75
+ // enable the save button
76
+ document.getElementById('cp_save').disabled = false;
77
+ document.getElementById('cp_save').setAttribute("class","");
78
+
79
+ // display the 'save your settings 'notice
80
+ if (event != 'onload') document.getElementById('cp_save_notice').style.display = 'inline';
81
+
82
+ // hide the 'invalid settings' notice
83
+ if (event != 'onload') document.getElementById('cp_invalid_notice').style.display = 'none';
84
+ }
85
+ else
86
+ {
87
+ // disable the settings button
88
+ document.getElementById('cp_save').disabled = true;
89
+ document.getElementById('cp_save').setAttribute("class","disabled");
90
+
91
+ // display the 'invalid settings' notice
92
+ document.getElementById('cp_invalid_notice').style.display = 'inline';
93
+
94
+ // hide the 'save your settings' notice
95
+ if (event != 'onload') document.getElementById('cp_save_notice').style.display = 'none';
96
+ }
97
+
98
+ // set a return message for invalid login data situation
99
+ if (answer.responseText == 'impossible') answer.responseText = 'Invalid login data.';
100
+
101
+ // feed the div with the right content
102
+ div.innerHTML = answer.responseText;
103
+
104
+ }
105
+ });
106
+ }, 1000);
107
+ }
108
+
109
+ </script>
110
+
111
+ <div class="content-header">
112
+ <h3 class="icon-head head-system-account">Copernica Marketing Software : Settings</h3>
113
+ <p class="form-buttons">
114
+ <span id="cp_save_notice" style="color: white; font-weight: bold; padding: 2px 4px; background-color: #188F11; border: thin solid #660000; display:none;">Warning: the settings are not yet saved !</span>
115
+ <span id="cp_invalid_notice" style="color: white; font-weight: bold; padding: 2px 4px; background-color: #CC3300; border: thin solid #660000; display:none;">Warning: the settings are invalid !</span>
116
+ <button type="button" onclick="cpForm.submit();" name="cp_save" id="cp_save">Save connection settings</button>
117
+ </p>
118
+ </div>
119
+ <div class="entry-edit">
120
+ <form action="<?php echo $this->getPostUrl(); ?>" method="post" name="cp_form" id="cp_form">
121
+ <?php echo $this->getBlockHtml('formkey'); ?>
122
+ <div class="entry-edit-head">
123
+ <h4 class="icon-head head-edit-form fieldset-legend">Login Information</h4>
124
+ <a href="#" onclick ="document.getElementById('settings_help').style.display='block';" id="page-help-link" style="float: right; line-height:18px; return false;">More information</a>
125
+ </div>
126
+ <div class="fieldset">
127
+ <div class="hor-scroll">
128
+ <table cellspacing="0" class="form-list">
129
+ <tbody>
130
+ <tr>
131
+ <td class="label"><label for="cp_host">Hostname <span class="required">*</span></label></td>
132
+ <td class="value"><input type="text" class=" required-entry input-text validate-url" title="Hostname" value="<?php echo $_config->getHostname(); ?>" name="cp_host" id="cp_host"></td>
133
+ </tr>
134
+
135
+ <tr>
136
+ <td class="label"><label for="cp_user">Username <span class="required">*</span></label></td>
137
+ <td class="value"><input type="text" class=" required-entry input-text" title="Username" value="<?php echo $_config->getUsername(); ?>" name="cp_user" id="cp_user"></td>
138
+ </tr>
139
+
140
+ <tr>
141
+ <td class="label"><label for="cp_account">Account Name <span class="required">*</span></label></td>
142
+ <td class="value"><input type="text" class=" required-entry input-text" title="Account Name" value="<?php echo $_config->getAccount(); ?>" name="cp_account" id="cp_account"></td>
143
+ </tr>
144
+
145
+ <tr>
146
+ <td class="label"><label for="cp_pass">Password <span class="required">*</span></label></td>
147
+ <td class="value"><input type="password" class=" required-entry input-text" title="Password" value="<?php echo $_config->getPassword(); ?>" name="cp_pass" id="cp_pass"></td>
148
+ </tr>
149
+
150
+ <tr>
151
+ <td class="label"><label for="settings_status">Status </label></td>
152
+ <td class="value"><div id="settings_status">Checking account information...</div></td>
153
+ </tr>
154
+ </tbody>
155
+ </table>
156
+ </div>
157
+ </div>
158
+ </form>
159
+
160
+ <div class="entry-edit-head">
161
+ <h4 class="icon-head head-edit-form fieldset-legend">Important Notice</h4>
162
+ </div>
163
+ <div class="fieldset">
164
+ <div class="hor-scroll">
165
+ <table cellspacing="0" class="form-list">
166
+ <tbody>
167
+ <tr>
168
+ <td>To enable the Magento extension, you need to have a valid license for <a href="https://www.copernica.com/en/magento" target="_blank" title="Copernica Marketing Software">Copernica Marketing Software</a>.</td>
169
+ </tr>
170
+ </tbody>
171
+ </table>
172
+ </div>
173
+ </div>
174
+
175
+ <div class="entry-edit-head">
176
+ <h4 class="icon-head head-edit-form fieldset-legend">Environment Information</h4>
177
+ </div>
178
+ <div class="fieldset">
179
+ <div class="hor-scroll">
180
+ <table cellspacing="0" class="form-list">
181
+ <tbody>
182
+ <tr>
183
+ <td class="label">Copernica extension version: </td>
184
+ <td class="value"><strong><?php echo $_helper->getExtensionVersion();?></strong></td>
185
+ </tr>
186
+ <tr>
187
+ <td class="label">Magento webshop version: </td>
188
+ <td class="value"><strong><?php echo Mage::getVersion();?></strong></td>
189
+ </tr>
190
+ </tbody>
191
+ </table>
192
+ </div>
193
+ </div>
194
+ </div>
195
+
196
+ <!-- settings help -->
197
+ <div id="settings_help" style="display: none; position: absolute; top: 30%; left: 30%; width: 580px; height: 300px; padding: 20px; border: 1px solid black; z-index:1002;background-color: #FDFAB1; color: black;">
198
+ <h3 style="text-align: center;">Account Settings HOW-TO</h3>
199
+ Set your login details used to access your user account available in Copernica Marketing Software:
200
+ <br/><br/>
201
+ - Hostname : The URL (http://publisher.copernica.nl) that you use to connect to your Copernica user account
202
+ <br/>
203
+ - Username : Your Copernica username
204
+ <br/>
205
+ - Account Name: The Copernica master account that hosts your user account
206
+ <br/>
207
+ - Password : The password for your Copernica user account
208
+ <br/><br/>
209
+ The "Status" field will display the current account information status. If you change values of any account details fields, this status will be updated.
210
+ <br/><br/>
211
+ [+] Be sure to "Save connection settings" after specifying new account details. You can do this by using the button in the top-right corner.
212
+ <br/><br/>
213
+ [+] A Copernica Database administration can be found in the "Link Fields" submenu under the "Copernica Marketing Software" menu.
214
+ <br/>
215
+ <a href="#" onclick="document.getElementById('settings_help').style.display='none';" style="top:0; right:6px; position: absolute; return false;">Close</a>
216
+ </div>
217
+
218
+ <script type="text/javascript">
219
+ //<![CDATA[
220
+ var customForm = new varienForm('cp_form', true);
221
+ cpForm = new varienForm('cp_form', '');
222
+ //]]>
223
+ </script>
app/etc/modules/Copernica_MarketingSoftware.xml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Copernica_MarketingSoftware>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ <depends>
8
+ <Mage_Catalog/>
9
+ <Mage_Checkout/>
10
+ <Mage_Customer/>
11
+ <Mage_Newsletter/>
12
+ <Mage_Sales/>
13
+ </depends>
14
+ </Copernica_MarketingSoftware>
15
+ </modules>
16
+ </config>
js/copernica/marketingsoftware/collection.js ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Javascript holds the implementation of the CopernicaCollection class
3
+ * A collection object handles a collection
4
+ * Copernica Marketing Software v 1.2.0
5
+ * April 2011
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ /**
10
+ * Constructor
11
+ * @param Database The containing database
12
+ * @param string Type of collection, 'cartproducts', 'orders', 'orderproducts' or 'addresses'
13
+ */
14
+
15
+ function CopernicaCollection(database, type)
16
+ {
17
+ // store arguments to the constructor
18
+ this.parent = database;
19
+ this.type = type;
20
+
21
+ // construct an array of all fields in this collection
22
+ this.fields = [];
23
+
24
+ // fields are stored in a global variable
25
+ if (type == 'cartproducts') var theFields = cartItemFields;
26
+ else if (type == 'orders') var theFields = orderFields;
27
+ else if (type == 'orderproducts') var theFields = orderItemFields;
28
+ else var theFields = addressFields;
29
+
30
+ // we always want to have an object, PHP can do this
31
+ // for us but this is only supported in PHP 5.3.0 and up
32
+ if (theFields.length === 0) theFields = {};
33
+
34
+ // loop through the fields and convert them to objects
35
+ for (var x in theFields)
36
+ {
37
+ // append field to the
38
+ this.fields.push(new CopernicaField(this, x));
39
+ }
40
+
41
+ // access to the input html element
42
+ var input = this.htmlElement('input');
43
+
44
+ // the initial value for the input element
45
+ this.initialValue = input.value;
46
+
47
+ // get reference to ourselves
48
+ var self = this;
49
+
50
+ // timer that is set when key event is caught
51
+ var timer = 0;
52
+
53
+ // install handler when a key is pressed in the input box
54
+ input.onkeydown = function()
55
+ {
56
+ // a key was pressed, mark the field status as 'checking'
57
+ self.setStatus('checking');
58
+
59
+ // is already a timer running for the key events?
60
+ if (timer) clearTimeout(timer);
61
+
62
+ // we do not want to send the ajax call right away, because that might
63
+ // result in a lot of ajax call for every character typed. Instead, we
64
+ // set a timer and if a new key event occurs within that period, we cancel
65
+ // the ajax call and schedule a new one
66
+ timer = setTimeout(function() {
67
+
68
+ // start checking
69
+ self.check();
70
+
71
+ }, 1000);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Has the collection - or one of it fields - been modified
77
+ * @return boolean
78
+ */
79
+ CopernicaCollection.prototype.modified = function()
80
+ {
81
+ // check if the input box has been modified
82
+ var input = this.htmlElement('input');
83
+ if (input.value != this.initialValue) return true;
84
+
85
+ // check if one of the fields was modified
86
+ for (var i=0; i<this.fields.length; i++)
87
+ {
88
+ // check the field
89
+ if (this.fields[i].modified()) return true;
90
+ }
91
+
92
+ // not modified
93
+ return false;
94
+ }
95
+
96
+ /**
97
+ * Function to get access to the HTML element that represents the field.
98
+ * Inside the form, the field is linked to a number of HTML elements, like
99
+ * the textbox, the selectbox and a number of span elements that represent
100
+ * the field status. The type parameter shows the type of HTML element to
101
+ * return. The following types are recognized:
102
+ * input Returns the <input type='text'> element
103
+ * checking Returns the 'span' element that says that the collection is busy checking
104
+ * impossible Returns the 'span' element that says that the check can not be performed, because API is unreachable or database does not exist
105
+ * notexists Returns the 'span' element that says that the collection does not exist
106
+ * notvalid Returns the 'span' element that says that the collection exists, but misses some required fields
107
+ * ok Returns the 'span' element that says that the collection is valid
108
+ * @param string Type of element
109
+ * @return Object Element object
110
+ */
111
+ CopernicaCollection.prototype.htmlElement = function(type)
112
+ {
113
+ return document.getElementById(this.type + '_' + type);
114
+ }
115
+
116
+ /**
117
+ * Get the current field value
118
+ * @return string
119
+ */
120
+ CopernicaCollection.prototype.value = function()
121
+ {
122
+ return this.htmlElement('input').value;
123
+ }
124
+
125
+ /**
126
+ * Get the current field status.
127
+ * @return string 'checking', 'impossible', 'notexists', 'notvalid' or 'ok'
128
+ */
129
+ CopernicaCollection.prototype.status = function()
130
+ {
131
+ // the supported status values
132
+ var supported = ['checking','impossible','notexists','notvalid','ok'];
133
+
134
+ // loop through the span elements that describe this status
135
+ for (var i=0; i<supported.length; i++)
136
+ {
137
+ // check if this HTML element is now visible
138
+ var status = supported[i];
139
+ if (this.htmlElement(status).style.display != 'none') return status;
140
+ }
141
+
142
+ // not a single HTML element was visible, assume status is 'impossible'
143
+ return 'impossible';
144
+ }
145
+
146
+ /**
147
+ * Does the collection exist?
148
+ * @return boolean
149
+ */
150
+ CopernicaCollection.prototype.exists = function()
151
+ {
152
+ var status = this.status();
153
+ return status == 'ok' || status == 'notvalid';
154
+ }
155
+
156
+ /**
157
+ * Function to start checking all fields if they exist
158
+ */
159
+ CopernicaCollection.prototype.checkFields = function()
160
+ {
161
+ // self reference
162
+ var self = this;
163
+
164
+ // function to check if a field exist
165
+ var checkField = function(counter)
166
+ {
167
+ // stop if this field does not exist
168
+ if (self.fields.length <= counter) return;
169
+
170
+ // if the current collection no longer exists, it makes no sense to continue checking fields
171
+ if (!self.exists()) return;
172
+
173
+ // check if the field exist, with a callback for checking the next field
174
+ self.fields[counter].check(function() {
175
+ checkField(counter + 1);
176
+ });
177
+ }
178
+
179
+ // start checking the first field
180
+ checkField(0);
181
+ }
182
+
183
+ /**
184
+ * Retrieve one specific Field Object from all Fields Objects available in the CopernicaCollections Structure
185
+ * @param string Name of the field
186
+ * @return Object|null We return the Fields object or null
187
+ */
188
+ CopernicaCollection.prototype.field = function(name)
189
+ {
190
+ for (var i=0;i<this.fields.length;i++)
191
+ {
192
+ if (this.fields[i].name == name) return this.fields[i];
193
+ }
194
+ return null;
195
+ }
196
+
197
+ /**
198
+ * Change the current field status
199
+ * @param string New status, supported are: 'checking', 'impossible', 'notexists', 'notvalid' and 'ok'
200
+ */
201
+ CopernicaCollection.prototype.setStatus = function(status)
202
+ {
203
+ // skip if status does not change
204
+ var oldstatus = this.status();
205
+ if ((oldstatus == status) && (status != 'impossible')) return;
206
+
207
+ // check if the collection did exist before
208
+ var didexist = this.exists();
209
+
210
+ // the supported status values
211
+ var supported = ['checking','impossible','notexists','notvalid','ok'];
212
+
213
+ // loop through the span elements that describe this status
214
+ for (var i=0; i<supported.length; i++)
215
+ {
216
+ // update the visibility of this span element
217
+ this.htmlElement(supported[i]).style.display = (status === supported[i]) ? 'inline' : 'none';
218
+ }
219
+
220
+ // should we re-check all fields?
221
+ var doesexist = this.exists();
222
+ if ((didexist == doesexist) && (status != 'impossible')) return;
223
+
224
+ // does the collection came into existance?
225
+ if (doesexist)
226
+ {
227
+ // check all fields
228
+ this.checkFields();
229
+ }
230
+ else
231
+ {
232
+ // mark all fields as impossible to check
233
+ for (var i=0; i<this.fields.length; i++) this.fields[i].setStatus('impossible');
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Do a certain ajax call
239
+ * @param string Type of call
240
+ * @param function Callback function
241
+ */
242
+ CopernicaCollection.prototype.ajaxCall = function(type, callback)
243
+ {
244
+ // while the ajax call is in progress, the status is set to 'checking'
245
+ this.setStatus('checking');
246
+
247
+ // self reference
248
+ var self = this;
249
+
250
+ // do the ajax call
251
+ doAjaxCall({
252
+ type: type,
253
+ collection_type: this.type,
254
+ database: this.parent.value(),
255
+ collection: this.value()
256
+ }, function(answer) {
257
+ // set the status
258
+ answer.responseText = (answer.responseText === '') ? 'ok' : answer.responseText;
259
+ self.setStatus(answer.responseText);
260
+
261
+ // depending on the status, display the relevant notice
262
+ var database = self.parent;
263
+
264
+ // we have the database object, we can now change the value
265
+ (answer.responseText !== 'ok') ? database.invalidSettingsWarning('collection_'+self.type) : database.updateSaveWarning('collection_'+self.type);
266
+
267
+ // call the callback, if it was supplied
268
+ if (callback) callback(answer.responseText == 'ok');
269
+ });
270
+ }
271
+
272
+ /**
273
+ * Perform the check.
274
+ * This method sends an ajax request to the server to check if the collection exists and is valid
275
+ * @param function Optional callback function that will be called when the ajax call completes
276
+ */
277
+ CopernicaCollection.prototype.check = function(callback)
278
+ {
279
+ // do the ajax call
280
+ this.ajaxCall('check_collection', callback);
281
+
282
+ }
283
+
284
+ /**
285
+ * Create the collection.
286
+ * This method sends an ajax request to create the collection in Copernica
287
+ * @param function Optional callback function that will be called when ajax call completes
288
+ */
289
+ CopernicaCollection.prototype.create = function(callback)
290
+ {
291
+ // do the ajax call
292
+ this.ajaxCall('create_collection', callback);
293
+ }
294
+
295
+ /**
296
+ * Repair the collection.
297
+ * This method sends an ajax request to create missing fields in the collection
298
+ * @param function Optional callback function that will be called when ajax call completes
299
+ */
300
+ CopernicaCollection.prototype.repair = function(callback)
301
+ {
302
+ // do the ajax call
303
+ this.ajaxCall('repair_collection', callback);
304
+ }
js/copernica/marketingsoftware/database.js ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Javascript holds the implementation of the CopernicaDatabase class
3
+ * A database object handles a database
4
+ * Copernica Marketing Software v 1.2.0
5
+ * April 2011
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ /**
10
+ * Constructor
11
+ */
12
+ function CopernicaDatabase()
13
+ {
14
+ // set type
15
+ this.type = 'database';
16
+ this.invalidFields = [];
17
+
18
+ // the database has two collections
19
+ this.cartItemsCollection = new CopernicaCollection(this, 'cartproducts');
20
+ this.ordersCollection = new CopernicaCollection(this, 'orders');
21
+ this.orderItemsCollection = new CopernicaCollection(this, 'orderproducts');
22
+ this.addressCollection = new CopernicaCollection(this, 'addresses');
23
+
24
+ // construct an array of all fields in this collection
25
+ this.fields = [];
26
+
27
+ // we always want to have an object, PHP can do this
28
+ // for us but this is only supported in PHP 5.3.0 and up
29
+ if (customerFields.length === 0) customerFields = {};
30
+
31
+ // fields are stored in a global variable,
32
+ // loop through those fields and convert them to objects
33
+ for (var x in customerFields)
34
+ {
35
+ // append field to the
36
+ this.fields.push(new CopernicaField(this, x));
37
+ }
38
+
39
+ // access to the input html element
40
+ var input = this.htmlElement('input');
41
+
42
+ // the initial value for the input element
43
+ this.initialValue = input.value;
44
+
45
+ // timer that is set when key event is caught
46
+ var timer = 0;
47
+
48
+ // get reference to ourselves
49
+ var self = this;
50
+
51
+ // install handler when a key is pressed in the input box
52
+ input.onkeydown = function()
53
+ {
54
+ // a key was pressed, mark the field status as 'checking'
55
+ self.setStatus('checking');
56
+
57
+ // is already a timer running for the key events?
58
+ if (timer) clearTimeout(timer);
59
+
60
+ // we do not want to send the ajax call right away, because that might
61
+ // result in a lot of ajax call for every character typed. Instead, we
62
+ // set a timer and if a new key event occurs within that period, we cancel
63
+ // the ajax call and schedule a new one
64
+ timer = setTimeout(function() {
65
+
66
+ // start checking
67
+ self.check();
68
+
69
+ }, 1000);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Has the database - or one of its collection or fields - been modified
75
+ * @return boolean
76
+ */
77
+ CopernicaDatabase.prototype.modified = function()
78
+ {
79
+ // check if the input box has been modified
80
+ var input = this.htmlElement('input');
81
+ if (input.value != this.initialValue) return true;
82
+
83
+ // check if one of the fields was modified
84
+ for (var i=0; i<this.fields.length; i++)
85
+ {
86
+ // check the field
87
+ if (this.fields[i].modified()) return true;
88
+ }
89
+
90
+ // check if the collections were modified
91
+ return this.cartItemsCollection.modified() || this.orderItemsCollection.modified() || this.ordersCollection.modified() || this.addressCollection.modified();
92
+ }
93
+
94
+ /**
95
+ * Enable or disable the warning that fields still need to be saved
96
+ * Also, enable the Save button and hide the "Not valid account settings" notice.
97
+ */
98
+ CopernicaDatabase.prototype.updateSaveWarning = function(fieldName)
99
+ {
100
+ // get the right warning element
101
+ var el = document.getElementById('cp_save_notice');
102
+ if (!el) return;
103
+
104
+ // if a field name is given and appears in the list of invalid
105
+ // fields, than it should be removed there.
106
+ if (fieldName != undefined)
107
+ {
108
+ var newInvalidFields = [];
109
+
110
+ // iterate over the already registered invalid fields
111
+ for (var i = 0; i < this.invalidFields.length; i++)
112
+ {
113
+ // remove the matching element
114
+ if (this.invalidFields[i] != fieldName) newInvalidFields[newInvalidFields.length] = this.invalidFields[i];
115
+ }
116
+
117
+ // store the data in the old var
118
+ this.invalidFields = newInvalidFields;
119
+ }
120
+
121
+ // there are still some fields with errors, return
122
+ if (this.invalidFields.length > 0) return;
123
+
124
+ // show or hide the warning
125
+ el.style.display = this.modified() ? 'inline' : 'none';
126
+
127
+ // hide the 'couldn't establish a connection' notice
128
+ document.getElementById('cp_warning_notice').style.display = 'none';
129
+
130
+ // enable the save button
131
+ document.getElementById('cp_pc_save').disabled = false;
132
+ document.getElementById('cp_pc_save').setAttribute("class","");
133
+ }
134
+
135
+ CopernicaDatabase.prototype.invalidSettingsWarning = function(fieldName)
136
+ {
137
+ // if a field name is given add it to the list of fields with
138
+ // errors
139
+ if (fieldName != undefined)
140
+ {
141
+ // By default the item is not found
142
+ var found = false;
143
+
144
+ for (var i = 0; i < this.invalidFields.length; i++)
145
+ {
146
+ // is the element already in there
147
+ if (this.invalidFields[i] == fieldName) found = true;
148
+ }
149
+
150
+ // the element is not already in there add it
151
+ if (!found) this.invalidFields[this.invalidFields.length] = fieldName;
152
+ }
153
+
154
+ // hide the 'save your settings' notice, as is irelevant
155
+ document.getElementById('cp_save_notice').style.display = 'none';
156
+
157
+ // pop-up a warning notice with a connection couldn't be established message
158
+ document.getElementById('cp_warning_notice').style.display = 'inline';
159
+
160
+ // disable the save button
161
+ document.getElementById('cp_pc_save').disabled = true;
162
+ document.getElementById('cp_pc_save').setAttribute("class","disabled");
163
+ }
164
+ /**
165
+ * Function to get access to the HTML element that represents the database.
166
+ * Inside the form, the database is linked to a number of HTML elements, like
167
+ * the textbox and a number of span elements that represent
168
+ * the status. The type parameter shows the type of HTML element to
169
+ * return. The following types are recognized:
170
+ * input Returns the <input type='text'> element
171
+ * checking Returns the 'span' element that says that the database is busy checking
172
+ * impossible Returns the 'span' element that says that the check can not be performed, because API is unreachable or some other reason
173
+ * notexists Returns the 'span' element that says that the database does not exist
174
+ * notvalid Returns the 'span' element that says that the database exists, but misses some required fields
175
+ * ok Returns the 'span' element that says that the database is valid
176
+ * @param string Type of element
177
+ * @return object Element object
178
+ */
179
+ CopernicaDatabase.prototype.htmlElement = function(type)
180
+ {
181
+ return document.getElementById('db_' + type);
182
+ }
183
+
184
+ /**
185
+ * Get the current database value
186
+ * @return string
187
+ */
188
+ CopernicaDatabase.prototype.value = function()
189
+ {
190
+ return this.htmlElement('input').value;
191
+ }
192
+
193
+ /**
194
+ * Get the current database status.
195
+ * @return string 'checking', 'impossible', 'notexists', 'notvalid' or 'ok'
196
+ */
197
+ CopernicaDatabase.prototype.status = function()
198
+ {
199
+ // the supported status values
200
+ var supported = ['checking','impossible','notexists','notvalid','ok'];
201
+
202
+ // loop through the span elements that describe this status
203
+ for (var i=0; i<supported.length; i++)
204
+ {
205
+ // check if this HTML element is now visible
206
+ var status = supported[i];
207
+ if (this.htmlElement(status).style.display != 'none') return status;
208
+ }
209
+
210
+ // not a single HTML element was visible, assume status is 'impossible'
211
+ return 'impossible';
212
+ }
213
+
214
+ /**
215
+ * Does the database exist?
216
+ * @return boolean
217
+ */
218
+ CopernicaDatabase.prototype.exists = function()
219
+ {
220
+ var status = this.status();
221
+ return status == 'ok' || status == 'notvalid';
222
+ }
223
+
224
+ /**
225
+ * Function to start checking all fields if they exist
226
+ */
227
+ CopernicaDatabase.prototype.checkFields = function()
228
+ {
229
+ // self reference
230
+ var self = this;
231
+
232
+ // function to check if a field exist
233
+ var checkField = function(counter)
234
+ {
235
+ // if the current collection no longer exists, it makes no sense to continue checking fields
236
+ if (!self.exists()) return;
237
+
238
+ // special treatment for checking the collections
239
+ if (counter == self.fields.length)
240
+ {
241
+ // check the products collection
242
+ self.cartItemsCollection.check(function() { checkField(counter + 1); })
243
+ }
244
+ else if (counter == self.fields.length + 1)
245
+ {
246
+ // check the orders collection
247
+ self.ordersCollection.check(function() { checkField(counter + 1); })
248
+ }
249
+ else if (counter == self.fields.length + 2)
250
+ {
251
+ // check the orders collection
252
+ self.orderItemsCollection.check(function() { checkField(counter + 1); })
253
+ }
254
+ else if (counter == self.fields.length + 3)
255
+ {
256
+ // check the orders collection
257
+ self.addressCollection.check(function() { checkField(counter + 1); })
258
+ }
259
+ else if (counter < self.fields.length)
260
+ {
261
+ // check if the field exist, with a callback for checking the next field
262
+ self.fields[counter].check(function() {
263
+ checkField(counter + 1);
264
+ });
265
+ }
266
+ }
267
+
268
+ // start checking
269
+ checkField(0);
270
+ }
271
+
272
+ /**
273
+ * Retrieve one specific Field Object from all Fields Objects available in the CopernicaDatabase Profile Structure
274
+ * @param string Name of the field
275
+ * @return Object|null We return the Fields object or null
276
+ */
277
+ CopernicaDatabase.prototype.field = function(name)
278
+ {
279
+ for (var i=0;i<this.fields.length;i++)
280
+ {
281
+ if (this.fields[i].name == name) return this.fields[i];
282
+ }
283
+ return null;
284
+ }
285
+
286
+
287
+ /**
288
+ * Change the current database status
289
+ * @param string New status, supported are: 'checking', 'impossible', 'notexists', 'notvalid' and 'ok'
290
+ */
291
+ CopernicaDatabase.prototype.setStatus = function(status)
292
+ {
293
+ // skip if status does not change
294
+ var oldstatus = this.status();
295
+ if (oldstatus == status) return;
296
+
297
+ // check if the database did exist before
298
+ var didexist = this.exists();
299
+
300
+ // the supported status values
301
+ var supported = ['checking','impossible','notexists','notvalid','ok'];
302
+
303
+ // loop through the span elements that describe this status
304
+ for (var i=0; i<supported.length; i++)
305
+ {
306
+ // update the visibility of this span element
307
+ this.htmlElement(supported[i]).style.display = (status === supported[i]) ? 'inline' : 'none';
308
+ }
309
+
310
+ // should we re-check all fields?
311
+ var doesexist = this.exists();
312
+ if ((didexist == doesexist) && (status != 'impossible')) return;
313
+
314
+ // does the collection came into existance?
315
+ if (doesexist)
316
+ {
317
+ // check all fields
318
+ this.checkFields();
319
+ }
320
+ else
321
+ {
322
+ // mark all fields as impossible to check
323
+ for (var i=0; i<this.fields.length; i++) this.fields[i].setStatus('impossible');
324
+
325
+ // mark the collections as impossible to check too
326
+ this.ordersCollection.setStatus('impossible');
327
+ this.cartItemsCollection.setStatus('impossible');
328
+ this.orderItemsCollection.setStatus('impossible');
329
+ this.addressCollection.setStatus('impossible');
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Do a certain ajax call
335
+ * @param string Type of call
336
+ * @param function Callback function
337
+ */
338
+ CopernicaDatabase.prototype.ajaxCall = function(type, callback)
339
+ {
340
+ // while the ajax call is in progress, the status is set to 'checking'
341
+ this.setStatus('checking');
342
+
343
+ // self reference
344
+ var self = this;
345
+
346
+ // do the ajax call
347
+ doAjaxCall({
348
+ type: type,
349
+ database: this.value()
350
+ }, function(answer) {
351
+
352
+ // set the status
353
+ answer.responseText = (answer.responseText === '') ? 'ok' : answer.responseText;
354
+ self.setStatus(answer.responseText);
355
+
356
+ // depending on the status, display the relevant notice
357
+ (answer.responseText !== 'ok') ? self.invalidSettingsWarning('database') : self.updateSaveWarning('database');
358
+
359
+ // call the callback, if it was supplied
360
+ if (callback) callback(answer.responseText == 'ok');
361
+ });
362
+ }
363
+
364
+ /**
365
+ * Perform the check.
366
+ * This method sends an ajax request to the server to check if the database exists and is valid
367
+ * @param function Optional callback function that will be called when the ajax call completes
368
+ */
369
+ CopernicaDatabase.prototype.check = function(callback)
370
+ {
371
+ // do the ajax call
372
+ this.ajaxCall('check_database', callback);
373
+ }
374
+
375
+ /**
376
+ * Create the database.
377
+ * This method sends an ajax request to create the database in Copernica
378
+ * @param function Optional callback function that will be called when ajax call completes
379
+ */
380
+ CopernicaDatabase.prototype.create = function(callback)
381
+ {
382
+ // do the ajax call
383
+ this.ajaxCall('create_database', callback);
384
+ }
385
+
386
+ /**
387
+ * Repair the database.
388
+ * This method sends an ajax request to create missing fields in the database
389
+ * @param function Optional callback function that will be called when ajax call completes
390
+ */
391
+ CopernicaDatabase.prototype.repair = function(callback)
392
+ {
393
+ // do the ajax call
394
+ this.ajaxCall('repair_database', callback);
395
+ }
js/copernica/marketingsoftware/field.js ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Javascript holds the implementation of the CopernicaField class
3
+ * A field object represents one Magento field in a database
4
+ * Copernica Marketing Software v 1.2.0
5
+ * April 2011
6
+ * http://www.copernica.com/
7
+ */
8
+
9
+ /**
10
+ * Constructor
11
+ * @param Database|Collection Database or Collection object that holds the field
12
+ * @param string Name of the field
13
+ */
14
+ function CopernicaField(parent, name)
15
+ {
16
+ // store reference to the database and the name
17
+ this.parent = parent;
18
+ this.name = name;
19
+
20
+ // get reference to ourselved
21
+ var self = this;
22
+
23
+ // get access to a number of HTML elements that we need in the handlers
24
+ var input = this.htmlElement('input');
25
+ var select = this.htmlElement('select');
26
+
27
+ // store the initial value
28
+ this.initialSelectValue = select ? select.selectedIndex : -1;
29
+ this.initialInputValue = input.value;
30
+
31
+ // timer that is set for handling keypress events
32
+ var timer = 0;
33
+
34
+ if (select)
35
+ {
36
+ // install handler when select box changes its value
37
+ select.onchange = function()
38
+ {
39
+ // is the field now linked?
40
+ if (select.selectedIndex == 0)
41
+ {
42
+ // the selectbox is set to 'not linked'
43
+ self.setStatus('notlinked');
44
+ input.value = '';
45
+ input.style.display = 'none';
46
+ }
47
+ else if (select.selectedIndex == 2)
48
+ {
49
+ input.value = self.fieldName();
50
+ input.style.display = 'block';
51
+
52
+ // the field should be checked
53
+ self.ajaxCall('check_field', false);
54
+ }
55
+ else if (input.value == '')
56
+ {
57
+ // the selectbox is set to 'linked', but no value is entered in the input box
58
+ self.setStatus('impossible');
59
+ input.style.display = 'block';
60
+ }
61
+ else
62
+ {
63
+ // check if the field exists
64
+ self.check();
65
+ input.style.display = 'block';
66
+ }
67
+ }
68
+ }
69
+
70
+ // install handler when a key is pressed in the input box
71
+ input.onchange = input.onkeydown = function()
72
+ {
73
+ // a key was pressed, mark the field status as 'checking'
74
+ self.setStatus('checking');
75
+
76
+ // is already a timer running for the key events?
77
+ if (timer) clearTimeout(timer);
78
+
79
+ // we do not want to send the ajax call right away, because that might
80
+ // result in a lot of ajax call for every character typed. In stead, we
81
+ // set a timer and if a new key event occurs within that period, we cancel
82
+ // the ajax call and schedule a new one
83
+ timer = setTimeout(function() {
84
+
85
+ // start checking
86
+ self.check();
87
+
88
+ }, 1000);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Check if the field setting has been modified since it was loaded on the page
94
+ * @return boolean
95
+ */
96
+ CopernicaField.prototype.modified = function()
97
+ {
98
+ // get access to a number of HTML elements that we need in the handlers
99
+ var input = this.htmlElement('input');
100
+ var select = this.htmlElement('select');
101
+
102
+ // check if the selectbox or input box has been changed
103
+ if (select && select.selectedIndex != this.initialSelectValue) return true;
104
+ return input.value != this.initialInputValue;
105
+ }
106
+
107
+ /**
108
+ * Function to get access to the HTML element that represents the field.
109
+ * Inside the form, the field is linked to a number of HTML elements, like
110
+ * the textbox, the selectbox and a number of span elements that represent
111
+ * the field status. The type parameter shows the type of HTML element to
112
+ * return. The following types are recognized:
113
+ * input Returns the <input type='text'> element
114
+ * select Returns the <select> box
115
+ * checking Returns the 'span' element that says that the field is busy checking
116
+ * impossible Returns the 'span' element that says that the check can not be performed, because API is unreachable or database does not exist
117
+ * notexists Returns the 'span' element that says that the field does not exist
118
+ * ok Returns the 'span' element that says that the collection is valid
119
+ * @param string Type of element
120
+ * @return object Element object
121
+ */
122
+ CopernicaField.prototype.htmlElement = function(type)
123
+ {
124
+ return document.getElementById(type + '_' + this.name);
125
+ }
126
+
127
+ /**
128
+ * Get the current field value
129
+ * @return string
130
+ */
131
+ CopernicaField.prototype.value = function()
132
+ {
133
+ return this.htmlElement('input').value;
134
+ }
135
+
136
+ /**
137
+ * Get the name of the field
138
+ * @return string
139
+ */
140
+ CopernicaField.prototype.fieldName = function()
141
+ {
142
+ // what do we need to replace
143
+ var search = this.parent.type == 'database' ? 'customer' : this.parent.type;
144
+
145
+ // remove the parent type from the name
146
+ return this.name.replace(search + '_', '');
147
+ }
148
+
149
+ /**
150
+ * Get the current field status.
151
+ * @return string 'notlinked', 'checking', 'impossible', 'notexists', 'ok'
152
+ */
153
+ CopernicaField.prototype.status = function()
154
+ {
155
+ // check if the selectbox is set to 'not linked'
156
+ if (this.htmlElement('select') && this.htmlElement('select').selectedIndex == 0) return 'notlinked';
157
+
158
+ // the supported status values
159
+ var supported = ['checking','impossible','notexists','ok'];
160
+
161
+ // loop through the span elements that describe this status
162
+ for (var i=0; i<supported.length; i++)
163
+ {
164
+ // check if this HTML element is now visible
165
+ var status = supported[i];
166
+
167
+ if (this.htmlElement(status).style.display != 'none') return status;
168
+ }
169
+
170
+ // not a single HTML element was visible, assume status is 'impossible'
171
+ return 'impossible';
172
+ }
173
+
174
+ /**
175
+ * Change the current field status
176
+ * @param string New status, supported are: 'notlinked', 'checking', 'impossible', 'notexists' and 'ok'
177
+ */
178
+ CopernicaField.prototype.setStatus = function(status)
179
+ {
180
+ // skip if status does not change
181
+ //if (this.status() == status) return;
182
+
183
+ // the supported status values
184
+ var supported = ['checking','impossible','notexists','ok','notlinked','notvalid'];
185
+
186
+ // skip if the field is not linked
187
+ if (this.status() == 'notlinked') status = 'notlinked_empty';
188
+
189
+ // loop through the span elements that describe this status
190
+ for (var i=0; i<supported.length; i++)
191
+ {
192
+ // update the visibility of this span element
193
+ this.htmlElement(supported[i]).style.display = (status === supported[i]) ? 'inline' : 'none';
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Do a certain ajax call
199
+ * @param string Type of call
200
+ * @param function Callback function
201
+ */
202
+ CopernicaField.prototype.ajaxCall = function(type, callback)
203
+ {
204
+ // self reference
205
+ var self = this;
206
+
207
+ // checking status
208
+ if (type == 'create_field' || type == 'check_field' || type == 'repair_field') self.setStatus('checking');
209
+
210
+ // do the ajax call
211
+ doAjaxCall({
212
+ type: type,
213
+ database: this.parent.type == 'database' ? this.parent.value() : this.parent.parent.value(),
214
+ collection: this.parent.type,
215
+ collectionName: this.parent.type == 'database' ? '' : this.parent.value(),
216
+ field: this.value(),
217
+ field_system_name: this.fieldName()
218
+ }, function(answer) {
219
+ // set the status
220
+ answer.responseText = (answer.responseText === '') ? 'ok' : answer.responseText;
221
+ self.setStatus(answer.responseText);
222
+
223
+ // depending on the status, display the relevant notice
224
+ if (self.parent.type == 'database') var database = self.parent;
225
+ else var database = self.parent.parent;
226
+
227
+ // we have the database object, we can now change the value
228
+ (answer.responseText !== 'ok') ? database.invalidSettingsWarning(self.name) : database.updateSaveWarning(self.name);
229
+
230
+ // call the callback, if it was supplied
231
+ if (callback) callback(answer.responseText == 'ok');
232
+ });
233
+ }
234
+
235
+ /**
236
+ * Perform the check.
237
+ * This method sends an ajax request to the server to check if the field exists
238
+ * @param function Optional callback function that will be called when the ajax call completes
239
+ */
240
+ CopernicaField.prototype.check = function(callback)
241
+ {
242
+ // do the ajax call to check the field
243
+ if (this.htmlElement('select') && this.htmlElement('select').selectedIndex == 0)
244
+ {
245
+ // field is not linked, we need to call the callback right away
246
+ if (callback) setTimeout(function() { callback(false); }, 0);
247
+ }
248
+ else
249
+ {
250
+ // do the ajax call to check
251
+ this.ajaxCall('check_field', callback);
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Create the field
257
+ * This method sends an ajax request to create the field in Copernica
258
+ * @param function Optional callback function that will be called when ajax call completes
259
+ */
260
+ CopernicaField.prototype.create = function(callback)
261
+ {
262
+ // do the ajax call to create the field
263
+ this.ajaxCall('create_field', callback);
264
+ }
265
+
266
+ /**
267
+ * Create a special field
268
+ * This methods sends an ajax request to create a special field (telephone, fax) in Copernica
269
+ * @param function Optional callback function that will be called when ajax call completes
270
+ */
271
+ CopernicaField.prototype.repair = function(callback)
272
+ {
273
+ // do the ajax call to create the special field
274
+ this.ajaxCall('repair_field', callback);
275
+ }
package.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Copernica_MarketingSoftware</name>
4
+ <version>1.2.4</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Plugin to exchange data from Magento with Copernica Marketing Software.</summary>
10
+ <description>When you install the integration, all contact, order and shop cart data from Magento will be automatically synchronized and stored in Copernica. By synchronizing data between your Magento webshop and Copernica, you are able to set up targeted email campaigns. For example you can consider emailing customers with abandoned shopcarts automatically every week. Your contacts will only receive information relevant to them, which will make them come back to your shop time and again. The available integration is also compatible with the Magento Enterprise edition.</description>
11
+ <notes>Improvements:&#xD;
12
+ - Deleted an unnecessary SOAP call. &#xD;
13
+ &#xD;
14
+ Bugs:&#xD;
15
+ &#xD;
16
+ - Fixed, when deleting a customer from the backoffice an error occured. </notes>
17
+ <authors><author><name>Cream</name><user>creaminternet</user><email>info@cream.nl</email></author></authors>
18
+ <date>2012-01-20</date>
19
+ <time>10:17:35</time>
20
+ <contents><target name="magecommunity"><dir name="Copernica"><dir name="MarketingSoftware"><dir name="Block"><dir name="Adminhtml"><dir name="Marketingsoftware"><file name="Export.php" hash="a0c98a7b89f2757a7b27c599d8a2f8f8"/><file name="Link.php" hash="15e331131759fedf98c2e461ee97385f"/><file name="Settings.php" hash="f880b7232fdf18d1605885242e9632e8"/></dir></dir></dir><dir name="Helper"><file name="Api.php" hash="cc01df8fbbfd92564163222dec03de95"/><file name="Config.php" hash="331efdf28b14cce05165e2fcac34cf31"/><file name="Data.php" hash="b88354a7e08d1ca7a39f2a59ee25787d"/></dir><dir name="Model"><dir name="Abstraction"><file name="Address.php" hash="75eacde3e77b6b76c85d32ba865a9192"/><file name="Attributes.php" hash="0e5699302fc6575733824acbfee0b445"/><file name="Customer.php" hash="4777627f10de4efa84040988230933fb"/><file name="Name.php" hash="519508275dcac2990532828bd8dbf0ee"/><dir name="Order"><dir name="Item"><file name="Options.php" hash="1c9d5d7c23a5a9f12ff3d777a01fa7d5"/></dir><file name="Item.php" hash="a119a36c52123a78f330ea532d7798d1"/></dir><file name="Order.php" hash="babfe3d247989ac179a83442b4af4100"/><file name="Price.php" hash="bf133886520769200060cf360e0941d6"/><file name="Product.php" hash="461ed687dd25af1b67c358294ad73358"/><dir name="Quote"><dir name="Item"><file name="Options.php" hash="7b7f3e826527fa29ceef8df0ad61c3d3"/></dir><file name="Item.php" hash="a8705d21b21229b521ecdd66f24b9570"/></dir><file name="Quote.php" hash="8e227f1bdcb0608ae5f86f0d6907a8ca"/><file name="Storeview.php" hash="5ae134522abe867554cda35d8acf7457"/><file name="Subscription.php" hash="f4a0bd6bb094b71d6b12b3404f22ea8f"/><file name="readme.txt" hash="d450b7fa3d88b6a5c2b5efa526d17077"/></dir><file name="AsyncPomSoapClient.php" hash="77cc23e1a61cfcc1ee36a33d6e7d6d3e"/><dir name="Copernica"><file name="Abstract.php" hash="b2d065859580ca9c55ac7e8c392db61e"/><dir name="Address"><file name="Subprofile.php" hash="b963f768c25d4790c47deb013de2c44a"/></dir><dir name="Cartitem"><file name="Subprofile.php" hash="5bbb3bee33d774b11ad0f8d794330eec"/></dir><dir name="Order"><file name="Subprofile.php" hash="dc90bdf195538b67276961194ecc6da5"/></dir><dir name="Orderitem"><file name="Subprofile.php" hash="7dc3904bb45c3b0d33e714b7ee101338"/></dir><file name="Profile.php" hash="52f14d70ceaac0066ca35bc3791c906c"/><file name="Profilecustomer.php" hash="5a3e2df1d370c12eccac229941d0f099"/><file name="Profileorder.php" hash="1c2e0c9c844ff2a60c0736f7c8af2442"/><file name="Profilequote.php" hash="0e885b4508698d2bf9835c89b9ce52b9"/><file name="Profilesubscription.php" hash="1f24673069daba911f83b62d9eb34c99"/></dir><file name="Error.php" hash="0660881720c0210c65e25cb14b1011fe"/><file name="Marketingsoftware.php" hash="bd7290f645a46b98da8bf15072bffef5"/><dir name="Mysql4"><dir name="Queue"><file name="Collection.php" hash="64b29b94d61a809a14ff0036888f3596"/></dir><file name="Queue.php" hash="db3f8b50caf3697a61bc1f587259e1ef"/></dir><file name="Observer.php" hash="0dd703b10d7febc5aecce7af7bd51b6d"/><file name="PomSoapClient.php" hash="2dc657ed44acd003df8aef41986aeb88"/><file name="Queue.php" hash="5cad0c42996f2673924e33b5f047fe46"/><dir name="QueueEvent"><file name="Abstract.php" hash="897bb46d1437599b832f9d304eda6832"/><file name="CustomerAdd.php" hash="f2093ea8abc444f7c329ae2884a6cd27"/><file name="CustomerFull.php" hash="f66aaa9afa75c6658958b9ecf7b55cd7"/><file name="CustomerModify.php" hash="a9bd99258679e6ccfdc6011139e90fcc"/><file name="CustomerRemove.php" hash="a061c5646f9c776a38063325f0a39e1b"/><file name="OrderAdd.php" hash="d0b1edb9ed91def6840f29a5b2777901"/><file name="OrderModify.php" hash="a1cb1cdffbf8b8c1a5b4ddbbc5ae0a0b"/><file name="QuoteItem.php" hash="a064df99bbf8d8d3002b03335f5e844b"/><file name="QuoteItemAdd.php" hash="499c4c4d5e34d124918c12bffb72e28b"/><file name="QuoteItemModify.php" hash="f60c728a3b5d3c11451fd6332ecea912"/><file name="QuoteItemRemove.php" hash="a7e4fb9e227ddb538420d0c2b485bb36"/><file name="QuoteModify.php" hash="66bd14c78630895f14c4b48532b2d3a9"/><file name="StartSync.php" hash="a687e69cc9470122611029ccce66b6d8"/><file name="SubscriptionAdd.php" hash="445455dd4fda2867b1ce9d67d7133aaa"/><file name="SubscriptionModify.php" hash="bf59206f322c76cf766b1f33409b946e"/><file name="SubscriptionRemove.php" hash="f3051c5f35e8a6c4bd727d895cad479f"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="Marketingsoftware"><file name="ExportController.php" hash="f22c80e7650e3a2d47f43d9ffab783e9"/><file name="LinkController.php" hash="686554d1960024bb01c2db027ea62b9b"/><file name="SettingsController.php" hash="b62fa5f9c2d37152449530fb6a9a5988"/></dir></dir><file name="ProductController.php" hash="02bcb287f671266a131ddc57c5171754"/><file name="UnsubscribeController.php" hash="691be73c944b1e4fb641803a4271c7a2"/></dir><dir name="etc"><file name="adminhtml.xml" hash="70433e755407e049a938075763e01e6d"/><file name="config.xml" hash="fc9f9fe969e8d887fe2d3f4b83913f8b"/></dir><dir name="sql"><dir name="marketingsoftware_setup"><file name="mysql4-install-1.2.0.php" hash="624d62aad61c642dba4a9488a0b9508f"/><file name="mysql4-upgrade-1.1.5-1.1.6.php" hash="135144b872076048040f4bdae123a08f"/><file name="mysql4-upgrade-1.1.6-1.1.7.php" hash="e587cbbd9c0ddb77248abafef55df46e"/><file name="mysql4-upgrade-1.1.7-1.1.8.php" hash="e255e732e015f852796bde55bde07dd9"/><file name="mysql4-upgrade-1.1.8-1.2.0.php" hash="54fd03029d3a39b556d62ed95ed423f3"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Copernica_MarketingSoftware.xml" hash="04c9e69139dbff42d829bad22fa2ab85"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="marketingsoftware"><file name="export.phtml" hash="4a3783aac318f5683060bc9119893989"/><file name="link.phtml" hash="a0906a990d5a50fde0f523ef99a39f3f"/><file name="settings.phtml" hash="7497c7d74e93797f455d5b47a846bf82"/></dir></dir></dir></dir></dir></target><target name="mageweb"><dir name="js"><dir name="copernica"><dir name="marketingsoftware"><file name="collection.js" hash="260f06a4e891df402e145bec4d15bc51"/><file name="database.js" hash="4e51925d1fedd36a203c625050fb9b07"/><file name="field.js" hash="c4f98de6a9c210c626db36730485b853"/></dir></dir></dir></target></contents>
21
+ <compatible/>
22
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php><extension><name>soap</name><min></min><max></max></extension></required></dependencies>
23
+ </package>