Passed
Push — 328-fieldmap-screen-design-upd... ( 52ae6b...2f6b31 )
by Jonathan
07:17
created

Object_Sync_Sf_Activate::require_ssl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 1
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * What to do when the plugin is activated
4
 *
5
 * @class   Object_Sync_Sf_Activate
6
 * @package Object_Sync_Salesforce
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * Object_Sync_Sf_Activate class.
13
 */
14
class Object_Sync_Sf_Activate {
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
	 * Object_Sync_Sf_Queue class
74
	 *
75
	 * @var object
76
	 */
77
	public $queue;
78
79
	/**
80
	 * Constructor for activate class
81
	 */
82
	public function __construct() {
83
		$this->version                = object_sync_for_salesforce()->version;
84
		$this->user_installed_version = object_sync_for_salesforce()->user_installed_version;
85
		$this->file                   = object_sync_for_salesforce()->file;
86
		$this->wpdb                   = object_sync_for_salesforce()->wpdb;
87
		$this->slug                   = object_sync_for_salesforce()->slug;
88
		$this->option_prefix          = object_sync_for_salesforce()->option_prefix;
89
		$this->action_group_suffix    = object_sync_for_salesforce()->action_group_suffix;
90
91
		$this->schedulable_classes = object_sync_for_salesforce()->schedulable_classes;
92
		$this->queue               = object_sync_for_salesforce()->queue;
93
94
		$this->add_actions();
95
	}
96
97
	/**
98
	 * Activation hooks
99
	 */
100
	private function add_actions() {
101
102
		// on initial activation, run these hooks.
103
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'php_requirements' ) );
104
		// to maybe add later:
105
		// register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'require_ssl' ) );
106
		// if we determine we need to check for SSL on activation.
107
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'wordpress_salesforce_tables' ) );
108
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'add_roles_capabilities' ) );
109
110
		// this should run when the user is in the admin area to make sure the database gets updated.
111
		add_action( 'admin_init', array( $this, 'wordpress_salesforce_update_db_check' ), 10 );
112
113
		// when users upgrade the plugin, run these hooks.
114
		add_action( 'upgrader_process_complete', array( $this, 'check_for_action_scheduler' ), 10, 2 );
115
	}
116
117
	/**
118
	 * Check for the minimum required version of php
119
	 */
120
	public function php_requirements() {
121
		if ( version_compare( PHP_VERSION, '5.6.20', '<' ) ) {
122
			deactivate_plugins( plugin_basename( __FILE__ ) );
123
			wp_die( '<strong>This plugin requires PHP Version 5.6.20</strong> <br />Please contact your host to upgrade PHP on your server, and then retry activating the plugin.' );
124
		}
125
	}
126
127
	/**
128
	 * Require SSL because otherwise the plugin will not authorize
129
	 */
130
	public function require_ssl() {
131
		// although we might instead have to run this on plugin initalization rather than activation.
132
	}
133
134
	/**
135
	 * Create database tables for Salesforce
136
	 * This creates tables for fieldmaps (between types of objects) and object maps (between individual instances of objects).
137
	 * Important requirement for developers: when you update the SQL for either of these tables, also update it in the documentation file located at /docs/troubleshooting-unable-to-create-database-tables.md and make sure that is included in your commit(s).
138
	 */
139
	public function wordpress_salesforce_tables() {
140
141
		$charset_collate = $this->wpdb->get_charset_collate();
142
143
		$field_map_table = $this->wpdb->prefix . 'object_sync_sf_field_map';
144
		$field_map_sql   = "CREATE TABLE $field_map_table (
145
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
146
			label varchar(64) NOT NULL DEFAULT '',
147
			name varchar(64) NOT NULL DEFAULT '',
148
			wordpress_object varchar(128) NOT NULL DEFAULT '',
149
			wordpress_object_default_status varchar(255) NOT NULL DEFAULT '',
150
			salesforce_object varchar(255) NOT NULL DEFAULT '',
151
			salesforce_record_types_allowed longblob,
152
			salesforce_record_type_default varchar(255) NOT NULL DEFAULT '',
153
			fields longtext NOT NULL,
154
			pull_trigger_field varchar(128) NOT NULL DEFAULT 'LastModifiedDate',
155
			sync_triggers text NOT NULL,
156
			push_async tinyint(1) NOT NULL DEFAULT '0',
157
			push_drafts tinyint(1) NOT NULL DEFAULT '0',
158
			pull_to_drafts tinyint(1) NOT NULL DEFAULT '0',
159
			weight tinyint(1) NOT NULL DEFAULT '0',
160
			version varchar(255) NOT NULL DEFAULT '',
161
			PRIMARY KEY  (id),
162
			UNIQUE KEY name (name),
163
			KEY name_sf_type_wordpress_type (wordpress_object,salesforce_object)
164
		) ENGINE=InnoDB $charset_collate";
