Passed
Pull Request — master (#386)
by Jonathan
04:40 queued 01:02
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 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 1
rs 10
1
<?php
2
/**
3
 * Class file for the Object_Sync_Sf_Activate class.
4
 *
5
 * @file
6
 */
7
8
if ( ! class_exists( 'Object_Sync_Salesforce' ) ) {
9
	die();
10
}
11
12
/**
13
 * What to do when the plugin is activated
14
 */
15
class Object_Sync_Sf_Activate {
16
17
	protected $wpdb;
18
	protected $version;
19
	protected $slug;
20
	protected $option_prefix;
21
	protected $schedulable_classes;
22
	protected $queue;
23
24
	private $action_group_suffix;
25
	private $user_installed_version;
26
27
	/**
28
	* Constructor which sets up activate hooks
29
	*
30
	* @param object $wpdb
31
	* @param string $version
32
	* @param string $slug
33
	* @param string $option_prefix
34
	* @param array $schedulable_classes
35
	* @param object $queue
36
	*
37
	*/
38
	public function __construct( $wpdb, $version, $slug, $option_prefix = '', $schedulable_classes = array(), $queue = '' ) {
39
		$this->wpdb                = $wpdb;
40
		$this->version             = $version;
41
		$this->slug                = $slug;
42
		$this->option_prefix       = isset( $option_prefix ) ? $option_prefix : 'object_sync_for_salesforce_';
43
		$this->schedulable_classes = $schedulable_classes;
44
		$this->queue               = $queue;
45
46
		$this->action_group_suffix    = '_check_records';
47
		$this->user_installed_version = get_option( $this->option_prefix . 'db_version', '' );
48
49
		$this->add_actions();
50
	}
51
52
	/**
53
	* Activation hooks
54
	*/
55
	private function add_actions() {
56
57
		// on initial activation, run these hooks
58
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'php_requirements' ) );
59
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'require_ssl' ) );
60
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'wordpress_salesforce_tables' ) );
61
		register_activation_hook( dirname( __DIR__ ) . '/' . $this->slug . '.php', array( $this, 'add_roles_capabilities' ) );
62
63
		// this should run when the user is in the admin area to make sure the database gets updated
64
		add_action( 'admin_init', array( $this, 'wordpress_salesforce_update_db_check' ), 10 );
65
66
		// when users upgrade the plugin, run these hooks
67
		add_action( 'upgrader_process_complete', array( $this, 'check_for_action_scheduler' ), 10, 2 );
68
	}
69
70
	/**
71
	* Check for the minimum required version of php
72
	*/
73
	public function php_requirements() {
74
		if ( version_compare( PHP_VERSION, '5.6.20', '<' ) ) {
75
			deactivate_plugins( plugin_basename( __FILE__ ) );
76
			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.' );
77
		}
78
	}
79
80
	/**
81
	* Require SSL because otherwise the plugin will not authorize
82
	*/
83
	public function require_ssl() {
84
		// although we might instead have to run this on plugin initalization rather than activation.
85
	}
86
87
	/**
88
	* Create database tables for Salesforce
89
	* This creates tables for fieldmaps (between types of objects) and object maps (between individual instances of objects).
90
	* 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).
91
	*
92
	*/
93
	public function wordpress_salesforce_tables() {
94
95
		$charset_collate = $this->wpdb->get_charset_collate();
96
97
		$field_map_table = $this->wpdb->prefix . 'object_sync_sf_field_map';
98
		$field_map_sql   = "CREATE TABLE $field_map_table (
99
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
100
			label varchar(64) NOT NULL DEFAULT '',
101
			name varchar(64) NOT NULL DEFAULT '',
102
			wordpress_object varchar(128) NOT NULL DEFAULT '',
103
			salesforce_object varchar(255) NOT NULL DEFAULT '',
104
			salesforce_record_types_allowed longblob,
105
			salesforce_record_type_default varchar(255) NOT NULL DEFAULT '',
106
			fields longtext NOT NULL,
107
			pull_trigger_field varchar(128) NOT NULL DEFAULT 'LastModifiedDate',
108
			sync_triggers text NOT NULL,
109
			push_async tinyint(1) NOT NULL DEFAULT '0',
110
			push_drafts tinyint(1) NOT NULL DEFAULT '0',
111
			pull_to_drafts tinyint(1) NOT NULL DEFAULT '0',
112
			weight tinyint(1) NOT NULL DEFAULT '0',
113
			version varchar(255) NOT NULL DEFAULT '',
114
			PRIMARY KEY  (id),
115
			UNIQUE KEY name (name),
116
			KEY name_sf_type_wordpress_type (wordpress_object,salesforce_object)
117
		) ENGINE=InnoDB $charset_collate";
118
119
		$object_map_table = $this->wpdb->prefix . 'object_sync_sf_object_map';
120
		$object_map_sql   = "CREATE TABLE $object_map_table (
121
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
122
			wordpress_id varchar(32) NOT NULL,
123
			salesforce_id varbinary(32) NOT NULL DEFAULT '',
124
			wordpress_object varchar(128) NOT NULL DEFAULT '',
125
			created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
126
			object_updated datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
127
			last_sync datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
128
			last_sync_action varchar(128) DEFAULT NULL,
129
			last_sync_status tinyint(1) NOT NULL DEFAULT '0',
130
			last_sync_message varchar(255) DEFAULT NULL,
131
			PRIMARY KEY  (id),
132
			KEY wordpress_object (wordpress_object,wordpress_id),
133
			KEY salesforce_object (salesforce_id)
134
		) $charset_collate";
135
136
		if ( ! function_exists( 'dbDelta' ) ) {
137
			if ( ! is_admin() ) {
138
				return false;
139
			}
140
			require_once ABSPATH . 'wp-admin/includes/upgrade.php';
141
		}
