Completed
Push — master ( ce5918...20c3c4 )
by David
02:48
created

Wordlift_Linked_Data_Service   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 279
Duplicated Lines 4.3 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
dl 12
loc 279
rs 10
c 0
b 0
f 0
wmc 17
lcom 1
cbo 6

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 12 12 1
A get_instance() 0 4 1
A push() 0 21 3
A remove() 0 8 1
B do_push() 0 37 4
A has_valid_uri() 0 18 3
B get_delete_statements() 0 26 1
A get_insert_tuples() 0 20 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Services: Linked Data Service.
4
 *
5
 * A service to handle data to be pushed to the remote Linked Data store.
6
 *
7
 * @since      3.15.0
8
 * @package    Wordlift
9
 * @subpackage Wordlift/includes
10
 */
11
12
/**
13
 * Define the {@link Wordlift_Linked_Data_Service} class.
14
 *
15
 * @since      3.15.0
16
 * @package    Wordlift
17
 * @subpackage Wordlift/includes
18
 */
19
class Wordlift_Linked_Data_Service {
20
21
	/**
22
	 * A {@link Wordlift_Log_Service} instance.
23
	 *
24
	 * @since  3.15.0
25
	 * @access private
26
	 * @var \Wordlift_Log_Service $log A {@link Wordlift_Log_Service} instance.
27
	 */
28
	private $log;
29
30
	/**
31
	 * The {@link Wordlift_Entity_Service} instance.
32
	 *
33
	 * @since  3.15.0
34
	 * @access private
35
	 * @var \Wordlift_Entity_Service $entity_service The {@link Wordlift_Entity_Service} instance.
36
	 */
37
	private $entity_service;
38
39
	/**
40
	 * The {@link Wordlift_Entity_Type_Service} instance.
41
	 *
42
	 * @since  3.15.0
43
	 * @access private
44
	 * @var \Wordlift_Entity_Type_Service $entity_type_service The {@link Wordlift_Entity_Type_Service} instance.
45
	 */
46
	private $entity_type_service;
47
48
	/**
49
	 * The {@link Wordlift_Schema_Service} instance.
50
	 *
51
	 * @since  3.15.0
52
	 * @access private
53
	 * @var \Wordlift_Schema_Service $schema_service The {@link Wordlift_Schema_Service} instance.
54
	 */
55
	private $schema_service;
56
57
	/**
58
	 * The {@link Wordlift_Linked_Data_Service} singleton instance.
59
	 *
60
	 * @since  3.15.0
61
	 * @access private
62
	 * @var \Wordlift_Linked_Data_Service $instance The {@link Wordlift_Linked_Data_Service} singleton instance.
63
	 */
64
	private static $instance;
65
66
	/**
67
	 * The {@link Wordlift_Sparql_Service} instance.
68
	 *
69
	 * @since  3.15.0
70
	 * @access private
71
	 * @var \Wordlift_Sparql_Service $sparql_service The {@link Wordlift_Sparql_Service} instance.
72
	 */
73
	private $sparql_service;
74
75
	/**
76
	 * Create a {@link Wordlift_Linked_Data_Service} instance.
77
	 *
78
	 * @since 3.15.0
79
	 *
80
	 * @param \Wordlift_Entity_Service      $entity_service      The {@link Wordlift_Entity_Service} instance.
81
	 * @param \Wordlift_Entity_Type_Service $entity_type_service The {@link Wordlift_Entity_Type_Service} instance.
82
	 * @param \Wordlift_Schema_Service      $schema_service      The {@link Wordlift_Schema_Service} instance.
83
	 * @param \Wordlift_Sparql_Service      $sparql_service      The {@link Wordlift_Sparql_Service} instance.
84
	 */
85 View Code Duplication
	public function __construct( $entity_service, $entity_type_service, $schema_service, $sparql_service ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
87
		$this->log = Wordlift_Log_Service::get_logger( 'Wordlift_Linked_Data_Service' );
88
89
		$this->entity_service      = $entity_service;
90
		$this->entity_type_service = $entity_type_service;
91
		$this->schema_service      = $schema_service;
92
		$this->sparql_service      = $sparql_service;
93
94
		self::$instance = $this;
95
96
	}
97
98
	/**
99
	 * Get the singleton instance of {@link Wordlift_Linked_Data_Service}.
100
	 *
101
	 * @since 3.15.0
102
	 *
103
	 * @return Wordlift_Linked_Data_Service The singleton instance of <a href='psi_element://Wordlift_Linked_Data_Service'>Wordlift_Linked_Data_Service</a>.
104
	 */
105
	public static function get_instance() {
106
107
		return self::$instance;
108
	}
109
110
	/**
111
	 * Push a {@link WP_Post} to the Linked Data store.
112
	 *
113
	 * If the {@link WP_Post} is an entity and it's not of the `Article` type,
114
	 * then it is pushed to the remote Linked Data store.
115
	 *
116
	 * @since 3.15.0
117
	 *
118
	 * @param int $post_id The {@link WP_Post}'s id.
119
	 */
120
	public function push( $post_id ) {
121
122
		$this->log->debug( "Pushing post $post_id..." );
123
124
		// Bail out if it's not an entity: we do NOT publish non entities or
125
		// entities of type `Article`s.
126
		if ( ! $this->entity_service->is_entity( $post_id ) ) {
127
			$this->log->debug( "Post $post_id is not an entity." );
128
129
			return;
130
		}
131
132
		// Get the post and push it to the Linked Data store.
133
		$this->do_push( $post_id );
134
135
		// Reindex the triple store if buffering is turned off.
136
		if ( false === WL_ENABLE_SPARQL_UPDATE_QUERIES_BUFFERING ) {
137
			wordlift_reindex_triple_store();
138
		}
139
140
	}
141
142
	/**
143
	 * Remove the specified {@link WP_Post} from the Linked Data.
144
	 *
145
	 * @since 3.15.0
146
	 *
147
	 * @param int $post_id The {@link WP_Post}'s id.
148
	 */
149
	public function remove( $post_id ) {
150
151
		// Get the delete statements.
152
		$deletes      = $this->get_delete_statements( $post_id );
153
		$delete_query = implode( "\n", $deletes );
154
		$this->sparql_service->execute( $delete_query );
155
156
	}
157
158
	/**
159
	 * Push an entity to the Linked Data store.
160
	 *
161
	 * @since 3.15.0
162
	 *
163
	 * @param int $post_id The {@link WP_Post}'s id.
164
	 */
165
	private function do_push( $post_id ) {
166
		$this->log->debug( "Doing post $post_id push..." );
167
168
		// Get the post.
169
		$post = get_post( $post_id );
170
171
		// Bail out if the post isn't found.
172
		if ( null === $post ) {
173
			$this->log->warn( "Post $post_id not found." );
174
175
			return;
176
		}
177
178
		// Bail out if the post isn't published.
179
		if ( 'publish' !== $post->post_status ) {
180
			$this->log->info( "Post $post_id not published." );
181
182
			return;
183
		}
184
185
		// Bail out if the URI isn't valid.
186
		if ( ! $this->has_valid_uri( $post_id ) ) {
187
			$this->log->warn( "Post $post_id URI invalid." );
188
189
			return;
190
		}
191
192
		// First remove the post data.
193
		$this->remove( $post_id );
194
195
		// Get the insert statements.
196
		$insert_tuples     = $this->get_insert_tuples( $post_id );
197
		$insert_query_body = implode( "\n", $insert_tuples );
198
		$insert_query      = "INSERT DATA { $insert_query_body };";
199
		$this->sparql_service->execute( $insert_query );
200
201
	}
202
203
	/**
204
	 * Check if an entity's {@link WP_Post} has a valid URI.
205
	 *
206
	 * @since 3.15.0
207
	 *
208
	 * @param int $post_id The entity's {@link WP_Post}'s id.
209
	 *
210
	 * @return bool True if the URI is valid otherwise false.
211
	 */
212
	private function has_valid_uri( $post_id ) {
213
214
		// Get the entity's URI.
215
		$uri = $this->entity_service->get_uri( $post_id );
216
217
		// If the URI isn't found, return false.
218
		if ( null === $uri ) {
219
			return false;
220
		}
221
222
		// If the URI ends with a trailing slash, return false.
223
		if ( '/' === substr( $uri, - 1 ) ) {
224
			return false;
225
		}
226
227
		// URI is valid.
228
		return true;
229
	}
230
231
	/**
232
	 * Get the delete statements.
233
	 *
234
	 * @since 3.15.0
235
	 *
236
	 * @param int $post_id The {@link WP_Post}'s id.
237
	 *
238
	 * @return array An array of delete statements.
239
	 */
240
	private function get_delete_statements( $post_id ) {
241
242
		// Get the entity URI.
243
		$uri = $this->entity_service->get_uri( $post_id );
244
245
		// Prepare the delete statements with the entity as subject.
246
		$as_subject = array_map( function ( $item ) use ( $uri ) {
247
			return Wordlift_Query_Builder
248
				::new_instance()
249
				->delete()
250
				->statement( $uri, $item, '?o' )
251
				->build();
252
		}, $this->schema_service->get_all_predicates() );
253
254
		// Prepare the delete statements with the entity as object.
255
		$as_object = array_map( function ( $item ) use ( $uri ) {
256
			return Wordlift_Query_Builder
257
				::new_instance()
258
				->delete()
259
				->statement( '?s', $item, $uri, Wordlift_Query_Builder::OBJECT_URI )
260
				->build();
261
		}, $this->schema_service->get_all_predicates() );
262
263
		// Merge the delete statements and return them.
264
		return array_merge( $as_subject, $as_object );
265
	}
266
267
	/**
268
	 * Get the SPARQL insert tuples ( ?s ?p ?o ) for the specified {@link WP_Post}.
269
	 *
270
	 * @since 3.15.0
271
	 *
272
	 * @param int $post_id The {@link WP_Post}'s id.
273
	 *
274
	 * @return array An array of insert tuples.
275
	 */
276
	private function get_insert_tuples( $post_id ) {
277
278
		// Get the entity type.
279
		$type = $this->entity_type_service->get( $post_id );
280
281
		// Get the Linked Data properties.
282
		$properties = $type['linked_data'];
283
284
		// Accumulate the tuples.
285
		$tuples = array();
286
		/** @var Wordlift_Sparql_Tuple_Rendition $property A {@link Wordlift_Sparql_Tuple_Rendition} instance. */
287
		foreach ( $properties as $property ) {
288
			foreach ( $property->get( $post_id ) as $tuple ) {
289
				$tuples[] = $tuple;
290
			}
291
		}
292
293
		// Finally return the tuples.
294
		return $tuples;
295
	}
296
297
}
298