165
166
		$object_map_table = $this->wpdb->prefix . 'object_sync_sf_object_map';
167
		$object_map_sql   = "CREATE TABLE $object_map_table (
168
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
169
			wordpress_id varchar(32) NOT NULL,
170
			salesforce_id varbinary(32) NOT NULL DEFAULT '',
171
			wordpress_object varchar(128) NOT NULL DEFAULT '',
172
			created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
173
			object_updated datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
174
			last_sync datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
175
			last_sync_action varchar(128) DEFAULT NULL,
176
			last_sync_status tinyint(1) NOT NULL DEFAULT '0',
177
			last_sync_message varchar(255) DEFAULT NULL,
178
			PRIMARY KEY  (id),
179
			KEY wordpress_object (wordpress_object,wordpress_id),
180
			KEY salesforce_object (salesforce_id)
181
		) $charset_collate";
182
183
		if ( ! function_exists( 'dbDelta' ) ) {
184
			if ( ! is_admin() ) {
185
				return false;
186
			}
187
			require_once ABSPATH . 'wp-admin/includes/upgrade.php';
188
		}
189
190
		// Note: see https://wordpress.stackexchange.com/questions/67345/how-to-implement-wordpress-plugin-update-that-modifies-the-database
191
		// When we run the dbDelta method below, "it checks if the table exists. What's more, it checks the column types. So if the table doesn't exist, it creates it, if it does, but some column types have changed it updates them, and if a column doesn't exists - it adds it."
192
		// This does not remove columns if we remove columns, so we'll need to expand beyond this in the future if that happens, although I think the schema is pretty solid now.
193
		$result_field_map  = dbDelta( $field_map_sql );
194
		$result_object_map = dbDelta( $object_map_sql );
195
196
		$remove_key_version = '1.8.0';
197
		if ( '' !== $this->user_installed_version && version_compare( $this->user_installed_version, $remove_key_version, '<' ) ) {
198
			$wpdb = $this->wpdb;
199
			$wpdb->query( $wpdb->prepare( 'ALTER TABLE %s DROP INDEX salesforce', $object_map_table ) );
200
			$wpdb->query( $wpdb->prepare( 'ALTER TABLE %s DROP INDEX salesforce_wordpress', $object_map_table ) );
201
			$result_key = true;
202
		}
203
204
		// store right now as the time for the plugin's activation.
205
		update_option( $this->option_prefix . 'activate_time', time() );
206
207
		// utf8mb4 conversion.
208
		maybe_convert_table_to_utf8mb4( $field_map_table );
209
		maybe_convert_table_to_utf8mb4( $object_map_table );
210
211
		if ( '' === $this->user_installed_version || version_compare( $this->user_installed_version, $this->version, '<' ) ) {
212
			update_option( $this->option_prefix . 'db_version', $this->version );
213
		}
214
215
		if ( ! isset( $result_key ) && empty( $result_field_map ) && empty( $result_object_map ) ) {
216
			// No changes, database already exists and is up-to-date.
217
			return;
218
		}
219
220
	}
221
222
	/**
223
	 * Add roles and capabilities
224
	 * This adds the configure_salesforce capability to the admin role
225
	 *
226
	 * It also allows other plugins to add the capability to other roles
227
	 */
228
	public function add_roles_capabilities() {
229
230
		// by default, only administrators can configure the plugin.
231
		$role = get_role( 'administrator' );
232
		$role->add_cap( 'configure_salesforce' );
233
234
		// hook that allows other roles to configure the plugin as well.
235
		$roles = apply_filters( $this->option_prefix . 'roles_configure_salesforce', null );
236
237
		// for each role that we have, give it the configure salesforce capability.
238
		if ( null !== $roles ) {
239
			foreach ( $roles as $role ) {
240
				$role = get_role( $role );
241
				$role->add_cap( 'configure_salesforce' );
242
			}
243
		}
244
245
	}
246
247
	/**
248
	 * Check for database version
249
	 * When the plugin is loaded in the admin, if the database version does not match the current version, perform these methods
250
	 */
251
	public function wordpress_salesforce_update_db_check() {
252
253
		// user is running a version less than the current one.
254
		if ( version_compare( $this->user_installed_version, $this->version, '<' ) ) {
255
			$this->log_trigger_settings();
256
			$this->wordpress_salesforce_tables();
257
		} else {
258
			return true;
259
		}
260
	}
261
262
	/**
263
	 * Check for log trigger settings based on plugin version
264
	 * When the plugin is loaded in the admin, if the previously installed version is below 2.0.0, update the values for the log trigger settings.
265
	 */