142
143
		// Note: see https://wordpress.stackexchange.com/questions/67345/how-to-implement-wordpress-plugin-update-that-modifies-the-database
144
		// 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."
145
		// 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.
146
		$result_field_map  = dbDelta( $field_map_sql );
147
		$result_object_map = dbDelta( $object_map_sql );
148
149
		$remove_key_version = '1.8.0';
150
		if ( '' !== $this->user_installed_version && version_compare( $this->user_installed_version, $remove_key_version, '<' ) ) {
0 ignored issues
show
Bug introduced by
It seems like $this->user_installed_version can also be of type boolean; however, parameter $version1 of version_compare() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

150
		if ( '' !== $this->user_installed_version && version_compare( /** @scrutinizer ignore-type */ $this->user_installed_version, $remove_key_version, '<' ) ) {
Loading history...
151
			$this->wpdb->query( "ALTER TABLE $object_map_table DROP INDEX salesforce" );
152
			$this->wpdb->query( "ALTER TABLE $object_map_table DROP INDEX salesforce_wordpress" );
153
			$result_key = true;
154
		}
155
156
		// store right now as the time for the plugin's activation
157
		update_option( $this->option_prefix . 'activate_time', time() );
158
159
		// utf8mb4 conversion.
160
		maybe_convert_table_to_utf8mb4( $field_map_table );
161
		maybe_convert_table_to_utf8mb4( $object_map_table );
162
163
		if ( '' === $this->user_installed_version || version_compare( $this->user_installed_version, $this->version, '<' ) ) {
164
			update_option( $this->option_prefix . 'db_version', $this->version );
165
		}
166
167
		if ( ! isset( $result_key ) && empty( $result_field_map ) && empty( $result_object_map ) ) {
168
			// No changes, database already exists and is up-to-date
169
			return;
170
		}
171
172
		return;
173
174
	}
175
176
	/**
177
	* Add roles and capabilities
178
	* This adds the configure_salesforce capability to the admin role
179
	*
180
	* It also allows other plugins to add the capability to other roles
181
	*
182
	*/
183
	public function add_roles_capabilities() {
184
185
		// by default, only administrators can configure the plugin
186
		$role = get_role( 'administrator' );
187
		$role->add_cap( 'configure_salesforce' );
188
189
		// hook that allows other roles to configure the plugin as well
190
		$roles = apply_filters( $this->option_prefix . 'roles_configure_salesforce', null );
191
192
		// for each role that we have, give it the configure salesforce capability
193
		if ( null !== $roles ) {
194
			foreach ( $roles as $role ) {
195
				$role = get_role( $role );
196
				$role->add_cap( 'configure_salesforce' );
197
			}
198
		}
199
200
	}
201
202
	/**
203
	* Check for database version
204
	* When the plugin is loaded in the admin, if the database version does not match the current version, perform these methods
205
	*
206
	*/
207
	public function wordpress_salesforce_update_db_check() {
208
209
		// user is running a version less than the current one
210
		if ( version_compare( $this->user_installed_version, $this->version, '<' ) ) {
0 ignored issues
show
Bug introduced by
It seems like $this->user_installed_version can also be of type boolean; however, parameter $version1 of version_compare() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

210
		if ( version_compare( /** @scrutinizer ignore-type */ $this->user_installed_version, $this->version, '<' ) ) {
Loading history...
211
			$this->wordpress_salesforce_tables();
212
		} else {
213
			return true;
214
		}
215
	}
216
217
	/**
218
	* Check whether the user has action scheduler tasks when they upgrade
219
	*
220
	* @param object $upgrader_object
221
	* @param array $hook_extra
222
	*
223
	* See https://developer.wordpress.org/reference/hooks/upgrader_process_complete/
224
	*
225
	*/
226
	public function check_for_action_scheduler( $upgrader_object, $hook_extra ) {
227
228
		// skip if this action isn't this plugin being updated
229
		if ( 'plugin' !== $hook_extra['type'] && 'update' !== $hook_extra['action'] && $hook_extra['plugin'] !== $this->slug ) {
230
			return;
231
		}
232
233
		// user is running a version less than 1.4.0
234
		$action_scheduler_version = '1.4.0';
235
		$previous_version         = get_transient( $this->option_prefix . 'installed_version' );
236
		if ( version_compare( $previous_version, $action_scheduler_version, '<' ) ) {
237
			// delete old options
238
			delete_option( $this->option_prefix . 'push_schedule_number' );
239
			delete_option( $this->option_prefix . 'push_schedule_unit' );
240
			delete_option( $this->option_prefix . 'salesforce_schedule_number' );
241
			delete_option( $this->option_prefix . 'salesforce_schedule_unit' );
242
			if ( '' === $this->queue ) {
243
				delete_transient( $this->option_prefix . 'installed_version' );
244
				return;
245
			}
246
			foreach ( $this->schedulable_classes as $key => $schedule ) {
247
				$schedule_name     = $key;
248
				$action_group_name = $schedule_name . $this->action_group_suffix;
249
				// exit if there is no initializer property on this schedule
250
				if ( ! isset( $this->schedulable_classes[ $schedule_name ]['initializer'] ) ) {
251
					continue;
252
				}
253
				// create new recurring task for action-scheduler to check for data to pull from Salesforce
254
				$this->queue->schedule_recurring(
255
					time(), // plugin seems to expect UTC
256
					$this->queue->get_frequency( $schedule_name, 'seconds' ),
257
					$this->schedulable_classes[ $schedule_name ]['initializer'],
258
					array(),
259
					$action_group_name
260
				);
261
			}
262
			delete_transient( $this->option_prefix . 'installed_version' );
263
		}
264
	}
265
266
}
267