Completed
Pull Request — develop (#1282)
by David
07:16 queued 04:07
created

Sync_Service::next()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace Wordlift\Dataset;
4
5
use Wordlift\Api\Api_Service;
6
use Wordlift\Jsonld\Jsonld_Service;
7
8
class Sync_Service {
9
	const JSONLD_HASH = '_wl_jsonld_hash';
10
	const SYNCED_GMT = '_wl_synced_gmt';
11
12
	/**
13
	 * @var \Wordlift_Log_Service
14
	 */
15
	private $log;
16
17
	/**
18
	 * @var Api_Service
19
	 */
20
	private $api_service;
21
22
	/**
23
	 * @var Jsonld_Service
24
	 */
25
	private $jsonld_service;
26
27
	/**
28
	 * @var Sync_Background_Process
29
	 */
30
	private $sync_background_process;
31
32
	/**
33
	 * The number of posts processed in one call.
34
	 *
35
	 * @var int The batch size.
36
	 */
37
	private $batch_size;
38
39
	/**
40
	 * @var Sync_Object_Adapter_Factory
41
	 */
42
	private $sync_object_adapter_factory;
43
44
	/**
45
	 * @var Sync_Service
46
	 */
47
	private static $instance;
48
	private $entity_service;
49
50
	/**
51
	 * Constructor.
52
	 *
53
	 * @param Api_Service $api_service The {@link Api_Service} used to communicate with the remote APIs.
54
	 * @param Sync_Object_Adapter_Factory $sync_object_adapter_factory
55
	 * @param Jsonld_Service $jsonld_service
56
	 * @param \Wordlift_Entity_Service $entity_service
57
	 */
58
	public function __construct( $api_service, $sync_object_adapter_factory, $jsonld_service, $entity_service ) {
59
60
		$this->log = \Wordlift_Log_Service::get_logger( get_class() );
61
62
		$this->api_service                 = $api_service;
63
		$this->sync_object_adapter_factory = $sync_object_adapter_factory;
64
		$this->jsonld_service              = $jsonld_service;
65
		$this->entity_service              = $entity_service;
66
		$this->batch_size                  = 10;
67
68
		// You need to initialize this early, otherwise the Background Process isn't registered in AJAX calls.
69
//		$this->sync_background_process = new Sync_Background_Process( $this );;
70
71
		// Exclude the JSONLD_HASH meta key from those that require a resync.
72
		add_filter( 'wl_dataset__sync_hooks__ignored_meta_keys', function ( $args ) {
73
			$args[] = Sync_Service::JSONLD_HASH;
74
			$args[] = Sync_Service::SYNCED_GMT;
75
76
			return $args;
77
		} );
78
79
		self::$instance = $this;
80
	}
81
82
	public static function get_instance() {
83
		return self::$instance;
84
	}
85
86
	/**
87
	 * @param int $type
88
	 * @param int $object_id
89
	 *
90
	 * @return array|false
91
	 * @throws \Exception
92
	 */
93
	public function sync_one( $type, $object_id ) {
94
95
		$object = $this->sync_object_adapter_factory->create( $type, $object_id );
96
97
		return $this->sync_many( array( $object ) );
98
	}
99
100
	public function delete_one( $type, $object_id ) {
101
		$object = $this->sync_object_adapter_factory->create( $type, $object_id );
102
		$uri    = $object->get_meta( 'entity_url', true );
103
104
		// Entity URL isn't set, bail out.
105
		if ( empty( $uri ) ) {
106
			return false;
107
		}
108
109
		$response = $this->api_service->request(
110
			'DELETE', sprintf( '/middleware/dataset?uri=%s', rawurlencode( $uri ) ) );
111
112
		// Update the sync date in case of success, otherwise log an error.
113
		if ( ! $response->is_success() ) {
114
			return false;
115
		}
116
117
		return true;
118
	}
119
120
	/**
121
	 * @param Sync_Object_Adapter[] $objects
122
	 *
123
	 * @return bool
124
	 * @throws \Exception
125
	 */
126
	public function sync_many( $objects, $force = false ) {
127
128
		$hashes   = array();
129
		$payloads = array();
130
		foreach ( $objects as $object ) {
131
			// Bail out if no payload.
132
			$payload_as_string = $this->get_payload_as_string( $object );
133
			if ( empty( $payload_as_string ) ) {
134
				continue;
135
			}
136
137
			$new_hash = sha1( $payload_as_string );
138
			$old_hash = $object->get_meta( self::JSONLD_HASH, true );
139
			// JSON-LD hasn't changed, bail out.
140
			if ( ! $force && $new_hash === $old_hash ) {
141
				continue;
142
			}
143
144
			// Collect the hashes and the payloads.
145
			$hashes[]   = array( $object, $new_hash );
146
			$payloads[] = $payload_as_string;
147
		}
148
149
		// Bail out if payloads are empty.
150
		if ( empty( $payloads ) ) {
151
			return false;
152
		}
153
154
		$response = $this->api_service->request(
155
			'POST', '/middleware/dataset/batch',
156
			array( 'Content-Type' => 'application/json', ),
157
			// Put the payload in a JSON array w/o decoding/encoding again.
158
			'[ ' . implode( ', ', $payloads ) . ' ]' );
159
160
		// Update the sync date in case of success, otherwise log an error.
161
		if ( ! $response->is_success() ) {
162
			return false;
163
		}
164
165
		// If successful update the hashes and sync'ed datetime.
166
		foreach ( $hashes as $hash ) {
167
			$object   = $hash[0];
168
			$new_hash = $hash[1];
169
			$object->update_meta( self::JSONLD_HASH, $new_hash );
170
			$object->update_meta( self::SYNCED_GMT, current_time( 'mysql', true ) );
171
		}
172
173
		return true;
174
	}
175
176
	/**
177
	 * @param Sync_Object_Adapter $object
178
	 *
179
	 * @return false|string
180
	 * @throws \Exception
181
	 */
182
	private function get_payload_as_string( $object ) {
183
		$type      = $object->get_type();
184
		$object_id = $object->get_object_id();
185
186
		$jsonld_as_string = wp_json_encode( apply_filters( 'wl_dataset__sync_service__sync_item__jsonld',
187
			$this->jsonld_service->get( $type, $object_id ), $type, $object_id ) );
188
		$uri              = $this->entity_service->get_uri( $object_id, $type );
189
190
		// Entity URL isn't set, bail out.
191
		if ( empty( $uri ) ) {
192
			return false;
193
		}
194
195
		return wp_json_encode( array(
196
			'uri'     => $uri,
197
			'model'   => $jsonld_as_string,
198
			'private' => ! $object->is_public(),
199
		) );
200
	}
201
//
202
//	/**
203
//	 * Starts a new synchronization.
204
//	 */
205
//	public function start() {
206
//
207
//		// Create the Sync_Background_Process.
208
//		$this->sync_background_process->start();
209
//
210
//	}
211
//
212
//	/**
213
//	 * Request to cancel a background process.
214
//	 */
215
//	public function request_cancel() {
216
//
217
//		$this->sync_background_process->request_cancel();
218
//
219
//	}
220
//
221
//	/**
222
//	 * Get the next post IDs to synchronize.
223
//	 *
224
//	 * @return array An array of post IDs.
225
//	 */
226
//	public function next() {
227
//		global $wpdb;
228
//
229
//		$state = $this->info();
230
//
231
//		// Limit the query to the allowed post types.
232
//		$post_type_in = implode( "','", array_map( 'esc_sql', \Wordlift_Entity_Service::valid_entity_post_types() ) );
233
//
234
//		// Get the next post ID.
235
//		return $wpdb->get_col( "
236
//			SELECT p.ID
237
//			FROM $wpdb->posts p
238
//			WHERE p.post_status = 'publish'
239
//			  AND p.post_type IN ('$post_type_in')
240
//			ORDER BY p.ID
241
//			LIMIT {$state->index},{$this->batch_size}
242
//			" );
243
//	}
244
//
245
//	public function count() {
246
//		global $wpdb;
247
//		$post_type_in = implode( "','", array_map( 'esc_sql', \Wordlift_Entity_Service::valid_entity_post_types() ) );
248
//
249
//		return $wpdb->get_var( "
250
//			SELECT COUNT(1)
251
//			FROM $wpdb->posts p
252
//			WHERE p.post_status = 'publish'
253
//			  AND p.post_type IN ('$post_type_in')
254
//			" );
255
//	}
256
//
257
//	public function info() {
258
//		return Sync_Background_Process::get_state();
259
//	}
260
//
261
//	public function sync_items(
262
//		$post_ids, $clear = true
263
//	) {
264
//
265
//		$this->log->debug( sprintf( 'Synchronizing post(s) %s...', implode( ', ', $post_ids ) ) );
266
//
267
//		// If we're starting the sync, try to clear the dataset.
268
//		if ( $clear && 0 === $this->info()->index ) {
269
//			$this->api_service->request( 'DELETE', '/middleware/dataset/delete' );
270
//		}
271
//
272
//		$that         = $this;
273
//		$request_body = array_filter( array_map( function ( $post_id ) use ( $that ) {
274
//			// Check if the post type is public.
275
//			$post_type     = get_post_type( $post_id );
276
//			$post_type_obj = get_post_type_object( $post_type );
277
//			if ( ! $post_type_obj->public ) {
278
//				return false;
279
//			}
280
//
281
//			$is_private       = ( 'publish' !== get_post_status( $post_id ) );
282
//			$uri              = get_post_meta( $post_id, 'entity_url', true );
283
//			$object_adapter   = $that->sync_object_adapter_factory->create( Object_Type_Enum::POST, $post_id );
284
//			$jsonld           = $object_adapter->get_jsonld_and_update_hash();
285
//			$jsonld_as_string = wp_json_encode( $jsonld );
286
//
287
//			$that->log->trace( "Posting JSON-LD:\n$jsonld_as_string" );
288
//
289
//			return array(
290
//				'uri'     => $uri,
291
//				'model'   => $jsonld_as_string,
292
//				'private' => $is_private
293
//			);
294
//		}, $post_ids ) );
295
//
296
//		// There's no point in making a request if the request is empty.
297
//		if ( empty( $request_body ) ) {
298
//			return true;
299
//		}
300
//
301
//		// Make a request to the remote endpoint.
302
//		$state              = $this->info();
303
//		$state_header_value = str_replace( "\n", '', wp_json_encode( $state ) );
304
//		$response           = $this->api_service->request(
305
//			'POST', '/middleware/dataset/batch',
306
//			array(
307
//				'Content-Type'                     => 'application/json',
308
//				'X-Wordlift-Dataset-Sync-State-V1' => $state_header_value
309
//			),
310
//			wp_json_encode( $request_body ) );
311
//
312
//		$this->log->debug( "Response received: " . ( $response->is_success() ? 'yes' : 'no' ) );
313
//
314
//		// Update the sync date in case of success, otherwise log an error.
315
//		if ( $response->is_success() ) {
316
//
317
//			foreach ( $post_ids as $post_id ) {
318
//				update_post_meta( $post_id, '_wl_synced_gmt', current_time( 'mysql', true ) );
319
//			}
320
//
321
//			$this->log->debug( sprintf( 'Posts %s synchronized.', implode( ', ', $post_ids ) ) );
322
//
323
//			return true;
324
//		} else {
325
//			// @@todo: should we put a limit retry here?
326
//			$response_dump = var_export( $response, true );
327
//			$this->log->error(
328
//				sprintf( 'An error occurred while synchronizing the data for post IDs %s: %s', implode( ', ', $post_ids ), $response_dump ) );
329
//
330
//			return false;
331
//		}
332
//
333
//	}
334
335
	/**
336
	 * @param $post_id
337
	 *
338
	 * @todo Complete the delete item.
339
	 */
340
	public function delete_item( $post_id ) {
341
		$uri = get_post_meta( $post_id, 'entity_url', true );
342
		// Make a request to the remote endpoint.
343
		$response = $this->api_service->request(
0 ignored issues
show
Unused Code introduced by
$response is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
344
			'DELETE', '/middleware/dataset?uri=' . rawurlencode( $uri ),
345
			array( 'Content-Type' => 'application/ld+json', ) );
346
	}
347
348
	public function get_batch_size() {
349
350
		return $this->batch_size;
351
	}
352
353
	public function delete_all() {
354
		$this->api_service->request( 'DELETE', '/middleware/dataset/all' );
355
	}
356
357
}
358