266
	private function log_trigger_settings() {
267
		$triggers_to_log = get_option( $this->option_prefix . 'triggers_to_log', array() );
268
		if ( ! empty( $triggers_to_log ) ) {
269
			// in version 2.0.0 of this plugin, we replaced the bit flags with strings to make them more legible.
270
			// when the database version changes to 2.0.0, we should update the option value to use the new strings.
271
			if ( version_compare( $this->version, '2.0.0', '==' ) && version_compare( $this->user_installed_version, '2.0.0', '<' ) ) {
272
				$mappings                = new Object_Sync_Sf_Mapping();
273
				$updated_triggers_to_log = array();
274
				foreach ( $triggers_to_log as $key => $value ) {
275
					if ( (string) $value === (string) $mappings->sync_off_v1 ) {
276
						$updated_triggers_to_log[] = $mappings->sync_off;
277
					}
278
					if ( (string) $value === (string) $mappings->sync_wordpress_create_v1 ) {
279
						$updated_triggers_to_log[] = $mappings->sync_wordpress_create;
280
					}
281
					if ( (string) $value === (string) $mappings->sync_wordpress_update_v1 ) {
282
						$updated_triggers_to_log[] = $mappings->sync_wordpress_update;
283
					}
284
					if ( (string) $value === (string) $mappings->sync_wordpress_delete_v1 ) {
285
						$updated_triggers_to_log[] = $mappings->sync_wordpress_delete;
286
					}
287
					if ( (string) $value === (string) $mappings->sync_sf_create_v1 ) {
288
						$updated_triggers_to_log[] = $mappings->sync_sf_create;
289
					}
290
					if ( (string) $value === (string) $mappings->sync_sf_update_v1 ) {
291
						$updated_triggers_to_log[] = $mappings->sync_sf_update;
292
					}
293
					if ( (string) $value === (string) $mappings->sync_sf_delete_v1 ) {
294
						$updated_triggers_to_log[] = $mappings->sync_sf_delete;
295
					}
296
				}
297
				$triggers_to_log = $updated_triggers_to_log;
298
				update_option( $this->option_prefix . 'triggers_to_log', $triggers_to_log );
299
			}
300
		}
301
	}
302
303
	/**
304
	 * Check whether the user has ActionScheduler tasks when they upgrade
305
	 *
306
	 * @param object $upgrader_object this is the WP_Upgrader object.
307
	 * @param array  $hook_extra the array of bulk item update data.
308
	 * @see https://developer.wordpress.org/reference/hooks/upgrader_process_complete/
309
	 * @deprecated since 2.0.0.
310
	 */
311
	public function check_for_action_scheduler( $upgrader_object, $hook_extra ) {
312
313
		// skip if this action isn't this plugin being updated.
314
		if ( 'plugin' !== $hook_extra['type'] && 'update' !== $hook_extra['action'] && $hook_extra['plugin'] !== $this->slug ) {
315
			return;
316
		}
317
318
		// user is running a version of this plugin that is less than 1.4.0.
319
		$action_scheduler_version = '1.4.0';
320
		$previous_version         = get_transient( $this->option_prefix . 'installed_version' );
321
		if ( version_compare( $previous_version, $action_scheduler_version, '<' ) ) {
322
			// delete old options.
323
			delete_option( $this->option_prefix . 'push_schedule_number' );
324
			delete_option( $this->option_prefix . 'push_schedule_unit' );
325
			delete_option( $this->option_prefix . 'salesforce_schedule_number' );
326
			delete_option( $this->option_prefix . 'salesforce_schedule_unit' );
327
			if ( '' === $this->queue ) {
0 ignored issues
show
introduced by
The condition '' === $this->queue is always false.
Loading history...
328
				delete_transient( $this->option_prefix . 'installed_version' );
329
				return;
330
			}
331
			foreach ( $this->schedulable_classes as $key => $schedule ) {
332
				$schedule_name     = $key;
333
				$action_group_name = $schedule_name . $this->action_group_suffix;
334
				// exit if there is no initializer property on this schedule.
335
				if ( ! isset( $this->schedulable_classes[ $schedule_name ]['initializer'] ) ) {
336
					continue;
337
				}
338
				// create new recurring task for ActionScheduler to check for data to pull from Salesforce.
339
				$this->queue->schedule_recurring(
340
					time(), // plugin seems to expect UTC.
341
					$this->queue->get_frequency( $schedule_name, 'seconds' ),
342
					$this->schedulable_classes[ $schedule_name ]['initializer'],
343
					array(),
344
					$action_group_name
345
				);
346
			}
347
			delete_transient( $this->option_prefix . 'installed_version' );
348
		}
349
	}
350
351
}
352