|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* The main plugin class |
|
4
|
|
|
* |
|
5
|
|
|
* @class Object_Sync_Salesforce |
|
6
|
|
|
* @package Object_Sync_Salesforce |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
defined( 'ABSPATH' ) || exit; |
|
10
|
|
|
|
|
11
|
|
|
/** |
|
12
|
|
|
* Object_Sync_Salesforce class. |
|
13
|
|
|
*/ |
|
14
|
|
|
class Object_Sync_Salesforce { |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Current version of the plugin |
|
18
|
|
|
* |
|
19
|
|
|
* @var string |
|
20
|
|
|
*/ |
|
21
|
|
|
public $version; |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* The user's installed version of this plugin's database setup |
|
25
|
|
|
* |
|
26
|
|
|
* @var string |
|
27
|
|
|
*/ |
|
28
|
|
|
public $user_installed_version; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* The main plugin file |
|
32
|
|
|
* |
|
33
|
|
|
* @var string |
|
34
|
|
|
*/ |
|
35
|
|
|
public $file; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* Global object of `$wpdb`, the WordPress database |
|
39
|
|
|
* |
|
40
|
|
|
* @var object |
|
41
|
|
|
*/ |
|
42
|
|
|
public $wpdb; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* The plugin's slug so we can include it when necessary |
|
46
|
|
|
* |
|
47
|
|
|
* @var string |
|
48
|
|
|
*/ |
|
49
|
|
|
public $slug; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* The plugin's prefix when saving options to the database |
|
53
|
|
|
* |
|
54
|
|
|
* @var string |
|
55
|
|
|
*/ |
|
56
|
|
|
public $option_prefix; |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* Suffix for group name in ActionScheduler |
|
60
|
|
|
* |
|
61
|
|
|
* @var string |
|
62
|
|
|
*/ |
|
63
|
|
|
public $action_group_suffix; |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Array of what classes in the plugin can be scheduled to occur with `wp_cron` events |
|
67
|
|
|
* |
|
68
|
|
|
* @var array |
|
69
|
|
|
*/ |
|
70
|
|
|
public $schedulable_classes; |
|
71
|
|
|
|
|
72
|
|
|
/** |
|
73
|
|
|
* Legacy property that holds an instance of the plugin class. |
|
74
|
|
|
* |
|
75
|
|
|
* @var object |
|
76
|
|
|
* @deprecated since 2.0.0 |
|
77
|
|
|
*/ |
|
78
|
|
|
public static $instance; |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
|
|
* Object_Sync_Sf_Queue class |
|
82
|
|
|
* |
|
83
|
|
|
* @var object |
|
84
|
|
|
*/ |
|
85
|
|
|
public $queue; |
|
86
|
|
|
|
|
87
|
|
|
/** |
|
88
|
|
|
* Object_Sync_Sf_Activate class |
|
89
|
|
|
* |
|
90
|
|
|
* @var object |
|
91
|
|
|
*/ |
|
92
|
|
|
private $activated; |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* Tells us if composer has been autoloaded |
|
96
|
|
|
* |
|
97
|
|
|
* @var bool |
|
98
|
|
|
*/ |
|
99
|
|
|
private $composer_loaded; |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Login credentials for the Salesforce API; comes from wp-config or from the plugin settings |
|
103
|
|
|
* |
|
104
|
|
|
* @var array |
|
105
|
|
|
*/ |
|
106
|
|
|
public $login_credentials; |
|
107
|
|
|
|
|
108
|
|
|
/** |
|
109
|
|
|
* Object_Sync_Sf_Logging class |
|
110
|
|
|
* |
|
111
|
|
|
* @var object |
|
112
|
|
|
*/ |
|
113
|
|
|
public $logging; |
|
114
|
|
|
|
|
115
|
|
|
/** |
|
116
|
|
|
* Object_Sync_Sf_Mapping class |
|
117
|
|
|
* |
|
118
|
|
|
* @var object |
|
119
|
|
|
*/ |
|
120
|
|
|
public $mappings; |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Object_Sync_Sf_WordPress class |
|
124
|
|
|
* |
|
125
|
|
|
* @var object |
|
126
|
|
|
*/ |
|
127
|
|
|
public $wordpress; |
|
128
|
|
|
|
|
129
|
|
|
/** |
|
130
|
|
|
* Object_Sync_Sf_Salesforce class |
|
131
|
|
|
* This contains Salesforce API methods |
|
132
|
|
|
* |
|
133
|
|
|
* @var array |
|
134
|
|
|
*/ |
|
135
|
|
|
public $salesforce; |
|
136
|
|
|
|
|
137
|
|
|
/** |
|
138
|
|
|
* Object_Sync_Sf_Salesforce_Push class |
|
139
|
|
|
* |
|
140
|
|
|
* @var object |
|
141
|
|
|
*/ |
|
142
|
|
|
public $push; |
|
143
|
|
|
|
|
144
|
|
|
/** |
|
145
|
|
|
* Object_Sync_Sf_Salesforce_Pull class |
|
146
|
|
|
* |
|
147
|
|
|
* @var object |
|
148
|
|
|
*/ |
|
149
|
|
|
public $pull; |
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* Object_Sync_Sf_Rest class |
|
153
|
|
|
* |
|
154
|
|
|
* @var object |
|
155
|
|
|
*/ |
|
156
|
|
|
private $rest; |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* This is our constructor |
|
160
|
|
|
* |
|
161
|
|
|
* @param string $version is the plugin version. |
|
162
|
|
|
* @param string $file is the main plugin file. |
|
163
|
|
|
* @return void |
|
164
|
|
|
*/ |
|
165
|
|
|
public function __construct( $version, $file ) { |
|
166
|
|
|
|
|
167
|
|
|
global $wpdb; |
|
168
|
|
|
|
|
169
|
|
|
$this->version = $version; |
|
170
|
|
|
$this->user_installed_version = get_option( $this->option_prefix . 'db_version', $this->version ); |
|
|
|
|
|
|
171
|
|
|
$this->file = $file; |
|
172
|
|
|
$this->wpdb = $wpdb; |
|
173
|
|
|
$this->slug = 'object-sync-for-salesforce'; |
|
174
|
|
|
$this->option_prefix = 'object_sync_for_salesforce_'; |
|
175
|
|
|
$this->action_group_suffix = '_check_records'; |
|
176
|
|
|
|
|
177
|
|
|
$this->schedulable_classes = array( |
|
178
|
|
|
'salesforce_push' => array( |
|
179
|
|
|
'label' => 'Push to Salesforce', |
|
180
|
|
|
'class' => 'Object_Sync_Sf_Salesforce_Push', |
|
181
|
|
|
'callback' => $this->option_prefix . 'push_record', |
|
182
|
|
|
), |
|
183
|
|
|
'salesforce_pull' => array( |
|
184
|
|
|
'label' => 'Pull from Salesforce', |
|
185
|
|
|
'class' => 'Object_Sync_Sf_Salesforce_Pull', |
|
186
|
|
|
'initializer' => $this->option_prefix . 'pull_check_records', |
|
187
|
|
|
'callback' => $this->option_prefix . 'pull_process_records', |
|
188
|
|
|
), |
|
189
|
|
|
); |
|
190
|
|
|
|
|
191
|
|
|
// users can modify the list of schedulable classes. |
|
192
|
|
|
$this->schedulable_classes = apply_filters( $this->option_prefix . 'modify_schedulable_classes', $this->schedulable_classes ); |
|
193
|
|
|
|
|
194
|
|
|
/* // phpcs:ignore Squiz.PHP.CommentedOutCode.Found |
|
195
|
|
|
* example to modify the array of classes by adding one and removing one |
|
196
|
|
|
* add_filter( 'object_sync_for_salesforce_modify_schedulable_classes', 'modify_schedulable_classes', 10, 1 ); |
|
197
|
|
|
* function modify_schedulable_classes( $schedulable_classes ) { |
|
198
|
|
|
* $schedulable_classes = array( |
|
199
|
|
|
* 'salesforce_push' => array( |
|
200
|
|
|
* 'label' => 'Push to Salesforce', |
|
201
|
|
|
* 'class' => 'Object_Sync_Sf_Salesforce_Push', |
|
202
|
|
|
* 'callback' => 'salesforce_push_sync_rest', |
|
203
|
|
|
* ), |
|
204
|
|
|
* 'wordpress' => array( // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled |
|
205
|
|
|
* 'label' => 'WordPress', |
|
206
|
|
|
* 'class' => 'Object_Sync_Sf_WordPress', |
|
207
|
|
|
* ), |
|
208
|
|
|
* 'salesforce' => array( |
|
209
|
|
|
* 'label' => 'Salesforce Authorization', |
|
210
|
|
|
* 'class' => 'Object_Sync_Sf_Salesforce', |
|
211
|
|
|
* ), |
|
212
|
|
|
* ); |
|
213
|
|
|
* return $schedulable_classes; |
|
214
|
|
|
* } |
|
215
|
|
|
*/ |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
|
|
/** |
|
219
|
|
|
* Load the static $instance property that holds the instance of the class. |
|
220
|
|
|
* This is preserved for legacy usage, as the same thing exists in the `object_sync_for_salesforce` function. |
|
221
|
|
|
* |
|
222
|
|
|
* @return object $plugin |
|
223
|
|
|
* @deprecated since 2.0.0 |
|
224
|
|
|
*/ |
|
225
|
|
|
public static function get_instance() { |
|
226
|
|
|
|
|
227
|
|
|
if ( function_exists( 'object_sync_for_salesforce' ) ) { |
|
228
|
|
|
return object_sync_for_salesforce(); |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
static $plugin; |
|
232
|
|
|
|
|
233
|
|
|
if ( is_null( $plugin ) ) { |
|
234
|
|
|
$plugin = new Object_Sync_Salesforce( OBJECT_SYNC_SF_VERSION, OBJECT_SYNC_SF_FILE ); |
|
235
|
|
|
} |
|
236
|
|
|
|
|
237
|
|
|
return $plugin; |
|
238
|
|
|
} |
|
239
|
|
|
|
|
240
|
|
|
/** |
|
241
|
|
|
* Initialize the plugin and start the action hooks. |
|
242
|
|
|
* We run this separately because activate can't run without the right priority. |
|
243
|
|
|
*/ |
|
244
|
|
|
public function init() { |
|
245
|
|
|
|
|
246
|
|
|
// methods for the ActionScheduler queue. This needs to be loaded early because it is used during activation. |
|
247
|
|
|
$this->queue = new Object_Sync_Sf_Queue(); |
|
248
|
|
|
|
|
249
|
|
|
// methods for activation. |
|
250
|
|
|
$this->activated = new Object_Sync_Sf_Activate(); |
|
251
|
|
|
|
|
252
|
|
|
// action hooks. |
|
253
|
|
|
$this->add_actions(); |
|
254
|
|
|
} |
|
255
|
|
|
|
|
256
|
|
|
/** |
|
257
|
|
|
* Run non-activation actions. |
|
258
|
|
|
* We do this on -10 because ActionScheduler has to have access to plugins_loaded with priority of zero. |
|
259
|
|
|
*/ |
|
260
|
|
|
private function add_actions() { |
|
261
|
|
|
// public actions. |
|
262
|
|
|
add_action( 'plugins_loaded', array( $this, 'run' ), -10 ); |
|
263
|
|
|
add_action( 'plugins_loaded', array( $this, 'textdomain' ) ); |
|
264
|
|
|
} |
|
265
|
|
|
|
|
266
|
|
|
/** |
|
267
|
|
|
* Run the plugin, independent of activation methods. |
|
268
|
|
|
*/ |
|
269
|
|
|
public function run() { |
|
270
|
|
|
|
|
271
|
|
|
$this->composer_loaded = $this->composer_loaded(); |
|
272
|
|
|
|
|
273
|
|
|
$this->login_credentials = $this->get_login_credentials(); |
|
274
|
|
|
|
|
275
|
|
|
// methods for deactivation. |
|
276
|
|
|
$deactivate = new Object_Sync_Sf_Deactivate(); |
|
277
|
|
|
|
|
278
|
|
|
// logging methods. |
|
279
|
|
|
$this->logging = new Object_Sync_Sf_Logging(); |
|
280
|
|
|
|
|
281
|
|
|
// methods for fieldmaps and object maps. |
|
282
|
|
|
$this->mappings = new Object_Sync_Sf_Mapping(); |
|
283
|
|
|
|
|
284
|
|
|
// methods for WordPress. |
|
285
|
|
|
$this->wordpress = new Object_Sync_Sf_WordPress(); |
|
286
|
|
|
|
|
287
|
|
|
// methods for calling the Salesforce API. |
|
288
|
|
|
$this->salesforce = $this->salesforce_get_api(); |
|
289
|
|
|
|
|
290
|
|
|
// methods to push to Salesforce. |
|
291
|
|
|
$this->push = new Object_Sync_Sf_Salesforce_Push(); |
|
292
|
|
|
|
|
293
|
|
|
// methods to pull from Salesforce. |
|
294
|
|
|
$this->pull = new Object_Sync_Sf_Salesforce_Pull(); |
|
295
|
|
|
|
|
296
|
|
|
$this->rest = new Object_Sync_Sf_Rest(); |
|
297
|
|
|
|
|
298
|
|
|
// admin functionality. |
|
299
|
|
|
new Object_Sync_Sf_Admin(); |
|
300
|
|
|
} |
|
301
|
|
|
|
|
302
|
|
|
/** |
|
303
|
|
|
* Autoload things from Composer. |
|
304
|
|
|
* |
|
305
|
|
|
* @return bool true |
|
306
|
|
|
*/ |
|
307
|
|
|
private function composer_loaded() { |
|
308
|
|
|
require_once plugin_dir_path( $this->file ) . 'vendor/autoload.php'; |
|
309
|
|
|
return true; |
|
310
|
|
|
} |
|
311
|
|
|
|
|
312
|
|
|
/** |
|
313
|
|
|
* Get the pre-login Salesforce credentials. |
|
314
|
|
|
* These depend on the plugin's settings or constants defined in wp-config.php. |
|
315
|
|
|
* |
|
316
|
|
|
* @return array $login_credentials |
|
317
|
|
|
*/ |
|
318
|
|
|
private function get_login_credentials() { |
|
319
|
|
|
|
|
320
|
|
|
$consumer_key = defined( 'OBJECT_SYNC_SF_SALESFORCE_CONSUMER_KEY' ) ? OBJECT_SYNC_SF_SALESFORCE_CONSUMER_KEY : get_option( $this->option_prefix . 'consumer_key', '' ); |
|
|
|
|
|
|
321
|
|
|
$consumer_secret = defined( 'OBJECT_SYNC_SF_SALESFORCE_CONSUMER_SECRET' ) ? OBJECT_SYNC_SF_SALESFORCE_CONSUMER_SECRET : get_option( $this->option_prefix . 'consumer_secret', '' ); |
|
|
|
|
|
|
322
|
|
|
$callback_url = defined( 'OBJECT_SYNC_SF_SALESFORCE_CALLBACK_URL' ) ? OBJECT_SYNC_SF_SALESFORCE_CALLBACK_URL : get_option( $this->option_prefix . 'callback_url', '' ); |
|
|
|
|
|
|
323
|
|
|
$login_base_url = defined( 'OBJECT_SYNC_SF_SALESFORCE_LOGIN_BASE_URL' ) ? OBJECT_SYNC_SF_SALESFORCE_LOGIN_BASE_URL : get_option( $this->option_prefix . 'login_base_url', '' ); |
|
|
|
|
|
|
324
|
|
|
$authorize_url_path = defined( 'OBJECT_SYNC_SF_SALESFORCE_AUTHORIZE_URL_PATH' ) ? OBJECT_SYNC_SF_SALESFORCE_AUTHORIZE_URL_PATH : get_option( $this->option_prefix . 'authorize_url_path', '' ); |
|
|
|
|
|
|
325
|
|
|
$token_url_path = defined( 'OBJECT_SYNC_SF_SALESFORCE_TOKEN_URL_PATH' ) ? OBJECT_SYNC_SF_SALESFORCE_TOKEN_URL_PATH : get_option( $this->option_prefix . 'token_url_path', '' ); |
|
|
|
|
|
|
326
|
|
|
$api_version = defined( 'OBJECT_SYNC_SF_SALESFORCE_API_VERSION' ) ? OBJECT_SYNC_SF_SALESFORCE_API_VERSION : get_option( $this->option_prefix . 'api_version', '' ); |
|
|
|
|
|
|
327
|
|
|
|
|
328
|
|
|
$login_credentials = array( |
|
329
|
|
|
'consumer_key' => $consumer_key, |
|
330
|
|
|
'consumer_secret' => $consumer_secret, |
|
331
|
|
|
'callback_url' => $callback_url, |
|
332
|
|
|
'login_url' => $login_base_url, |
|
333
|
|
|
'authorize_path' => $authorize_url_path, |
|
334
|
|
|
'token_path' => $token_url_path, |
|
335
|
|
|
'rest_api_version' => $api_version, |
|
336
|
|
|
); |
|
337
|
|
|
|
|
338
|
|
|
return $login_credentials; |
|
339
|
|
|
|
|
340
|
|
|
} |
|
341
|
|
|
|
|
342
|
|
|
/** |
|
343
|
|
|
* Public helper to load the Salesforce API and see if it is authenticated. |
|
344
|
|
|
* This is public so other plugins can access the same SF API instance we use. |
|
345
|
|
|
* |
|
346
|
|
|
* @return array |
|
347
|
|
|
*/ |
|
348
|
|
|
public function salesforce_get_api() { |
|
349
|
|
|
|
|
350
|
|
|
$soap_available = $this->is_soap_available(); |
|
351
|
|
|
$soap_loaded = $this->is_soap_loaded(); |
|
352
|
|
|
|
|
353
|
|
|
$consumer_key = $this->login_credentials['consumer_key']; |
|
354
|
|
|
$consumer_secret = $this->login_credentials['consumer_secret']; |
|
355
|
|
|
$is_authorized = false; |
|
356
|
|
|
$sfapi = ''; |
|
357
|
|
|
if ( $consumer_key && $consumer_secret ) { |
|
358
|
|
|
$sfapi = new Object_Sync_Sf_Salesforce(); |
|
359
|
|
|
if ( true === $sfapi->is_authorized() ) { |
|
360
|
|
|
$is_authorized = true; |
|
361
|
|
|
} |
|
362
|
|
|
} |
|
363
|
|
|
|
|
364
|
|
|
return array( |
|
365
|
|
|
'is_authorized' => $is_authorized, |
|
366
|
|
|
'sfapi' => $sfapi, |
|
367
|
|
|
'soap_available' => $soap_available, |
|
368
|
|
|
'soap_loaded' => $soap_loaded, |
|
369
|
|
|
); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
/** |
|
373
|
|
|
* Load textdomain |
|
374
|
|
|
*/ |
|
375
|
|
|
public function textdomain() { |
|
376
|
|
|
load_plugin_textdomain( 'object-sync-for-salesforce', false, dirname( plugin_basename( $this->file ) ) . '/languages/' ); |
|
377
|
|
|
} |
|
378
|
|
|
|
|
379
|
|
|
/** |
|
380
|
|
|
* Check the server to see if Soap is available |
|
381
|
|
|
* |
|
382
|
|
|
* @return bool $is_soap_available |
|
383
|
|
|
*/ |
|
384
|
|
|
private function is_soap_available() { |
|
385
|
|
|
$is_soap_available = false; |
|
386
|
|
|
if ( extension_loaded( 'soap' ) && class_exists( 'SoapClient' ) ) { |
|
387
|
|
|
$is_soap_available = true; |
|
388
|
|
|
} |
|
389
|
|
|
return $is_soap_available; |
|
390
|
|
|
} |
|
391
|
|
|
|
|
392
|
|
|
/** |
|
393
|
|
|
* Check the plugin to see if the Soap option has been enabled and the class has been loaded |
|
394
|
|
|
* |
|
395
|
|
|
* @return bool $is_soap_loaded |
|
396
|
|
|
*/ |
|
397
|
|
|
private function is_soap_loaded() { |
|
398
|
|
|
$is_soap_loaded = false; |
|
399
|
|
|
if ( false === $this->is_soap_available() ) { |
|
400
|
|
|
return $is_soap_loaded; |
|
401
|
|
|
} |
|
402
|
|
|
$use_soap = filter_var( get_option( 'object_sync_for_salesforce_use_soap', false ), FILTER_VALIDATE_BOOLEAN ); |
|
403
|
|
|
if ( false === $use_soap ) { |
|
404
|
|
|
return $is_soap_loaded; |
|
405
|
|
|
} |
|
406
|
|
|
if ( class_exists( 'Object_Sync_Sf_Salesforce_Soap_Partner' ) ) { |
|
407
|
|
|
$is_soap_loaded = true; |
|
408
|
|
|
} |
|
409
|
|
|
return $is_soap_loaded; |
|
410
|
|
|
} |
|
411
|
|
|
|
|
412
|
|
|
} // end class |
|
413
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.