Completed
Push — develop ( 1d2391...a94b56 )
by David
02:55 queued 11s
created

Sync_Background_Process::start()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
1
<?php
2
3
namespace Wordlift\Dataset;
4
5
use Tinify\Exception;
6
7
class Sync_Background_Process extends \Wordlift_Plugin_WP_Background_Process {
8
9
	protected $action = 'wl_dataset__sync';
10
11
	/**
12
	 * @var Sync_Service
13
	 */
14
	private $sync_service;
15
16
	/**
17
	 * @var \Wordlift_Log_Service
18
	 */
19
	private $log;
20
21
	/**
22
	 * Sync_Background_Process constructor.
23
	 *
24
	 * @param $sync_service Sync_Service A {@link Sync_Service} instance providing the supporting functions to this background process.
25
	 */
26
	public function __construct( $sync_service ) {
27
		parent::__construct();
28
29
		$this->log = \Wordlift_Log_Service::get_logger( get_class() );
30
31
		$this->sync_service = $sync_service;
32
33
	}
34
35
	/**
36
	 * This function is called:
37
	 *  - To start a new Synchronization, by passing a {@link Sync_Start_Message} instance.
38
	 *  - To synchronize a post, by passing a numeric ID.
39
	 *
40
	 * This function returns the parameter for the next call or NULL if there are no more posts to process.
41
	 *
42
	 * @param int $post_id The post ID.
43
	 *
44
	 * @return int|false The next post ID or false if there are no more.
45
	 */
46
	protected function task( $post_id ) {
47
48
		// Check if we must cancel.
49
		if ( $this->must_cancel() ) {
50
			$this->cancel();
51
52
			return false;
53
		}
54
55
		$this->log->debug( "Synchronizing post $post_id..." );
56
57
		// Sync the item.
58
		return $this->sync_item( $post_id );
59
	}
60
61
	/**
62
	 * Start the background processing.
63
	 *
64
	 * @return bool True if the process has been started, otherwise false.
65
	 */
66
	public function start() {
67
68
		// Create a new Sync_Model state of `started`.
69
		if ( ! $this->is_started( self::get_state() ) ) {
70
			$this->log->debug( "Starting..." );
71
72
			$sync_state = new Sync_State( time(), 0, $this->sync_service->count(), time(), 'started' );
73
			update_option( '_wl_dataset_sync', $sync_state );
74
75
			$next = $this->sync_service->next();
76
			$this->push_to_queue( $next );
77
			$this->save()->dispatch();
78
79
			$this->log->debug( "Started with post ID $next." );
80
81
			return true;
82
		}
83
84
		return false;
85
	}
86
87
	/**
88
	 * Set the transient to cancel the process. The next time the process runs, it'll check whether this transient is
89
	 * set and will stop processing.
90
	 */
91
	public function request_cancel() {
92
93
		set_transient( "{$this->action}__cancel", true );
94
95
	}
96
97
	/**
98
	 * Get the sync state.
99
	 *
100
	 * @return Sync_State The {@link Sync_State}.
101
	 */
102
	public static function get_state() {
103
104
		try {
105
			return get_option( '_wl_dataset_sync', Sync_State::unknown() );
106
		} catch ( Exception $e ) {
0 ignored issues
show
Bug introduced by
The class Tinify\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
107
			return Sync_State::unknown();
108
		}
109
110
	}
111
112
	/**
113
	 * Check whether the provided state is `started` or not.
114
	 *
115
	 * @param Sync_State $state The {@link Sync_State}.
116
	 *
117
	 * @return bool True if the state is started.
118
	 */
119
	private function is_started( $state ) {
120
		return $state instanceof Sync_State && 'started' === $state->state && 30 > ( time() - $state->last_update );
121
	}
122
123
	/**
124
	 * Check whether the process must cancel or not.
125
	 *
126
	 * @return bool Whether to cancel or not the process.
127
	 */
128
	private function must_cancel() {
129
130
		return get_transient( "{$this->action}__cancel" );
131
	}
132
133
	/**
134
	 * Cancels the current process.
135
	 */
136
	private function cancel() {
137
138
		$this->log->debug( "Cancelling synchronization..." );
139
140
		// Cleanup the process data.
141
		$this->cancel_process();
142
143
		// Set the state to cancelled.
144
		$state = self::get_state();
145
		$state->set_state( 'cancelled' );
146
		update_option( '_wl_dataset_sync', $state );
147
148
		// Finally delete the transient.
149
		delete_transient( "{$this->action}__cancel" );
150
151
	}
152
153
	/**
154
	 * Push the post with the provided ID to the remote platform.
155
	 *
156
	 * @param int $post_id The post ID.
157
	 *
158
	 * @return int|false The next post ID to process or false if processing is complete.
159
	 */
160
	private function sync_item( $post_id ) {
161
162
		// Sync this item.
163
		if ( $this->sync_service->sync_item( $post_id ) ) {
164
165
			$next       = $this->sync_service->next();
166
			$next_state = isset( $next ) ? 'started' : 'ended';
167
168
			/**
169
			 * Update the synchronization meta data, by increasing the current index.
170
			 *
171
			 * @var Sync_State $sync The {@link Sync_State}.
172
			 */
173
			$state = self::get_state()
174
			             ->increment_index()
175
			             ->set_state( $next_state );
176
			update_option( '_wl_dataset_sync', $state );
177
178
			// Return the next ID or false if there aren't.
179
			return isset( $next ) ? (int) $next : false;
180
		} else {
181
			// Retry.
182
			// @@todo: put a limit to the number of retries.
183
			return $post_id;
184
		}
185
186
	}
187
188
}
189