Completed
Push — update/sync-code-cleanup ( f4fab3 )
by
unknown
11:13
created

Jetpack_Sync_Module_Full_Sync::start()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 52
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 9
Bugs 1 Features 1
Metric Value
cc 7
eloc 22
c 9
b 1
f 1
nc 6
nop 1
dl 0
loc 52
rs 7.2396

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This class does a full resync of the database by
5
 * enqueuing an outbound action for every single object
6
 * that we care about.
7
 *
8
 * This class, and its related class Jetpack_Sync_Module, contain a few non-obvious optimisations that should be explained:
9
 * - we fire an action called jetpack_full_sync_start so that WPCOM can erase the contents of the cached database
10
 * - for each object type, we page through the object IDs and enqueue them by firing some monitored actions
11
 * - we load the full objects for those IDs in chunks of Jetpack_Sync_Module::ARRAY_CHUNK_SIZE (to reduce the number of MySQL calls)
12
 * - we fire a trigger for the entire array which the Jetpack_Sync_Listener then serializes and queues.
13
 */
14
15
require_once 'class.jetpack-sync-wp-replicastore.php';
16
17
class Jetpack_Sync_Module_Full_Sync extends Jetpack_Sync_Module {
18
	const STATUS_OPTION = 'jetpack_full_sync_status';
19
	const FULL_SYNC_TIMEOUT = 3600;
20
21
	public function name() {
22
		return 'full-sync';
23
	}
24
25
	function init_listeners( $callable ) {
26
		// synthetic actions for full sync
27
		add_action( 'jetpack_full_sync_start', $callable );
28
		add_action( 'jetpack_full_sync_end', $callable );
29
	}
30
31
	function init_before_send() {
32
		// this is triggered after actions have been processed on the server
33
		add_action( 'jetpack_sync_processed_actions', array( $this, 'update_sent_progress_action' ) );
34
	}
35
36
	function start( $modules = null ) {
37
		if ( ! $this->should_start_full_sync() ) {
38
			return false;
39
		}
40
41
		// ensure listener is loaded so we can guarantee full sync actions are enqueued
42
		require_once dirname( __FILE__ ) . '/class.jetpack-sync-listener.php';
43
		Jetpack_Sync_Listener::get_instance();
44
45
		/**
46
		 * Fires when a full sync begins. This action is serialized
47
		 * and sent to the server so that it knows a full sync is coming.
48
		 *
49
		 * @since 4.2.0
50
		 */
51
		do_action( 'jetpack_full_sync_start' );
52
		$this->set_status_queuing_started();
53
54
		foreach ( Jetpack_Sync_Modules::get_modules() as $module ) {
55
			$module_name = $module->name();
56
			if ( is_array( $modules ) && ! in_array( $module_name, $modules ) ) {
57
				continue;
58
			}
59
60
			$items_enqueued = $module->enqueue_full_sync_actions();
61
			if ( $items_enqueued !== 0 ) {
62
				$status = $this->get_status();
63
64
				if ( ! isset( $status['queue'][ $module_name ] ) ) {
65
					$status['queue'][ $module_name ] = 0;
66
				}
67
68
				$status['queue'][ $module_name ] += $items_enqueued;
69
				$this->update_status( $status );
70
			}
71
		}
72
73
		$this->set_status_queuing_finished();
74
75
		$store = new Jetpack_Sync_WP_Replicastore();
76
77
		/**
78
		 * Fires when a full sync ends. This action is serialized
79
		 * and sent to the server with checksums so that we can confirm the
80
		 * sync was successful.
81
		 *
82
		 * @since 4.2.0
83
		 */
84
		do_action( 'jetpack_full_sync_end', $store->checksum_all() );
85
86
		return true;
87
	}
88
89
	private function should_start_full_sync() {
90
		$status = $this->get_status();
91
92
		// We should try sync if we haven't started it yet or if we have finished it.
93
		if ( is_null( $status['started'] ) || is_integer( $status['finished'] ) ) {
94
			return true;
95
		}
96
97
		// allow enqueuing if last full sync was started more than FULL_SYNC_TIMEOUT seconds ago
98
		if ( intval( $status['started'] ) + self::FULL_SYNC_TIMEOUT < time() ) {
99
			return true;
100
		}
101
102
		return false;
103
	}
104
105
	function update_sent_progress_action( $actions ) {
106
		// quick way to map to first items with an array of arrays
107
		$actions_with_counts = array_count_values( array_map( 'reset', $actions ) );
108
109
		$status = $this->get_status();
110
		if ( is_null( $status['started'] ) || $status['finished'] ) {
111
			return;
112
		}
113
114
		if ( isset( $actions_with_counts['jetpack_full_sync_start'] ) ) {
115
			$status['sent_started'] = time();
116
		}
117
118
		foreach ( Jetpack_Sync_Modules::get_modules() as $module ) {
119
			$module_name    = $module->name();
120
			$module_actions = $module->get_full_sync_actions();
121
			foreach ( $module_actions as $module_action ) {
122
				if ( isset( $actions_with_counts[ $module_action ] ) ) {
123
					if ( ! isset( $status['sent'][ $module_name ] ) ) {
124
						$status['sent'][ $module_name ] = 0;
125
					}
126
					$status['sent'][ $module_name ] += $actions_with_counts[ $module_action ];
127
				}
128
			}
129
		}
130
131
		if ( isset( $actions_with_counts['jetpack_full_sync_end'] ) ) {
132
			$status['finished'] = time();
133
		}
134
135
		$this->update_status( $status );
136
	}
137
138
	private function set_status_queuing_started() {
139
		$status            = $this->initial_status;
140
		$status['started'] = time();
141
		$this->update_status( $status );
142
	}
143
144
	private function set_status_queuing_finished() {
145
		$this->update_status( array( 'queue_finished' => time() ) );
146
	}
147
148
	private $initial_status = array(
149
		'started'        => null,
150
		'queue_finished' => null,
151
		'sent_started'   => null,
152
		'finished'       => null,
153
		'sent'           => array(),
154
		'queue'          => array(),
155
	);
156
157
	public function get_status() {
158
		return get_option( self::STATUS_OPTION, $this->initial_status );
159
	}
160
161
	public function update_status( $status ) {
162
		return update_option(
163
			self::STATUS_OPTION,
164
			array_merge( $this->get_status(), $status )
165
		);
166
	}
167
168
	public function clear_status() {
169
		delete_option( self::STATUS_OPTION );
170
	}
171
}
172